2 * Routines for lapb frame disassembly
3 * Olivier Abad <oabad@noos.fr>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <epan/packet.h>
30 #include <epan/xdlc.h>
32 static int proto_lapb
= -1;
33 static int hf_lapb_address
= -1;
34 static int hf_lapb_control
= -1;
35 static int hf_lapb_n_r
= -1;
36 static int hf_lapb_n_s
= -1;
37 static int hf_lapb_p
= -1;
38 static int hf_lapb_f
= -1;
39 static int hf_lapb_s_ftype
= -1;
40 static int hf_lapb_u_modifier_cmd
= -1;
41 static int hf_lapb_u_modifier_resp
= -1;
42 static int hf_lapb_ftype_i
= -1;
43 static int hf_lapb_ftype_s_u
= -1;
45 static gint ett_lapb
= -1;
46 static gint ett_lapb_control
= -1;
48 static dissector_handle_t x25_dir_handle
;
49 static dissector_handle_t x25_handle
;
51 static const xdlc_cf_items lapb_cf_items
= {
57 &hf_lapb_u_modifier_cmd
,
58 &hf_lapb_u_modifier_resp
,
64 dissect_lapb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
66 proto_tree
*lapb_tree
, *ti
;
72 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "LAPB");
73 col_clear(pinfo
->cinfo
, COL_INFO
);
75 switch (pinfo
->p2p_dir
) {
78 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "DTE");
79 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "DCE");
83 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "DCE");
84 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "DTE");
88 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "N/A");
89 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "N/A");
93 byte0
= tvb_get_guint8(tvb
, 0);
95 if (byte0
!= 0x01 && byte0
!= 0x03 && byte0
!= 0x07 && byte0
!= 0x0f) /* invalid LAPB frame */
97 col_set_str(pinfo
->cinfo
, COL_INFO
, "Invalid LAPB frame");
99 proto_tree_add_protocol_format(tree
, proto_lapb
, tvb
, 0, -1,
100 "Invalid LAPB frame");
104 switch (pinfo
->p2p_dir
) {
122 * XXX - should we base this on the source and destination
123 * addresses? The problem is that we can tell one direction
124 * from another with that, but we can't say which is DTE->DCE
125 * and which is DCE->DTE.
131 ti
= proto_tree_add_protocol_format(tree
, proto_lapb
, tvb
, 0, 2,
133 lapb_tree
= proto_item_add_subtree(ti
, ett_lapb
);
134 proto_tree_add_uint(lapb_tree
, hf_lapb_address
, tvb
, 0, 1, byte0
);
136 control
= dissect_xdlc_control(tvb
, 1, pinfo
, lapb_tree
, hf_lapb_control
,
137 ett_lapb_control
, &lapb_cf_items
, NULL
, NULL
, NULL
,
138 is_response
, FALSE
, FALSE
);
140 /* information frame ==> X.25 */
141 if (XDLC_IS_INFORMATION(control
)) {
142 next_tvb
= tvb_new_subset_remaining(tvb
, 2);
143 switch (pinfo
->p2p_dir
) {
147 call_dissector(x25_dir_handle
, next_tvb
, pinfo
, tree
);
151 call_dissector(x25_handle
, next_tvb
, pinfo
, tree
);
158 proto_register_lapb(void)
160 static hf_register_info hf
[] = {
162 { "Address", "lapb.address", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
166 { "Control Field", "lapb.control", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
170 { "N(R)", "lapb.control.n_r", FT_UINT8
, BASE_DEC
,
171 NULL
, XDLC_N_R_MASK
, NULL
, HFILL
}},
174 { "N(S)", "lapb.control.n_s", FT_UINT8
, BASE_DEC
,
175 NULL
, XDLC_N_S_MASK
, NULL
, HFILL
}},
178 { "Poll", "lapb.control.p", FT_BOOLEAN
, 8,
179 TFS(&tfs_set_notset
), XDLC_P_F
, NULL
, HFILL
}},
182 { "Final", "lapb.control.f", FT_BOOLEAN
, 8,
183 TFS(&tfs_set_notset
), XDLC_P_F
, NULL
, HFILL
}},
186 { "Supervisory frame type", "lapb.control.s_ftype", FT_UINT8
, BASE_HEX
,
187 VALS(stype_vals
), XDLC_S_FTYPE_MASK
, NULL
, HFILL
}},
189 { &hf_lapb_u_modifier_cmd
,
190 { "Command", "lapb.control.u_modifier_cmd", FT_UINT8
, BASE_HEX
,
191 VALS(modifier_vals_cmd
), XDLC_U_MODIFIER_MASK
, NULL
, HFILL
}},
193 { &hf_lapb_u_modifier_resp
,
194 { "Response", "lapb.control.u_modifier_resp", FT_UINT8
, BASE_HEX
,
195 VALS(modifier_vals_resp
), XDLC_U_MODIFIER_MASK
, NULL
, HFILL
}},
198 { "Frame type", "lapb.control.ftype", FT_UINT8
, BASE_HEX
,
199 VALS(ftype_vals
), XDLC_I_MASK
, NULL
, HFILL
}},
201 { &hf_lapb_ftype_s_u
,
202 { "Frame type", "lapb.control.ftype", FT_UINT8
, BASE_HEX
,
203 VALS(ftype_vals
), XDLC_S_U_MASK
, NULL
, HFILL
}},
205 static gint
*ett
[] = {
210 proto_lapb
= proto_register_protocol("Link Access Procedure Balanced (LAPB)",
212 proto_register_field_array (proto_lapb
, hf
, array_length(hf
));
213 proto_register_subtree_array(ett
, array_length(ett
));
215 register_dissector("lapb", dissect_lapb
, proto_lapb
);
219 proto_reg_handoff_lapb(void)
221 dissector_handle_t lapb_handle
;
224 * Get handles for the X.25 dissectors; we don't get an X.25
225 * pseudo-header for LAPB-over-Ethernet, but we do get it
228 x25_dir_handle
= find_dissector("x.25_dir");
229 x25_handle
= find_dissector("x.25");
231 lapb_handle
= find_dissector("lapb");
232 dissector_add_uint("wtap_encap", WTAP_ENCAP_LAPB
, lapb_handle
);