PA-PK-AS-REP-Win2k ::= PaPkAsRep
[metze/wireshark/wip.git] / epan / xdlc.c
1 /* xdlc.c
2  * Routines for use by various SDLC-derived protocols, such as HDLC
3  * and its derivatives LAPB, IEEE 802.2 LLC, etc..
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include "config.h"
13
14 #include <stdio.h>
15 #include <string.h>
16
17 #include <glib.h>
18 #include <epan/packet.h>
19 #include <epan/xdlc.h>
20 #include <wsutil/pint.h>
21
22 const value_string ftype_vals[] = {
23     { XDLC_I, "Information frame" },
24     { XDLC_S, "Supervisory frame" },
25     { XDLC_U, "Unnumbered frame" },
26     { 0,      NULL }
27 };
28
29 const value_string stype_vals[] = {
30     { XDLC_RR>>2,   "Receiver ready" },
31     { XDLC_RNR>>2,  "Receiver not ready" },
32     { XDLC_REJ>>2,  "Reject" },
33     { XDLC_SREJ>>2, "Selective reject" },
34     { 0,            NULL }
35 };
36
37 static const value_string modifier_short_vals_cmd[] = {
38     { XDLC_UI,    "UI" },
39     { XDLC_UP,    "UP" },
40     { XDLC_DISC,  "DISC" },
41     { XDLC_UA,    "UA" },
42     { XDLC_SNRM,  "SNRM" },
43     { XDLC_SNRME, "SNRME" },
44     { XDLC_TEST,  "TEST" },
45     { XDLC_SIM,   "SIM" },
46     { XDLC_FRMR,  "FRMR" },
47     { XDLC_CFGR,  "CFGR" },
48     { XDLC_SARM,  "SARM" },
49     { XDLC_SABM,  "SABM" },
50     { XDLC_SARME, "SARME" },
51     { XDLC_SABME, "SABME" },
52     { XDLC_RESET, "RESET" },
53     { XDLC_XID,   "XID" },
54     { XDLC_SNRME, "SNRME" },
55     { XDLC_BCN,   "BCN" },
56     { 0,          NULL }
57 };
58
59 const value_string modifier_vals_cmd[] = {
60     { XDLC_UI>>2,    "Unnumbered Information" },
61     { XDLC_UP>>2,    "Unnumbered Poll" },
62     { XDLC_DISC>>2,  "Disconnect" },
63     { XDLC_UA>>2,    "Unnumbered Acknowledge" },
64     { XDLC_SNRM>>2,  "Set Normal Response Mode" },
65     { XDLC_TEST>>2,  "Test" },
66     { XDLC_SIM>>2,   "Set Initialization Mode" },
67     { XDLC_FRMR>>2,  "Frame reject" },
68     { XDLC_CFGR>>2,  "Configure" },
69     { XDLC_SARM>>2,  "Set Asynchronous Response Mode" },
70     { XDLC_SABM>>2,  "Set Asynchronous Balanced Mode" },
71     { XDLC_SARME>>2, "Set Asynchronous Response Mode Extended" },
72     { XDLC_SABME>>2, "Set Asynchronous Balanced Mode Extended" },
73     { XDLC_RESET>>2, "Reset" },
74     { XDLC_XID>>2,   "Exchange identification" },
75     { XDLC_SNRME>>2, "Set Normal Response Mode Extended" },
76     { XDLC_BCN>>2,   "Beacon" },
77     { 0,             NULL }
78 };
79
80 static const value_string modifier_short_vals_resp[] = {
81     { XDLC_UI,    "UI" },
82     { XDLC_UP,    "UP" },
83     { XDLC_RD,    "RD" },
84     { XDLC_UA,    "UA" },
85     { XDLC_SNRM,  "SNRM" },
86     { XDLC_TEST,  "TEST" },
87     { XDLC_RIM,   "RIM" },
88     { XDLC_FRMR,  "FRMR" },
89     { XDLC_CFGR,  "CFGR" },
90     { XDLC_DM,    "DM" },
91     { XDLC_SABM,  "SABM" },
92     { XDLC_SARME, "SARME" },
93     { XDLC_SABME, "SABME" },
94     { XDLC_RESET, "RESET" },
95     { XDLC_XID,   "XID" },
96     { XDLC_SNRME, "SNRME" },
97     { XDLC_BCN,   "BCN" },
98     { 0,          NULL }
99 };
100
101 const value_string modifier_vals_resp[] = {
102     { XDLC_UI>>2,    "Unnumbered Information" },
103     { XDLC_UP>>2,    "Unnumbered Poll" },
104     { XDLC_RD>>2,    "Request Disconnect" },
105     { XDLC_UA>>2,    "Unnumbered Acknowledge" },
106     { XDLC_SNRM>>2,  "Set Normal Response Mode" },
107     { XDLC_TEST>>2,  "Test" },
108     { XDLC_RIM>>2,   "Request Initialization Mode" },
109     { XDLC_FRMR>>2,  "Frame reject" },
110     { XDLC_CFGR>>2,  "Configure" },
111     { XDLC_DM>>2,    "Disconnected mode" },
112     { XDLC_SABM>>2,  "Set Asynchronous Balanced Mode" },
113     { XDLC_SARME>>2, "Set Asynchronous Response Mode Extended" },
114     { XDLC_SABME>>2, "Set Asynchronous Balanced Mode Extended" },
115     { XDLC_RESET>>2, "Reset" },
116     { XDLC_XID>>2,   "Exchange identification" },
117     { XDLC_SNRME>>2, "Set Normal Response Mode Extended" },
118     { XDLC_BCN>>2,   "Beacon" },
119     { 0,             NULL }
120 };
121
122 int
123 get_xdlc_control(const guint8 *pd, int offset, gboolean is_extended)
124 {
125     guint16 control;
126
127     switch (pd[offset] & 0x03) {
128
129     case XDLC_S:
130     default:
131         /*
132          * Supervisory or Information frame.
133          */
134         if (is_extended)
135                 control = pletoh16(&pd[offset]);
136         else
137                 control = pd[offset];
138         break;
139
140     case XDLC_U:
141         /*
142          * Unnumbered frame.
143          *
144          * XXX - is this two octets, with a P/F bit, in HDLC extended
145          * operation?  It's one octet in LLC, even though the control
146          * field of I and S frames is a 2-byte extended-operation field
147          * in LLC.  Given that there are no sequence numbers in the
148          * control field of a U frame, there doesn't appear to be any
149          * need for it to be 2 bytes in extended operation.
150          */
151         control = pd[offset];
152         break;
153     }
154     return control;
155 }
156
157 int
158 dissect_xdlc_control(tvbuff_t *tvb, int offset, packet_info *pinfo,
159   proto_tree *xdlc_tree, int hf_xdlc_control, gint ett_xdlc_control,
160   const xdlc_cf_items *cf_items_nonext, const xdlc_cf_items *cf_items_ext,
161   const value_string *u_modifier_short_vals_cmd,
162   const value_string *u_modifier_short_vals_resp, gboolean is_response,
163   gboolean is_extended, gboolean append_info)
164 {
165     guint16 control;
166     int control_len;
167     const xdlc_cf_items *cf_items;
168     const char *control_format;
169     guint16 poll_final;
170     char *info;
171     proto_tree *tc, *control_tree;
172     const gchar *frame_type = NULL;
173     const gchar *modifier;
174
175     info=(char *)wmem_alloc(wmem_packet_scope(), 80);
176     switch (tvb_get_guint8(tvb, offset) & 0x03) {
177
178     case XDLC_S:
179         /*
180          * Supervisory frame.
181          */
182         if (is_extended) {
183             control = tvb_get_letohs(tvb, offset);
184             control_len = 2;
185             cf_items = cf_items_ext;
186             control_format = "Control field: %s (0x%04X)";
187         } else {
188             control = tvb_get_guint8(tvb, offset);
189             control_len = 1;
190             cf_items = cf_items_nonext;
191             control_format = "Control field: %s (0x%02X)";
192         }
193         switch (control & XDLC_S_FTYPE_MASK) {
194         case XDLC_RR:
195             frame_type = "RR";
196             break;
197
198         case XDLC_RNR:
199             frame_type = "RNR";
200             break;
201
202         case XDLC_REJ:
203             frame_type = "REJ";
204             break;
205
206         case XDLC_SREJ:
207             frame_type = "SREJ";
208             break;
209         }
210         if (is_extended) {
211             poll_final = (control & XDLC_P_F_EXT);
212             g_snprintf(info, 80, "S%s, func=%s, N(R)=%u",
213                         (poll_final ?
214                             (is_response ? " F" : " P") :
215                             ""),
216                         frame_type,
217                         (control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT);
218         } else {
219             poll_final = (control & XDLC_P_F);
220             g_snprintf(info, 80, "S%s, func=%s, N(R)=%u",
221                         (poll_final ?
222                             (is_response ? " F" : " P") :
223                             ""),
224                         frame_type,
225                         (control & XDLC_N_R_MASK) >> XDLC_N_R_SHIFT);
226         }
227         if (append_info) {
228             col_append_str(pinfo->cinfo, COL_INFO, ", ");
229             col_append_str(pinfo->cinfo, COL_INFO, info);
230         } else {
231             col_add_str(pinfo->cinfo, COL_INFO, info);
232         }
233         if (xdlc_tree) {
234             tc = proto_tree_add_uint_format(xdlc_tree, hf_xdlc_control, tvb,
235                 offset, control_len, control, control_format, info, control);
236             control_tree = proto_item_add_subtree(tc, ett_xdlc_control);
237             proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_n_r,
238                 tvb, offset, control_len, control);
239             if (poll_final) {
240                 proto_tree_add_boolean(control_tree,
241                         (is_response ? *cf_items->hf_xdlc_f :
242                                        *cf_items->hf_xdlc_p),
243                         tvb, offset, control_len, control);
244             }
245             proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_s_ftype,
246                 tvb, offset, control_len, control);
247             /* This will always say it's a supervisory frame */
248             proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_ftype_s_u,
249                 tvb, offset, control_len, control);
250         }
251         break;
252
253     case XDLC_U:
254         /*
255          * Unnumbered frame.
256          *
257          * XXX - is this two octets, with a P/F bit, in HDLC extended
258          * operation?  It's one octet in LLC, even though the control
259          * field of I and S frames is a 2-byte extended-operation field
260          * in LLC.  Given that there are no sequence numbers in the
261          * control field of a U frame, there doesn't appear to be any
262          * need for it to be 2 bytes in extended operation.
263          */
264         if (u_modifier_short_vals_cmd == NULL)
265                 u_modifier_short_vals_cmd = modifier_short_vals_cmd;
266         if (u_modifier_short_vals_resp == NULL)
267                 u_modifier_short_vals_resp = modifier_short_vals_resp;
268         control = tvb_get_guint8(tvb, offset);
269         control_len = 1;
270         cf_items = cf_items_nonext;
271         control_format = "Control field: %s (0x%02X)";
272         if (is_response) {
273                 modifier = val_to_str(control & XDLC_U_MODIFIER_MASK,
274                         u_modifier_short_vals_resp, "Unknown");
275         } else {
276                 modifier = val_to_str(control & XDLC_U_MODIFIER_MASK,
277                         u_modifier_short_vals_cmd, "Unknown");
278         }
279         poll_final = (control & XDLC_P_F);
280         g_snprintf(info, 80, "U%s, func=%s",
281                 (poll_final ?
282                     (is_response ? " F" : " P") :
283                     ""),
284                 modifier);
285         if (append_info) {
286             col_append_str(pinfo->cinfo, COL_INFO, ", ");
287         col_append_str(pinfo->cinfo, COL_INFO, info);
288         } else {
289             col_add_str(pinfo->cinfo, COL_INFO, info);
290         }
291         if (xdlc_tree) {
292             tc = proto_tree_add_uint_format(xdlc_tree, hf_xdlc_control, tvb,
293                 offset, control_len, control, control_format, info, control);
294             control_tree = proto_item_add_subtree(tc, ett_xdlc_control);
295             if (poll_final) {
296                 proto_tree_add_boolean(control_tree,
297                         (is_response ? *cf_items->hf_xdlc_f:
298                                        *cf_items->hf_xdlc_p),
299                         tvb, offset, control_len, control);
300             }
301             proto_tree_add_uint(control_tree,
302                 (is_response ? *cf_items->hf_xdlc_u_modifier_resp :
303                                *cf_items->hf_xdlc_u_modifier_cmd),
304                 tvb, offset, control_len, control);
305             /* This will always say it's an unnumbered frame */
306             proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_ftype_s_u,
307                 tvb, offset, control_len, control);
308         }
309         break;
310
311     default:
312         /*
313          * Information frame.
314          */
315         if (is_extended) {
316             control = tvb_get_letohs(tvb, offset);
317             control_len = 2;
318             cf_items = cf_items_ext;
319             control_format = "Control field: %s (0x%04X)";
320             poll_final = (control & XDLC_P_F_EXT);
321             g_snprintf(info, 80, "I%s, N(R)=%u, N(S)=%u",
322                         ((control & XDLC_P_F_EXT) ? " P" : ""),
323                         (control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT,
324                         (control & XDLC_N_S_EXT_MASK) >> XDLC_N_S_EXT_SHIFT);
325         } else {
326             control = tvb_get_guint8(tvb, offset);
327             control_len = 1;
328             cf_items = cf_items_nonext;
329             control_format = "Control field: %s (0x%02X)";
330             poll_final = (control & XDLC_P_F);
331             g_snprintf(info, 80, "I%s, N(R)=%u, N(S)=%u",
332                         ((control & XDLC_P_F) ? " P" : ""),
333                         (control & XDLC_N_R_MASK) >> XDLC_N_R_SHIFT,
334                         (control & XDLC_N_S_MASK) >> XDLC_N_S_SHIFT);
335         }
336         if (append_info) {
337             col_append_str(pinfo->cinfo, COL_INFO, ", ");
338         col_append_str(pinfo->cinfo, COL_INFO, info);
339         } else {
340             col_add_str(pinfo->cinfo, COL_INFO, info);
341         }
342         if (xdlc_tree) {
343             tc = proto_tree_add_uint_format(xdlc_tree, hf_xdlc_control, tvb,
344                 offset, control_len, control, control_format, info, control);
345             control_tree = proto_item_add_subtree(tc, ett_xdlc_control);
346             proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_n_r,
347                 tvb, offset, control_len, control);
348             proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_n_s,
349                 tvb, offset, control_len, control);
350             if (poll_final) {
351                 proto_tree_add_boolean(control_tree, *cf_items->hf_xdlc_p,
352                         tvb, offset, control_len, control);
353             }
354             /* This will always say it's an information frame */
355             proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_ftype_i,
356                 tvb, offset, control_len, control);
357         }
358         break;
359     }
360     return control;
361 }
362
363 /*
364  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
365  *
366  * Local variables:
367  * c-basic-offset: 4
368  * tab-width: 8
369  * indent-tabs-mode: nil
370  * End:
371  *
372  * vi: set shiftwidth=4 tabstop=8 expandtab:
373  * :indentSize=4:tabSize=8:noTabs=true:
374  */