2 * Routines for use by various SDLC-derived protocols, such as HDLC
3 * and its derivatives LAPB, IEEE 802.2 LLC, etc..
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include <epan/packet.h>
19 #include <epan/xdlc.h>
20 #include <wsutil/pint.h>
22 const value_string ftype_vals[] = {
23 { XDLC_I, "Information frame" },
24 { XDLC_S, "Supervisory frame" },
25 { XDLC_U, "Unnumbered frame" },
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" },
37 static const value_string modifier_short_vals_cmd[] = {
40 { XDLC_DISC, "DISC" },
42 { XDLC_SNRM, "SNRM" },
43 { XDLC_SNRME, "SNRME" },
44 { XDLC_TEST, "TEST" },
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" },
54 { XDLC_SNRME, "SNRME" },
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" },
80 static const value_string modifier_short_vals_resp[] = {
85 { XDLC_SNRM, "SNRM" },
86 { XDLC_TEST, "TEST" },
88 { XDLC_FRMR, "FRMR" },
89 { XDLC_CFGR, "CFGR" },
91 { XDLC_SABM, "SABM" },
92 { XDLC_SARME, "SARME" },
93 { XDLC_SABME, "SABME" },
94 { XDLC_RESET, "RESET" },
96 { XDLC_SNRME, "SNRME" },
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" },
123 get_xdlc_control(const guint8 *pd, int offset, gboolean is_extended)
127 switch (pd[offset] & 0x03) {
132 * Supervisory or Information frame.
135 control = pletoh16(&pd[offset]);
137 control = pd[offset];
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.
151 control = pd[offset];
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)
167 const xdlc_cf_items *cf_items;
168 const char *control_format;
171 proto_tree *tc, *control_tree;
172 const gchar *frame_type = NULL;
173 const gchar *modifier;
175 info=(char *)wmem_alloc(wmem_packet_scope(), 80);
176 switch (tvb_get_guint8(tvb, offset) & 0x03) {
183 control = tvb_get_letohs(tvb, offset);
185 cf_items = cf_items_ext;
186 control_format = "Control field: %s (0x%04X)";
188 control = tvb_get_guint8(tvb, offset);
190 cf_items = cf_items_nonext;
191 control_format = "Control field: %s (0x%02X)";
193 switch (control & XDLC_S_FTYPE_MASK) {
211 poll_final = (control & XDLC_P_F_EXT);
212 g_snprintf(info, 80, "S%s, func=%s, N(R)=%u",
214 (is_response ? " F" : " P") :
217 (control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT);
219 poll_final = (control & XDLC_P_F);
220 g_snprintf(info, 80, "S%s, func=%s, N(R)=%u",
222 (is_response ? " F" : " P") :
225 (control & XDLC_N_R_MASK) >> XDLC_N_R_SHIFT);
228 col_append_str(pinfo->cinfo, COL_INFO, ", ");
229 col_append_str(pinfo->cinfo, COL_INFO, info);
231 col_add_str(pinfo->cinfo, COL_INFO, info);
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);
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);
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);
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.
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);
270 cf_items = cf_items_nonext;
271 control_format = "Control field: %s (0x%02X)";
273 modifier = val_to_str(control & XDLC_U_MODIFIER_MASK,
274 u_modifier_short_vals_resp, "Unknown");
276 modifier = val_to_str(control & XDLC_U_MODIFIER_MASK,
277 u_modifier_short_vals_cmd, "Unknown");
279 poll_final = (control & XDLC_P_F);
280 g_snprintf(info, 80, "U%s, func=%s",
282 (is_response ? " F" : " P") :
286 col_append_str(pinfo->cinfo, COL_INFO, ", ");
287 col_append_str(pinfo->cinfo, COL_INFO, info);
289 col_add_str(pinfo->cinfo, COL_INFO, info);
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);
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);
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);
316 control = tvb_get_letohs(tvb, offset);
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);
326 control = tvb_get_guint8(tvb, offset);
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);
337 col_append_str(pinfo->cinfo, COL_INFO, ", ");
338 col_append_str(pinfo->cinfo, COL_INFO, info);
340 col_add_str(pinfo->cinfo, COL_INFO, info);
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);
351 proto_tree_add_boolean(control_tree, *cf_items->hf_xdlc_p,
352 tvb, offset, control_len, control);
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);
364 * Editor modelines - http://www.wireshark.org/tools/modelines.html
369 * indent-tabs-mode: nil
372 * vi: set shiftwidth=4 tabstop=8 expandtab:
373 * :indentSize=4:tabSize=8:noTabs=true: