/src/wireshark/epan/dissectors/packet-v120.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-v120.c |
2 | | * Routines for v120 frame disassembly |
3 | | * Bert Driehuis <driehuis@playbeing.org> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
14 | | #include <epan/packet.h> |
15 | | #include <epan/xdlc.h> |
16 | | #include <epan/tfs.h> |
17 | | #include <wsutil/array.h> |
18 | | |
19 | | void proto_register_v120(void); |
20 | | |
21 | | static int proto_v120; |
22 | | static int hf_v120_address; |
23 | | static int hf_v120_rc; |
24 | | static int hf_v120_lli; |
25 | | static int hf_v120_ea0; |
26 | | static int hf_v120_ea1; |
27 | | static int hf_v120_control; |
28 | | static int hf_v120_n_r; |
29 | | static int hf_v120_n_s; |
30 | | static int hf_v120_p; |
31 | | static int hf_v120_p_ext; |
32 | | static int hf_v120_f; |
33 | | static int hf_v120_f_ext; |
34 | | static int hf_v120_s_ftype; |
35 | | static int hf_v120_u_modifier_cmd; |
36 | | static int hf_v120_u_modifier_resp; |
37 | | static int hf_v120_ftype_i; |
38 | | static int hf_v120_ftype_s_u; |
39 | | static int hf_v120_ftype_s_u_ext; |
40 | | static int hf_v120_header8; |
41 | | static int hf_v120_header_ext8; |
42 | | static int hf_v120_header_break8; |
43 | | static int hf_v120_header_error_control8; |
44 | | static int hf_v120_header_segb8; |
45 | | static int hf_v120_header_segf8; |
46 | | static int hf_v120_header16; |
47 | | static int hf_v120_header_ext16; |
48 | | static int hf_v120_header_break16; |
49 | | static int hf_v120_header_error_control16; |
50 | | static int hf_v120_header_segb16; |
51 | | static int hf_v120_header_segf16; |
52 | | static int hf_v120_header_e; |
53 | | static int hf_v120_header_dr; |
54 | | static int hf_v120_header_sr; |
55 | | static int hf_v120_header_rr; |
56 | | |
57 | | static int ett_v120; |
58 | | static int ett_v120_address; |
59 | | static int ett_v120_control; |
60 | | static int ett_v120_header; |
61 | | |
62 | | static int dissect_v120_header(tvbuff_t *tvb, int offset, proto_tree *tree); |
63 | | |
64 | | /* Used only for U frames */ |
65 | | static const xdlc_cf_items v120_cf_items = { |
66 | | NULL, |
67 | | NULL, |
68 | | &hf_v120_p, |
69 | | &hf_v120_f, |
70 | | NULL, |
71 | | &hf_v120_u_modifier_cmd, |
72 | | &hf_v120_u_modifier_resp, |
73 | | NULL, |
74 | | &hf_v120_ftype_s_u |
75 | | }; |
76 | | |
77 | | /* Used only for I and S frames */ |
78 | | static const xdlc_cf_items v120_cf_items_ext = { |
79 | | &hf_v120_n_r, |
80 | | &hf_v120_n_s, |
81 | | &hf_v120_p_ext, |
82 | | &hf_v120_f_ext, |
83 | | &hf_v120_s_ftype, |
84 | | NULL, |
85 | | NULL, |
86 | | &hf_v120_ftype_i, |
87 | | &hf_v120_ftype_s_u_ext |
88 | | }; |
89 | | |
90 | | static int |
91 | | dissect_v120(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
92 | 4 | { |
93 | 4 | proto_tree *v120_tree, *address_tree; |
94 | 4 | proto_item *ti, *tc; |
95 | 4 | int is_response; |
96 | 4 | int v120len; |
97 | 4 | uint8_t byte0, byte1; |
98 | 4 | uint16_t control; |
99 | 4 | tvbuff_t *next_tvb; |
100 | | |
101 | 4 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "V.120"); |
102 | 4 | col_clear(pinfo->cinfo, COL_INFO); |
103 | | |
104 | 4 | byte0 = tvb_get_uint8(tvb, 0); |
105 | | |
106 | 4 | col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "0x%02X", byte0); |
107 | | |
108 | 4 | byte1 = tvb_get_uint8(tvb, 1); |
109 | | |
110 | 4 | if ( ((byte0 & 0x01) != 0x00) && ((byte1 & 0x01) != 0x01) ) |
111 | 0 | { |
112 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Invalid V.120 frame"); |
113 | 0 | if (tree) |
114 | 0 | proto_tree_add_protocol_format(tree, proto_v120, tvb, 0, -1, |
115 | 0 | "Invalid V.120 frame"); |
116 | 0 | return 2; |
117 | 0 | } |
118 | | |
119 | 4 | if (pinfo->p2p_dir == P2P_DIR_SENT) { |
120 | 1 | is_response = (byte0 & 0x02) ? false: true; |
121 | 1 | col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE"); |
122 | 1 | col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE"); |
123 | 3 | } else { |
124 | | /* XXX - what if the direction is unknown? */ |
125 | 3 | is_response = (byte0 & 0x02) ? true : false; |
126 | 3 | col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE"); |
127 | 3 | col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE"); |
128 | 3 | } |
129 | | |
130 | 4 | ti = proto_tree_add_protocol_format(tree, proto_v120, tvb, 0, -1, "V.120"); |
131 | 4 | v120_tree = proto_item_add_subtree(ti, ett_v120); |
132 | 4 | tc = proto_tree_add_item(v120_tree, hf_v120_address, tvb, 0, 2, ENC_BIG_ENDIAN); |
133 | 4 | proto_item_append_text(tc, "LLI: %d C/R: %s", |
134 | 4 | ((byte0 & 0xfc) << 5) | ((byte1 & 0xfe) >> 1), |
135 | 4 | byte0 & 0x02 ? "R" : "C"); |
136 | 4 | address_tree = proto_item_add_subtree(tc, ett_v120_address); |
137 | | |
138 | 4 | proto_tree_add_item(address_tree, hf_v120_rc, tvb, 0, 2, ENC_BIG_ENDIAN); |
139 | 4 | proto_tree_add_item(address_tree, hf_v120_lli, tvb, 0, 2, ENC_BIG_ENDIAN); |
140 | 4 | proto_tree_add_item(address_tree, hf_v120_ea0, tvb, 0, 2, ENC_BIG_ENDIAN); |
141 | 4 | proto_tree_add_item(address_tree, hf_v120_ea1, tvb, 0, 2, ENC_BIG_ENDIAN); |
142 | | |
143 | 4 | control = dissect_xdlc_control(tvb, 2, pinfo, v120_tree, hf_v120_control, |
144 | 4 | ett_v120_control, &v120_cf_items, &v120_cf_items_ext, |
145 | 4 | NULL, NULL, is_response, true, false); |
146 | | |
147 | 4 | v120len = 2 + XDLC_CONTROL_LEN(control, true); |
148 | | |
149 | 4 | if (tvb_bytes_exist(tvb, v120len, 1)) |
150 | 3 | v120len += dissect_v120_header(tvb, v120len, v120_tree); |
151 | 4 | proto_item_set_len(ti, v120len); |
152 | 4 | next_tvb = tvb_new_subset_remaining(tvb, v120len); |
153 | 4 | call_data_dissector(next_tvb, pinfo, v120_tree); |
154 | | |
155 | 4 | return tvb_captured_length(tvb); |
156 | 4 | } |
157 | | |
158 | | static int |
159 | | dissect_v120_header(tvbuff_t *tvb, int offset, proto_tree *tree) |
160 | 3 | { |
161 | 3 | int header_len; |
162 | 3 | uint8_t byte0; |
163 | 3 | proto_tree *h_tree; |
164 | 3 | proto_item *tc; |
165 | | |
166 | 3 | byte0 = tvb_get_uint8(tvb, offset); |
167 | 3 | if (byte0 & 0x80) { |
168 | 1 | header_len = 1; |
169 | 1 | tc = proto_tree_add_item(tree, hf_v120_header8, tvb, 0, 1, ENC_BIG_ENDIAN); |
170 | | |
171 | 1 | h_tree = proto_item_add_subtree(tc, ett_v120_header); |
172 | 1 | proto_tree_add_item(h_tree, hf_v120_header_ext8, tvb, 0, 1, ENC_NA); |
173 | 1 | proto_tree_add_item(h_tree, hf_v120_header_break8, tvb, 0, 1, ENC_NA); |
174 | 1 | proto_tree_add_item(h_tree, hf_v120_header_error_control8, tvb, 0, 1, ENC_BIG_ENDIAN); |
175 | 1 | proto_tree_add_item(h_tree, hf_v120_header_segb8, tvb, 0, 1, ENC_NA); |
176 | 1 | proto_tree_add_item(h_tree, hf_v120_header_segf8, tvb, 0, 1, ENC_NA); |
177 | 2 | } else { |
178 | 2 | header_len = 2; |
179 | 2 | tc = proto_tree_add_item(tree, hf_v120_header16, tvb, 0, 2, ENC_BIG_ENDIAN); |
180 | 2 | h_tree = proto_item_add_subtree(tc, ett_v120_header); |
181 | 2 | proto_tree_add_item(h_tree, hf_v120_header_ext16, tvb, 0, 2, ENC_BIG_ENDIAN); |
182 | 2 | proto_tree_add_item(h_tree, hf_v120_header_break16, tvb, 0, 2, ENC_BIG_ENDIAN); |
183 | 2 | proto_tree_add_item(h_tree, hf_v120_header_error_control16, tvb, 0, 2, ENC_BIG_ENDIAN); |
184 | 2 | proto_tree_add_item(h_tree, hf_v120_header_segb16, tvb, 0, 2, ENC_BIG_ENDIAN); |
185 | 2 | proto_tree_add_item(h_tree, hf_v120_header_segf16, tvb, 0, 2, ENC_BIG_ENDIAN); |
186 | 2 | proto_tree_add_item(h_tree, hf_v120_header_e, tvb, 0, 2, ENC_BIG_ENDIAN); |
187 | 2 | proto_tree_add_item(h_tree, hf_v120_header_dr, tvb, 0, 2, ENC_BIG_ENDIAN); |
188 | 2 | proto_tree_add_item(h_tree, hf_v120_header_sr, tvb, 0, 2, ENC_BIG_ENDIAN); |
189 | 2 | proto_tree_add_item(h_tree, hf_v120_header_rr, tvb, 0, 2, ENC_BIG_ENDIAN); |
190 | 2 | } |
191 | | |
192 | 3 | proto_item_append_text(tc, " B: %d F: %d", |
193 | 3 | byte0 & 0x02 ? 1:0, byte0 & 0x01 ? 1:0); |
194 | | |
195 | 3 | return header_len; |
196 | 3 | } |
197 | | |
198 | | void |
199 | | proto_register_v120(void) |
200 | 14 | { |
201 | 14 | static hf_register_info hf[] = { |
202 | 14 | { &hf_v120_address, |
203 | 14 | { "Link Address", "v120.address", FT_UINT16, BASE_HEX, NULL, |
204 | 14 | 0x0, NULL, HFILL }}, |
205 | 14 | { &hf_v120_rc, |
206 | 14 | { "R/C", "v120.rc", FT_BOOLEAN, 16, TFS(&tfs_response_command), |
207 | 14 | 0x0002, NULL, HFILL }}, |
208 | 14 | { &hf_v120_lli, |
209 | 14 | { "LLI", "v120.lli", FT_UINT16, BASE_HEX, NULL, |
210 | 14 | 0xfefc, NULL, HFILL }}, |
211 | 14 | { &hf_v120_ea0, |
212 | 14 | { "EA0", "v120.ea0", FT_BOOLEAN, 16, TFS(&tfs_error_ok), |
213 | 14 | 0x0001, NULL, HFILL }}, |
214 | 14 | { &hf_v120_ea1, |
215 | 14 | { "EA1", "v120.ea1", FT_BOOLEAN, 16, TFS(&tfs_ok_error), |
216 | 14 | 0x0100, NULL, HFILL }}, |
217 | 14 | { &hf_v120_control, |
218 | 14 | { "Control Field", "v120.control", FT_UINT16, BASE_HEX, NULL, 0x0, |
219 | 14 | NULL, HFILL }}, |
220 | 14 | { &hf_v120_n_r, |
221 | 14 | { "N(R)", "v120.control.n_r", FT_UINT16, BASE_DEC, |
222 | 14 | NULL, XDLC_N_R_EXT_MASK, NULL, HFILL }}, |
223 | 14 | { &hf_v120_n_s, |
224 | 14 | { "N(S)", "v120.control.n_s", FT_UINT16, BASE_DEC, |
225 | 14 | NULL, XDLC_N_S_EXT_MASK, NULL, HFILL }}, |
226 | 14 | { &hf_v120_p, |
227 | 14 | { "Poll", "v120.control.p", FT_BOOLEAN, 8, |
228 | 14 | TFS(&tfs_set_notset), XDLC_P_F, NULL, HFILL }}, |
229 | 14 | { &hf_v120_p_ext, |
230 | 14 | { "Poll", "v120.control.p", FT_BOOLEAN, 16, |
231 | 14 | TFS(&tfs_set_notset), XDLC_P_F_EXT, NULL, HFILL }}, |
232 | 14 | { &hf_v120_f, |
233 | 14 | { "Final", "v120.control.f", FT_BOOLEAN, 8, |
234 | 14 | TFS(&tfs_set_notset), XDLC_P_F, NULL, HFILL }}, |
235 | 14 | { &hf_v120_f_ext, |
236 | 14 | { "Final", "v120.control.f", FT_BOOLEAN, 16, |
237 | 14 | TFS(&tfs_set_notset), XDLC_P_F_EXT, NULL, HFILL }}, |
238 | 14 | { &hf_v120_s_ftype, |
239 | 14 | { "Supervisory frame type", "v120.control.s_ftype", FT_UINT16, BASE_HEX, |
240 | 14 | VALS(stype_vals), XDLC_S_FTYPE_MASK, NULL, HFILL }}, |
241 | 14 | { &hf_v120_u_modifier_cmd, |
242 | 14 | { "Command", "v120.control.u_modifier_cmd", FT_UINT8, BASE_HEX, |
243 | 14 | VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, NULL, HFILL }}, |
244 | 14 | { &hf_v120_u_modifier_resp, |
245 | 14 | { "Response", "v120.control.u_modifier_resp", FT_UINT8, BASE_HEX, |
246 | 14 | VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, NULL, HFILL }}, |
247 | 14 | { &hf_v120_ftype_i, |
248 | 14 | { "Frame type", "v120.control.ftype", FT_UINT16, BASE_HEX, |
249 | 14 | VALS(ftype_vals), XDLC_I_MASK, NULL, HFILL }}, |
250 | 14 | { &hf_v120_ftype_s_u, |
251 | 14 | { "Frame type", "v120.control.ftype", FT_UINT8, BASE_HEX, |
252 | 14 | VALS(ftype_vals), XDLC_S_U_MASK, NULL, HFILL }}, |
253 | 14 | { &hf_v120_ftype_s_u_ext, |
254 | 14 | { "Frame type", "v120.control.ftype", FT_UINT16, BASE_HEX, |
255 | 14 | VALS(ftype_vals), XDLC_S_U_MASK, NULL, HFILL }}, |
256 | 14 | { &hf_v120_header8, |
257 | 14 | { "Header", "v120.header", FT_UINT8, BASE_HEX, NULL, 0x0, |
258 | 14 | NULL, HFILL }}, |
259 | 14 | { &hf_v120_header_ext8, |
260 | 14 | { "Extension octet", "v120.header.ext", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80, |
261 | 14 | NULL, HFILL }}, |
262 | 14 | { &hf_v120_header_break8, |
263 | 14 | { "Break condition", "v120.header.break", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40, |
264 | 14 | NULL, HFILL }}, |
265 | 14 | { &hf_v120_header_error_control8, |
266 | 14 | { "Error control C1/C2", "v120.error_control", FT_UINT8, BASE_HEX, NULL, 0x0C, |
267 | 14 | NULL, HFILL }}, |
268 | 14 | { &hf_v120_header_segb8, |
269 | 14 | { "Bit B", "v120.header.segb", FT_BOOLEAN, 8, TFS(&tfs_segmentation_no_segmentation), 0x02, |
270 | 14 | NULL, HFILL }}, |
271 | 14 | { &hf_v120_header_segf8, |
272 | 14 | { "Bit F", "v120.header.segf", FT_BOOLEAN, 8, TFS(&tfs_segmentation_no_segmentation), 0x01, |
273 | 14 | NULL, HFILL }}, |
274 | 14 | { &hf_v120_header16, |
275 | 14 | { "Header", "v120.header", FT_UINT16, BASE_HEX, NULL, 0x0, |
276 | 14 | NULL, HFILL }}, |
277 | 14 | { &hf_v120_header_ext16, |
278 | 14 | { "Extension octet", "v120.header.ext", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0080, |
279 | 14 | NULL, HFILL }}, |
280 | 14 | { &hf_v120_header_break16, |
281 | 14 | { "Break condition", "v120.header.break", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0040, |
282 | 14 | NULL, HFILL }}, |
283 | 14 | { &hf_v120_header_error_control16, |
284 | 14 | { "Error control C1/C2", "v120.error_control", FT_UINT16, BASE_HEX, NULL, 0x0C, |
285 | 14 | NULL, HFILL }}, |
286 | 14 | { &hf_v120_header_segb16, |
287 | 14 | { "Bit B", "v120.header.segb", FT_BOOLEAN, 16, TFS(&tfs_segmentation_no_segmentation), 0x0002, |
288 | 14 | NULL, HFILL }}, |
289 | 14 | { &hf_v120_header_segf16, |
290 | 14 | { "Bit F", "v120.header.segf", FT_BOOLEAN, 16, TFS(&tfs_segmentation_no_segmentation), 0x0001, |
291 | 14 | NULL, HFILL }}, |
292 | 14 | { &hf_v120_header_e, |
293 | 14 | { "E", "v120.header.e", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x8000, |
294 | 14 | NULL, HFILL }}, |
295 | 14 | { &hf_v120_header_dr, |
296 | 14 | { "DR", "v120.header.dr", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x4000, |
297 | 14 | NULL, HFILL }}, |
298 | 14 | { &hf_v120_header_sr, |
299 | 14 | { "SR", "v120.header.sr", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x2000, |
300 | 14 | NULL, HFILL }}, |
301 | 14 | { &hf_v120_header_rr, |
302 | 14 | { "RR", "v120.header.rr", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x1000, |
303 | 14 | NULL, HFILL }}, |
304 | 14 | }; |
305 | 14 | static int *ett[] = { |
306 | 14 | &ett_v120, |
307 | 14 | &ett_v120_address, |
308 | 14 | &ett_v120_control, |
309 | 14 | &ett_v120_header, |
310 | 14 | }; |
311 | | |
312 | 14 | proto_v120 = proto_register_protocol("Async data over ISDN (V.120)", |
313 | 14 | "V.120", "v120"); |
314 | 14 | proto_register_field_array (proto_v120, hf, array_length(hf)); |
315 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
316 | | |
317 | 14 | register_dissector("v120", dissect_v120, proto_v120); |
318 | 14 | } |
319 | | |
320 | | /* |
321 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
322 | | * |
323 | | * Local variables: |
324 | | * c-basic-offset: 8 |
325 | | * tab-width: 8 |
326 | | * indent-tabs-mode: t |
327 | | * End: |
328 | | * |
329 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
330 | | * :indentSize=8:tabSize=8:noTabs=false: |
331 | | */ |