2 * Routines for lapb frame disassembly
3 * Olivier Abad <oabad@noos.fr>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <wiretap/wtap.h>
16 #include <epan/xdlc.h>
18 #include <wsutil/array.h>
20 void proto_register_lapb(void);
21 void proto_reg_handoff_lapb(void);
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
;
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
;
37 static int ett_lapb_control
;
39 static dissector_handle_t x25_dir_handle
;
40 static dissector_handle_t x25_handle
;
41 static dissector_handle_t lapb_handle
;
43 static const xdlc_cf_items lapb_cf_items
= {
49 &hf_lapb_u_modifier_cmd
,
50 &hf_lapb_u_modifier_resp
,
56 dissect_lapb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
58 proto_tree
*lapb_tree
, *ti
;
64 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LAPB");
65 col_clear(pinfo
->cinfo
, COL_INFO
);
67 switch (pinfo
->p2p_dir
) {
70 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "DTE");
71 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "DCE");
75 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "DCE");
76 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "DTE");
80 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "N/A");
81 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "N/A");
85 byte0
= tvb_get_uint8(tvb
, 0);
87 if (byte0
!= 0x01 && byte0
!= 0x03 && byte0
!= 0x07 && byte0
!= 0x0f) /* invalid LAPB frame */
89 col_set_str(pinfo
->cinfo
, COL_INFO
, "Invalid LAPB frame");
91 proto_tree_add_protocol_format(tree
, proto_lapb
, tvb
, 0, -1,
92 "Invalid LAPB frame");
96 switch (pinfo
->p2p_dir
) {
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.
123 ti
= proto_tree_add_protocol_format(tree
, proto_lapb
, tvb
, 0, 2,
125 lapb_tree
= proto_item_add_subtree(ti
, ett_lapb
);
126 proto_tree_add_uint(lapb_tree
, hf_lapb_address
, tvb
, 0, 1, byte0
);
128 control
= dissect_xdlc_control(tvb
, 1, pinfo
, lapb_tree
, hf_lapb_control
,
129 ett_lapb_control
, &lapb_cf_items
, NULL
, NULL
, NULL
,
130 is_response
, false, false);
132 /* information frame ==> X.25 */
133 if (XDLC_IS_INFORMATION(control
)) {
134 next_tvb
= tvb_new_subset_remaining(tvb
, 2);
135 switch (pinfo
->p2p_dir
) {
139 call_dissector(x25_dir_handle
, next_tvb
, pinfo
, tree
);
143 call_dissector(x25_handle
, next_tvb
, pinfo
, tree
);
147 return tvb_captured_length(tvb
);
151 proto_register_lapb(void)
153 static hf_register_info hf
[] = {
155 { "Address", "lapb.address", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
159 { "Control Field", "lapb.control", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
163 { "N(R)", "lapb.control.n_r", FT_UINT8
, BASE_DEC
,
164 NULL
, XDLC_N_R_MASK
, NULL
, HFILL
}},
167 { "N(S)", "lapb.control.n_s", FT_UINT8
, BASE_DEC
,
168 NULL
, XDLC_N_S_MASK
, NULL
, HFILL
}},
171 { "Poll", "lapb.control.p", FT_BOOLEAN
, 8,
172 TFS(&tfs_set_notset
), XDLC_P_F
, NULL
, HFILL
}},
175 { "Final", "lapb.control.f", FT_BOOLEAN
, 8,
176 TFS(&tfs_set_notset
), XDLC_P_F
, NULL
, HFILL
}},
179 { "Supervisory frame type", "lapb.control.s_ftype", FT_UINT8
, BASE_HEX
,
180 VALS(stype_vals
), XDLC_S_FTYPE_MASK
, NULL
, HFILL
}},
182 { &hf_lapb_u_modifier_cmd
,
183 { "Command", "lapb.control.u_modifier_cmd", FT_UINT8
, BASE_HEX
,
184 VALS(modifier_vals_cmd
), XDLC_U_MODIFIER_MASK
, NULL
, HFILL
}},
186 { &hf_lapb_u_modifier_resp
,
187 { "Response", "lapb.control.u_modifier_resp", FT_UINT8
, BASE_HEX
,
188 VALS(modifier_vals_resp
), XDLC_U_MODIFIER_MASK
, NULL
, HFILL
}},
191 { "Frame type", "lapb.control.ftype", FT_UINT8
, BASE_HEX
,
192 VALS(ftype_vals
), XDLC_I_MASK
, NULL
, HFILL
}},
194 { &hf_lapb_ftype_s_u
,
195 { "Frame type", "lapb.control.ftype", FT_UINT8
, BASE_HEX
,
196 VALS(ftype_vals
), XDLC_S_U_MASK
, NULL
, HFILL
}},
198 static int *ett
[] = {
203 proto_lapb
= proto_register_protocol("Link Access Procedure Balanced (LAPB)",
205 proto_register_field_array (proto_lapb
, hf
, array_length(hf
));
206 proto_register_subtree_array(ett
, array_length(ett
));
208 lapb_handle
= register_dissector("lapb", dissect_lapb
, proto_lapb
);
212 proto_reg_handoff_lapb(void)
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
219 x25_dir_handle
= find_dissector_add_dependency("x.25_dir", proto_lapb
);
220 x25_handle
= find_dissector_add_dependency("x.25", proto_lapb
);
222 dissector_add_uint("wtap_encap", WTAP_ENCAP_LAPB
, lapb_handle
);
226 * Editor modelines - https://www.wireshark.org/tools/modelines.html
231 * indent-tabs-mode: nil
234 * vi: set shiftwidth=4 tabstop=8 expandtab:
235 * :indentSize=4:tabSize=8:noTabs=true: