/* packet-x25.c
* Routines for x25 packet disassembly
- * Olivier Abad <abad@daba.dhis.net>
+ * Olivier Abad <oabad@cybercable.fr>
*
- * $Id: packet-x25.c,v 1.28 2000/05/25 21:34:57 oabad Exp $
+ * $Id: packet-x25.c,v 1.53 2001/07/18 15:49:29 oabad Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
#include <glib.h>
#include <stdlib.h>
#include <string.h>
-#include "etypes.h"
+#include "llcsaps.h"
#include "packet.h"
-#include "packet-x25.h"
-#include "packet-ip.h"
-#include "packet-osi.h"
-#include "packet-clnp.h"
#include "nlpid.h"
#define FROM_DCE 0x80
#define X25_FAC_PRIORITY 0xD2
static int proto_x25 = -1;
+static int hf_x25_gfi = -1;
+static int hf_x25_abit = -1;
static int hf_x25_qbit = -1;
static int hf_x25_dbit = -1;
static int hf_x25_mod = -1;
static int hf_x25_lcn = -1;
static int hf_x25_type = -1;
-static int hf_x25_p_r = -1;
-static int hf_x25_mbit = -1;
-static int hf_x25_p_s = -1;
-static int proto_ex25 = -1;
-static int hf_ex25_qbit = -1;
-static int hf_ex25_dbit = -1;
-static int hf_ex25_mod = -1;
-static int hf_ex25_lcn = -1;
-static int hf_ex25_type = -1;
-static int hf_ex25_p_r = -1;
-static int hf_ex25_mbit = -1;
-static int hf_ex25_p_s = -1;
+static int hf_x25_p_r_mod8 = -1;
+static int hf_x25_p_r_mod128 = -1;
+static int hf_x25_mbit_mod8 = -1;
+static int hf_x25_mbit_mod128 = -1;
+static int hf_x25_p_s_mod8 = -1;
+static int hf_x25_p_s_mod128 = -1;
static gint ett_x25 = -1;
+static gint ett_x25_gfi = -1;
static gint ett_x25_fac = -1;
static gint ett_x25_fac_unknown = -1;
static gint ett_x25_fac_mark = -1;
{ 0, NULL}
};
+static dissector_handle_t ip_handle;
+static dissector_handle_t ositp_handle;
+
/*
* each vc_info node contains :
* the time of the first frame using this dissector (secs and usecs)
typedef struct _vc_info {
guint32 first_frame_secs, first_frame_usecs;
guint32 last_frame_secs, last_frame_usecs;
- void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
+ dissector_handle_t dissect;
struct _vc_info *next;
} vc_info;
static global_vc_info *hash_table[64];
-void
+static void
free_vc_info(vc_info *pt)
{
vc_info *vci = pt;
}
}
-void
+static void
x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
- void (*dissect)(const u_char *, int, frame_data *,
- proto_tree *))
+ dissector_handle_t dissect)
{
int idx = vc % 64;
global_vc_info *hash_ent;
}
}
-void
+static void
x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
{
global_vc_info *hash_ent = hash_table[vc%64];
vci->last_frame_usecs = frame_usecs;
}
-void (*x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc))(const u_char *, int, frame_data *, proto_tree *)
+static dissector_handle_t
+x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc)
{
global_vc_info *hash_ent = hash_table[vc%64];
vc_info *vci;
return "DTE Originated";
if (code == 0x01)
return "Number Busy";
+ if (code == 0x03)
+ return "Invalid Facility Requested";
+ if (code == 0x05)
+ return "Network Congestion";
if (code == 0x09)
return "Out Of Order";
+ if (code == 0x0B)
+ return "Access Barred";
+ if (code == 0x0D)
+ return "Not Obtainable";
if (code == 0x11)
return "Remote Procedure Error";
+ if (code == 0x13)
+ return "Local Procedure Error";
+ if (code == 0x15)
+ return "RPOA Out Of Order";
if (code == 0x19)
return "Reverse Charging Acceptance Not Subscribed";
if (code == 0x21)
return "Fast Select Acceptance Not Subscribed";
if (code == 0x39)
return "Destination Absent";
- if (code == 0x03)
- return "Invalid Facility Requested";
- if (code == 0x0B)
- return "Access Barred";
- if (code == 0x13)
- return "Local Procedure Error";
- if (code == 0x05)
- return "Network Congestion";
- if (code == 0x0D)
- return "Not Obtainable";
- if (code == 0x15)
- return "RPOA Out Of Order";
sprintf(buffer, "Unknown %02X", code);
return "Unknown called DNIC";
if (code == 122)
return "Maintenance action";
+ if (code == 144)
+ return "Timer expired or retransmission count surpassed";
+ if (code == 145)
+ return "Timer expired or retransmission count surpassed for INTERRUPT";
+ if (code == 146)
+ return "Timer expired or retransmission count surpassed for DATA "
+ "packet transmission";
+ if (code == 147)
+ return "Timer expired or retransmission count surpassed for REJECT";
+ if (code == 160)
+ return "DTE-specific signals";
+ if (code == 161)
+ return "DTE operational";
+ if (code == 162)
+ return "DTE not operational";
+ if (code == 163)
+ return "DTE resource constraint";
+ if (code == 164)
+ return "Fast select not subscribed";
+ if (code == 165)
+ return "Invalid partially full DATA packet";
+ if (code == 166)
+ return "D-bit procedure not supported";
+ if (code == 167)
+ return "Registration/Cancellation confirmed";
+ if (code == 224)
+ return "OSI network service problem";
+ if (code == 225)
+ return "Disconnection (transient condition)";
+ if (code == 226)
+ return "Disconnection (permanent condition)";
+ if (code == 227)
+ return "Connection rejection - reason unspecified (transient "
+ "condition)";
+ if (code == 228)
+ return "Connection rejection - reason unspecified (permanent "
+ "condition)";
+ if (code == 229)
+ return "Connection rejection - quality of service not available "
+ "transient condition)";
+ if (code == 230)
+ return "Connection rejection - quality of service not available "
+ "permanent condition)";
+ if (code == 231)
+ return "Connection rejection - NSAP unreachable (transient condition)";
+ if (code == 232)
+ return "Connection rejection - NSAP unreachable (permanent condition)";
+ if (code == 233)
+ return "reset - reason unspecified";
+ if (code == 234)
+ return "reset - congestion";
+ if (code == 235)
+ return "Connection rejection - NSAP address unknown (permanent "
+ "condition)";
+ if (code == 240)
+ return "Higher layer initiated";
+ if (code == 241)
+ return "Disconnection - normal";
+ if (code == 242)
+ return "Disconnection - abnormal";
+ if (code == 243)
+ return "Disconnection - incompatible information in user data";
+ if (code == 244)
+ return "Connection rejection - reason unspecified (transient "
+ "condition)";
+ if (code == 245)
+ return "Connection rejection - reason unspecified (permanent "
+ "condition)";
+ if (code == 246)
+ return "Connection rejection - quality of service not available "
+ "(transient condition)";
+ if (code == 247)
+ return "Connection rejection - quality of service not available "
+ "(permanent condition)";
+ if (code == 248)
+ return "Connection rejection - incompatible information in user data";
+ if (code == 249)
+ return "Connection rejection - unrecognizable protocol indentifier "
+ "in user data";
+ if (code == 250)
+ return "Reset - user resynchronization";
sprintf(buffer, "Unknown %d", code);
return buffer;
}
-void
+static void
dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
{
guint8 fac, byte1, byte2, byte3;
}
}
-void
+static void
x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
frame_data *fd, gboolean toa)
{
(*offset) += ((len1 + len2 + 1) / 2);
}
-int
+static int
get_x25_pkt_len(tvbuff_t *tvb)
{
- int length, called_len, calling_len, dte_len, dce_len;
+ guint length, called_len, calling_len, dte_len, dce_len;
guint8 byte2, bytex;
byte2 = tvb_get_guint8(tvb, 2);
called_len = (bytex >> 0) & 0x0F;
calling_len = (bytex >> 4) & 0x0F;
length = 4 + (called_len + calling_len + 1) / 2; /* addr */
- if (length < tvb_length(tvb))
+ if (length < tvb_reported_length(tvb))
length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
- return MIN(tvb_length(tvb),length);
+ return MIN(tvb_reported_length(tvb),length);
case X25_CALL_ACCEPTED:
+ /* The calling/called address length byte (following the packet type)
+ * is not mandatory, so we must check the packet length before trying
+ * to read it */
+ if (tvb_reported_length(tvb) == 3)
+ return(3);
bytex = tvb_get_guint8(tvb, 3);
called_len = (bytex >> 0) & 0x0F;
calling_len = (bytex >> 4) & 0x0F;
length = 4 + (called_len + calling_len + 1) / 2; /* addr */
- if (length < tvb_length(tvb))
+ if (length < tvb_reported_length(tvb))
length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
- return MIN(tvb_length(tvb),length);
+ return MIN(tvb_reported_length(tvb),length);
case X25_CLEAR_REQUEST:
case X25_RESET_REQUEST:
case X25_RESTART_REQUEST:
- return MIN(tvb_length(tvb),5);
+ return MIN(tvb_reported_length(tvb),5);
case X25_DIAGNOSTIC:
- return MIN(tvb_length(tvb),4);
+ return MIN(tvb_reported_length(tvb),4);
case X25_CLEAR_CONFIRMATION:
case X25_INTERRUPT:
case X25_INTERRUPT_CONFIRMATION:
case X25_RESET_CONFIRMATION:
case X25_RESTART_CONFIRMATION:
- return MIN(tvb_length(tvb),3);
+ return MIN(tvb_reported_length(tvb),3);
case X25_REGISTRATION_REQUEST:
bytex = tvb_get_guint8(tvb, 3);
dce_len = (bytex >> 0) & 0x0F;
dte_len = (bytex >> 4) & 0x0F;
length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
- if (length < tvb_length(tvb))
+ if (length < tvb_reported_length(tvb))
length += (1 + tvb_get_guint8(tvb, length)); /* registration */
- return MIN(tvb_length(tvb),length);
+ return MIN(tvb_reported_length(tvb),length);
case X25_REGISTRATION_CONFIRMATION:
bytex = tvb_get_guint8(tvb, 5);
dce_len = (bytex >> 0) & 0x0F;
dte_len = (bytex >> 4) & 0x0F;
length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
- if (length < tvb_length(tvb))
+ if (length < tvb_reported_length(tvb))
length += (1 + tvb_get_guint8(tvb, length)); /* registration */
- return MIN(tvb_length(tvb),length);
+ return MIN(tvb_reported_length(tvb),length);
}
- if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_length(tvb),3);
+ if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_reported_length(tvb),3);
switch (byte2 & 0x1F)
{
case X25_RR:
- return MIN(tvb_length(tvb),3);
+ return MIN(tvb_reported_length(tvb),3);
case X25_RNR:
- return MIN(tvb_length(tvb),3);
+ return MIN(tvb_reported_length(tvb),3);
case X25_REJ:
- return MIN(tvb_length(tvb),3);
+ return MIN(tvb_reported_length(tvb),3);
}
return 0;
{0x00, NULL}
};
-void
+static void
dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_tree *x25_tree=0, *ti;
- int localoffset=0;
- int x25_pkt_len;
+ proto_tree *x25_tree=0, *gfi_tree=0;
+ proto_item *ti;
+ guint localoffset=0;
+ guint x25_pkt_len;
int modulo;
guint16 vc;
- void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
+ dissector_handle_t dissect;
gboolean toa; /* TOA/NPI address format */
guint16 bytes0_1;
guint8 pkt_type;
tvbuff_t *next_tvb;
- const guint8 *next_pd;
- int next_offset;
-
- pinfo->current_proto = "X.25";
if (check_col(pinfo->fd, COL_PROTOCOL))
- col_add_str(pinfo->fd, COL_PROTOCOL, "X.25");
+ col_set_str(pinfo->fd, COL_PROTOCOL, "X.25");
bytes0_1 = tvb_get_ntohs(tvb, 0);
if (x25_pkt_len < 3) /* packet too short */
{
if (check_col(pinfo->fd, COL_INFO))
- col_add_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
+ col_set_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
if (tree)
- proto_tree_add_protocol_format(tree,
- (modulo == 8 ? proto_x25 : proto_ex25), tvb, 0,
+ proto_tree_add_protocol_format(tree, proto_x25, tvb, 0,
tvb_length(tvb), "Invalid/short X.25 packet");
return;
}
+
+ pkt_type = tvb_get_guint8(tvb, 2);
+
if (tree) {
- ti = proto_tree_add_protocol_format(tree,
- (modulo == 8) ? proto_x25 : proto_ex25, tvb, 0, x25_pkt_len,
- "X.25");
+ ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, FALSE);
x25_tree = proto_item_add_subtree(ti, ett_x25);
- if (bytes0_1 & 0x8000)
- proto_tree_add_item(x25_tree,
- (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit, tvb, 0, 2,
+ ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, FALSE);
+ gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
+ if ((pkt_type & 0x01) == X25_DATA)
+ proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
+ bytes0_1);
+ else if (pkt_type == X25_CALL_REQUEST ||
+ pkt_type == X25_CALL_ACCEPTED ||
+ pkt_type == X25_CLEAR_REQUEST ||
+ pkt_type == X25_CLEAR_CONFIRMATION)
+ proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
bytes0_1);
- if (bytes0_1 & 0x4000)
- proto_tree_add_item(x25_tree,
- (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit, tvb, 0, 2,
+ if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
+ (pkt_type & 0x01) == X25_DATA)
+ proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
bytes0_1);
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod,
- tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
}
- pkt_type = tvb_get_guint8(tvb, 2);
switch (pkt_type) {
case X25_CALL_REQUEST:
if (check_col(pinfo->fd, COL_INFO))
: "Call req." ,
vc);
if (x25_tree) {
- proto_tree_add_item(x25_tree,
- (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
0, 2, bytes0_1);
- proto_tree_add_uint_format(x25_tree,
- (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
X25_CALL_REQUEST,
(pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
: "Call request");
if (localoffset < x25_pkt_len) /* facilities */
dump_facilities(x25_tree, &localoffset, tvb);
- if (localoffset < tvb_length(tvb)) /* user data */
+ if (localoffset < tvb_reported_length(tvb)) /* user data */
{
guint8 spi;
guint8 prt_id;
spi = tvb_get_guint8(tvb, localoffset);
switch (spi) {
- /* XXX - handle other NLPIDs, e.g. PPP? */
-
+ /*
+ * XXX - handle other NLPIDs, e.g. PPP?
+ * See RFC 1356 for information on at least some other
+ * ways of running other protocols atop X.25.
+ */
case NLPID_IP:
x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
- pinfo->fd->abs_usecs, dissect_ip);
+ pinfo->fd->abs_usecs, ip_handle);
if (x25_tree)
proto_tree_add_text(x25_tree, tvb, localoffset, 1,
"X.224 secondary protocol ID: IP");
case PRT_ID_ISO_8073:
/* ISO 8073 COTP */
x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
- pinfo->fd->abs_usecs, dissect_cotp);
+ pinfo->fd->abs_usecs, ositp_handle);
break;
default:
unknown:
if (x25_tree) {
proto_tree_add_text(x25_tree, tvb, localoffset,
- tvb_length(tvb)-localoffset, "Data");
+ tvb_reported_length(tvb)-localoffset, "Data");
}
- localoffset = tvb_length(tvb);
+ localoffset = tvb_reported_length(tvb);
}
}
}
: "Call acc." ,
vc);
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
- tvb, 0, 2, bytes0_1);
- proto_tree_add_uint_format(x25_tree,
- (modulo == 8) ? hf_x25_type : hf_ex25_type,
- tvb, 2, 1, X25_CALL_ACCEPTED,
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_CALL_ACCEPTED,
(pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
: "Call accepted");
}
if (localoffset < x25_pkt_len) /* facilities */
dump_facilities(x25_tree, &localoffset, tvb);
- if (localoffset < tvb_length(tvb)) { /* user data */
+ if (localoffset < tvb_reported_length(tvb)) { /* user data */
if (x25_tree)
proto_tree_add_text(x25_tree, tvb, localoffset,
- tvb_length(tvb)-localoffset, "Data");
- localoffset=tvb_length(tvb);
+ tvb_reported_length(tvb)-localoffset, "Data");
+ localoffset=tvb_reported_length(tvb);
}
break;
case X25_CLEAR_REQUEST:
}
x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
- 0, 2, bytes0_1);
- proto_tree_add_uint_format(x25_tree,
- (modulo == 8) ? hf_x25_type : hf_ex25_type,
- tvb, localoffset+2, 1, X25_CLEAR_REQUEST,
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb,
+ localoffset+2, 1, X25_CLEAR_REQUEST,
(pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
: "Clear request");
proto_tree_add_text(x25_tree, tvb, 3, 1,
if(check_col(pinfo->fd, COL_INFO))
col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
- 0, 2, bytes0_1);
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
- 2, 1, X25_CLEAR_CONFIRMATION);
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_CLEAR_CONFIRMATION);
}
localoffset = x25_pkt_len;
- if (localoffset < tvb_length(tvb)) /* extended clear conf format */
+ if (localoffset < tvb_reported_length(tvb)) /* extended clear conf format */
x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
- if (localoffset < tvb_length(tvb)) /* facilities */
+ if (localoffset < tvb_reported_length(tvb)) /* facilities */
dump_facilities(x25_tree, &localoffset, tvb);
break;
case X25_DIAGNOSTIC:
(int)tvb_get_guint8(tvb, 3));
}
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
- 2, 1, X25_DIAGNOSTIC);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_DIAGNOSTIC);
proto_tree_add_text(x25_tree, tvb, 3, 1,
"Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
}
if(check_col(pinfo->fd, COL_INFO))
col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
- 0, 2, bytes0_1);
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
- 2, 1, X25_INTERRUPT);
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_INTERRUPT);
}
localoffset = x25_pkt_len;
break;
if(check_col(pinfo->fd, COL_INFO))
col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
- 0, 2, bytes0_1);
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
- 2, 1, X25_INTERRUPT_CONFIRMATION);
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_INTERRUPT_CONFIRMATION);
}
localoffset = x25_pkt_len;
break;
}
x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
- 0, 2, bytes0_1);
- proto_tree_add_uint_format(x25_tree,
- (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
X25_RESET_REQUEST,
(pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
: "Reset request");
if(check_col(pinfo->fd, COL_INFO))
col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
- 0, 2, bytes0_1);
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
- 2, 1, X25_RESET_CONFIRMATION);
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_RESET_CONFIRMATION);
}
localoffset = x25_pkt_len;
break;
(int)tvb_get_guint8(tvb, 3));
}
if (x25_tree) {
- proto_tree_add_uint_format(x25_tree,
- (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
X25_RESTART_REQUEST,
(pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
: "Restart request");
break;
case X25_RESTART_CONFIRMATION:
if(check_col(pinfo->fd, COL_INFO))
- col_add_str(pinfo->fd, COL_INFO, "Restart conf.");
+ col_set_str(pinfo->fd, COL_INFO, "Restart conf.");
if (x25_tree)
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
- 2, 1, X25_RESTART_CONFIRMATION);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_RESTART_CONFIRMATION);
localoffset = x25_pkt_len;
break;
case X25_REGISTRATION_REQUEST:
if(check_col(pinfo->fd, COL_INFO))
- col_add_str(pinfo->fd, COL_INFO, "Registration req.");
+ col_set_str(pinfo->fd, COL_INFO, "Registration req.");
if (x25_tree)
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
- 2, 1, X25_REGISTRATION_REQUEST);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_REGISTRATION_REQUEST);
localoffset = 3;
if (localoffset < x25_pkt_len)
x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
tvb_get_guint8(tvb, localoffset) & 0x7F,
"Registration");
}
- localoffset = tvb_length(tvb);
+ localoffset = tvb_reported_length(tvb);
break;
case X25_REGISTRATION_CONFIRMATION:
if(check_col(pinfo->fd, COL_INFO))
- col_add_str(pinfo->fd, COL_INFO, "Registration conf.");
+ col_set_str(pinfo->fd, COL_INFO, "Registration conf.");
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
- 2, 1, X25_REGISTRATION_CONFIRMATION);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_REGISTRATION_CONFIRMATION);
proto_tree_add_text(x25_tree, tvb, 3, 1,
"Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
proto_tree_add_text(x25_tree, tvb, 4, 1,
tvb_get_guint8(tvb, localoffset) & 0x7F,
"Registration");
}
- localoffset = tvb_length(tvb);
+ localoffset = tvb_reported_length(tvb);
break;
default :
localoffset = 2;
(tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
}
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
- tvb, localoffset-2, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+ 2, bytes0_1);
+ proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
+ localoffset, 1, X25_DATA);
if (modulo == 8) {
- proto_tree_add_item_hidden(x25_tree, hf_x25_type, tvb,
- localoffset, 1, X25_DATA);
- proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
localoffset, 1, pkt_type);
if (pkt_type & 0x10)
- proto_tree_add_item(x25_tree, hf_x25_mbit, tvb, localoffset, 1,
- pkt_type);
- proto_tree_add_item(x25_tree, hf_x25_p_s, tvb, localoffset, 1,
- pkt_type);
+ proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
+ localoffset, 1, pkt_type);
proto_tree_add_text(x25_tree, tvb, localoffset, 1,
decode_boolean_bitfield(pkt_type, 0x01, 1*8,
NULL, "DATA"));
}
else {
- proto_tree_add_item_hidden(x25_tree, hf_ex25_type, tvb,
- localoffset, 1, X25_DATA);
- proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
localoffset, 1, pkt_type);
- proto_tree_add_item(x25_tree, hf_x25_p_s, tvb,
- localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
+ proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
+ localoffset+1, 1,
+ tvb_get_guint8(tvb, localoffset+1));
if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
- proto_tree_add_item(x25_tree, hf_ex25_mbit, tvb,
- localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
+ proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
+ localoffset+1, 1,
+ tvb_get_guint8(tvb, localoffset+1));
}
}
localoffset += (modulo == 8) ? 1 : 2;
vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
}
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
- tvb, localoffset-2, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+ 2, bytes0_1);
if (modulo == 8) {
- proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
localoffset, 1, pkt_type);
- proto_tree_add_item(x25_tree, hf_x25_type, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
localoffset, 1, X25_RR);
}
else {
- proto_tree_add_item(x25_tree, hf_ex25_type, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
localoffset, 1, X25_RR);
- proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
- localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
+ proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
+ localoffset+1, 1, FALSE);
}
}
break;
vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
}
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
- tvb, localoffset-2, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+ 2, bytes0_1);
if (modulo == 8) {
- proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
localoffset, 1, pkt_type);
- proto_tree_add_item(x25_tree, hf_x25_type, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
localoffset, 1, X25_RNR);
}
else {
- proto_tree_add_item(x25_tree, hf_ex25_type, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
localoffset, 1, X25_RNR);
- proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
- localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
+ proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
+ localoffset+1, 1, FALSE);
}
}
break;
vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
}
if (x25_tree) {
- proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
- tvb, localoffset-2, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+ 2, bytes0_1);
if (modulo == 8) {
- proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
localoffset, 1, pkt_type);
- proto_tree_add_item(x25_tree, hf_x25_type, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
localoffset, 1, X25_REJ);
}
else {
- proto_tree_add_item(x25_tree, hf_ex25_type, tvb,
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
localoffset, 1, X25_REJ);
- proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
- localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
+ proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
+ localoffset+1, 1, FALSE);
}
}
}
localoffset += (modulo == 8) ? 1 : 2;
}
- if (localoffset >= tvb_length(tvb)) return;
+ if (localoffset >= tvb_reported_length(tvb)) return;
next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
- tvb_compat(next_tvb, &next_pd, &next_offset);
/* search the dissector in the hash table */
if ((dissect = x25_hash_get_dissect(pinfo->fd->abs_secs, pinfo->fd->abs_usecs, vc)))
- (*dissect)(next_pd, next_offset, pinfo->fd, tree);
+ call_dissector(dissect, next_tvb, pinfo, tree);
else {
/* If the Call Req. has not been captured, assume these packets carry IP */
if (tvb_get_guint8(tvb, localoffset) == 0x45) {
x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
- pinfo->fd->abs_usecs, dissect_ip);
- dissect_ip(next_pd, next_offset, pinfo->fd, tree);
+ pinfo->fd->abs_usecs, ip_handle);
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
}
else {
- dissect_data(next_pd, next_offset, pinfo->fd, tree);
+ dissect_data(next_tvb, 0, pinfo, tree);
}
}
}
void
proto_register_x25(void)
{
- static hf_register_info hf8[] = {
+ static hf_register_info hf[] = {
+ { &hf_x25_gfi,
+ { "GFI", "x.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
+ "General format identifier", HFILL }},
+ { &hf_x25_abit,
+ { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
+ "Address Bit", HFILL }},
{ &hf_x25_qbit,
- { "Q Bit", "x25.q", FT_BOOLEAN, 2, NULL, 0x8000,
- "Qualifier Bit" } },
- { &hf_x25_qbit,
- { "D Bit", "x25.d", FT_BOOLEAN, 2, NULL, 0x4000,
- "Delivery Confirmation Bit" } },
+ { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
+ "Qualifier Bit", HFILL }},
+ { &hf_x25_dbit,
+ { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
+ "Delivery Confirmation Bit", HFILL }},
{ &hf_x25_mod,
- { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
- "Specifies whether the frame is modulo 8 or 128" } },
+ { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
+ "Specifies whether the frame is modulo 8 or 128", HFILL }},
{ &hf_x25_lcn,
- { "Logical Channel", "x25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
- "Logical Channel Number" } },
+ { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
+ "Logical Channel Number", HFILL }},
{ &hf_x25_type,
- { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
- "Packet Type" } },
- { &hf_x25_p_r,
- { "P(R)", "x25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
- "Packet Receive Sequence Number" } },
- { &hf_x25_mbit,
- { "M Bit", "x25.m", FT_BOOLEAN, 1, NULL, 0x10,
- "More Bit" } },
- { &hf_x25_p_s,
- { "P(S)", "x25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
- "Packet Send Sequence Number" } },
- };
-
- static hf_register_info hf128[] = {
- { &hf_ex25_qbit,
- { "Q Bit", "ex25.q", FT_BOOLEAN, 2, NULL, 0x8000,
- "Qualifier Bit" } },
- { &hf_ex25_qbit,
- { "D Bit", "ex25.d", FT_BOOLEAN, 2, NULL, 0x4000,
- "Delivery Confirmation Bit" } },
- { &hf_ex25_mod,
- { "Modulo", "ex25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
- "Specifies whether the frame is modulo 8 or 128" } },
- { &hf_ex25_lcn,
- { "Logical Channel", "ex25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
- "Logical Channel Number" } },
- { &hf_ex25_type,
- { "Packet Type", "ex25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
- "Packet Type" } },
- { &hf_ex25_p_r,
- { "P(R)", "ex25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
- "Packet Receive Sequence Number" } },
- { &hf_ex25_mbit,
- { "M Bit", "ex25.m", FT_BOOLEAN, 1, NULL, 0x01,
- "More Bit" } },
- { &hf_ex25_p_s,
- { "P(S)", "ex25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
- "Packet Send Sequence Number" } },
+ { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
+ "Packet Type", HFILL }},
+ { &hf_x25_p_r_mod8,
+ { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
+ "Packet Receive Sequence Number", HFILL }},
+ { &hf_x25_p_r_mod128,
+ { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
+ "Packet Receive Sequence Number", HFILL }},
+ { &hf_x25_mbit_mod8,
+ { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x10,
+ "More Bit", HFILL }},
+ { &hf_x25_mbit_mod128,
+ { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x01,
+ "More Bit", HFILL }},
+ { &hf_x25_p_s_mod8,
+ { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
+ "Packet Send Sequence Number", HFILL }},
+ { &hf_x25_p_s_mod128,
+ { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
+ "Packet Send Sequence Number", HFILL }},
};
static gint *ett[] = {
&ett_x25,
+ &ett_x25_gfi,
&ett_x25_fac,
&ett_x25_fac_unknown,
&ett_x25_fac_mark,
&ett_x25_fac_priority
};
- proto_x25 = proto_register_protocol ("X.25", "x25");
- proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)", "ex25");
- proto_register_field_array (proto_x25, hf8, array_length(hf8));
- proto_register_field_array (proto_ex25, hf128, array_length(hf128));
+ proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
+ proto_register_field_array (proto_x25, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_init_routine(&reinit_x25_hashtable);
+
+ register_dissector("x.25", dissect_x25, proto_x25);
+}
+
+void
+proto_reg_handoff_x25(void)
+{
+ /*
+ * Get handles for the IP and OSI TP (COTP/CLTP) dissectors.
+ */
+ ip_handle = find_dissector("ip");
+ ositp_handle = find_dissector("ositp");
+
+ dissector_add("llc.dsap", SAP_X25, dissect_x25, proto_x25);
}