1999-08-02 02:26:22 +00:00
|
|
|
/* packet-lapb.c
|
|
|
|
* Routines for lapb frame disassembly
|
2002-09-01 14:30:34 +00:00
|
|
|
* Olivier Abad <oabad@noos.fr>
|
1999-08-02 02:26:22 +00:00
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
1999-08-05 02:26:21 +00:00
|
|
|
*
|
1999-08-02 02:26:22 +00:00
|
|
|
* Ethereal - Network traffic analyzer
|
2001-12-03 04:00:26 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
1999-08-02 02:26:22 +00:00
|
|
|
* Copyright 1998
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1999-08-02 02:26:22 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1999-08-02 02:26:22 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1999-08-02 02:26:22 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include <string.h>
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
1999-08-04 04:37:46 +00:00
|
|
|
#include "xdlc.h"
|
1999-08-02 02:26:22 +00:00
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
static int proto_lapb = -1;
|
|
|
|
static int hf_lapb_address = -1;
|
|
|
|
static int hf_lapb_control = -1;
|
2004-01-03 03:51:27 +00:00
|
|
|
static int hf_lapb_n_r = -1;
|
|
|
|
static int hf_lapb_n_s = -1;
|
|
|
|
static int hf_lapb_p = -1;
|
|
|
|
static int hf_lapb_f = -1;
|
|
|
|
static int hf_lapb_s_ftype = -1;
|
|
|
|
static int hf_lapb_u_modifier_cmd = -1;
|
|
|
|
static int hf_lapb_u_modifier_resp = -1;
|
|
|
|
static int hf_lapb_ftype_i = -1;
|
|
|
|
static int hf_lapb_ftype_s_u = -1;
|
1999-11-16 11:44:20 +00:00
|
|
|
|
|
|
|
static gint ett_lapb = -1;
|
|
|
|
static gint ett_lapb_control = -1;
|
1999-08-02 02:26:22 +00:00
|
|
|
|
2002-04-09 08:15:04 +00:00
|
|
|
static dissector_handle_t x25_dir_handle;
|
2003-09-26 08:19:55 +00:00
|
|
|
static dissector_handle_t x25_handle;
|
If you register more than one field with the same name, the dfilter code
can now handle that; this allows us to register both the modulo-8 and
the modulo-128 versions of various X.25 bitfields with "x.25.XXX" names,
which lets us get rid of the "ex.25" protocol stuff completely and use
"x.25" for both modulo-8 and modulo-128 X.25. Do so. (Also, fix up
some cases where we appeared to be using the modulo-8 fields when
dissecting modulo-128 X.25.)
This, in turn, allows us to register the X.25 dissector, as there's now
only one protocol with which it's associated, and make it static and
have it called only through a handle, and to, when registering it with
the "llc.dsap" dissector table, associate it with "proto_x25".
That, in turn, allows us to get rid of the "CHECK_DISPLAY_AS_DATA()"
calls, and the code to set "pinfo->current_proto", in the X.25
dissector.
The code for the display filter expression dialog would, if there are
two fields with the same name registered under a protocol, list both of
them; have it list only one of them - the fields should have the same
type, the same radix, and the same value_string/true_false_string table
if any (if they don't, they're really not the same field...).
svn path=/trunk/; revision=3023
2001-02-12 09:06:19 +00:00
|
|
|
|
2004-01-03 03:51:27 +00:00
|
|
|
static const xdlc_cf_items lapb_cf_items = {
|
|
|
|
&hf_lapb_n_r,
|
|
|
|
&hf_lapb_n_s,
|
|
|
|
&hf_lapb_p,
|
|
|
|
&hf_lapb_f,
|
|
|
|
&hf_lapb_s_ftype,
|
|
|
|
&hf_lapb_u_modifier_cmd,
|
|
|
|
&hf_lapb_u_modifier_resp,
|
|
|
|
&hf_lapb_ftype_i,
|
|
|
|
&hf_lapb_ftype_s_u
|
|
|
|
};
|
|
|
|
|
2000-11-29 05:16:15 +00:00
|
|
|
static void
|
2000-05-25 08:45:54 +00:00
|
|
|
dissect_lapb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
1999-08-02 02:26:22 +00:00
|
|
|
{
|
2000-05-25 08:45:54 +00:00
|
|
|
proto_tree *lapb_tree, *ti;
|
|
|
|
int is_response;
|
|
|
|
guint8 byte0;
|
|
|
|
tvbuff_t *next_tvb;
|
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPB");
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2000-05-25 08:45:54 +00:00
|
|
|
|
2003-09-26 08:19:55 +00:00
|
|
|
switch (pinfo->p2p_dir) {
|
|
|
|
|
|
|
|
case P2P_DIR_SENT:
|
|
|
|
if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
|
|
|
|
col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
|
2001-12-10 00:26:21 +00:00
|
|
|
if(check_col(pinfo->cinfo, COL_RES_DL_DST))
|
2003-09-26 08:19:55 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P2P_DIR_RECV:
|
2001-12-10 00:26:21 +00:00
|
|
|
if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
|
|
|
|
col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
|
|
|
|
if(check_col(pinfo->cinfo, COL_RES_DL_DST))
|
2003-09-26 08:19:55 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2001-12-10 00:26:21 +00:00
|
|
|
if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
|
2003-09-26 08:19:55 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
|
|
|
|
if(check_col(pinfo->cinfo, COL_RES_DL_DST))
|
|
|
|
col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
|
|
|
|
break;
|
2000-05-25 08:45:54 +00:00
|
|
|
}
|
1999-08-02 02:26:22 +00:00
|
|
|
|
2000-05-25 08:45:54 +00:00
|
|
|
byte0 = tvb_get_guint8(tvb, 0);
|
1999-08-02 02:26:22 +00:00
|
|
|
|
2000-05-25 08:45:54 +00:00
|
|
|
if (byte0 != 0x01 && byte0 != 0x03) /* invalid LAPB frame */
|
1999-09-12 18:37:01 +00:00
|
|
|
{
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_set_str(pinfo->cinfo, COL_INFO, "Invalid LAPB frame");
|
1999-09-12 18:37:01 +00:00
|
|
|
if (tree)
|
2002-01-24 09:20:54 +00:00
|
|
|
ti = proto_tree_add_protocol_format(tree, proto_lapb, tvb, 0, -1,
|
|
|
|
"Invalid LAPB frame");
|
1999-09-12 18:37:01 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-09-26 08:19:55 +00:00
|
|
|
switch (pinfo->p2p_dir) {
|
|
|
|
|
|
|
|
case P2P_DIR_SENT:
|
|
|
|
if (byte0 == 0x03)
|
|
|
|
is_response = TRUE;
|
|
|
|
else
|
|
|
|
is_response = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case P2P_DIR_RECV:
|
|
|
|
if (byte0 == 0x01)
|
|
|
|
is_response = TRUE;
|
|
|
|
else
|
|
|
|
is_response = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* XXX - should we base this on the source and destination
|
|
|
|
* addresses? The problem is that we can tell one direction
|
|
|
|
* from another with that, but we can't say which is DTE->DCE
|
|
|
|
* and which is DCE->DTE.
|
|
|
|
*/
|
1999-08-04 04:37:46 +00:00
|
|
|
is_response = FALSE;
|
2003-09-26 08:19:55 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-08-02 02:26:22 +00:00
|
|
|
|
1999-08-04 04:37:46 +00:00
|
|
|
if (tree) {
|
2000-05-25 08:45:54 +00:00
|
|
|
ti = proto_tree_add_protocol_format(tree, proto_lapb, tvb, 0, 2,
|
1999-08-02 02:26:22 +00:00
|
|
|
"LAPB");
|
1999-11-16 11:44:20 +00:00
|
|
|
lapb_tree = proto_item_add_subtree(ti, ett_lapb);
|
2000-05-25 08:45:54 +00:00
|
|
|
proto_tree_add_uint_format(lapb_tree, hf_lapb_address, tvb, 0, 1, byte0,
|
|
|
|
"Address: 0x%02X", byte0);
|
1999-08-02 02:26:22 +00:00
|
|
|
}
|
1999-08-04 04:37:46 +00:00
|
|
|
else
|
|
|
|
lapb_tree = NULL;
|
2000-05-25 08:45:54 +00:00
|
|
|
|
2000-05-31 03:58:56 +00:00
|
|
|
dissect_xdlc_control(tvb, 1, pinfo, lapb_tree, hf_lapb_control,
|
2004-01-18 08:32:46 +00:00
|
|
|
ett_lapb_control, &lapb_cf_items, NULL, NULL, NULL,
|
|
|
|
is_response, FALSE, FALSE);
|
1999-08-02 02:26:22 +00:00
|
|
|
|
|
|
|
/* not end of frame ==> X.25 */
|
2002-01-24 09:20:54 +00:00
|
|
|
if (tvb_reported_length(tvb) > 2) {
|
2003-09-26 08:19:55 +00:00
|
|
|
next_tvb = tvb_new_subset(tvb, 2, -1, -1);
|
|
|
|
switch (pinfo->p2p_dir) {
|
|
|
|
|
|
|
|
case P2P_DIR_SENT:
|
|
|
|
case P2P_DIR_RECV:
|
2002-04-09 08:15:04 +00:00
|
|
|
call_dissector(x25_dir_handle, next_tvb, pinfo, tree);
|
2003-09-26 08:19:55 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
call_dissector(x25_handle, next_tvb, pinfo, tree);
|
|
|
|
break;
|
|
|
|
}
|
2000-05-25 08:45:54 +00:00
|
|
|
}
|
1999-08-02 02:26:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_lapb(void)
|
|
|
|
{
|
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{ &hf_lapb_address,
|
2002-08-28 21:04:11 +00:00
|
|
|
{ "Address Field", "lapb.address", FT_UINT8, BASE_HEX, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Address", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-08-02 02:26:22 +00:00
|
|
|
{ &hf_lapb_control,
|
2000-03-15 19:17:08 +00:00
|
|
|
{ "Control Field", "lapb.control", FT_UINT8, BASE_HEX, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Control field", HFILL }},
|
2004-01-03 03:51:27 +00:00
|
|
|
|
|
|
|
{ &hf_lapb_n_r,
|
|
|
|
{ "N(R)", "lapb.control.n_r", FT_UINT8, BASE_DEC,
|
|
|
|
NULL, XDLC_N_R_MASK, "", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lapb_n_s,
|
|
|
|
{ "N(S)", "lapb.control.n_s", FT_UINT8, BASE_DEC,
|
|
|
|
NULL, XDLC_N_S_MASK, "", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lapb_p,
|
|
|
|
{ "Poll", "lapb.control.p", FT_BOOLEAN, 8,
|
|
|
|
TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lapb_f,
|
|
|
|
{ "Final", "lapb.control.f", FT_BOOLEAN, 8,
|
|
|
|
TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lapb_s_ftype,
|
|
|
|
{ "Supervisory frame type", "lapb.control.s_ftype", FT_UINT8, BASE_HEX,
|
|
|
|
VALS(stype_vals), XDLC_S_FTYPE_MASK, "", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lapb_u_modifier_cmd,
|
|
|
|
{ "Command", "lapb.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
|
|
|
|
VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, "", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lapb_u_modifier_resp,
|
|
|
|
{ "Response", "lapb.control.u_modifier_resp", FT_UINT8, BASE_HEX,
|
|
|
|
VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, "", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lapb_ftype_i,
|
|
|
|
{ "Frame type", "lapb.control.ftype", FT_UINT8, BASE_HEX,
|
|
|
|
VALS(ftype_vals), XDLC_I_MASK, "", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lapb_ftype_s_u,
|
|
|
|
{ "Frame type", "lapb.control.ftype", FT_UINT8, BASE_HEX,
|
|
|
|
VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
|
1999-08-02 02:26:22 +00:00
|
|
|
};
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_lapb,
|
|
|
|
&ett_lapb_control,
|
|
|
|
};
|
1999-08-02 02:26:22 +00:00
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
proto_lapb = proto_register_protocol("Link Access Procedure Balanced (LAPB)",
|
|
|
|
"LAPB", "lapb");
|
1999-08-02 02:26:22 +00:00
|
|
|
proto_register_field_array (proto_lapb, hf, array_length(hf));
|
1999-11-16 11:44:20 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2000-12-29 02:27:21 +00:00
|
|
|
|
2001-01-09 06:32:10 +00:00
|
|
|
register_dissector("lapb", dissect_lapb, proto_lapb);
|
1999-08-02 02:26:22 +00:00
|
|
|
}
|
2000-11-29 05:16:15 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_lapb(void)
|
|
|
|
{
|
2001-12-03 04:00:26 +00:00
|
|
|
dissector_handle_t lapb_handle;
|
|
|
|
|
If you register more than one field with the same name, the dfilter code
can now handle that; this allows us to register both the modulo-8 and
the modulo-128 versions of various X.25 bitfields with "x.25.XXX" names,
which lets us get rid of the "ex.25" protocol stuff completely and use
"x.25" for both modulo-8 and modulo-128 X.25. Do so. (Also, fix up
some cases where we appeared to be using the modulo-8 fields when
dissecting modulo-128 X.25.)
This, in turn, allows us to register the X.25 dissector, as there's now
only one protocol with which it's associated, and make it static and
have it called only through a handle, and to, when registering it with
the "llc.dsap" dissector table, associate it with "proto_x25".
That, in turn, allows us to get rid of the "CHECK_DISPLAY_AS_DATA()"
calls, and the code to set "pinfo->current_proto", in the X.25
dissector.
The code for the display filter expression dialog would, if there are
two fields with the same name registered under a protocol, list both of
them; have it list only one of them - the fields should have the same
type, the same radix, and the same value_string/true_false_string table
if any (if they don't, they're really not the same field...).
svn path=/trunk/; revision=3023
2001-02-12 09:06:19 +00:00
|
|
|
/*
|
2003-09-26 08:19:55 +00:00
|
|
|
* Get handles for the X.25 dissectors; we don't get an X.25
|
|
|
|
* pseudo-header for LAPB-over-Ethernet, but we do get it
|
|
|
|
* for raw LAPB.
|
If you register more than one field with the same name, the dfilter code
can now handle that; this allows us to register both the modulo-8 and
the modulo-128 versions of various X.25 bitfields with "x.25.XXX" names,
which lets us get rid of the "ex.25" protocol stuff completely and use
"x.25" for both modulo-8 and modulo-128 X.25. Do so. (Also, fix up
some cases where we appeared to be using the modulo-8 fields when
dissecting modulo-128 X.25.)
This, in turn, allows us to register the X.25 dissector, as there's now
only one protocol with which it's associated, and make it static and
have it called only through a handle, and to, when registering it with
the "llc.dsap" dissector table, associate it with "proto_x25".
That, in turn, allows us to get rid of the "CHECK_DISPLAY_AS_DATA()"
calls, and the code to set "pinfo->current_proto", in the X.25
dissector.
The code for the display filter expression dialog would, if there are
two fields with the same name registered under a protocol, list both of
them; have it list only one of them - the fields should have the same
type, the same radix, and the same value_string/true_false_string table
if any (if they don't, they're really not the same field...).
svn path=/trunk/; revision=3023
2001-02-12 09:06:19 +00:00
|
|
|
*/
|
2002-04-09 08:15:04 +00:00
|
|
|
x25_dir_handle = find_dissector("x.25_dir");
|
2003-09-26 08:19:55 +00:00
|
|
|
x25_handle = find_dissector("x.25");
|
If you register more than one field with the same name, the dfilter code
can now handle that; this allows us to register both the modulo-8 and
the modulo-128 versions of various X.25 bitfields with "x.25.XXX" names,
which lets us get rid of the "ex.25" protocol stuff completely and use
"x.25" for both modulo-8 and modulo-128 X.25. Do so. (Also, fix up
some cases where we appeared to be using the modulo-8 fields when
dissecting modulo-128 X.25.)
This, in turn, allows us to register the X.25 dissector, as there's now
only one protocol with which it's associated, and make it static and
have it called only through a handle, and to, when registering it with
the "llc.dsap" dissector table, associate it with "proto_x25".
That, in turn, allows us to get rid of the "CHECK_DISPLAY_AS_DATA()"
calls, and the code to set "pinfo->current_proto", in the X.25
dissector.
The code for the display filter expression dialog would, if there are
two fields with the same name registered under a protocol, list both of
them; have it list only one of them - the fields should have the same
type, the same radix, and the same value_string/true_false_string table
if any (if they don't, they're really not the same field...).
svn path=/trunk/; revision=3023
2001-02-12 09:06:19 +00:00
|
|
|
|
2001-12-03 04:00:26 +00:00
|
|
|
lapb_handle = find_dissector("lapb");
|
|
|
|
dissector_add("wtap_encap", WTAP_ENCAP_LAPB, lapb_handle);
|
2000-11-29 05:16:15 +00:00
|
|
|
}
|