Get rid of the last global variable.
[obnox/wireshark/wip.git] / packet-qllc.c
1 /* packet-qllc.c
2  * Routines for QLLC protocol - Qualified? LLC
3  * Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * $Id: packet-qllc.c,v 1.5 2002/01/24 09:20:50 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 2001 Gerald Combs
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <glib.h>
35 #include <epan/packet.h>
36
37
38 static int proto_qllc = -1;
39 static int hf_qllc_address = -1;
40 static int hf_qllc_control = -1;
41
42 static gint ett_qllc = -1;
43
44 #define QSM                 0x93
45 #define QDISC               0x53
46 #define QXID                0xbf
47 #define QTEST               0xf3
48 #define QRR                 0xf1
49 #define QRD                 0x53
50 #define QUA                 0x73
51 #define QDM                 0x1f
52 #define QFRMR               0x97
53 #define QUI                 0x03
54 #define QUI_NO_REPLY        0x13
55 #define QSIM                0x17
56
57 #define QRD_QDISC_VALUE     0x53
58 #define QDISC_TEXT          "QDISC"
59 #define QRD_TEXT            "QRD"
60
61 /* Control Field */
62 static const value_string qllc_control_vals[] = {
63     { QUI,          "QUI" },
64     { QUI_NO_REPLY, "QUI - reply required" },
65     { QSIM,         "QSIM" },
66     { QDM,          "QDM" },
67     { QUA,          "QUA" },
68     { QSM,          "QSM" },
69     { QFRMR,        "QFRMR" },
70     { QXID,         "QXID" },
71     { QRR,          "QRR" },
72     { QTEST,        "QTEST" },
73     { QDISC,        QDISC_TEXT },
74     { QRD,          QRD_TEXT },
75     { 0x00, NULL },
76 };
77
78
79 static void
80 dissect_qllc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
81 {
82         proto_tree      *qllc_tree = NULL;
83         proto_item      *qllc_ti = NULL;
84     guint8      address, ctrl;
85     gboolean    command = FALSE;
86
87         /* Summary information */
88         if (check_col(pinfo->cinfo, COL_PROTOCOL))
89                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "QLLC");
90         if (check_col(pinfo->cinfo, COL_INFO))
91                 col_clear(pinfo->cinfo, COL_INFO);
92
93         if (tree) {
94                 qllc_ti = proto_tree_add_item(tree, proto_qllc, tvb, 0, -1,
95                     FALSE);
96                 qllc_tree = proto_item_add_subtree(qllc_ti, ett_qllc);
97
98     }
99
100     /* Get the address; we need it to determine if this is a
101      * COMMAND or a RESPONSE */
102     address = tvb_get_guint8(tvb, 0);
103     if (tree) {
104                 proto_tree_add_item(qllc_tree, hf_qllc_address, tvb, 0, 1, FALSE);
105     }
106
107     /* The address field equals X'FF' in commands (except QRR)
108      * and anything in responses. */
109     ctrl = tvb_get_guint8(tvb, 1);
110     if (ctrl != QRR && address == 0xff) {
111         command = TRUE;
112     }
113
114
115     /* Disambiguate QRD_QDISC_VALUE, based on whether this packet is
116      * a COMMAND or RESPONSE. */
117     if (ctrl == QRD_QDISC_VALUE) {
118         if (command) {
119             if (check_col(pinfo->cinfo, COL_INFO)) {
120                 col_set_str(pinfo->cinfo, COL_INFO, QDISC_TEXT);
121             }
122             if (tree) {
123                 proto_tree_add_text(qllc_tree, tvb,
124                         1, 1, "Control Field: %s (0x%02x)", QDISC_TEXT, ctrl);
125             }
126         }
127         else {
128             if (check_col(pinfo->cinfo, COL_INFO)) {
129                 col_set_str(pinfo->cinfo, COL_INFO, QRD_TEXT);
130             }
131             if (tree) {
132                 proto_tree_add_text(qllc_tree, tvb,
133                         1, 1, "Control Field: %s (0x%02x)", QRD_TEXT, ctrl);
134             }
135         }
136
137         /* Add the field for filtering purposes */
138         if (tree) {
139             proto_tree_add_uint_hidden(qllc_tree, hf_qllc_control, tvb,
140                     1, 1, ctrl);
141         }
142     }
143     else {
144         /* Non-ambiguous control field value */
145         if (check_col(pinfo->cinfo, COL_INFO)) {
146             col_set_str(pinfo->cinfo, COL_INFO, 
147                     val_to_str(ctrl, qllc_control_vals,
148                         "Control Field: 0x%02x (unknown)"));
149         }
150         if (tree) {
151             proto_tree_add_uint(qllc_tree, hf_qllc_control, tvb,
152                     1, 1, ctrl);
153         }
154     }
155
156     /* Do we have an I field ? */
157     /* XXX - I field exists for QUI too, but only for subarea nodes. 
158      * Need to test for this. */
159     if (ctrl == QXID || ctrl == QTEST || ctrl == QFRMR) {
160         /* yes */
161     }
162
163 }
164
165
166 void
167 proto_register_qllc(void)
168 {
169         static hf_register_info hf[] = {
170                 { &hf_qllc_address,
171                 { "Address Field",      "qllc.address", FT_UINT8, BASE_HEX, NULL, 0x0,
172                         "", HFILL }},
173
174                 { &hf_qllc_control,
175                 { "Control Field",      "qllc.control", FT_UINT8, BASE_HEX, 
176             VALS(qllc_control_vals), 0x0, "", HFILL }},
177
178         };
179
180         static gint *ett[] = {
181                 &ett_qllc,
182         };
183
184         proto_qllc = proto_register_protocol("Qualified Logical Link Control",
185             "QLLC", "qllc");
186         proto_register_field_array(proto_qllc, hf, array_length(hf));
187         proto_register_subtree_array(ett, array_length(ett));
188         register_dissector("qllc", dissect_qllc, proto_qllc);
189 }
190