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 uint8_t *pd
, int offset
, bool 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
, int 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
, bool is_response
,
163 bool is_extended
, bool append_info
)
167 const xdlc_cf_items
*cf_items
;
168 const char *control_format
;
171 proto_tree
*tc
, *control_tree
;
172 const char *frame_type
= NULL
;
173 const char *modifier
;
175 info
=(char *)wmem_alloc(pinfo
->pool
, 80);
176 switch (tvb_get_uint8(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_uint8(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 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 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_uint8(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 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 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_uint8(tvb
, offset
);
328 cf_items
= cf_items_nonext
;
329 control_format
= "Control field: %s (0x%02X)";
330 poll_final
= (control
& XDLC_P_F
);
331 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 - https://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: