/src/wireshark/epan/dissectors/packet-lapb.c
Line | Count | Source |
1 | | /* packet-lapb.c |
2 | | * Routines for lapb frame disassembly |
3 | | * Olivier Abad <oabad@noos.fr> |
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 <wiretap/wtap.h> |
16 | | #include <epan/tfs.h> |
17 | | #include <wsutil/array.h> |
18 | | #include "packet-xdlc.h" |
19 | | |
20 | | void proto_register_lapb(void); |
21 | | void proto_reg_handoff_lapb(void); |
22 | | |
23 | | static int proto_lapb; |
24 | | static int hf_lapb_address; |
25 | | static int hf_lapb_control; |
26 | | static int hf_lapb_n_r; |
27 | | static int hf_lapb_n_s; |
28 | | static int hf_lapb_p; |
29 | | static int hf_lapb_f; |
30 | | static int hf_lapb_s_ftype; |
31 | | static int hf_lapb_u_modifier_cmd; |
32 | | static int hf_lapb_u_modifier_resp; |
33 | | static int hf_lapb_ftype_i; |
34 | | static int hf_lapb_ftype_s_u; |
35 | | |
36 | | static int ett_lapb; |
37 | | static int ett_lapb_control; |
38 | | |
39 | | static dissector_handle_t x25_dir_handle; |
40 | | static dissector_handle_t x25_handle; |
41 | | static dissector_handle_t lapb_handle; |
42 | | |
43 | | static const xdlc_cf_items lapb_cf_items = { |
44 | | &hf_lapb_n_r, |
45 | | &hf_lapb_n_s, |
46 | | &hf_lapb_p, |
47 | | &hf_lapb_f, |
48 | | &hf_lapb_s_ftype, |
49 | | &hf_lapb_u_modifier_cmd, |
50 | | &hf_lapb_u_modifier_resp, |
51 | | &hf_lapb_ftype_i, |
52 | | &hf_lapb_ftype_s_u |
53 | | }; |
54 | | |
55 | | static int |
56 | | dissect_lapb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
57 | 42 | { |
58 | 42 | proto_tree *lapb_tree, *ti; |
59 | 42 | uint16_t control; |
60 | 42 | int is_response; |
61 | 42 | uint8_t byte0; |
62 | 42 | tvbuff_t *next_tvb; |
63 | | |
64 | 42 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPB"); |
65 | 42 | col_clear(pinfo->cinfo, COL_INFO); |
66 | | |
67 | 42 | switch (pinfo->p2p_dir) { |
68 | | |
69 | 0 | case P2P_DIR_SENT: |
70 | 0 | col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE"); |
71 | 0 | col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE"); |
72 | 0 | break; |
73 | | |
74 | 0 | case P2P_DIR_RECV: |
75 | 0 | col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE"); |
76 | 0 | col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE"); |
77 | 0 | break; |
78 | | |
79 | 42 | default: |
80 | 42 | col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A"); |
81 | 42 | col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A"); |
82 | 42 | break; |
83 | 42 | } |
84 | | |
85 | 42 | byte0 = tvb_get_uint8(tvb, 0); |
86 | | |
87 | 42 | if (byte0 != 0x01 && byte0 != 0x03 && byte0 != 0x07 && byte0 != 0x0f) /* invalid LAPB frame */ |
88 | 14 | { |
89 | 14 | col_set_str(pinfo->cinfo, COL_INFO, "Invalid LAPB frame"); |
90 | 14 | if (tree) |
91 | 14 | proto_tree_add_protocol_format(tree, proto_lapb, tvb, 0, -1, |
92 | 14 | "Invalid LAPB frame"); |
93 | 14 | return 1; |
94 | 14 | } |
95 | | |
96 | 28 | switch (pinfo->p2p_dir) { |
97 | | |
98 | 0 | case P2P_DIR_SENT: |
99 | 0 | if (byte0 == 0x03) |
100 | 0 | is_response = true; |
101 | 0 | else |
102 | 0 | is_response = false; |
103 | 0 | break; |
104 | | |
105 | 0 | case P2P_DIR_RECV: |
106 | 0 | if (byte0 == 0x01) |
107 | 0 | is_response = true; |
108 | 0 | else |
109 | 0 | is_response = false; |
110 | 0 | break; |
111 | | |
112 | 25 | default: |
113 | | /* |
114 | | * XXX - should we base this on the source and destination |
115 | | * addresses? The problem is that we can tell one direction |
116 | | * from another with that, but we can't say which is DTE->DCE |
117 | | * and which is DCE->DTE. |
118 | | */ |
119 | 25 | is_response = false; |
120 | 25 | break; |
121 | 28 | } |
122 | | |
123 | 25 | ti = proto_tree_add_protocol_format(tree, proto_lapb, tvb, 0, 2, |
124 | 25 | "LAPB"); |
125 | 25 | lapb_tree = proto_item_add_subtree(ti, ett_lapb); |
126 | 25 | proto_tree_add_uint(lapb_tree, hf_lapb_address, tvb, 0, 1, byte0); |
127 | | |
128 | 25 | control = dissect_xdlc_control(tvb, 1, pinfo, lapb_tree, hf_lapb_control, |
129 | 25 | ett_lapb_control, &lapb_cf_items, NULL, NULL, NULL, |
130 | 25 | is_response, false, false); |
131 | | |
132 | | /* information frame ==> X.25 */ |
133 | 25 | if (XDLC_IS_INFORMATION(control)) { |
134 | 25 | next_tvb = tvb_new_subset_remaining(tvb, 2); |
135 | 25 | switch (pinfo->p2p_dir) { |
136 | | |
137 | 0 | case P2P_DIR_SENT: |
138 | 0 | case P2P_DIR_RECV: |
139 | 0 | call_dissector(x25_dir_handle, next_tvb, pinfo, tree); |
140 | 0 | break; |
141 | | |
142 | 25 | default: |
143 | 25 | call_dissector(x25_handle, next_tvb, pinfo, tree); |
144 | 25 | break; |
145 | 25 | } |
146 | 25 | } |
147 | 20 | return tvb_captured_length(tvb); |
148 | 25 | } |
149 | | |
150 | | void |
151 | | proto_register_lapb(void) |
152 | 16 | { |
153 | 16 | static hf_register_info hf[] = { |
154 | 16 | { &hf_lapb_address, |
155 | 16 | { "Address", "lapb.address", FT_UINT8, BASE_HEX, NULL, 0x0, |
156 | 16 | NULL, HFILL }}, |
157 | | |
158 | 16 | { &hf_lapb_control, |
159 | 16 | { "Control Field", "lapb.control", FT_UINT8, BASE_HEX, NULL, 0x0, |
160 | 16 | NULL, HFILL }}, |
161 | | |
162 | 16 | { &hf_lapb_n_r, |
163 | 16 | { "N(R)", "lapb.control.n_r", FT_UINT8, BASE_DEC, |
164 | 16 | NULL, XDLC_N_R_MASK, NULL, HFILL }}, |
165 | | |
166 | 16 | { &hf_lapb_n_s, |
167 | 16 | { "N(S)", "lapb.control.n_s", FT_UINT8, BASE_DEC, |
168 | 16 | NULL, XDLC_N_S_MASK, NULL, HFILL }}, |
169 | | |
170 | 16 | { &hf_lapb_p, |
171 | 16 | { "Poll", "lapb.control.p", FT_BOOLEAN, 8, |
172 | 16 | TFS(&tfs_set_notset), XDLC_P_F, NULL, HFILL }}, |
173 | | |
174 | 16 | { &hf_lapb_f, |
175 | 16 | { "Final", "lapb.control.f", FT_BOOLEAN, 8, |
176 | 16 | TFS(&tfs_set_notset), XDLC_P_F, NULL, HFILL }}, |
177 | | |
178 | 16 | { &hf_lapb_s_ftype, |
179 | 16 | { "Supervisory frame type", "lapb.control.s_ftype", FT_UINT8, BASE_HEX, |
180 | 16 | VALS(stype_vals), XDLC_S_FTYPE_MASK, NULL, HFILL }}, |
181 | | |
182 | 16 | { &hf_lapb_u_modifier_cmd, |
183 | 16 | { "Command", "lapb.control.u_modifier_cmd", FT_UINT8, BASE_HEX, |
184 | 16 | VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, NULL, HFILL }}, |
185 | | |
186 | 16 | { &hf_lapb_u_modifier_resp, |
187 | 16 | { "Response", "lapb.control.u_modifier_resp", FT_UINT8, BASE_HEX, |
188 | 16 | VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, NULL, HFILL }}, |
189 | | |
190 | 16 | { &hf_lapb_ftype_i, |
191 | 16 | { "Frame type", "lapb.control.ftype", FT_UINT8, BASE_HEX, |
192 | 16 | VALS(ftype_vals), XDLC_I_MASK, NULL, HFILL }}, |
193 | | |
194 | 16 | { &hf_lapb_ftype_s_u, |
195 | 16 | { "Frame type", "lapb.control.ftype", FT_UINT8, BASE_HEX, |
196 | 16 | VALS(ftype_vals), XDLC_S_U_MASK, NULL, HFILL }}, |
197 | 16 | }; |
198 | 16 | static int *ett[] = { |
199 | 16 | &ett_lapb, |
200 | 16 | &ett_lapb_control, |
201 | 16 | }; |
202 | | |
203 | 16 | proto_lapb = proto_register_protocol("Link Access Procedure Balanced (LAPB)", |
204 | 16 | "LAPB", "lapb"); |
205 | 16 | proto_register_field_array (proto_lapb, hf, array_length(hf)); |
206 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
207 | | |
208 | 16 | lapb_handle = register_dissector("lapb", dissect_lapb, proto_lapb); |
209 | 16 | } |
210 | | |
211 | | void |
212 | | proto_reg_handoff_lapb(void) |
213 | 16 | { |
214 | | /* |
215 | | * Get handles for the X.25 dissectors; we don't get an X.25 |
216 | | * pseudo-header for LAPB-over-Ethernet, but we do get it |
217 | | * for raw LAPB. |
218 | | */ |
219 | 16 | x25_dir_handle = find_dissector_add_dependency("x.25_dir", proto_lapb); |
220 | 16 | x25_handle = find_dissector_add_dependency("x.25", proto_lapb); |
221 | | |
222 | 16 | dissector_add_uint("wtap_encap", WTAP_ENCAP_LAPB, lapb_handle); |
223 | 16 | } |
224 | | |
225 | | /* |
226 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
227 | | * |
228 | | * Local variables: |
229 | | * c-basic-offset: 4 |
230 | | * tab-width: 8 |
231 | | * indent-tabs-mode: nil |
232 | | * End: |
233 | | * |
234 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
235 | | * :indentSize=4:tabSize=8:noTabs=true: |
236 | | */ |