aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS5
-rw-r--r--Makefile.am8
-rw-r--r--doc/ethereal.pod.template1
-rw-r--r--nlpid.h4
-rw-r--r--packet-clnp.c1777
-rw-r--r--packet-clnp.h41
-rw-r--r--packet-esis.c438
-rw-r--r--packet-esis.h69
-rw-r--r--packet-isis-clv.c6
-rw-r--r--packet-isis-hello.c109
-rw-r--r--packet-isis-lsp.c34
-rw-r--r--packet-isis-snp.c43
-rw-r--r--packet-isis.c191
-rw-r--r--packet-isis.h64
-rw-r--r--packet-osi-options.c466
-rw-r--r--packet-osi-options.h39
-rw-r--r--packet-osi.c1864
-rw-r--r--packet-osi.h90
-rw-r--r--packet-x25.c3
19 files changed, 3253 insertions, 1999 deletions
diff --git a/AUTHORS b/AUTHORS
index 7ed2fedf73..c79c2793cf 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -294,6 +294,11 @@ Graham Bloice <graham.bloice@trihedral.com> {
add version/copyright/etc. information to Win32 executables
}
+Ralf Schneider <ralf.schneider@alcatel.se> {
+ Enhancements to OSI CLNP, CLTP, and ISIS support
+ OSI ESIS support
+}
+
Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to
give his permission to use his version of snprintf.c.
diff --git a/Makefile.am b/Makefile.am
index 813c2ec05e..245910c5a3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal
#
-# $Id: Makefile.am,v 1.184 2000/04/15 04:10:27 guy Exp $
+# $Id: Makefile.am,v 1.185 2000/04/15 22:11:07 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@zing.org>
@@ -58,11 +58,15 @@ DISSECTOR_SOURCES = \
packet-cgmp.h \
packet-clip.c \
packet-clip.h \
+ packet-clnp.c \
+ packet-clnp.h \
packet-data.c \
packet-ddtp.c \
packet-ddtp.h \
packet-dns.c \
packet-dns.h \
+ packet-esis.h \
+ packet-esis.c \
packet-eth.c \
packet-eth.h \
packet-ethertype.c \
@@ -140,6 +144,8 @@ DISSECTOR_SOURCES = \
packet-null.h \
packet-osi.c \
packet-osi.h \
+ packet-osi-options.c \
+ packet-osi-options.h \
packet-ospf.c \
packet-ospf.h \
packet-pim.c \
diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template
index 896800d88a..0d4615666d 100644
--- a/doc/ethereal.pod.template
+++ b/doc/ethereal.pod.template
@@ -840,6 +840,7 @@ B<http://ethereal.zing.org>.
Andreas Sikkema <andreas.sikkema@philips.com>
Mark Muhlestein <mmm@netapp.com>
Graham Bloice <graham.bloice@trihedral.com>
+ Ralf Schneider <ralf.schneider@alcatel.se>
Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to give his
permission to use his version of snprintf.c.
diff --git a/nlpid.h b/nlpid.h
index 2ddc5994ae..cec1e25df0 100644
--- a/nlpid.h
+++ b/nlpid.h
@@ -2,7 +2,7 @@
* Definitions of OSI NLPIDs (Network Layer Protocol IDs)
* Laurent Deniel <deniel@worldnet.fr>
*
- * $Id: nlpid.h,v 1.3 2000/01/30 05:50:02 guy Exp $
+ * $Id: nlpid.h,v 1.4 2000/04/15 22:11:07 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -36,7 +36,7 @@
#define NLPID_ISO8473_CLNP 0x81 /* X.233 */
#define NLPID_ISO9542_ESIS 0x82
#define NLPID_ISO10589_ISIS 0x83
-#define NLPID_ISO10747 0x85
+#define NLPID_ISO10747_IDRP 0x85
#define NLPID_ISO9542X25_ESIS 0x8a
#define NLPID_ISO10030 0x8c
#define NLPID_ISO11577 0x8d /* X.273 */
diff --git a/packet-clnp.c b/packet-clnp.c
new file mode 100644
index 0000000000..7a7478a428
--- /dev/null
+++ b/packet-clnp.c
@@ -0,0 +1,1777 @@
+/* packet-clnp.c
+ * Routines for ISO/OSI network and transport protocol packet disassembly
+ *
+ * $Id: packet-clnp.c,v 1.1 2000/04/15 22:11:07 guy Exp $
+ * Laurent Deniel <deniel@worldnet.fr>
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *
+ * To do:
+ *
+ * - add other network protocols (IS-IS)
+ * - add NSAP decoding & resolution
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+#include "packet.h"
+#include "packet-osi.h"
+#include "packet-osi-options.h"
+#include "packet-clnp.h"
+#include "packet-isis.h"
+#include "packet-esis.h"
+#include "packet-h1.h"
+#include "nlpid.h"
+
+/* protocols and fields */
+
+static int proto_clnp = -1;
+static int proto_cotp = -1;
+static gint ett_clnp = -1;
+static gint ett_cotp = -1;
+
+static int hf_clnp_id = -1;
+static int hf_clnp_length = -1;
+static int hf_clnp_version = -1;
+static int hf_clnp_ttl = -1;
+static int hf_clnp_type = -1;
+static int hf_clnp_pdu_length = -1;
+static int hf_clnp_checksum = -1;
+static int hf_clnp_dest_length = -1;
+static int hf_clnp_dest = -1;
+static int hf_clnp_src_length = -1;
+static int hf_clnp_src = -1;
+
+
+
+/*
+ * ISO 8473 OSI CLNP definition (see RFC994)
+ *
+ * _________________________________
+ * | Fixed Part |
+ * |_________________________________|
+ * | Address Part |
+ * |_________________________________|
+ * | Segmentation Part (optional) |
+ * |_________________________________|
+ * | Options Part (optional) |
+ * |_________________________________|
+ * | Data (optional) |
+ * |_________________________________|
+ */
+
+#define ISO8473_V1 0x01 /* CLNP version 1 */
+
+/* Fixed part */
+
+struct clnp_header {
+ u_char cnf_proto_id; /* network layer protocol identifier */
+ u_char cnf_hdr_len; /* length indicator (octets) */
+ u_char cnf_vers; /* version/protocol identifier extension */
+ u_char cnf_ttl; /* lifetime (500 milliseconds) */
+ u_char cnf_type; /* type code */
+ u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
+ u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
+ u_char cnf_cksum_msb; /* checksum high byte */
+ u_char cnf_cksum_lsb; /* checksum low byte */
+};
+
+#define CNF_TYPE 0x1f
+#define CNF_ERR_OK 0x20
+#define CNF_MORE_SEGS 0x40
+#define CNF_SEG_OK 0x80
+
+#define DT_NPDU 0x1C
+#define MD_NPDU 0x1D
+#define ER_NPDU 0x01
+#define ERQ_NPDU 0x1E
+#define ERP_NPDU 0x1F
+
+static const value_string npdu_type_vals[] = {
+ { DT_NPDU, "DT" },
+ { MD_NPDU, "MD" },
+ { ER_NPDU, "ER" },
+ { ERQ_NPDU, "ERQ" },
+ { ERP_NPDU, "ERP" },
+ { 0, NULL }
+};
+
+/* field position */
+
+#define P_ADDRESS_PART 9
+
+/* Segmentation part */
+
+struct clnp_segment {
+ u_short cng_id; /* data unit identifier */
+ u_short cng_off; /* segment offset */
+ u_short cng_tot_len; /* total length */
+};
+
+/* NSAP selector */
+
+#define NSEL_NET 0x00
+#define NSEL_NP 0x20
+#define NSEL_TP 0x21
+
+/*
+ * ISO8073 OSI COTP definition (see RFC905)
+ */
+
+/* don't use specific TPDU types to avoid alignment problems & copy overhead */
+
+/* TPDU definition */
+
+#define ED_TPDU 0x1
+#define EA_TPDU 0x2
+#define RJ_TPDU 0x5
+#define AK_TPDU 0x6
+#define ER_TPDU 0x7
+#define DR_TPDU 0x8
+#define DC_TPDU 0xC
+#define CC_TPDU 0xD
+#define CR_TPDU 0xE
+#define DT_TPDU 0xF
+
+/* field position */
+
+#define P_LI 0
+#define P_TPDU 1
+#define P_CDT 1
+#define P_DST_REF 2
+#define P_SRC_REF 4
+#define P_TPDU_NR_0_1 2
+#define P_TPDU_NR_234 4
+#define P_VAR_PART_NDT 5
+#define P_VAR_PART_EDT 8
+#define P_VAR_PART_NAK 5
+#define P_VAR_PART_CC 7
+#define P_VAR_PART_EAK 10
+#define P_VAR_PART_DC 6
+#define P_VAR_PART_DR 7
+#define P_CDT_IN_AK 8
+#define P_CDT_IN_RJ 8
+#define P_REJECT_ER 4
+#define P_REASON_IN_DR 6
+#define P_CLASS_OPTION 6
+
+/* TPDU length indicator */
+
+#define LI_NORMAL_DT_CLASS_01 2
+#define LI_NORMAL_DT_WITH_CHECKSUM 8
+#define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
+#define LI_EXTENDED_DT_WITH_CHECKSUM 11
+#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
+#define LI_NORMAL_EA_WITH_CHECKSUM 8
+#define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
+#define LI_EXTENDED_EA_WITH_CHECKSUM 11
+#define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
+#define LI_NORMAL_RJ 4
+#define LI_EXTENDED_RJ 9
+#define LI_MIN_DR 6
+#define LI_MAX_DC 9
+#define LI_MAX_AK 27
+#define LI_MAX_EA 11
+#define LI_MAX_ER 8
+#define LI_DC_WITH_CHECKSUM 9
+#define LI_DC_WITHOUT_CHECKSUM 5
+#define is_LI_NORMAL_AK(p) ( p & 0x01 )
+
+/* variant part */
+
+#define VP_ACK_TIME 0x85
+#define VP_RES_ERROR 0x86
+#define VP_PRIORITY 0x87
+#define VP_TRANSIT_DEL 0x88
+#define VP_THROUGHPUT 0x89
+#define VP_SEQ_NR 0x8A /* in AK */
+#define VP_REASSIGNMENT 0x8B
+#define VP_FLOW_CNTL 0x8C /* in AK */
+#define VP_TPDU_SIZE 0xC0
+#define VP_SRC_TSAP 0xC1 /* in CR/CC */
+#define VP_DST_TSAP 0xC2
+#define VP_CHECKSUM 0xC3
+#define VP_VERSION_NR 0xC4
+#define VP_PROTECTION 0xC5
+#define VP_OPT_SEL 0xC6
+#define VP_PROTO_CLASS 0xC7
+
+/* misc */
+
+#define EXTRACT_SHORT(p) pntohs(p)
+#define EXTRACT_LONG(p) pntohl(p)
+
+/* global variables */
+
+static u_char li, tpdu, cdt; /* common fields */
+static u_short dst_ref;
+
+/* function definitions */
+
+static int osi_decode_DR(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ u_short src_ref;
+ u_char reason;
+ char *str;
+
+ if (li < LI_MIN_DR)
+ return -1;
+
+ src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
+ reason = pd[offset + P_REASON_IN_DR];
+
+ switch(reason) {
+ case (128+0): str = "Normal Disconnect"; break;
+ case (128+1): str = "Remote transport entity congestion"; break;
+ case (128+2): str = "Connection negotiation failed"; break;
+ case (128+3): str = "Duplicate source reference"; break;
+ case (128+4): str = "Mismatched references"; break;
+ case (128+5): str = "Protocol error"; break;
+ case (128+7): str = "Reference overflow"; break;
+ case (128+8): str = "Connection requestion refused"; break;
+ case (128+10):str = "Header or parameter length invalid"; break;
+ case (0): str = "Reason not specified"; break;
+ case (1): str = "Congestion at TSAP"; break;
+ case (2): str = "Session entity not attached to TSAP"; break;
+ case (3): str = "Address unknown"; break;
+ default: return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
+ src_ref, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (DR)", tpdu);
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ proto_tree_add_text(cotp_tree, offset + 4, 2,
+ "Source reference: 0x%04x", src_ref);
+ proto_tree_add_text(cotp_tree, offset + 6, 1,
+ "Cause: %s", str);
+ }
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return pi.captured_len; /* we dissected all of the containing PDU */
+
+} /* osi_decode_DR */
+
+/* Returns TRUE if we called a sub-dissector, FALSE if not. */
+static gboolean osi_decode_DT(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree,
+ gboolean uses_inactive_subset)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ u_int tpdu_nr ;
+ u_short checksum = 0;
+ u_char code = 0, length = 0;
+ u_int fragment = 0;
+
+ switch (li) {
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ fragment = 1;
+ code = pd[offset + P_VAR_PART_NDT];
+ if (code == VP_CHECKSUM)
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
+ else
+ return -1;
+ break;
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ fragment = 1;
+ break;
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ fragment = 1;
+ code = pd[offset + P_VAR_PART_EDT];
+ if (code == VP_CHECKSUM)
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
+ else
+ return -1;
+ break;
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ fragment = 1;
+ break;
+ case LI_NORMAL_DT_CLASS_01 :
+ tpdu_nr = pd[offset + P_TPDU_NR_0_1];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ fragment = 1;
+ break;
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s",
+ tpdu_nr,
+ dst_ref,
+ (fragment)? "(fragment)" : "");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (DT)", tpdu);
+
+ if (li != LI_NORMAL_DT_CLASS_01)
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+
+ switch (li) {
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "TPDU number: 0x%02x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NDT, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NDT + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NDT + 2, length,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "TPDU number: 0x%02x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ break;
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 4,
+ "TPDU number: 0x%08x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EDT, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EDT + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EDT + 2, length,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 4,
+ "TPDU number: 0x%08x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ break;
+ case LI_NORMAL_DT_CLASS_01 :
+ proto_tree_add_text(cotp_tree, offset + 2, 1,
+ "TPDU number: 0x%02x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ break;
+ }
+ } /* tree */
+
+ offset += li + 1;
+ if (uses_inactive_subset){
+ dissect_h1(pd, offset, fd, tree);
+ return TRUE;
+ }
+ else {
+ dissect_data(pd, offset, fd, tree);
+ return FALSE;
+ }
+} /* osi_decode_DT */
+
+static int osi_decode_ED(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ u_int tpdu_nr ;
+ u_short checksum = 0;
+ u_char code = 0, length = 0;
+
+ /* ED TPDUs are never fragmented */
+
+ switch (li) {
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ return -1;
+ code = pd[offset + P_VAR_PART_NDT];
+ length = pd[offset + P_VAR_PART_NDT + 1];
+ if (code == VP_CHECKSUM)
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
+ else
+ return -1;
+ break;
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ return -1;
+ break;
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ return -1;
+ code = pd[offset + P_VAR_PART_EDT];
+ length = pd[offset + P_VAR_PART_EDT + 1];
+ if (code == VP_CHECKSUM)
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
+ else
+ return -1;
+ break;
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ return -1;
+ break;
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ } /* li */
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (ED)", tpdu);
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+
+ switch (li) {
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "TPDU number: 0x%02x", tpdu_nr);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NDT, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NDT + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NDT + 2, length,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "TPDU number: 0x%02x", tpdu_nr);
+ break;
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 4,
+ "TPDU number: 0x%02x", tpdu_nr);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EDT, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EDT + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EDT + 2, length,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 4,
+ "TPDU number: 0x%02x", tpdu_nr);
+ break;
+ }
+ } /* tree */
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return pi.captured_len; /* we dissected all of the containing PDU */
+
+} /* osi_decode_ED */
+
+static int osi_decode_RJ(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ u_int tpdu_nr ;
+ u_short credit = 0;
+
+ switch(li) {
+ case LI_NORMAL_RJ :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ break;
+ case LI_EXTENDED_RJ :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
+ break;
+ default :
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (RJ)", tpdu);
+ if (li == LI_NORMAL_RJ)
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "Credit: %u", cdt);
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ if (li == LI_NORMAL_RJ)
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ else {
+ proto_tree_add_text(cotp_tree, offset + 4, 4,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ proto_tree_add_text(cotp_tree, offset + 8, 2,
+ "Credit: 0x%02x", credit);
+ }
+ }
+
+ offset += li + 1;
+
+ return offset;
+
+} /* osi_decode_RJ */
+
+#define MAX_TSAP_LEN 32
+
+static gchar *print_tsap(const u_char *tsap, int length)
+{
+
+ static gchar str[3][MAX_TSAP_LEN * 2 + 1];
+ static gchar *cur;
+ gchar tmp[3];
+ gboolean allprintable;
+ int i;
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+
+ cur[0] = '\0';
+ if (length <= 0 || length > MAX_TSAP_LEN)
+ sprintf(cur, "<unsupported TSAP length>");
+ else {
+ allprintable=TRUE;
+ for (i=0;i<length;i++) {
+ if (!isprint(tsap[i])) { /* if any byte is not printable */
+ allprintable=FALSE; /* switch to hexdump */
+ break;
+ }
+ }
+ if (!allprintable){
+ strcat(cur,"0x");
+ }
+ while (length != 0) {
+ if (allprintable)
+ sprintf(tmp, "%c", *tsap ++);
+ else
+ sprintf(tmp, "%02x", *tsap ++);
+ strcat(cur, tmp);
+ length --;
+ }
+ }
+ return cur;
+
+} /* print_tsap */
+
+static int osi_decode_CC(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree)
+{
+
+ /* CC & CR decoding in the same function */
+
+ proto_tree *cotp_tree = NULL;
+ proto_item *ti;
+ u_short src_ref, checksum;
+ u_char class_option, code, length;
+ u_int i = 0;
+
+ src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
+ class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
+ if (class_option > 4)
+ return -1;
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
+ (tpdu == CR_TPDU) ? "CR" : "CC",
+ src_ref,
+ dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (%s)", tpdu,
+ (tpdu == CR_TPDU) ? "CR" : "CC");
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ proto_tree_add_text(cotp_tree, offset + 4, 2,
+ "Source reference: 0x%04x", src_ref);
+ proto_tree_add_text(cotp_tree, offset + 6, 1,
+ "Class option: 0x%02x", class_option);
+ }
+
+ if (tree)
+ while(li > P_VAR_PART_CC + i - 1) {
+
+ u_char c1;
+ u_short s, s1,s2,s3,s4;
+ u_int t1,t2,t3,t4;
+
+ switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
+ case VP_CHECKSUM :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Checksum: 0x%04x", checksum);
+ i += length + 2;
+ break;
+ case VP_SRC_TSAP :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (src-tsap)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Calling TSAP: %s",
+ print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
+ length));
+ i += length + 2;
+ break;
+ case VP_DST_TSAP :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (dst-tsap)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Called TSAP: %s",
+ print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
+ length));
+ i += length + 2;
+ break;
+ case VP_TPDU_SIZE :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (tpdu-size)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "TPDU size: %u", 2 << c1);
+ i += length + 2;
+ break;
+ case VP_OPT_SEL :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (options)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ if (class_option == 1) {
+ if (c1 & 0x8)
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use of network expedited data");
+ else
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Non use of network expedited data");
+ if (c1 & 0x4)
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use of Receipt confirmation");
+ else
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use of explicit AK variant");
+ } else if (class_option == 4) {
+ if (c1 & 0x2)
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use 16 bit checksum ");
+ else
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Non-use 16 bit checksum in class 4");
+ }
+ if (c1 & 0x1)
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use of transport expedited data transfer\n");
+ else
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Non-use of transport expedited data transfer");
+ i += length + 2;
+ break;
+ case VP_ACK_TIME :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (ack time)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Ack time (ms): %u", s);
+ i += length + 2;
+ break;
+ case VP_THROUGHPUT :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
+ t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
+ t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
+ t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (throughput)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 4,
+ "Target value / calling-called: %u o/s", t1);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 6, 4,
+ "Minimum / calling-called: %u o/s", t2);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 10, 4,
+ "Target value / called-calling: %u o/s", t3);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 14, 4,
+ "Minimum / called-calling: %u o/s", t4);
+ i += length + 2;
+ break;
+ case VP_TRANSIT_DEL :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
+ s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
+ s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
+ s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (transit delay)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 2,
+ "Target value / calling-called: %u ms", s1);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 4, 2,
+ "Minimum / calling-called: %u ms", s2);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 6, 2,
+ "Target value / called-calling: %u ms", s3);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 8, 2,
+ "Minimum / called-calling: %u ms", s4);
+ i += length + 2;
+ break;
+ case VP_PRIORITY :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (priority)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Priority: %u", s);
+ i += length + 2;
+ break;
+
+ case VP_VERSION_NR :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ c1 = pd[offset + P_VAR_PART_CC + i + 2];
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (version)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Version: %u", c1);
+ i += length + 2;
+ break;
+
+ case VP_REASSIGNMENT: /* todo */
+ case VP_RES_ERROR :
+ case VP_PROTECTION :
+ case VP_PROTO_CLASS :
+ default : /* no decoding */
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 0, 1,
+ "Parameter code: 0x%02x", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Parameter value: <not shown>");
+ i += length + 2;
+ break;
+ }
+ } /* while */
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return pi.captured_len; /* we dissected all of the containing PDU */
+
+} /* osi_decode_CC */
+
+static int osi_decode_DC(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ u_short src_ref, checksum = 0;
+ u_char length = 0, code = 0;
+
+ if (li > LI_MAX_DC)
+ return -1;
+
+ src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
+
+ switch(li) {
+ case LI_DC_WITHOUT_CHECKSUM :
+ break;
+ case LI_DC_WITH_CHECKSUM :
+ if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
+ return -1;
+ length = pd[offset + P_VAR_PART_DC + 1];
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
+ break;
+ default :
+ return -1;
+ /*NOTREACHED*/
+ break;
+ } /* li */
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
+ src_ref,
+ dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (DC)", tpdu);
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ proto_tree_add_text(cotp_tree, offset + 4, 2,
+ "Source reference: 0x%04x", src_ref);
+ if (code) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_DC + 0, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_DC + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_DC + 2, 2,
+ "Checksum: 0x%04x", checksum);
+ }
+ }
+
+ offset += li + 1;
+
+ return offset;
+
+} /* osi_decode_DC */
+
+static int osi_decode_AK(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree)
+{
+ proto_tree *cotp_tree = NULL;
+ proto_item *ti;
+ u_int tpdu_nr,i =0, r_lower_window_edge ;
+ u_short cdt_in_ak;
+ u_short checksum, seq_nr, r_seq_nr, r_cdt;
+ u_char code, length;
+
+ if (li > LI_MAX_AK)
+ return -1;
+
+ if (!is_LI_NORMAL_AK(li)) {
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (AK)", tpdu);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "Credit: %u", cdt);
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ }
+
+ while(li > P_VAR_PART_NAK + i - 1) {
+ switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
+ case VP_CHECKSUM :
+ length = pd[offset + P_VAR_PART_NAK + i + 1];
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
+ if (tree) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 0, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 2, 2,
+ "Checksum: 0x%04x", checksum);
+ }
+ i += length + 2;
+ break;
+ case VP_FLOW_CNTL :
+ length = pd[offset + P_VAR_PART_NAK + i + 1];
+ r_lower_window_edge =
+ EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
+ r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
+ r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
+ if (tree) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 0, 1,
+ "Parameter code: 0x%02x (flow control)",
+ code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 2, 4,
+ "Lower window edge: 0x%08x",
+ r_lower_window_edge);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 6, 2,
+ "Sequence number: 0x%04x",
+ r_seq_nr);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 8, 2,
+ "Credit: 0x%04x",
+ r_cdt);
+ }
+ i += length + 2;
+ break;
+ case VP_SEQ_NR :
+ length = pd[offset + P_VAR_PART_NAK + i + 1];
+ seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
+ if (tree) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 0, 1,
+ "Parameter code: 0x%02x (seq number)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 2, 2,
+ "Sequence number: 0x%04x", seq_nr);
+ }
+ i += length + 2;
+ break;
+ default :
+ length = pd[offset + P_VAR_PART_NAK + i + 1];
+ if (tree) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 0, 1,
+ "Parameter code: 0x%02x (unknown)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 2, length,
+ "Parameter value: <not shown>");
+ }
+ i += length + 2;
+ break;
+ } /* code */
+ }
+ } else { /* extended format */
+
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (AK)", tpdu);
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ proto_tree_add_text(cotp_tree, offset + 4, 4,
+ "Your TPDU number: 0x%08x", tpdu_nr);
+ proto_tree_add_text(cotp_tree, offset + 8, 2,
+ "Credit: 0x%04x", cdt_in_ak);
+ }
+
+ while(li > P_VAR_PART_EAK + i - 1) {
+ switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
+ case VP_CHECKSUM :
+ length = pd[offset + P_VAR_PART_EAK + i + 1];
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
+ if (tree) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 0, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 2, 2,
+ "Checksum: 0x%04x", checksum);
+ }
+ i += length + 2;
+ break;
+ case VP_FLOW_CNTL :
+ length = pd[offset + P_VAR_PART_EAK + i + 1];
+ r_lower_window_edge =
+ EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
+ r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
+ r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
+ if (tree) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 0, 1,
+ "Parameter code: 0x%02x (flow control)",
+ code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 2, 4,
+ "Lower window edge: 0x%08x",
+ r_lower_window_edge);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 6, 2,
+ "Sequence number: 0x%04x",
+ r_seq_nr);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 8, 2,
+ "Credit: 0x%04x",
+ r_cdt);
+ }
+ i += length + 2;
+ break;
+ case VP_SEQ_NR :
+ length = pd[offset + P_VAR_PART_EAK + i + 1];
+ seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
+ if (tree) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 0, 1,
+ "Parameter code: 0x%02x (seq number)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 2, 2,
+ "Sequence number: 0x%04x", seq_nr);
+ }
+ i += length + 2;
+ break;
+ default :
+ length = pd[offset + P_VAR_PART_EAK + i + 1];
+ if (tree) {
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 0, 1,
+ "Parameter code: 0x%02x (unknown)", code);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 1, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 2, length,
+ "Parameter value: <not shown>");
+ }
+ i += length + 2;
+ break;
+ } /* code */
+ }
+
+ } /* is_LI_NORMAL_AK */
+
+ offset += li + 1;
+
+ return offset;
+
+} /* osi_decode_AK */
+
+static int osi_decode_EA(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ u_int tpdu_nr ;
+ u_short checksum = 0;
+ u_char code = 0;
+ u_char length = 0;
+
+ if (li > LI_MAX_EA)
+ return -1;
+
+ switch (li) {
+ case LI_NORMAL_EA_WITH_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ code = pd[offset + P_VAR_PART_NDT];
+ length = pd[offset + P_VAR_PART_NDT + 1];
+ if (code != VP_CHECKSUM || length != 1)
+ return -1;
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
+ break;
+ case LI_NORMAL_EA_WITHOUT_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ break;
+ case LI_EXTENDED_EA_WITH_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ code = pd[offset + P_VAR_PART_EDT];
+ length = pd[offset + P_VAR_PART_EDT + 1];
+ if (code != VP_CHECKSUM || length != 1)
+ return -1;
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
+ break;
+ case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ break;
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ } /* li */
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO,
+ "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (EA)", tpdu);
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+
+ switch (li) {
+ case LI_NORMAL_EA_WITH_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ proto_tree_add_text(cotp_tree, offset + 5, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree, offset + 6, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree, offset + 7, 2,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_NORMAL_EA_WITHOUT_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ break;
+ case LI_EXTENDED_EA_WITH_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 4,
+ "Your TPDU number: 0x%08x", tpdu_nr);
+ proto_tree_add_text(cotp_tree, offset + 8, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ proto_tree_add_text(cotp_tree, offset + 9, 1,
+ "Parameter length: %u", length);
+ proto_tree_add_text(cotp_tree, offset + 10, 2,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
+ proto_tree_add_text(cotp_tree, offset + 4, 4,
+ "Your TPDU number: 0x%08x", tpdu_nr);
+ break;
+ default :
+ break;
+ } /* li */
+ } /* tree */
+
+ offset += li + 1;
+
+ return offset;
+
+} /* osi_decode_EA */
+
+static int osi_decode_ER(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ u_char *str;
+
+ if (li > LI_MAX_ER)
+ return -1;
+
+ switch(pd[offset + P_REJECT_ER]) {
+ case 0 :
+ str = "Reason not specified";
+ break;
+ case 1 :
+ str = "Invalid parameter code";
+ break;
+ case 2 :
+ str = "Invalid TPDU type";
+ break;
+ case 3 :
+ str = "Invalid parameter value";
+ break;
+ default:
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_text(cotp_tree, offset + 1, 1,
+ "TPDU code: 0x%x (ER)", tpdu);
+ proto_tree_add_text(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ proto_tree_add_text(cotp_tree, offset + 4, 1,
+ "Reject cause: %s", str);
+ }
+
+ offset += li + 1;
+
+ return offset;
+
+} /* osi_decode_ER */
+
+/* Returns TRUE if we found at least one valid COTP PDU, FALSE
+ otherwise. */
+static gboolean dissect_cotp_internal(const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree,
+ gboolean uses_inactive_subset)
+{
+ gboolean first_tpdu = TRUE;
+ int new_offset;
+ gboolean found_cotp = FALSE;
+ gboolean subdissector_found = FALSE;
+
+ /* Initialize the COL_INFO field; each of the TPDUs will have its
+ information appended. */
+ if (check_col(fd, COL_INFO))
+ col_add_str(fd, COL_INFO, "");
+
+ while (IS_DATA_IN_FRAME(offset)) {
+ if (!first_tpdu) {
+ if (check_col(fd, COL_INFO))
+ col_append_str(fd, COL_INFO, ", ");
+ }
+ if ((li = pd[offset + P_LI]) == 0) {
+ if (check_col(fd, COL_INFO))
+ col_append_str(fd, COL_INFO, "Length indicator is zero");
+ if (!first_tpdu)
+ dissect_data(pd, offset, fd, tree);
+ return found_cotp;
+ }
+ if (!BYTES_ARE_IN_FRAME(offset, P_LI + li + 1)) {
+ if (check_col(fd, COL_INFO))
+ col_append_str(fd, COL_INFO, "Captured data in frame doesn't include entire frame");
+ if (!first_tpdu)
+ dissect_data(pd, offset, fd, tree);
+ return found_cotp;
+ }
+
+ tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
+ cdt = pd[offset + P_CDT] & 0x0F;
+ dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
+
+ switch (tpdu) {
+ case CC_TPDU :
+ case CR_TPDU :
+ new_offset = osi_decode_CC(pd, offset, fd, tree);
+ break;
+ case DR_TPDU :
+ new_offset = osi_decode_DR(pd, offset, fd, tree);
+ break;
+ case DT_TPDU :
+ if (osi_decode_DT(pd, offset, fd, tree, uses_inactive_subset))
+ subdissector_found = TRUE;
+ new_offset = pi.captured_len; /* DT PDUs run to the end of the packet */
+ break;
+ case ED_TPDU :
+ new_offset = osi_decode_ED(pd, offset, fd, tree);
+ break;
+ case RJ_TPDU :
+ new_offset = osi_decode_RJ(pd, offset, fd, tree);
+ break;
+ case DC_TPDU :
+ new_offset = osi_decode_DC(pd, offset, fd, tree);
+ break;
+ case AK_TPDU :
+ new_offset = osi_decode_AK(pd, offset, fd, tree);
+ break;
+ case EA_TPDU :
+ new_offset = osi_decode_EA(pd, offset, fd, tree);
+ break;
+ case ER_TPDU :
+ new_offset = osi_decode_ER(pd, offset, fd, tree);
+ break;
+ default :
+ if (first_tpdu && check_col(fd, COL_INFO))
+ col_append_fstr(fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
+ new_offset = -1; /* bad PDU type */
+ break;
+ }
+
+ if (new_offset == -1) { /* incorrect TPDU */
+ if (!first_tpdu)
+ dissect_data(pd, offset, fd, tree);
+ break;
+ }
+
+ if (first_tpdu) {
+ /* Well, we found at least one valid COTP PDU, so I guess this
+ is COTP. */
+ if (!subdissector_found && check_col(fd, COL_PROTOCOL))
+ col_add_str(fd, COL_PROTOCOL, "COTP");
+ found_cotp = TRUE;
+ }
+
+ offset = new_offset;
+ first_tpdu = FALSE;
+ }
+ return found_cotp;
+} /* dissect_cotp_internal */
+
+void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
+ proto_tree *tree)
+{
+ if (!dissect_cotp_internal(pd, offset, fd, tree, FALSE))
+ dissect_data(pd, offset, fd, tree);
+}
+
+
+/*
+ * CLNP part / main entry point
+*/
+
+void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
+ proto_tree *tree)
+{
+
+ struct clnp_header clnp;
+ proto_tree *clnp_tree = NULL;
+ proto_item *ti;
+ u_char src_len, dst_len, nsel, opt_len = 0;
+ u_int first_offset = offset;
+ char flag_string[6+1];
+ char *pdu_type_string;
+ guint16 segment_length;
+ guint16 segment_offset = 0;
+ guint len;
+
+ if (check_col(fd, COL_PROTOCOL))
+ col_add_str(fd, COL_PROTOCOL, "CLNP");
+
+ /* avoid alignment problem */
+ memcpy(&clnp, &pd[offset], sizeof(clnp));
+
+ if (clnp.cnf_proto_id == NLPID_NULL) {
+ if (check_col(fd, COL_INFO))
+ col_add_str(fd, COL_INFO, "Inactive subset");
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_clnp, offset, 1, NULL);
+ clnp_tree = proto_item_add_subtree(ti, ett_clnp);
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_id, offset, 1,
+ clnp.cnf_proto_id,
+ "Inactive subset");
+ }
+ dissect_cotp_internal(pd, offset+1, fd, tree, TRUE);
+ return;
+ }
+
+ if (!BYTES_ARE_IN_FRAME(offset, sizeof(clnp))) {
+ dissect_data(pd, offset, fd, tree);
+ return;
+ }
+
+ /* return if version not known */
+ if (clnp.cnf_vers != ISO8473_V1) {
+ dissect_data(pd, offset, fd, tree);
+ return;
+ }
+
+ /* fixed part decoding */
+ opt_len = clnp.cnf_hdr_len;
+
+ segment_length = EXTRACT_SHORT(&clnp.cnf_seglen_msb);
+ flag_string[0] = '\0';
+ if (clnp.cnf_type & CNF_SEG_OK)
+ strcat(flag_string, "S ");
+ if (clnp.cnf_type & CNF_MORE_SEGS)
+ strcat(flag_string, "M ");
+ if (clnp.cnf_type & CNF_ERR_OK)
+ strcat(flag_string, "E ");
+ pdu_type_string = val_to_str(clnp.cnf_type & CNF_TYPE, npdu_type_vals,
+ "Unknown (0x%02x)");
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL);
+ clnp_tree = proto_item_add_subtree(ti, ett_clnp);
+ proto_tree_add_item(clnp_tree, hf_clnp_id, offset, 1,
+ clnp.cnf_proto_id);
+ proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1,
+ clnp.cnf_hdr_len);
+ proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1,
+ clnp.cnf_vers);
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, offset + 3, 1,
+ clnp.cnf_ttl,
+ "Holding Time : %u (%u secs)",
+ clnp.cnf_ttl, clnp.cnf_ttl / 2);
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_type, offset + 4, 1,
+ clnp.cnf_type,
+ "PDU Type : 0x%02x (%s%s)",
+ clnp.cnf_type,
+ flag_string,
+ pdu_type_string);
+ proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2,
+ segment_length);
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, offset + 7, 2,
+ EXTRACT_SHORT(&clnp.cnf_cksum_msb),
+ "Checksum : 0x%04x",
+ EXTRACT_SHORT(&clnp.cnf_cksum_msb));
+ opt_len -= 9; /* Fixed part of Hesder */
+ } /* tree */
+
+ /* stop here if header is not complete */
+
+ if (!BYTES_ARE_IN_FRAME(offset, clnp.cnf_hdr_len)) {
+ if (check_col(fd, COL_INFO))
+ col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
+ dissect_data(pd, offset, fd, tree);
+ return;
+ }
+
+ /* address part */
+
+ offset += P_ADDRESS_PART;
+ dst_len = pd[offset];
+ nsel = pd[offset + dst_len];
+ src_len = pd[offset + dst_len + 1];
+
+ if (tree) {
+ proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1,
+ dst_len);
+ proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len,
+ &pd[offset + 1],
+ " DA : %s",
+ print_nsap_net(&pd[offset + 1], dst_len));
+ proto_tree_add_item(clnp_tree, hf_clnp_src_length,
+ offset + 1 + dst_len, 1, src_len);
+ proto_tree_add_bytes_format(clnp_tree, hf_clnp_src,
+ offset + dst_len + 2, src_len,
+ &pd[offset + dst_len + 2],
+ " SA : %s",
+ print_nsap_net(&pd[offset + dst_len + 2], src_len));
+
+ opt_len -= dst_len + src_len +2;
+ }
+
+ if (check_col(fd, COL_RES_NET_SRC))
+ col_add_fstr(fd, COL_RES_NET_SRC, "%s",
+ print_nsap_net(&pd[offset + dst_len + 2], src_len));
+ if (check_col(fd, COL_RES_NET_DST))
+ col_add_fstr(fd, COL_RES_NET_DST, "%s",
+ print_nsap_net(&pd[offset + 1], dst_len));
+
+ /* Segmentation Part */
+
+ offset += dst_len + src_len + 2;
+
+ if (clnp.cnf_type & CNF_SEG_OK) {
+ struct clnp_segment seg; /* XXX - not used */
+ memcpy(&seg, &pd[offset], sizeof(seg)); /* XXX - not used */
+
+ segment_offset = EXTRACT_SHORT(&pd[offset + 2]);
+ if (tree) {
+ proto_tree_add_text(clnp_tree, offset, 2,
+ "Data unit identifier: %06u",
+ EXTRACT_SHORT(&pd[offset]));
+ proto_tree_add_text(clnp_tree, offset + 2 , 2,
+ "Segment offset : %6u",
+ segment_offset);
+ proto_tree_add_text(clnp_tree, offset + 4 , 2,
+ "Total length : %6u",
+ EXTRACT_SHORT(&pd[offset + 4]));
+ }
+
+ offset += 6;
+ opt_len -= 6;
+ }
+
+ if (tree) {
+ /* To do : decode options */
+/*
+ proto_tree_add_text(clnp_tree, offset,
+ clnp.cnf_hdr_len + first_offset - offset,
+ "Options/Data: <not shown>");
+*/
+/* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/
+
+ dissect_osi_options( 0xff,
+ opt_len,
+ pd, offset, fd, clnp_tree );
+ }
+
+ /* Length of CLNP datagram plus headers above it. */
+ len = segment_length + first_offset;
+
+ /* Set the payload and captured-payload lengths to the minima of (the
+ datagram length plus the length of the headers above it) and the
+ frame lengths. */
+ if (pi.len > len)
+ pi.len = len;
+ if (pi.captured_len > len)
+ pi.captured_len = len;
+
+ offset = first_offset + clnp.cnf_hdr_len;
+
+ /* For now, dissect the payload of segments other than the initial
+ segment as data, rather than handing them off to the transport
+ protocol, just as we do with fragments other than the first
+ fragment in a fragmented IP datagram; in the future, we will
+ probably reassemble fragments for IP, and may reassemble segments
+ for CLNP. */
+ if ((clnp.cnf_type & CNF_SEG_OK) && segment_offset != 0) {
+ if (check_col(fd, COL_INFO))
+ col_add_fstr(fd, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
+ pdu_type_string, flag_string, segment_offset);
+ dissect_data(pd, offset, fd, tree);
+ return;
+ }
+
+ if (IS_DATA_IN_FRAME(offset)) {
+ switch (clnp.cnf_type & CNF_TYPE) {
+
+ case DT_NPDU:
+ case MD_NPDU:
+ /* Continue with COTP if any data.
+ XXX - if this isn't the first Derived PDU of a segmented Initial
+ PDU, skip that? */
+
+ if (nsel == NSEL_TP) { /* just guessing here - valid for DECNet-OSI */
+ if (dissect_cotp_internal(pd, offset, fd, tree, FALSE))
+ return; /* yes, it appears to be COTP */
+ }
+ break;
+
+ case ER_NPDU:
+ /* The payload is the header and "none, some, or all of the data
+ part of the discarded PDU", i.e. it's like an ICMP error;
+ just as we don't yet trust ourselves to be able to dissect
+ the payload of an ICMP error packet, we don't yet trust
+ ourselves to dissect the payload of a CLNP ER packet. */
+ break;
+
+ case ERQ_NPDU:
+ case ERP_NPDU:
+ /* XXX - dissect this */
+ break;
+ }
+ }
+ if (check_col(fd, COL_INFO))
+ col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
+ dissect_data(pd, offset, fd, tree);
+
+} /* dissect_clnp */
+
+
+void proto_register_clnp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_clnp_id,
+ { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
+ VALS(nlpid_vals), 0x0, "" }},
+
+ { &hf_clnp_length,
+ { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_clnp_version,
+ { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_clnp_ttl,
+ { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_clnp_type,
+ { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_clnp_pdu_length,
+ { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_clnp_checksum,
+ { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_clnp_dest_length,
+ { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_clnp_dest,
+ { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }},
+
+ { &hf_clnp_src_length,
+ { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_clnp_src,
+ { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }},
+ };
+ static gint *ett[] = {
+ &ett_clnp,
+ };
+
+ proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "clnp");
+ proto_register_field_array(proto_clnp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void proto_register_cotp(void)
+{
+ /* static hf_register_info hf[] = {
+ { &variable,
+ { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
+ };*/
+ static gint *ett[] = {
+ &ett_cotp,
+ };
+
+ proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "cotp");
+ /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/packet-clnp.h b/packet-clnp.h
new file mode 100644
index 0000000000..9d76fd0ff3
--- /dev/null
+++ b/packet-clnp.h
@@ -0,0 +1,41 @@
+/* packet-clnp.h
+ * Defines and such for CLNP (and COTP) protocol decode.
+ *
+ * $Id: packet-clnp.h,v 1.1 2000/04/15 22:11:08 guy Exp $
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *
+ */
+
+#ifndef _PACKET_CLNP_H
+#define _PACKET_CLNP_H
+
+/*
+ * published API functions
+ */
+
+extern
+void dissect_clnp( const u_char *, int, frame_data *, proto_tree * );
+extern
+void dissect_cotp(const u_char *, int, frame_data *, proto_tree *);
+
+#endif /* _PACKET_CLNP_H */
diff --git a/packet-esis.c b/packet-esis.c
new file mode 100644
index 0000000000..8186990714
--- /dev/null
+++ b/packet-esis.c
@@ -0,0 +1,438 @@
+/* packet-esis.c
+ * Routines for ISO/OSI End System to Intermediate System
+ * Routeing Exchange Protocol ISO 9542.
+ *
+ * $Id: packet-esis.c,v 1.1 2000/04/15 22:11:08 guy Exp $
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include "packet.h"
+#include "nlpid.h"
+#include "packet-osi.h"
+#include "packet-osi-options.h"
+#include "packet-esis.h"
+
+
+/* esis base header */
+static int proto_esis = -1;
+
+static int hf_esis_nlpi = -1;
+static int hf_esis_length = -1;
+static int hf_esis_version = -1;
+static int hf_esis_reserved = -1;
+static int hf_esis_type = -1;
+static int hf_esis_holdtime = -1;
+static int hf_esis_checksum = -1;
+
+static gint ett_esis = -1;
+static gint ett_esis_area_addr = -1;
+
+static const value_string esis_vals[] = {
+ { ESIS_ESH_PDU, "ES HELLO"},
+ { ESIS_ISH_PDU, "IS HELLO"},
+ { ESIS_RD_PDU, "RD REQUEST"},
+ { 0, NULL} };
+
+/* internal prototypes */
+
+void esis_dissect_esh_pdu( u_char len, const u_char *pd, int offset,
+ frame_data *fd, proto_tree *treepd);
+void esis_dissect_ish_pdu( u_char len, const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree);
+void esis_dissect_redirect_pdu( u_char len, const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree);
+
+/* ################## Descriptions ###########################################*/
+/* Parameters for the ESH PDU
+ * Source Address Parameter:
+ *
+ * Octet: Length: Parameter Type:
+ * 10 1 Number of Source Adresses ( NSAPs served by this Network
+ * 11 1 Source Address Length Indicator ( SAL ) # Entity )
+ * 12-m-1 variable Source Address ( NSAP )
+ * m Options, dissected in osi.c
+ *
+ *
+ * Parameter for the ISH PDU:
+ * Network Entity Title Parameter:
+ *
+ * Octet: Length: Parameter Type:
+ * 10 1 Network Entity Title Length Indicator ( NETL )
+ * 11-m-1 variable Network Entity Title ( NET )
+ * m Options, dissected in osi.c
+ *
+ *
+ * Parameter for the RD PDU:
+ * When re-directed to an IS:
+ *
+ * Octet: Length: Parameter Type:
+ * 10 1 Destination Address Length Indicator ( DAL )
+ * 11>m-1 variable Destination Address ( DA )
+ * m 1 Subnetwork Address Length Indicator ( BSNPAL )
+ * m+1>n-1 variable Subnetwork Address ( BSNPA )
+ * n 1 Network Entity Title Length Indicator ( NETL )
+ * n+1>p-1 variable Network Entity Title ( NET )
+ * p Options, dissected in osi.c
+ *
+ *
+ * Parameter for the RD PDU:
+ * When re-directed to an ES:
+ *
+ * Octet: Length: Parameter Type:
+ * 10 1 Destination Address Length Indicator ( DAL )
+ * 11>m-1 variable Destination Address ( DA )
+ * m 1 Subnetwork Address Length Indicator ( BSNPAL )
+ * m+1>n-1 variable Subnetwork Address ( BSNPA )
+ * n 1 Network Entity Title Length Indicator ( NETL ) == 0
+ * n+1 Options, dissected in osi.c
+ *
+ */
+
+/* ############################ Tool Functions ############################## */
+
+
+/* ############################## Dissection Functions ###################### */
+/*
+ * Name: dissect_esis_unknown()
+ *
+ * Description:
+ * There was some error in the protocol and we are in unknown space
+ * here. Add a tree item to cover the error and go on. Note
+ * that we make sure we don't go off the end of the bleedin packet here!
+ *
+ * This is just a copy of isis.c and isis.h, so I keep the stuff also
+ * and adapt the names to cover possible protocol errors! Ive really no
+ * idea wether I need this or not.
+ *
+ * Input
+ * int offset : Current offset into packet data.
+ * int len : length of to dump.
+ * proto_tree * : tree of display data. May be NULL.
+ * frame_data * fd : frame data
+ * char * : format text
+ *
+ * Output:
+ * void (may modify proto tree)
+ */
+void
+esis_dissect_unknown(int offset,guint length,proto_tree *tree,frame_data *fd,
+ char *fmat, ...){
+ va_list ap;
+
+ if ( !IS_DATA_IN_FRAME(offset) ) {
+ /*
+ * big oops They were off the end of the packet already.
+ * Just ignore this one.
+ */
+ return;
+ }
+ if ( !BYTES_ARE_IN_FRAME(offset, length) ) {
+ /*
+ * length will take us past eop. Truncate length.
+ */
+ length = END_OF_FRAME;
+ }
+
+ va_start(ap, fmat);
+ proto_tree_add_text(tree, offset, length, fmat, ap);
+ va_end(ap);
+}
+
+
+void
+esis_dissect_esh_pdu( u_char len, const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree) {
+ proto_tree *esis_area_tree;
+ int no_sa = 0;
+ int sal = 0;
+
+ proto_item *ti;
+
+ if (tree) {
+ offset += ESIS_HDR_FIXED_LENGTH;
+
+ no_sa = pd[offset];
+ len -= 1;
+
+ ti = proto_tree_add_text( tree, offset++, END_OF_FRAME,
+ "Number of Source Addresses (SA, Format: NSAP) : %u", no_sa );
+
+ esis_area_tree = proto_item_add_subtree( ti, ett_esis_area_addr );
+ while ( no_sa-- > 0 ) {
+ sal = (int) pd[offset++];
+ proto_tree_add_text(esis_area_tree, offset, 1, "SAL: %2u Octets", sal);
+ proto_tree_add_text(esis_area_tree, offset + 1, sal,
+ " SA: %s", print_nsap_net( &pd[offset], sal ) );
+ offset += sal;
+ len -= ( sal + 1 );
+ }
+ dissect_osi_options( PDU_TYPE_ESIS_ESH, len, pd, offset, fd, tree );
+ }
+} /* esis_dissect_esh_pdu */ ;
+
+void
+esis_dissect_ish_pdu( u_char len, const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree) {
+
+ int netl = 0;
+
+ if (tree) {
+ offset += ESIS_HDR_FIXED_LENGTH;
+
+ netl = (int) pd[ offset ];
+ proto_tree_add_text( tree, offset, netl + 1,
+ "### Network Entity Titel Section ###");
+ proto_tree_add_text( tree, offset++, 1, "NETL: %2u Octets", netl);
+ proto_tree_add_text( tree, offset, netl,
+ " NET: %s", print_nsap_net( &pd[offset], netl ) );
+ offset += netl;
+ len -= ( netl + 1 );
+
+ dissect_osi_options( PDU_TYPE_ESIS_ISH, len, pd, offset, fd, tree );
+ }
+};
+
+void
+esis_dissect_redirect_pdu( u_char len, const u_char *pd, int offset,
+ frame_data *fd, proto_tree *tree) {
+
+ int tmpl = 0;
+
+ if (tree) {
+ offset += ESIS_HDR_FIXED_LENGTH;
+
+ tmpl = (int) pd[ offset ];
+ proto_tree_add_text( tree, offset, tmpl + 1,
+ "### Destination Address Section ###" );
+ proto_tree_add_text( tree, offset++, 1, "DAL: %2u Octets", tmpl);
+ proto_tree_add_text( tree, offset, tmpl,
+ " DA : %s", print_nsap_net( &pd[offset], tmpl ) );
+ offset += tmpl;
+ len -= ( tmpl + 1 );
+ tmpl = (int) pd[ offset ];
+
+ proto_tree_add_text( tree, offset, tmpl + 1,
+ "### Subnetwork Address Section ###");
+ proto_tree_add_text( tree, offset++, 1, "BSNPAL: %2u Octets", tmpl);
+ proto_tree_add_text( tree, offset, tmpl,
+ " BSNPA: %s", print_system_id( &pd[offset], tmpl ) );
+ offset += tmpl;
+ len -= ( tmpl + 1 );
+ tmpl = (int) pd[ offset ];
+
+ if ( 0 == tmpl ) {
+ proto_tree_add_text( tree, offset, 1,
+ "### No Network Entity Title Section ###" );
+ offset++;
+ len--;
+ }
+ else {
+ proto_tree_add_text( tree, offset, 1,
+ "### Network Entity Title Section ###" );
+ proto_tree_add_text( tree, offset++, 1, "NETL: %2u Octets", tmpl );
+ proto_tree_add_text( tree, offset, tmpl,
+ " NET: %s", print_nsap_net( &pd[offset], tmpl ) );
+ offset += tmpl;
+ len -= ( tmpl + 1 );
+ }
+ dissect_osi_options( PDU_TYPE_ESIS_RD, len, pd, offset, fd, tree );
+ }
+}
+
+
+/*
+ * Name: dissect_esis()
+ *
+ * Description:
+ * Main entry area for esis de-mangling. This will build the
+ * main esis tree data and call the sub-protocols as needed.
+ *
+ * Input:
+ * u_char * : packet data
+ * int : offset into packet where we are (packet_data[offset]== start
+ * of what we care about)
+ * frame_data * : frame data (whole packet with extra info)
+ * proto_tree * : tree of display data. May be NULL.
+ *
+ * Output:
+ * void, but we will add to the proto_tree if it is not NULL.
+ */
+void
+dissect_esis(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
+ char *pdu_type_string = NULL;
+ char *pdu_type_format_string = "PDU Type : %s (R:%s%s%s)";
+ esis_hdr_t *ehdr;
+ proto_item *ti;
+ proto_tree *esis_tree = NULL;
+ int variable_len = 0;
+ u_int tmp_uint = 0;
+
+ if (check_col(fd, COL_PROTOCOL))
+ col_add_str(fd, COL_PROTOCOL, "ESIS");
+
+ if (!BYTES_ARE_IN_FRAME(offset, sizeof(*ehdr))) {
+ esis_dissect_unknown(offset, sizeof(*ehdr), tree, fd,
+ "Not enough capture data for header (%d vs %d)",
+ sizeof(*ehdr), END_OF_FRAME);
+ return;
+ }
+
+ ehdr = (esis_hdr_t *) &pd[offset];
+
+ if (ehdr->esis_version != ESIS_REQUIRED_VERSION){
+ esis_dissect_unknown(offset, END_OF_FRAME, tree, fd,
+ "Unknown ESIS version (%d vs %d)",
+ ehdr->esis_version, ESIS_REQUIRED_VERSION );
+ return;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_esis, offset, END_OF_FRAME, NULL );
+ esis_tree = proto_item_add_subtree(ti, ett_esis);
+
+ proto_tree_add_item( esis_tree, hf_esis_nlpi, offset, 1, ehdr->esis_nlpi );
+ proto_tree_add_item( esis_tree, hf_esis_length,
+ offset + 1, 1, ehdr->esis_length );
+ proto_tree_add_item( esis_tree, hf_esis_version, offset + 2, 1,
+ ehdr->esis_version );
+ proto_tree_add_item( esis_tree, hf_esis_reserved, offset + 3, 1,
+ ehdr->esis_reserved );
+
+ pdu_type_string = val_to_str(ehdr->esis_type&OSI_PDU_TYPE_MASK,
+ esis_vals, "Unknown (0x%x)");
+
+ proto_tree_add_uint_format( esis_tree, hf_esis_type, offset + 4, 1,
+ ehdr->esis_type,
+ pdu_type_format_string,
+ pdu_type_string,
+ (ehdr->esis_type&BIT_8) ? "1" : "0",
+ (ehdr->esis_type&BIT_7) ? "1" : "0",
+ (ehdr->esis_type&BIT_6) ? "1" : "0");
+
+ tmp_uint = pntohs( ehdr->esis_holdtime );
+ proto_tree_add_uint_format(esis_tree, hf_esis_holdtime, offset + 5, 2,
+ tmp_uint, "Holding Time : %u seconds",
+ tmp_uint );
+
+ tmp_uint = pntohs( ehdr->esis_checksum );
+
+ proto_tree_add_uint_format( esis_tree, hf_esis_checksum, offset + 7, 2,
+ tmp_uint, "Checksum : 0x%x ( %s )",
+ tmp_uint, calc_checksum( &pd[offset],
+ ehdr->esis_length ,
+ tmp_uint ) );
+ }
+
+
+ /*
+ * Let us make sure we use the same names for all our decodes
+ * here. First, dump the name into info column, and THEN
+ * dispatch the sub-type.
+ */
+ if (check_col(fd, COL_INFO)) {
+ col_add_str(fd, COL_INFO,
+ val_to_str( ehdr->esis_type&OSI_PDU_TYPE_MASK, esis_vals,
+ "Unknown (0x%x)" ) );
+ }
+
+ variable_len = ehdr->esis_length - ESIS_HDR_FIXED_LENGTH;
+
+ switch (ehdr->esis_type) {
+ case ESIS_ESH_PDU:
+ esis_dissect_esh_pdu( variable_len, pd, offset, fd, esis_tree);
+ break;
+ case ESIS_ISH_PDU:
+ esis_dissect_ish_pdu( variable_len, pd, offset, fd, esis_tree);
+ break;
+ case ESIS_RD_PDU:
+ esis_dissect_redirect_pdu( variable_len, pd, offset, fd,
+ esis_tree);
+ break;
+ default:
+ esis_dissect_unknown(offset, END_OF_FRAME, tree, fd,
+ "unknown esis packet type" );
+ }
+} /* dissect_esis */
+
+
+/*
+ * Name: proto_register_esisesis()
+ *
+ * Description:
+ * main register for esis protocol set. We register some display
+ * formats and the protocol module variables.
+ *
+ * NOTE: this procedure to autolinked by the makefile process that
+ * builds register.c
+ *
+ * Input:
+ * void
+ *
+ * Output:
+ * void
+ */
+void
+proto_register_esis(void) {
+ static hf_register_info hf[] = {
+ { &hf_esis_nlpi,
+ { "Network Layer Protocol Identifier", "esis.nlpi",
+ FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "" }},
+ { &hf_esis_length,
+ { "PDU Length ", "esis.length", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+ { &hf_esis_version,
+ { "Version (==1) ", "esis.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+ { &hf_esis_reserved,
+ { "Reserved(==0) ", "esis.res", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+ { &hf_esis_type,
+ { "PDU Type ", "esis.type", FT_UINT8, BASE_DEC, VALS(esis_vals),
+ 0xff, "" }},
+ { &hf_esis_holdtime,
+ { "Holding Time ", "esis.htime", FT_UINT16, BASE_DEC, NULL, 0x0, " s"}},
+ { &hf_esis_checksum,
+ { "Checksum ", "esis.chksum", FT_UINT16, BASE_HEX, NULL, 0x0, "" }}
+ };
+ /*
+ *
+ *
+ */
+ static gint *ett[] = {
+ &ett_esis,
+ &ett_esis_area_addr,
+ };
+
+ proto_esis = proto_register_protocol( PROTO_STRING_ESIS, "esis");
+ proto_register_field_array(proto_esis, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+};
diff --git a/packet-esis.h b/packet-esis.h
new file mode 100644
index 0000000000..c6e49b24a7
--- /dev/null
+++ b/packet-esis.h
@@ -0,0 +1,69 @@
+/* packet-esis.h
+ * Defines and such for ESIS protocol decode.
+ *
+ * $Id: packet-esis.h,v 1.1 2000/04/15 22:11:09 guy Exp $
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *
+ */
+
+#ifndef _PACKET_ESIS_H
+#define _PACKET_ESIS_H
+
+/* The version we support is 1 */
+#define ESIS_REQUIRED_VERSION 1
+
+/* ESIS PDU types */
+#define ESIS_ESH_PDU 02
+#define ESIS_ISH_PDU 04
+#define ESIS_RD_PDU 06
+
+/* The length of the fixed part */
+#define ESIS_HDR_FIXED_LENGTH 9
+
+/* Inline Defines for masking */
+#define esis_type esis_type_reserved&OSI_PDU_TYPE_MASK
+#define esis_r8 esis_type_reserved&BIT_8
+#define esis_r7 esis_type_reserved&BIT_7
+#define esis_r6 esis_type_reserved&BIT_6
+
+/* The fixed part (9 octets) of the ESIS protocol header */
+typedef struct {
+ guint8 esis_nlpi; /* Network Layer Protocol Identifier == 0x82 */
+ guint8 esis_length; /* Header ( PDU too, NoData ) length in octets */
+ guint8 esis_version; /* ISIS version, must be 0x01 */
+ guint8 esis_reserved; /* reserved byte, must be 0 */
+ guint8 esis_type_reserved; /* packet type & MS-Bits (8-6) reserved */
+ guint8 esis_holdtime[2]; /* Maximum time (sec) this PDU is valid */
+ guint8 esis_checksum[2]; /* Computed on whole PDU Header, 0 means ignore */
+} esis_hdr_t;
+
+/*
+ * published API functions
+ */
+extern void dissect_esis(const u_char *pd, int offset, frame_data *fd,
+ proto_tree *tree);
+extern void proto_register_esis(void);
+extern void esis_dissect_unknown(int offset,guint length, proto_tree *tree,
+ frame_data *fd, char *fmat, ...);
+
+#endif /* _PACKET_ESIS_H */
diff --git a/packet-isis-clv.c b/packet-isis-clv.c
index 8cbfc6f539..1de98279c9 100644
--- a/packet-isis-clv.c
+++ b/packet-isis-clv.c
@@ -1,7 +1,7 @@
/* packet-isis-clv.c
* Common CLV decode routines.
*
- * $Id: packet-isis-clv.c,v 1.2 1999/12/15 22:52:04 guy Exp $
+ * $Id: packet-isis-clv.c,v 1.3 2000/04/15 22:11:09 guy Exp $
* Stuart Stanley <stuarts@mxmail.net>
*
* Ethereal - Network traffic analyzer
@@ -47,6 +47,7 @@
#include <string.h>
#include <glib.h>
#include "packet.h"
+#include "packet-osi.h"
#include "packet-isis.h"
#include "packet-isis-clv.h"
@@ -93,7 +94,8 @@ isis_dissect_area_address_clv(const u_char *pd, int offset,
* Lets turn the area address into "standard" 0000.0000.etc
* format string.
*/
- sbuf = isis_address_to_string ( pd, offset + 1, mylen );
+/* sbuf = isis_address_to_string ( pd, offset + 1, mylen );*/
+ sbuf = print_nsap_net( pd + offset + 1, mylen );
/* and spit it out */
if ( tree ) {
proto_tree_add_text ( tree, offset, mylen + 1,
diff --git a/packet-isis-hello.c b/packet-isis-hello.c
index a9ae715ffe..3c53125469 100644
--- a/packet-isis-hello.c
+++ b/packet-isis-hello.c
@@ -1,7 +1,7 @@
/* packet-isis-hello.c
* Routines for decoding isis hello packets and their CLVs
*
- * $Id: packet-isis-hello.c,v 1.5 2000/03/28 06:12:15 guy Exp $
+ * $Id: packet-isis-hello.c,v 1.6 2000/04/15 22:11:09 guy Exp $
* Stuart Stanley <stuarts@mxmail.net>
*
* Ethereal - Network traffic analyzer
@@ -38,28 +38,29 @@
#include <string.h>
#include <glib.h>
#include "packet.h"
+#include "packet-osi.h"
#include "packet-isis.h"
#include "packet-isis-clv.h"
#include "packet-isis-hello.h"
/* hello packets */
-static int proto_isis_hello = -1;
-static int hf_isis_hello_circuit_reserved = -1;
-static int hf_isis_hello_source_id = -1;
-static int hf_isis_hello_holding_timer = -1;
-static int hf_isis_hello_pdu_length = -1;
-static int hf_isis_hello_priority_reserved = -1;
-static int hf_isis_hello_lan_id = -1;
-static int hf_isis_hello_local_circuit_id = -1;
-static int hf_isis_hello_clv_ipv4_int_addr = -1;
-
-static gint ett_isis_hello = -1;
-static gint ett_isis_hello_clv_area_addr = -1;
-static gint ett_isis_hello_clv_is_neighbors = -1;
-static gint ett_isis_hello_clv_padding = -1;
-static gint ett_isis_hello_clv_unknown = -1;
-static gint ett_isis_hello_clv_nlpid = -1;
-static gint ett_isis_hello_clv_auth = -1;
+static int proto_isis_hello = -1;
+static int hf_isis_hello_circuit_reserved = -1;
+static int hf_isis_hello_source_id = -1;
+static int hf_isis_hello_holding_timer = -1;
+static int hf_isis_hello_pdu_length = -1;
+static int hf_isis_hello_priority_reserved = -1;
+static int hf_isis_hello_lan_id = -1;
+static int hf_isis_hello_local_circuit_id = -1;
+static int hf_isis_hello_clv_ipv4_int_addr = -1;
+
+static gint ett_isis_hello = -1;
+static gint ett_isis_hello_clv_area_addr = -1;
+static gint ett_isis_hello_clv_is_neighbors = -1;
+static gint ett_isis_hello_clv_padding = -1;
+static gint ett_isis_hello_clv_unknown = -1;
+static gint ett_isis_hello_clv_nlpid = -1;
+static gint ett_isis_hello_clv_auth = -1;
static gint ett_isis_hello_clv_ipv4_int_addr = -1;
static const value_string isis_hello_circuit_type_vals[] = {
@@ -360,9 +361,7 @@ dissect_hello_is_neighbors_clv(const u_char *pd, int offset,
*/
if ( tree ) {
proto_tree_add_text ( tree, offset, 6,
- "IS Neighbor: %02x%02x.%02x%02x.%02x%02x",
- pd[offset], pd[offset+1], pd[offset+2],
- pd[offset+3], pd[offset+4], pd[offset+5] );
+ "IS Neighbor: %s", print_system_id( pd + offset, 6 ) );
}
offset += 6;
length -= 6;
@@ -443,7 +442,7 @@ isis_dissect_isis_hello(int hello_type, int header_length,
proto_tree_add_uint_format(hello_tree,
hf_isis_hello_circuit_reserved,
offset, 1, ihp->isis_hello_circuit_reserved,
- "Circuit type: %s, reserved(0x%02x == 0)",
+ "Circuit type : %s, reserved(0x%02x == 0)",
val_to_str(ihp->isis_hello_circuit,
isis_hello_circuit_type_vals,
"Unknown (0x%x)"),
@@ -451,40 +450,25 @@ isis_dissect_isis_hello(int hello_type, int header_length,
);
proto_tree_add_string_format(hello_tree, hf_isis_hello_lan_id,
- offset + 1, 6, ihp->isis_hello_source_id,
- "Lan ID: %02x%02x.%02x%02x.%02x%02x",
- ihp->isis_hello_lan_id[0],
- ihp->isis_hello_lan_id[1],
- ihp->isis_hello_lan_id[2],
- ihp->isis_hello_lan_id[3],
- ihp->isis_hello_lan_id[4],
- ihp->isis_hello_lan_id[5]);
+ offset + 1, 6, ihp->isis_hello_source_id,
+ "SystemID{ Sender of PDU } : %s",
+ print_system_id( pd + offset + 1, 6 ) );
proto_tree_add_item(hello_tree, hf_isis_hello_holding_timer,
- offset + 7, 2,pntohs(&ihp->isis_hello_holding_timer[0]));
+ offset + 7, 2,pntohs(&ihp->isis_hello_holding_timer[0]));
proto_tree_add_item(hello_tree, hf_isis_hello_pdu_length,
- offset + 9, 2,pntohs(&ihp->isis_hello_pdu_length[0]));
- proto_tree_add_uint_format(hello_tree,
- hf_isis_hello_priority_reserved,
- offset + 11, 1, ihp->isis_hello_priority_reserved,
- "Priority: %d, reserved(0x%02x == 0)",
- ihp->isis_hello_priority,
- ihp->isis_hello_preserved );
+ offset + 9, 2,pntohs(&ihp->isis_hello_pdu_length[0]));
+ proto_tree_add_uint_format(hello_tree, hf_isis_hello_priority_reserved,
+ offset + 11, 1, ihp->isis_hello_priority_reserved,
+ "Priority : %d, reserved(0x%02x == 0)",
+ ihp->isis_hello_priority, ihp->isis_hello_preserved );
if (hello_type == ISIS_TYPE_PTP_HELLO) {
- proto_tree_add_item(hello_tree,
- hf_isis_hello_local_circuit_id,
- offset + 12, 1, ihp->isis_hello_lan_id[0] );
+ proto_tree_add_item(hello_tree, hf_isis_hello_local_circuit_id,
+ offset + 12, 1, ihp->isis_hello_lan_id[0] );
} else {
- proto_tree_add_string_format(hello_tree,
- hf_isis_hello_lan_id, offset + 12, 7,
- ihp->isis_hello_lan_id,
- "Lan ID: %02x%02x.%02x%02x.%02x%02x-%02d",
- ihp->isis_hello_lan_id[0],
- ihp->isis_hello_lan_id[1],
- ihp->isis_hello_lan_id[2],
- ihp->isis_hello_lan_id[3],
- ihp->isis_hello_lan_id[4],
- ihp->isis_hello_lan_id[5],
- ihp->isis_hello_lan_id[6]);
+ proto_tree_add_string_format(hello_tree, hf_isis_hello_lan_id,
+ offset + 12, 7, ihp->isis_hello_lan_id,
+ "SystemID{ Designated IS } : %s",
+ print_system_id( pd + offset + 12, 7 ) );
}
}
@@ -531,34 +515,35 @@ void
proto_register_isis_hello(void) {
static hf_register_info hf[] = {
{ &hf_isis_hello_circuit_reserved,
- { "Circuit type", "isis_hello.circuite_type",
+ { "Circuit type ", "isis_hello.circuite_type",
FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
{ &hf_isis_hello_source_id,
- { "Source ID", "isis_hello.source_id",
+ { "SystemID{ Sender of PDU } ", "isis_hello.source_id",
FT_ETHER, BASE_HEX, NULL, 0x0, "" }},
{ &hf_isis_hello_holding_timer,
- { "Holding timer", "isis_hello.holding_timer",
+ { "Holding timer ", "isis_hello.holding_timer",
FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
{ &hf_isis_hello_pdu_length,
- { "PDU length", "isis_hello.pdu_length",
+ { "PDU length ", "isis_hello.pdu_length",
FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
{ &hf_isis_hello_priority_reserved,
- { "Priority", "isis_hello.priority",FT_UINT8, BASE_DEC, NULL,
- ISIS_HELLO_P_RESERVED_MASK, "" }},
+ { "Priority ", "isis_hello.priority",FT_UINT8, BASE_DEC, NULL,
+ ISIS_HELLO_P_RESERVED_MASK, "" }},
{ &hf_isis_hello_lan_id,
- { "LAN ID", "isis_hello.lan_id", FT_STRING, BASE_DEC, NULL, 0x0, "" }},
+ { "SystemID{ Designated IS } ", "isis_hello.lan_id", FT_STRING, BASE_DEC, NULL,
+ 0x0, "" }},
{ &hf_isis_hello_local_circuit_id,
- { "Local circuit ID", "isis_hello.local_circuit_id", FT_UINT8,
+ { "Local circuit ID ", "isis_hello.local_circuit_id", FT_UINT8,
BASE_DEC, NULL, 0x0, "" }},
{ &hf_isis_hello_clv_ipv4_int_addr,
- { "IPv4 interface address", "isis_hello.clv_ipv4_int_addr", FT_IPv4,
+ { "IPv4 interface address ", "isis_hello.clv_ipv4_int_addr", FT_IPv4,
BASE_NONE, NULL, 0x0, "" }},
};
@@ -573,7 +558,7 @@ proto_register_isis_hello(void) {
&ett_isis_hello_clv_ipv4_int_addr,
};
- proto_isis_hello = proto_register_protocol("ISIS hello", "isis_hello");
+ proto_isis_hello = proto_register_protocol("ISIS HELLO", "isis_hello");
proto_register_field_array(proto_isis_hello, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
diff --git a/packet-isis-lsp.c b/packet-isis-lsp.c
index ef8793ace4..296123d7f0 100644
--- a/packet-isis-lsp.c
+++ b/packet-isis-lsp.c
@@ -1,7 +1,7 @@
/* packet-isis-lsp.c
* Routines for decoding isis lsp packets and their CLVs
*
- * $Id: packet-isis-lsp.c,v 1.4 2000/03/20 22:52:42 gram Exp $
+ * $Id: packet-isis-lsp.c,v 1.5 2000/04/15 22:11:09 guy Exp $
* Stuart Stanley <stuarts@mxmail.net>
*
* Ethereal - Network traffic analyzer
@@ -43,6 +43,7 @@
#endif
#include "packet.h"
+#include "packet-osi.h"
#include "packet-isis.h"
#include "packet-isis-clv.h"
#include "packet-isis-lsp.h"
@@ -515,17 +516,12 @@ dissect_lsp_eis_neighbors_clv_inner(const u_char *pd, int offset,
if ( tree ) {
if ( is_eis ) {
ti = proto_tree_add_text ( tree, offset, 11,
- "ES Neighbor: %02x%02x.%02x%02x.%02x%02x",
- pd[offset+4], pd[offset+5],
- pd[offset+6], pd[offset+7],
- pd[offset+8], pd[offset+9] );
+ "ES Neighbor: %s",
+ print_system_id( pd + offset + 4, 6 ) );
} else {
ti = proto_tree_add_text ( tree, offset, 11,
- "IS Neighbor: %02x%02x.%02x%02x.%02x%02x-%02x",
- pd[offset+4], pd[offset+5],
- pd[offset+6], pd[offset+7],
- pd[offset+8], pd[offset+9],
- pd[offset+10] );
+ "IS Neighbor: %s",
+ print_system_id( pd + offset + 4, 6 ) );
}
ntree = proto_item_add_subtree(ti,
ett_isis_lsp_clv_is_neighbors);
@@ -648,9 +644,8 @@ dissect_lsp_partition_dis_clv(const u_char *pd, int offset,
*/
if ( tree ) {
proto_tree_add_text ( tree, offset+4, 6,
- "Partition designated L2 IS: %02x%02x.%02x%02x.%02x%02x",
- pd[offset], pd[offset+1], pd[offset+2],
- pd[offset+3], pd[offset+4], pd[offset+5]);
+ "Partition designated L2 IS: %s",
+ print_system_id( pd + offset, 6 ) );
}
length -= 6;
offset += 6;
@@ -720,7 +715,7 @@ dissect_lsp_prefix_neighbors_clv(const u_char *pd, int offset,
* Lets turn the area address into "standard" 0000.0000.etc
* format string.
*/
- sbuf = isis_address_to_string ( pd, offset + 1, mylen );
+ sbuf = print_area( pd + offset + 1, mylen );
/* and spit it out */
if ( tree ) {
proto_tree_add_text ( tree, offset, mylen + 1,
@@ -750,13 +745,8 @@ void
isis_lsp_decode_lsp_id(char *tstr, proto_tree *tree, int offset,
isis_lsp_id_t *id ) {
proto_tree_add_text(tree, offset, 8,
- "%s: %02x%02x.%02x%02x.%02x%02x.%02x-%02x", tstr,
- id->source_id[0],
- id->source_id[1],
- id->source_id[2],
- id->source_id[3],
- id->source_id[4],
- id->source_id[5],
+ "%s: %s.%02x-%02x", tstr,
+ print_system_id( id->source_id, 6 ),
id->psuodonode_id,
id->lsp_number );
}
@@ -923,7 +913,7 @@ proto_register_isis_lsp(void) {
&ett_isis_lsp_clv_ip_reachability,
};
- proto_isis_lsp = proto_register_protocol("ISIS lsp", "ISIS-lsp");
+ proto_isis_lsp = proto_register_protocol( PROTO_STRING_LSP, "isis_lsp");
proto_register_field_array(proto_isis_lsp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
diff --git a/packet-isis-snp.c b/packet-isis-snp.c
index b5853f3528..6b37ac5f0d 100644
--- a/packet-isis-snp.c
+++ b/packet-isis-snp.c
@@ -1,7 +1,7 @@
/* packet-isis-snp.c
* Routines for decoding isis complete & partial SNP and their payload
*
- * $Id: packet-isis-snp.c,v 1.2 2000/01/24 03:33:32 guy Exp $
+ * $Id: packet-isis-snp.c,v 1.3 2000/04/15 22:11:10 guy Exp $
* Stuart Stanley <stuarts@mxmail.net>
*
* Ethereal - Network traffic analyzer
@@ -38,6 +38,7 @@
#include <string.h>
#include <glib.h>
#include "packet.h"
+#include "packet-osi.h"
#include "packet-isis.h"
#include "packet-isis-clv.h"
#include "packet-isis-lsp.h"
@@ -196,16 +197,16 @@ dissect_snp_lsp_entries(const u_char *pd, int offset, guint length,
return;
}
- proto_tree_add_text(tree, offset, 2, "Remaining life: %d",
+ proto_tree_add_text(tree, offset, 2, "Remaining life : %d",
pntohs(&ps->isis_snp_remaining_lifetime));
- isis_lsp_decode_lsp_id( "LSP ID", tree, offset + 2,
+ isis_lsp_decode_lsp_id( "LSP ID ", tree, offset + 2,
&ps->isis_snp_lsp_id );
proto_tree_add_text(tree, offset+10, 4,
- "LSP Sequence Number: 0x%04x",
+ "LSP Sequence Number : 0x%04x",
pntohl(&ps->isis_snp_sequence_number));
proto_tree_add_text(tree, offset+14, 2,
- "LSP checksum: 0x%02x",
- pntohl(&ps->isis_snp_checksum));
+ "LSP checksum : 0x%02x",
+ pntohs(&ps->isis_snp_checksum));
length -= sizeof ( isis_snp_t );
offset += sizeof ( isis_snp_t );
ps++;
@@ -258,18 +259,12 @@ isis_dissect_isis_csnp(int type, int header_length, const u_char *pd,
proto_tree_add_item(csnp_tree, hf_isis_csnp_pdu_length,
offset, 2, pntohs(&ilp->isis_csnp_pdu_length));
proto_tree_add_text(csnp_tree, offset + 2, 7,
- "Source id: %02x%02x.%02x%02x.%02x%02x.%02x",
- ilp->isis_csnp_source_id[0],
- ilp->isis_csnp_source_id[1],
- ilp->isis_csnp_source_id[2],
- ilp->isis_csnp_source_id[3],
- ilp->isis_csnp_source_id[4],
- ilp->isis_csnp_source_id[5],
- ilp->isis_csnp_source_id[6] );
- isis_lsp_decode_lsp_id( "Start LSP id", csnp_tree, offset + 9,
- &ilp->isis_csnp_start_lsp_id );
- isis_lsp_decode_lsp_id( "End LSP id", csnp_tree, offset + 17,
+ "Source id : %s",
+ print_system_id( pd + offset + 2, 7 ) );
+ isis_lsp_decode_lsp_id( "Start LSP id ", csnp_tree, offset + 9,
&ilp->isis_csnp_start_lsp_id );
+ isis_lsp_decode_lsp_id( "End LSP id ", csnp_tree, offset + 17,
+ &ilp->isis_csnp_end_lsp_id );
}
offset += hlen;
@@ -332,14 +327,8 @@ isis_dissect_isis_psnp(int type, int header_length, const u_char *pd,
proto_tree_add_item(psnp_tree, hf_isis_psnp_pdu_length,
offset, 2, pntohs(&ilp->isis_psnp_pdu_length));
proto_tree_add_text(psnp_tree, offset + 2, 7,
- "Source id: %02x%02x.%02x%02x.%02x%02x.%02x",
- ilp->isis_psnp_source_id[0],
- ilp->isis_psnp_source_id[1],
- ilp->isis_psnp_source_id[2],
- ilp->isis_psnp_source_id[3],
- ilp->isis_psnp_source_id[4],
- ilp->isis_psnp_source_id[5],
- ilp->isis_psnp_source_id[6] );
+ "Source id: %s",
+ print_system_id( pd + offset + 2, 7 ) );
}
offset += hlen;
@@ -441,7 +430,7 @@ proto_register_isis_csnp(void) {
&ett_isis_csnp_clv_unknown,
};
- proto_isis_csnp = proto_register_protocol("ISIS csnp", "ISIS-csnp");
+ proto_isis_csnp = proto_register_protocol(PROTO_STRING_CSNP, "isis_csnp");
proto_register_field_array(proto_isis_csnp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
@@ -479,7 +468,7 @@ proto_register_isis_psnp(void) {
&ett_isis_psnp_clv_unknown,
};
- proto_isis_psnp = proto_register_protocol("ISIS psnp", "ISIS-psnp");
+ proto_isis_psnp = proto_register_protocol(PROTO_STRING_PSNP, "isis_psnp");
proto_register_field_array(proto_isis_psnp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
diff --git a/packet-isis.c b/packet-isis.c
index ead27120e9..ef764fbeb2 100644
--- a/packet-isis.c
+++ b/packet-isis.c
@@ -2,7 +2,7 @@
* Routines for ISO/OSI network and transport protocol packet disassembly, core
* bits.
*
- * $Id: packet-isis.c,v 1.6 2000/04/13 08:14:35 guy Exp $
+ * $Id: packet-isis.c,v 1.7 2000/04/15 22:11:11 guy Exp $
* Stuart Stanley <stuarts@mxmail.net>
*
* Ethereal - Network traffic analyzer
@@ -40,37 +40,38 @@
#include <glib.h>
#include "packet.h"
#include "nlpid.h"
+#include "packet-osi.h"
#include "packet-isis.h"
#include "packet-isis-lsp.h"
#include "packet-isis-hello.h"
#include "packet-isis-snp.h"
+
/* isis base header */
-static int proto_isis = -1;
+static int proto_isis = -1;
-static int hf_isis_irpd = -1;
-static int hf_isis_header_length = -1;
-static int hf_isis_version = -1;
-static int hf_isis_reserved = -1;
-static int hf_isis_type = -1;
-static int hf_isis_version2 = -1;
-static int hf_isis_eco = -1;
-static int hf_isis_user_eco = -1;
+static int hf_isis_irpd = -1;
+static int hf_isis_header_length = -1;
+static int hf_isis_version = -1;
+static int hf_isis_system_id_length = -1;
+static int hf_isis_type = -1;
+static int hf_isis_version2 = -1;
+static int hf_isis_reserved = -1;
+static int hf_isis_max_area_adr = -1;
-static gint ett_isis = -1;
+static gint ett_isis = -1;
static const value_string isis_vals[] = {
- { ISIS_TYPE_L1_HELLO, "L1 HELLO"},
- { ISIS_TYPE_L2_HELLO, "L2 HELLO"},
- { ISIS_TYPE_PTP_HELLO, "P2P HELLO"},
- { ISIS_TYPE_L1_LSP, "L1 LSP"},
- { ISIS_TYPE_L2_LSP, "L2 LSP"},
- { ISIS_TYPE_L1_CSNP, "L1 CSNP"},
- { ISIS_TYPE_L2_CSNP, "L2 CSNP"},
- { ISIS_TYPE_L1_PSNP, "L1 PSNP"},
- { ISIS_TYPE_L2_PSNP, "L2 PSNP"},
- { 0, NULL} };
-
+ { ISIS_TYPE_L1_HELLO, "L1 HELLO"},
+ { ISIS_TYPE_L2_HELLO, "L2 HELLO"},
+ { ISIS_TYPE_PTP_HELLO, "P2P HELLO"},
+ { ISIS_TYPE_L1_LSP, "L1 LSP"},
+ { ISIS_TYPE_L2_LSP, "L2 LSP"},
+ { ISIS_TYPE_L1_CSNP, "L1 CSNP"},
+ { ISIS_TYPE_L2_CSNP, "L2 CSNP"},
+ { ISIS_TYPE_L1_PSNP, "L1 PSNP"},
+ { ISIS_TYPE_L2_PSNP, "L2 PSNP"},
+ { 0, NULL} };
/*
* Name: dissect_isis_unknown()
@@ -113,47 +114,6 @@ isis_dissect_unknown(int offset,guint length,proto_tree *tree,frame_data *fd,
proto_tree_add_text(tree, offset, length, fmat, ap);
va_end(ap);
}
-
-/*
- * Name: isis_address_to_string()
- *
- * Description:
- * Function for taking a byte string and turn it into a "0000.0000...."
- * format ISIS address.
- *
- * Input:
- * u_char * : Packet data
- * unt offset : Current offset into packet data.
- * int len : length of to dump.
- *
- * Output:
- * static char * : print string
- */
-char
-*isis_address_to_string ( const u_char *pd, int offset, int len ) {
- static char sbuf[768];
- char *s;
-
- sbuf[0] = 0;
- s = sbuf;
- while ( len > 0 ) {
- /* special case: len is 1, put ending on it */
- if ( len == 1 ) {
- s += sprintf ( s, "%02x", pd[offset++] );
- len--;
- } else {
- /* general case, just add 2 bytes */
- s+= sprintf ( s, "%02x%02x", pd[offset++],
- pd[offset++] );
- len -= 2;
- }
- if ( len > 0 ) {
- s += sprintf ( s, "." );
- }
- }
- return sbuf;
-}
-
/*
* Name: dissect_isis()
*
@@ -208,22 +168,22 @@ dissect_isis(const u_char *pd, int offset, frame_data *fd,
offset + 1, 1, ihdr->isis_header_length );
proto_tree_add_item(isis_tree, hf_isis_version,
offset + 2, 1, ihdr->isis_version );
- proto_tree_add_item(isis_tree, hf_isis_reserved,
- offset + 3, 1, ihdr->isis_reserved );
+ proto_tree_add_item(isis_tree, hf_isis_system_id_length,
+ offset + 3, 1, ihdr->isis_system_id_len );
proto_tree_add_uint_format(isis_tree, hf_isis_type,
offset + 4, 1, ihdr->isis_type,
- "Type: %s (R:%s%s%s)",
+ "Type : %s (R:%s%s%s)",
val_to_str(ihdr->isis_type & ISIS_TYPE_MASK, isis_vals,
- "Unknown (0x%x)"),
+ "Unknown (0x%x)"),
(ihdr->isis_type & ISIS_R8_MASK) ? "1" : "0",
(ihdr->isis_type & ISIS_R7_MASK) ? "1" : "0",
(ihdr->isis_type & ISIS_R6_MASK) ? "1" : "0");
proto_tree_add_item(isis_tree, hf_isis_version2,
offset + 5, 1, ihdr->isis_version2 );
- proto_tree_add_item(isis_tree, hf_isis_eco,
- offset + 6, 1, ihdr->isis_eco );
- proto_tree_add_item(isis_tree, hf_isis_user_eco,
- offset + 7, 1, ihdr->isis_user_eco );
+ proto_tree_add_item(isis_tree, hf_isis_reserved,
+ offset + 6, 1, ihdr->isis_reserved );
+ proto_tree_add_item(isis_tree, hf_isis_max_area_adr,
+ offset + 7, 1, ihdr->isis_max_area_adr );
}
@@ -304,49 +264,48 @@ dissect_isis(const u_char *pd, int offset, frame_data *fd,
*/
void
proto_register_isis(void) {
- static hf_register_info hf[] = {
- { &hf_isis_irpd,
- { "Intradomain Routing Protocol Discriminator", "isis.irpd",
- FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "" }},
-
- { &hf_isis_header_length,
- { "HDR Length", "isis.hdr_len", FT_UINT8, BASE_DEC,
- NULL, 0x0, "" }},
-
- { &hf_isis_version,
- { "Version (==1)", "isis.version", FT_UINT8,
- BASE_DEC, NULL, 0x0, "" }},
-
- { &hf_isis_reserved,
- { "Reserved(==0)", "isis.reserved",
- FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
-
- { &hf_isis_type,
- { "Type code", "isis.type", FT_UINT8, BASE_DEC,
- VALS(isis_vals), 0xff, "" }},
-
- { &hf_isis_version2,
- { "Version2(==1)", "isis.version2", FT_UINT8, BASE_DEC, NULL,
- 0x0, "" }},
-
- { &hf_isis_eco,
- { "ECO (==0)", "isis.eco",FT_UINT8, BASE_DEC, NULL,
- 0x0, "" }},
-
- { &hf_isis_user_eco,
- { "User ECO (==0)", "isis.user_eco", FT_UINT8, BASE_DEC, NULL,
- 0x0, "" }},
-
- };
- /*
- * Note, we pull in the unknown CLV handler here, since it
- * is used by all ISIS packet types.
- */
- static gint *ett[] = {
- &ett_isis,
- };
-
- proto_isis = proto_register_protocol("clnp ISIS", "isis");
- proto_register_field_array(proto_isis, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
+ static hf_register_info hf[] = {
+ { &hf_isis_irpd,
+ { "Intra Domain Routing Protocol Discriminator", "isis.irpd",
+ FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "" }},
+
+ { &hf_isis_header_length,
+ { "PDU Header Length ", "isis.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_isis_version,
+ { "Version (==1) ", "isis.version", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_isis_system_id_length,
+ { "System ID Length ", "isis.sysid_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+
+ { &hf_isis_type,
+ { "PDU Type :", "isis.type", FT_UINT8, BASE_DEC,
+ VALS(isis_vals), 0xff, "" }},
+
+ { &hf_isis_version2,
+ { "Version2 (==1) ", "isis.version2", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "" }},
+
+ { &hf_isis_reserved,
+ { "Reserved (==0) ", "isis.reserved", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "" }},
+
+ { &hf_isis_max_area_adr,
+ { "Max.AREAs: (0==3) ", "isis.max_area_adr", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "" }},
+
+ };
+ /*
+ * Note, we pull in the unknown CLV handler here, since it
+ * is used by all ISIS packet types.
+ */
+ static gint *ett[] = {
+ &ett_isis,
+ };
+
+ proto_isis = proto_register_protocol(PROTO_STRING_ISIS, "isis");
+ proto_register_field_array(proto_isis, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
}
diff --git a/packet-isis.h b/packet-isis.h
index 9ebc600a28..1c49542a9c 100644
--- a/packet-isis.h
+++ b/packet-isis.h
@@ -1,7 +1,7 @@
/* packet-isis.h
* Defines and such for core isis protcol decode.
*
- * $Id: packet-isis.h,v 1.2 2000/01/13 06:07:52 guy Exp $
+ * $Id: packet-isis.h,v 1.3 2000/04/15 22:11:11 guy Exp $
* Stuart Stanley <stuarts@mxmail.net>
*
* Ethereal - Network traffic analyzer
@@ -37,48 +37,50 @@
/*
* ISIS type field values
*/
-#define ISIS_TYPE_L1_HELLO 15
-#define ISIS_TYPE_L2_HELLO 16
-#define ISIS_TYPE_PTP_HELLO 17
-#define ISIS_TYPE_L1_LSP 18
-#define ISIS_TYPE_L2_LSP 20
-#define ISIS_TYPE_L1_CSNP 24
-#define ISIS_TYPE_L2_CSNP 25
-#define ISIS_TYPE_L1_PSNP 26
-#define ISIS_TYPE_L2_PSNP 27
+#define ISIS_TYPE_L1_HELLO 15
+#define ISIS_TYPE_L2_HELLO 16
+#define ISIS_TYPE_PTP_HELLO 17
+#define ISIS_TYPE_L1_LSP 18
+#define ISIS_TYPE_L2_LSP 20
+#define ISIS_TYPE_L1_CSNP 24
+#define ISIS_TYPE_L2_CSNP 25
+#define ISIS_TYPE_L1_PSNP 26
+#define ISIS_TYPE_L2_PSNP 27
+
+#define ISIS_TYPE_MASK 0x1f
+#define ISIS_R8_MASK 0x80
+#define ISIS_R7_MASK 0x40
+#define ISIS_R6_MASK 0x20
/*
* The common first 8 octets of the ISIS protocol header.
*/
typedef struct {
- guint8 isis_irpd; /* Intradomain Routing Protocol Descriminator. Must be 0x83 */
- guint8 isis_header_length; /* header length in octets */
- guint8 isis_version; /* isis version, must be 0x01 */
- guint8 isis_reserved; /* res byte, must be 0 */
- guint8 isis_type_reserved; /* packet type & reserved */
-#define ISIS_TYPE_MASK 0x1f
-#define ISIS_R8_MASK 0x80
-#define ISIS_R7_MASK 0x40
-#define ISIS_R6_MASK 0x20
- guint8 isis_version2; /* another version(?!), must be 0x01 */
-
- guint8 isis_eco; /* ECO, must be 0 */
- guint8 isis_user_eco; /* user ECO, must be 0 */
-} isis_hdr_t;
+ guint8 isis_irpd; /* Intradomain Routing Protocol Descriminator: 0x83 */
+ guint8 isis_header_length; /* header length in octets */
+ guint8 isis_version; /* isis version, must be 0x01 */
+ guint8 isis_system_id_len; /* length of the system ID fields */
+ guint8 isis_type_reserved; /* packet type & reserved */
+ guint8 isis_version2; /* another version(?!), must be 0x01 */
+ guint8 isis_reserved; /* reserved, must be 0 */
+ guint8 isis_max_area_adr; /* Maximum Number of AREA Addresses permitted */
+} isis_hdr_t; /* for this AREA. Value of 0 allows 3 Addresses */
#define isis_type isis_type_reserved&ISIS_TYPE_MASK
-#define isis_r8 isis_type_reserved&ISIS_R8_MASK
-#define isis_r7 isis_type_reserved&ISIS_R7_MASK
-#define isis_r6 isis_type_reserved&ISIS_R6_MASK
+#define isis_r8 isis_type_reserved&ISIS_R8_MASK
+#define isis_r7 isis_type_reserved&ISIS_R7_MASK
+#define isis_r6 isis_type_reserved&ISIS_R6_MASK
+
/*
* published API functions
*/
+
extern char *isis_address_to_string ( const u_char *pd, int offset, int len );
-extern void dissect_isis(const u_char *pd, int offset, frame_data *fd,
- proto_tree *tree);
+extern void dissect_isis( const u_char *pd, int offset, frame_data *fd,
+ proto_tree *tree);
extern void proto_register_isis(void);
-extern void isis_dissect_unknown(int offset,guint length,proto_tree *tree,frame_data *fd,
- char *fmat, ...);
+extern void isis_dissect_unknown( int offset, guint length, proto_tree *tree,
+ frame_data *fd, char *fmat, ...);
#endif /* _PACKET_ISIS_H */
diff --git a/packet-osi-options.c b/packet-osi-options.c
new file mode 100644
index 0000000000..9db8f89d7a
--- /dev/null
+++ b/packet-osi-options.c
@@ -0,0 +1,466 @@
+/* packet-osi-options.c
+ * Routines for the decode of ISO/OSI option part
+ * Covers:
+ * ISO 8473 CLNP (ConnectionLess Mode Network Service Protocol)
+ * ISO 10589 ISIS (Intradomain Routeing Information Exchange Protocol)
+ * ISO 9542 ESIS (End System To Intermediate System Routeing Exchange Protocol)
+ *
+ * $Id: packet-osi-options.c,v 1.1 2000/04/15 22:11:11 guy Exp $
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include "packet.h"
+#include "nlpid.h"
+#include "packet-osi.h"
+#include "packet-isis.h"
+#include "packet-isis-clv.h"
+#include "packet-isis-hello.h"
+#include "packet-isis-lsp.h"
+#include "packet-isis-snp.h"
+#include "packet-esis.h"
+#include "packet-clnp.h"
+#include "packet-osi-options.h"
+
+#define OSI_OPT_SECURITY 0xc5
+#define OSI_OPT_QOS_MAINTANANCE 0xc3
+#define OSI_OPT_PRIORITY 0xcd
+#define OSI_OPT_ADDRESS_MASK 0xe1
+#define OSI_OPT_SNPA_MASK 0xe2
+#define OSI_OPT_ES_CONFIG_TIMER 0xc6
+
+#define OSI_OPT_MAX_PRIORITY 0x0e
+
+#define OSI_OPT_PADDING 0xcc
+#define OSI_OPT_SOURCE_ROUTING 0xc8
+#define OSI_OPT_RECORD_OF_ROUTE 0xcb
+#define OSI_OPT_REASON_OF_DISCARD 0xc1
+
+#define OSI_OPT_SEC_MASK 0xc0
+#define OSI_OPT_SEC_RESERVED 0x00
+#define OSI_OPT_SEC_SRC_ADR_SPEC 0x40
+#define OSI_OPT_SEC_DST_ADR_SPEC 0x80
+#define OSI_OPT_SEC_GLOBAL_UNIQUE 0xc0
+
+#define OSI_OPT_QOS_MASK 0xc0
+#define OSI_OPT_QOS_RESERVED 0x00
+#define OSI_OPT_QOS_SRC_ADR_SPEC 0x40
+#define OSI_OPT_QOS_DST_ADR_SPEC 0x80
+#define OSI_OPT_QOS_GLOBAL_UNIQUE 0xc0
+
+#define OSI_OPT_QOS_SUB_MASK 0x3f
+#define OSI_OPT_QOS_SUB_RSVD 0x20
+#define OSI_OPT_QOS_SUB_SEQ_VS_TRS 0x10
+#define OSI_OPT_QOS_SUB_CONG_EXPED 0x08
+#define OSI_OPT_QOS_SUB_TSD_VS_COST 0x04
+#define OSI_OPT_QOS_SUB_RESERR_TRS 0x02
+#define OSI_OPT_QOS_SUB_RESERR_COST 0x01
+
+#define OSI_OPT_RFD_GENERAL 0x00
+#define OSI_OPT_RFD_ADDRESS 0x80
+#define OSI_OPT_RFD_SOURCE_ROUTEING 0x90
+#define OSI_OPT_RFD_LIFETIME 0xa0
+#define OSI_OPT_RFD_PDU_DISCARDED 0xb0
+#define OSI_OPT_RFD_REASSEMBLY 0xc0
+
+#define OSI_OPT_RFD_MASK 0xf0
+#define OSI_OPT_RFD_SUB_MASK 0x0f
+
+
+
+
+static gint ott_osi_options = -1;
+static gint ott_osi_qos = -1;
+static gint ott_osi_route = -1;
+static gint ott_osi_redirect = -1;
+
+static const value_string osi_opt_sec_vals[] = {
+ { OSI_OPT_SEC_RESERVED, "Reserved"},
+ { OSI_OPT_SEC_SRC_ADR_SPEC, "Source Address Specific"},
+ { OSI_OPT_SEC_DST_ADR_SPEC, "Destination Address Specific"},
+ { OSI_OPT_SEC_GLOBAL_UNIQUE, "Globally Unique"},
+ { 0, NULL} };
+
+static const value_string osi_opt_qos_vals[] = {
+ { OSI_OPT_QOS_RESERVED, "Reserved"},
+ { OSI_OPT_QOS_SRC_ADR_SPEC, "Source Address Specific"},
+ { OSI_OPT_QOS_DST_ADR_SPEC, "Destination Address Specific"},
+ { OSI_OPT_QOS_GLOBAL_UNIQUE, "Globally Unique"},
+ { 0, NULL} };
+
+static const value_string osi_opt_qos_sub_vals[] = {
+ { 0x20, " xx10 0000 Reserved"},
+ { 0x10, " xx01 0000 Sequencing versus transit delay"},
+ { 0x08, " xx00 1000 Congestion experienced"},
+ { 0x04, " xx00 0100 Transit delay versus cost"},
+ { 0x02, " xx00 0010 Residual error probability versus transit delay"},
+ { 0x01, " xx00 0001 Residual error probability versus cost"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_general[] = {
+ { 0x00, "Reason not specified"},
+ { 0x01, "Protocol procedure error"},
+ { 0x02, "Incorrect checksum"},
+ { 0x03, "PDU discarded due to congestion"},
+ { 0x04, "Header syntax error ( cannot be parsed )"},
+ { 0x05, "Segmentation needed but not permitted"},
+ { 0x06, "Incomplete PDU received"},
+ { 0x07, "Duplicate option"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_address[] = {
+ { 0x00, "Destination Address unreachable"},
+ { 0x01, "Destination Address unknown"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_src_route[] = {
+ { 0x00, "Unspecified source routeing error"},
+ { 0x01, "Syntax error in source routeing field"},
+ { 0x02, "Unknown address in source routeing field"},
+ { 0x03, "Path not acceptable"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_lifetime[] = {
+ { 0x00, "Lifetime expired while data unit in transit"},
+ { 0x01, "Lifetime expired during reassembly"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_discarded[] = {
+ { 0x00, "Unsupported option not specified"},
+ { 0x01, "Unsupported protocol version"},
+ { 0x02, "Unsupported security option"},
+ { 0x03, "Unsupported source routeing option"},
+ { 0x04, "Unsupported recording of route option"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_reassembly[] = {
+ { 0x00, "Reassembly interference"},
+ { 0, NULL} };
+
+
+void
+dissect_option_qos( const u_char type, const u_char sub_type, u_char offset,
+ u_char len, const u_char *pd, proto_tree *tree ) {
+
+ u_char tmp_type = 0;
+ proto_item *ti;
+ proto_tree *osi_qos_tree = NULL;
+
+
+ ti = proto_tree_add_text( tree, offset, len,
+ "Quality of service maintenance: %s",
+ val_to_str( type, osi_opt_qos_vals, "Unknown (0x%x)") );
+
+ osi_qos_tree = proto_item_add_subtree( ti, ott_osi_qos );
+
+ if ( OSI_OPT_SEC_MASK == type ) { /* Analye BIT field to get all Values */
+
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_RSVD;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_SEQ_VS_TRS;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type &OSI_OPT_QOS_SUB_CONG_EXPED;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_TSD_VS_COST;
+
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_RESERR_TRS;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_RESERR_COST;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ }
+};
+void
+dissect_option_route( u_char parm_type, u_char offset, u_char parm_len,
+ const u_char *pd, proto_tree *tree ) {
+
+ u_char next_hop = 0;
+ u_char this_hop = 0;
+ u_char netl = 0;
+ u_char last_hop = 0;
+ u_char cnt_hops = 0;
+
+ proto_item *ti;
+ proto_tree *osi_route_tree = NULL;
+
+ static const value_string osi_opt_route[] = {
+ { 0x03, "No Network Entity Titles Recorded Yet"},
+ { 0xff, "Recording Terminated !"},
+ { 0, NULL} };
+
+ if ( parm_type == OSI_OPT_SOURCE_ROUTING ) {
+ next_hop = pd[offset + 1 ];
+ netl = pd[next_hop + 2 ];
+ this_hop = offset + 3; /* points to first netl */
+
+ ti = proto_tree_add_text( tree, offset + next_hop, netl,
+ "Source Routing: %s ( Next Hop Highlighted In Data Buffer )",
+ (pd[offset] == 0) ? "Partial Source Routeing" :
+ "Complete Source Routeing" );
+ }
+ else {
+ last_hop = pd[offset + 1 ]; /* points to the end of the list */
+ netl = pd[ last_hop ]; /* mis-used to highlight buffer */
+
+ ti = proto_tree_add_text( tree, offset + next_hop, netl,
+ "Record of Route: %s : %s",
+ (pd[offset] == 0) ? "Partial Source Routeing" :
+ "Complete Source Routeing" ,
+ val_to_str( last_hop, osi_opt_route, "Unknown (0x%x" ) );
+ if ( 255 == last_hop )
+ this_hop = parm_len + 1; /* recording terminated, nothing to show */
+ else
+ this_hop = offset + 3;
+ }
+ osi_route_tree = proto_item_add_subtree( ti, ott_osi_route );
+
+ while ( this_hop < parm_len ) {
+ netl = pd[this_hop + 1];
+ proto_tree_add_text( osi_route_tree, offset + this_hop, netl,
+ "Hop #%3u NETL: %2u, NET: %s",
+ cnt_hops++,
+ netl,
+ print_nsap_net( &pd[this_hop + 1], netl ) );
+ this_hop += 1 + netl;
+ }
+};
+
+
+
+
+
+void
+dissect_option_rfd( const u_char error, const u_char field, u_char offset,
+ u_char len, const u_char *pd, proto_tree *tree ) {
+ u_char error_class = 0;
+ char *format_string[] =
+ { "Reason for discard {General} : %s, in field %u",
+ "Reason for discard {Address} : %s, in field %u",
+ "Reason for discard {Source Routeing}: %s, in field %u",
+ "Reason for discard {Lifetime} : %s, in field %u",
+ "Reason for discard {PDU discarded} : %s, in field %u",
+ "Reason for discard {Reassembly} : %s, in field %u"
+ };
+
+ error_class = error & OSI_OPT_RFD_MASK;
+
+ if ( OSI_OPT_RFD_GENERAL == error_class ) {
+ proto_tree_add_text( tree, offset + field, 1, format_string[0],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_general, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_ADDRESS == error_class ) {
+ proto_tree_add_text( tree, offset + field, 1, format_string[1],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_address, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_SOURCE_ROUTEING == error_class ) {
+ proto_tree_add_text( tree, offset + field, 1, format_string[2],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_src_route, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_LIFETIME == error_class ) {
+ proto_tree_add_text( tree, offset + field, 1, format_string[3],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_lifetime, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_PDU_DISCARDED == error_class ) {
+ proto_tree_add_text( tree, offset + field, 1, format_string[4],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_discarded, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_REASSEMBLY == error_class ) {
+ proto_tree_add_text( tree, offset + field, 1, format_string[5],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_reassembly, "Unknown (0x%x)"), field );
+ }
+ else {
+ proto_tree_add_text( tree, offset, len,
+ "Reason for discard: UNKNOWN Error Class" );
+ }
+};
+
+/* ############################## Dissection Functions ###################### */
+
+/*
+ * Name: dissect_osi_options()
+ *
+ * Description:
+ * Main entry area for esis de-mangling. This will build the
+ * main esis tree data and call the sub-protocols as needed.
+ *
+ * Input:
+ * u_char : PDU type to check if option is allowed or not
+ * u_char : length of option section
+ * u_char * : packet data
+ * int : offset into packet where we are (packet_data[offset]== start
+ * of what we care about)
+ * frame_data * : frame data (whole packet with extra info)
+ * proto_tree * : tree of display data. May be NULL.
+ *
+ * Output:
+ * void, but we will add to the proto_tree if it is not NULL.
+ */
+void
+dissect_osi_options( u_char pdu_type, u_char opt_len, const u_char *pd,
+ int offset, frame_data *fd, proto_tree *tree) {
+ proto_item *ti;
+ proto_tree *osi_option_tree = NULL;
+ u_char parm_len = 0;
+ u_char parm_type = 0;
+
+ if (tree) {
+ if ( 0 == opt_len ) {
+ proto_tree_add_text( tree, offset, 0,
+ "### No Options for this PDU ###" );
+ return;
+ }
+
+ if ( opt_len > END_OF_FRAME ) {
+ proto_tree_add_text( tree, offset, END_OF_FRAME,
+ "### Options go past the end of the captured data in this PDU ###" );
+ return;
+ }
+
+ ti = proto_tree_add_text( tree, offset, opt_len,
+ "### Option Section ###" );
+ osi_option_tree = proto_item_add_subtree( ti, ott_osi_options );
+
+ while ( 0 < opt_len ) {
+ parm_type = (int) pd[offset++];
+ parm_len = (int) pd[offset++];
+
+ switch ( parm_type ) {
+ case OSI_OPT_QOS_MAINTANANCE:
+ dissect_option_qos( pd[offset]&OSI_OPT_QOS_MASK,
+ pd[offset]&OSI_OPT_QOS_SUB_MASK,
+ offset, parm_len, pd, osi_option_tree );
+ break;
+ case OSI_OPT_SECURITY:
+ proto_tree_add_text( osi_option_tree, offset, parm_len,
+ "Security type: %s",
+ val_to_str( pd[offset]&OSI_OPT_SEC_MASK,
+ osi_opt_sec_vals, "Unknown (0x%x)") );
+ break;
+ case OSI_OPT_PRIORITY:
+ if ( OSI_OPT_MAX_PRIORITY >= pd[offset] ) {
+ proto_tree_add_text( osi_option_tree, offset, parm_len,
+ "Priority : %u", pd[offset] );
+ }
+ else {
+ proto_tree_add_text( osi_option_tree, offset, parm_len,
+ "Priority : %u ( Invalid )",
+ pd[offset] );
+ }
+ break;
+ case OSI_OPT_ADDRESS_MASK:
+ proto_tree_add_text( osi_option_tree, offset, parm_len,
+ "Address Mask: %s", print_area( &pd[offset], parm_len ) );
+ break;
+ case OSI_OPT_SNPA_MASK:
+ proto_tree_add_text( osi_option_tree, offset, parm_len,
+ "SNPA Mask : %s", print_system_id( &pd[offset], parm_len ));
+ break;
+ case OSI_OPT_ES_CONFIG_TIMER:
+ proto_tree_add_text( osi_option_tree, offset, parm_len,
+ "ESCT : %u seconds", pntohs( &pd[offset] ) );
+ break;
+ case OSI_OPT_PADDING:
+ proto_tree_add_text( osi_option_tree, offset, parm_len,
+ "Padding : %u Octets", parm_len ) ;
+ break;
+ case OSI_OPT_SOURCE_ROUTING:
+ case OSI_OPT_RECORD_OF_ROUTE:
+ dissect_option_route( parm_type,
+ offset, parm_len, pd, osi_option_tree );
+ break;
+ case OSI_OPT_REASON_OF_DISCARD:
+ dissect_option_rfd( pd[offset],
+ pd[offset + 1],
+ offset, parm_len, pd, osi_option_tree );
+ break;
+ }
+ opt_len -= parm_len + 2;
+ offset += parm_len;
+ }
+ }
+}; /* dissect-osi-options */
+
+
+/*
+ * Name: proto_register_osi_options()
+ *
+ * Description:
+ * main register for esis protocol set. We register some display
+ * formats and the protocol module variables.
+ *
+ * NOTE: this procedure to autolinked by the makefile process that
+ * builds register.c
+ *
+ * Input:
+ * void
+ *
+ * Output:
+ * void
+ */
+
+void
+proto_register_osi_options(void) {
+ static gint *ott[] = {
+ &ott_osi_options,
+ &ott_osi_qos,
+ &ott_osi_route,
+ &ott_osi_redirect,
+ };
+ proto_register_subtree_array( ott, array_length(ott));
+};
+
diff --git a/packet-osi-options.h b/packet-osi-options.h
new file mode 100644
index 0000000000..fdd54d8368
--- /dev/null
+++ b/packet-osi-options.h
@@ -0,0 +1,39 @@
+/* packet-osi-options.h
+ * Defines for OSI options part decode
+ *
+ * $Id: packet-osi-options.h,v 1.1 2000/04/15 22:11:12 guy Exp $
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *
+ */
+
+#ifndef _PACKET_OSI_OPTION_H
+#define _PACKET_OSI_OPTIONS_H
+
+/*
+ * published API functions
+ */
+extern void dissect_osi_options( u_char, u_char, const u_char *, int,
+ frame_data *, proto_tree *);
+extern void proto_register_osi_options(void);
+
+#endif /* _PACKET_OSI_OPTIONS_H */
diff --git a/packet-osi.c b/packet-osi.c
index ebd5c015a4..2b242597b6 100644
--- a/packet-osi.c
+++ b/packet-osi.c
@@ -1,8 +1,10 @@
/* packet-osi.c
* Routines for ISO/OSI network and transport protocol packet disassembly
+ * Main entrance point and common functions
*
- * $Id: packet-osi.c,v 1.29 2000/04/15 21:27:12 guy Exp $
+ * $Id: packet-osi.c,v 1.30 2000/04/15 22:11:12 guy Exp $
* Laurent Deniel <deniel@worldnet.fr>
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -26,9 +28,9 @@
*
* To do:
*
- * - add other network protocols (ES,IS-IS)
+ * - add other network protocols (IS-IS)
* - add NSAP decoding & resolution
- * - complete CLNP decoding (options)
+ *
*
*/
@@ -45,1693 +47,161 @@
#include <ctype.h>
#include <glib.h>
#include "packet.h"
-#include "packet-isis.h"
#include "packet-h1.h"
#include "nlpid.h"
+#include "packet-osi.h"
+#include "packet-clnp.h"
+#include "packet-isis.h"
+#include "packet-esis.h"
-/* protocols and fields */
-
-static int proto_clnp = -1;
-
-static int hf_clnp_id = -1;
-static int hf_clnp_length = -1;
-static int hf_clnp_version = -1;
-static int hf_clnp_ttl = -1;
-static int hf_clnp_type = -1;
-static int hf_clnp_pdu_length = -1;
-static int hf_clnp_checksum = -1;
-static int hf_clnp_dest_length = -1;
-static int hf_clnp_dest = -1;
-static int hf_clnp_src_length = -1;
-static int hf_clnp_src = -1;
-
-static gint ett_clnp = -1;
-
-static int proto_cotp = -1;
-
-static gint ett_cotp = -1;
-
-/*
- * ISO8473 OSI CLNP definition (see RFC994)
- *
- * _________________________________
- * | Fixed Part |
- * |_________________________________|
- * | Address Part |
- * |_________________________________|
- * | Segmentation Part (optional) |
- * |_________________________________|
- * | Options Part (optional) |
- * |_________________________________|
- * | Data (optional) |
- * |_________________________________|
- */
-
-#define ISO8473_V1 0x01 /* CLNP version 1 */
-
-/* Fixed part */
-
-struct clnp_header {
- u_char cnf_proto_id; /* network layer protocol identifier */
- u_char cnf_hdr_len; /* length indicator (octets) */
- u_char cnf_vers; /* version/protocol identifier extension */
- u_char cnf_ttl; /* lifetime (500 milliseconds) */
- u_char cnf_type; /* type code */
- u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
- u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
- u_char cnf_cksum_msb; /* checksum high byte */
- u_char cnf_cksum_lsb; /* checksum low byte */
-};
-
-#define CNF_TYPE 0x1f
-#define CNF_ERR_OK 0x20
-#define CNF_MORE_SEGS 0x40
-#define CNF_SEG_OK 0x80
-
-#define DT_NPDU 0x1C
-#define MD_NPDU 0x1D
-#define ER_NPDU 0x01
-#define ERQ_NPDU 0x1E
-#define ERP_NPDU 0x1F
-
-static const value_string npdu_type_vals[] = {
- { DT_NPDU, "DT" },
- { MD_NPDU, "MD" },
- { ER_NPDU, "ER" },
- { ERQ_NPDU, "ERQ" },
- { ERP_NPDU, "ERP" },
- { 0, NULL }
-};
-
-/* field position */
-
-#define P_ADDRESS_PART 9
-
-/* Segmentation part */
-
-struct clnp_segment {
- u_short cng_id; /* data unit identifier */
- u_short cng_off; /* segment offset */
- u_short cng_tot_len; /* total length */
-};
-
-/* NSAP selector */
-
-#define NSEL_NET 0x00
-#define NSEL_NP 0x20
-#define NSEL_TP 0x21
-
-/*
- * ISO8073 OSI COTP definition (see RFC905)
- */
-
-/* don't use specific TPDU types to avoid alignment problems & copy overhead */
-
-/* TPDU definition */
-
-#define ED_TPDU 0x1
-#define EA_TPDU 0x2
-#define RJ_TPDU 0x5
-#define AK_TPDU 0x6
-#define ER_TPDU 0x7
-#define DR_TPDU 0x8
-#define DC_TPDU 0xC
-#define CC_TPDU 0xD
-#define CR_TPDU 0xE
-#define DT_TPDU 0xF
-
-/* field position */
-
-#define P_LI 0
-#define P_TPDU 1
-#define P_CDT 1
-#define P_DST_REF 2
-#define P_SRC_REF 4
-#define P_TPDU_NR_0_1 2
-#define P_TPDU_NR_234 4
-#define P_VAR_PART_NDT 5
-#define P_VAR_PART_EDT 8
-#define P_VAR_PART_NAK 5
-#define P_VAR_PART_CC 7
-#define P_VAR_PART_EAK 10
-#define P_VAR_PART_DC 6
-#define P_VAR_PART_DR 7
-#define P_CDT_IN_AK 8
-#define P_CDT_IN_RJ 8
-#define P_REJECT_ER 4
-#define P_REASON_IN_DR 6
-#define P_CLASS_OPTION 6
-
-/* TPDU length indicator */
-
-#define LI_NORMAL_DT_CLASS_01 2
-#define LI_NORMAL_DT_WITH_CHECKSUM 8
-#define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
-#define LI_EXTENDED_DT_WITH_CHECKSUM 11
-#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
-#define LI_NORMAL_EA_WITH_CHECKSUM 8
-#define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
-#define LI_EXTENDED_EA_WITH_CHECKSUM 11
-#define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
-#define LI_NORMAL_RJ 4
-#define LI_EXTENDED_RJ 9
-#define LI_MIN_DR 6
-#define LI_MAX_DC 9
-#define LI_MAX_AK 27
-#define LI_MAX_EA 11
-#define LI_MAX_ER 8
-#define LI_DC_WITH_CHECKSUM 9
-#define LI_DC_WITHOUT_CHECKSUM 5
-#define is_LI_NORMAL_AK(p) ( p & 0x01 )
-
-/* variant part */
-
-#define VP_ACK_TIME 0x85
-#define VP_RES_ERROR 0x86
-#define VP_PRIORITY 0x87
-#define VP_TRANSIT_DEL 0x88
-#define VP_THROUGHPUT 0x89
-#define VP_SEQ_NR 0x8A /* in AK */
-#define VP_REASSIGNMENT 0x8B
-#define VP_FLOW_CNTL 0x8C /* in AK */
-#define VP_TPDU_SIZE 0xC0
-#define VP_SRC_TSAP 0xC1 /* in CR/CC */
-#define VP_DST_TSAP 0xC2
-#define VP_CHECKSUM 0xC3
-#define VP_VERSION_NR 0xC4
-#define VP_PROTECTION 0xC5
-#define VP_OPT_SEL 0xC6
-#define VP_PROTO_CLASS 0xC7
-
-/* misc */
-
-#define EXTRACT_SHORT(p) pntohs(p)
-#define EXTRACT_LONG(p) pntohl(p)
-
-/* global variables */
-
-static u_char li, tpdu, cdt; /* common fields */
-static u_short dst_ref;
-
-/* function definitions */
-
-static int osi_decode_DR(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree)
-{
- proto_tree *cotp_tree;
- proto_item *ti;
- u_short src_ref;
- u_char reason;
- char *str;
-
- if (li < LI_MIN_DR)
- return -1;
-
- src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
- reason = pd[offset + P_REASON_IN_DR];
-
- switch(reason) {
- case (128+0): str = "Normal Disconnect"; break;
- case (128+1): str = "Remote transport entity congestion"; break;
- case (128+2): str = "Connection negotiation failed"; break;
- case (128+3): str = "Duplicate source reference"; break;
- case (128+4): str = "Mismatched references"; break;
- case (128+5): str = "Protocol error"; break;
- case (128+7): str = "Reference overflow"; break;
- case (128+8): str = "Connection requestion refused"; break;
- case (128+10):str = "Header or parameter length invalid"; break;
- case (0): str = "Reason not specified"; break;
- case (1): str = "Congestion at TSAP"; break;
- case (2): str = "Session entity not attached to TSAP"; break;
- case (3): str = "Address unknown"; break;
- default: return -1;
- /*NOTREACHED*/
- break;
- }
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
- src_ref, dst_ref);
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (DR)", tpdu);
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
- proto_tree_add_text(cotp_tree, offset + 4, 2,
- "Source reference: 0x%04x", src_ref);
- proto_tree_add_text(cotp_tree, offset + 6, 1,
- "Cause: %s", str);
- }
-
- offset += li + 1;
- dissect_data(pd, offset, fd, tree);
-
- return pi.captured_len; /* we dissected all of the containing PDU */
-
-} /* osi_decode_DR */
-
-/* Returns TRUE if we called a sub-dissector, FALSE if not. */
-static gboolean osi_decode_DT(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree,
- gboolean uses_inactive_subset)
-{
- proto_tree *cotp_tree;
- proto_item *ti;
- u_int tpdu_nr ;
- u_short checksum = 0;
- u_char code = 0, length = 0;
- u_int fragment = 0;
-
- switch (li) {
- case LI_NORMAL_DT_WITH_CHECKSUM :
- tpdu_nr = pd[offset + P_TPDU_NR_234];
- if ( tpdu_nr & 0x80 )
- tpdu_nr = tpdu_nr & 0x7F;
- else
- fragment = 1;
- code = pd[offset + P_VAR_PART_NDT];
- if (code == VP_CHECKSUM)
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
- else
- return -1;
- break;
- case LI_NORMAL_DT_WITHOUT_CHECKSUM :
- tpdu_nr = pd[offset + P_TPDU_NR_234];
- if ( tpdu_nr & 0x80 )
- tpdu_nr = tpdu_nr & 0x7F;
- else
- fragment = 1;
- break;
- case LI_EXTENDED_DT_WITH_CHECKSUM :
- tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
- if ( tpdu_nr & 0x80000000 )
- tpdu_nr = tpdu_nr & 0x7FFFFFFF;
- else
- fragment = 1;
- code = pd[offset + P_VAR_PART_EDT];
- if (code == VP_CHECKSUM)
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
- else
- return -1;
- break;
- case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
- tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
- if ( tpdu_nr & 0x80000000 )
- tpdu_nr = tpdu_nr & 0x7FFFFFFF;
- else
- fragment = 1;
- break;
- case LI_NORMAL_DT_CLASS_01 :
- tpdu_nr = pd[offset + P_TPDU_NR_0_1];
- if ( tpdu_nr & 0x80 )
- tpdu_nr = tpdu_nr & 0x7F;
- else
- fragment = 1;
- break;
- default : /* bad TPDU */
- return -1;
- /*NOTREACHED*/
- break;
- }
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "DT TPDU (%d) dst-ref: 0x%04x %s",
- tpdu_nr,
- dst_ref,
- (fragment)? "(fragment)" : "");
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (DT)", tpdu);
-
- if (li != LI_NORMAL_DT_CLASS_01)
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
- switch (li) {
- case LI_NORMAL_DT_WITH_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "TPDU number: 0x%02x (%s)",
- tpdu_nr,
- (fragment)? "fragment":"complete");
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NDT, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NDT + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NDT + 2, length,
- "Checksum: 0x%04x", checksum);
- break;
- case LI_NORMAL_DT_WITHOUT_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "TPDU number: 0x%02x (%s)",
- tpdu_nr,
- (fragment)? "fragment":"complete");
- break;
- case LI_EXTENDED_DT_WITH_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 4,
- "TPDU number: 0x%08x (%s)",
- tpdu_nr,
- (fragment)? "fragment":"complete");
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EDT, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EDT + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EDT + 2, length,
- "Checksum: 0x%04x", checksum);
- break;
- case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 4,
- "TPDU number: 0x%08x (%s)",
- tpdu_nr,
- (fragment)? "fragment":"complete");
- break;
- case LI_NORMAL_DT_CLASS_01 :
- proto_tree_add_text(cotp_tree, offset + 2, 1,
- "TPDU number: 0x%02x (%s)",
- tpdu_nr,
- (fragment)? "fragment":"complete");
- break;
+gchar *print_system_id( const u_char *buffer, int length ) {
+ int tmp;
+ u_char *cur;
+ static gchar str[MAX_SYSTEMID_LEN * 3 + 5]; /* Don't trust exact matching */
+
+ if ( ( length <= 0 ) || ( length > MAX_SYSTEMID_LEN ) ) {
+ sprintf( str, "<Invalid length of SYSTEM ID>");
+ return( str );
+ }
+
+ cur = str;
+ if ( ( 6 == length ) || ( 7 == length ) ) { /* Special case, print as MAC */
+ cur += sprintf(str, "[%02x:%02x:%02x_%02x:%02x:%02x]", buffer[0], buffer[1],
+ buffer[2], buffer[3], buffer[4], buffer[5] );
+ if ( 7 == length ) {
+ sprintf( cur, "-%02x", buffer[6] );
}
- } /* tree */
-
- offset += li + 1;
- if (uses_inactive_subset){
- dissect_h1(pd, offset, fd, tree);
- return TRUE;
- }
+ }
else {
- dissect_data(pd, offset, fd, tree);
- return FALSE;
- }
-} /* osi_decode_DT */
-
-static int osi_decode_ED(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree)
-{
- proto_tree *cotp_tree;
- proto_item *ti;
- u_int tpdu_nr ;
- u_short checksum = 0;
- u_char code = 0, length = 0;
-
- /* ED TPDUs are never fragmented */
-
- switch (li) {
- case LI_NORMAL_DT_WITH_CHECKSUM :
- tpdu_nr = pd[offset + P_TPDU_NR_234];
- if ( tpdu_nr & 0x80 )
- tpdu_nr = tpdu_nr & 0x7F;
- else
- return -1;
- code = pd[offset + P_VAR_PART_NDT];
- length = pd[offset + P_VAR_PART_NDT + 1];
- if (code == VP_CHECKSUM)
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
- else
- return -1;
- break;
- case LI_NORMAL_DT_WITHOUT_CHECKSUM :
- tpdu_nr = pd[offset + P_TPDU_NR_234];
- if ( tpdu_nr & 0x80 )
- tpdu_nr = tpdu_nr & 0x7F;
- else
- return -1;
- break;
- case LI_EXTENDED_DT_WITH_CHECKSUM :
- tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
- if ( tpdu_nr & 0x80000000 )
- tpdu_nr = tpdu_nr & 0x7FFFFFFF;
- else
- return -1;
- code = pd[offset + P_VAR_PART_EDT];
- length = pd[offset + P_VAR_PART_EDT + 1];
- if (code == VP_CHECKSUM)
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
- else
- return -1;
- break;
- case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
- tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
- if ( tpdu_nr & 0x80000000 )
- tpdu_nr = tpdu_nr & 0x7FFFFFFF;
- else
- return -1;
- break;
- default : /* bad TPDU */
- return -1;
- /*NOTREACHED*/
- break;
- } /* li */
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "ED TPDU (%d) dst-ref: 0x%04x",
- tpdu_nr, dst_ref);
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (ED)", tpdu);
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
-
- switch (li) {
- case LI_NORMAL_DT_WITH_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "TPDU number: 0x%02x", tpdu_nr);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NDT, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NDT + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NDT + 2, length,
- "Checksum: 0x%04x", checksum);
- break;
- case LI_NORMAL_DT_WITHOUT_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "TPDU number: 0x%02x", tpdu_nr);
- break;
- case LI_EXTENDED_DT_WITH_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 4,
- "TPDU number: 0x%02x", tpdu_nr);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EDT, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EDT + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EDT + 2, length,
- "Checksum: 0x%04x", checksum);
- break;
- case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 4,
- "TPDU number: 0x%02x", tpdu_nr);
- break;
+ tmp = 0;
+ while ( tmp < length / 4 ) { /* 16 / 4 == 4 > four Octets left to print */
+ cur += sprintf( str, "%02x%02x%02x%02x.", buffer[tmp++], buffer[tmp++],
+ buffer[tmp++], buffer[tmp++] );
}
- } /* tree */
-
- offset += li + 1;
- dissect_data(pd, offset, fd, tree);
-
- return pi.captured_len; /* we dissected all of the containing PDU */
-
-} /* osi_decode_ED */
-
-static int osi_decode_RJ(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree)
-{
- proto_tree *cotp_tree;
- proto_item *ti;
- u_int tpdu_nr ;
- u_short credit = 0;
-
- switch(li) {
- case LI_NORMAL_RJ :
- tpdu_nr = pd[offset + P_TPDU_NR_234];
- break;
- case LI_EXTENDED_RJ :
- tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
- credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
- break;
- default :
- return -1;
- /*NOTREACHED*/
- break;
- }
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "RJ TPDU (%d) dst-ref: 0x%04x",
- tpdu_nr, dst_ref);
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (RJ)", tpdu);
- if (li == LI_NORMAL_RJ)
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "Credit: %d", cdt);
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
- if (li == LI_NORMAL_RJ)
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "Your TPDU number: 0x%02x", tpdu_nr);
- else {
- proto_tree_add_text(cotp_tree, offset + 4, 4,
- "Your TPDU number: 0x%02x", tpdu_nr);
- proto_tree_add_text(cotp_tree, offset + 8, 2,
- "Credit: 0x%02x", credit);
+ if ( 1 == tmp ) { /* Special case for Designated IS */
+ sprintf( --cur, "-%02x", buffer[tmp] );
}
- }
-
- offset += li + 1;
-
- return offset;
-
-} /* osi_decode_RJ */
-
-#define MAX_TSAP_LEN 32
-
-static gchar *print_tsap(const u_char *tsap, int length)
-{
-
- static gchar str[3][MAX_TSAP_LEN * 2 + 1];
- static gchar *cur;
- gchar tmp[3];
- gboolean allprintable;
- int i;
-
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
- }
-
-
- cur[0] = '\0';
- if (length <= 0 || length > MAX_TSAP_LEN)
- sprintf(cur, "<unsupported TSAP length>");
- else {
- allprintable=TRUE;
- for (i=0;i<length;i++) {
- if (!isprint(tsap[i])) { /* if any byte is not printable */
- allprintable=FALSE; /* switch to hexdump */
- break;
- }
- }
- if (!allprintable){
- strcat(cur,"0x");
+ else {
+ for ( ; tmp < length; ) { /* print the rest without dot */
+ cur += sprintf( cur, "%02x", buffer[tmp++] );
}
- while (length != 0) {
- if (allprintable)
- sprintf(tmp, "%c", *tsap ++);
- else
- sprintf(tmp, "%02x", *tsap ++);
- strcat(cur, tmp);
- length --;
}
}
- return cur;
-
-} /* print_tsap */
-
-static int osi_decode_CC(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree)
-{
-
- /* CC & CR decoding in the same function */
-
- proto_tree *cotp_tree = NULL;
- proto_item *ti;
- u_short src_ref, checksum;
- u_char class_option, code, length;
- u_int i = 0;
-
- src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
- class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
- if (class_option > 4)
- return -1;
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
- (tpdu == CR_TPDU) ? "CR" : "CC",
- src_ref,
- dst_ref);
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (%s)", tpdu,
- (tpdu == CR_TPDU) ? "CR" : "CC");
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
- proto_tree_add_text(cotp_tree, offset + 4, 2,
- "Source reference: 0x%04x", src_ref);
- proto_tree_add_text(cotp_tree, offset + 6, 1,
- "Class option: 0x%02x", class_option);
- }
-
- if (tree)
- while(li > P_VAR_PART_CC + i - 1) {
-
- u_char c1;
- u_short s, s1,s2,s3,s4;
- u_int t1,t2,t3,t4;
-
- switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
- case VP_CHECKSUM :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, length,
- "Checksum: 0x%04x", checksum);
- i += length + 2;
- break;
- case VP_SRC_TSAP :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (src-tsap)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, length,
- "Calling TSAP: %s",
- print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
- length));
- i += length + 2;
- break;
- case VP_DST_TSAP :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (dst-tsap)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, length,
- "Called TSAP: %s",
- print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
- length));
- i += length + 2;
- break;
- case VP_TPDU_SIZE :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (tpdu-size)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, length,
- "TPDU size: %u", 2 << c1);
- i += length + 2;
- break;
- case VP_OPT_SEL :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (options)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- if (class_option == 1) {
- if (c1 & 0x8)
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 1,
- "Use of network expedited data");
- else
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 1,
- "Non use of network expedited data");
- if (c1 & 0x4)
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 1,
- "Use of Receipt confirmation");
- else
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 1,
- "Use of explicit AK variant");
- } else if (class_option == 4) {
- if (c1 & 0x2)
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 1,
- "Use 16 bit checksum ");
- else
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 1,
- "Non-use 16 bit checksum in class 4");
- }
- if (c1 & 0x1)
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 1,
- "Use of transport expedited data transfer\n");
- else
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 1,
- "Non-use of transport expedited data transfer");
- i += length + 2;
- break;
- case VP_ACK_TIME :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (ack time)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, length,
- "Ack time (ms): %u", s);
- i += length + 2;
- break;
- case VP_THROUGHPUT :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
- t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
- t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
- t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (throughput)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 4,
- "Target value / calling-called: %u o/s", t1);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 6, 4,
- "Minimum / calling-called: %u o/s", t2);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 10, 4,
- "Target value / called-calling: %u o/s", t3);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 14, 4,
- "Minimum / called-calling: %u o/s", t4);
- i += length + 2;
- break;
- case VP_TRANSIT_DEL :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
- s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
- s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
- s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (transit delay)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, 2,
- "Target value / calling-called: %u ms", s1);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 4, 2,
- "Minimum / calling-called: %u ms", s2);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 6, 2,
- "Target value / called-calling: %u ms", s3);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 8, 2,
- "Minimum / called-calling: %u ms", s4);
- i += length + 2;
- break;
- case VP_PRIORITY :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (priority)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, length,
- "Priority: %u", s);
- i += length + 2;
- break;
-
- case VP_VERSION_NR :
- length = pd[offset + P_VAR_PART_CC + i + 1];
- c1 = pd[offset + P_VAR_PART_CC + i + 2];
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i, 1,
- "Parameter code: 0x%02x (version)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, length,
- "Version: %u", c1);
- i += length + 2;
- break;
-
- case VP_REASSIGNMENT: /* todo */
- case VP_RES_ERROR :
- case VP_PROTECTION :
- case VP_PROTO_CLASS :
- default : /* no decoding */
- length = pd[offset + P_VAR_PART_CC + i + 1];
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 0, 1,
- "Parameter code: 0x%02x", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_CC + i + 2, length,
- "Parameter value: <not shown>");
- i += length + 2;
- break;
- }
- } /* while */
-
- offset += li + 1;
- dissect_data(pd, offset, fd, tree);
-
- return pi.captured_len; /* we dissected all of the containing PDU */
-
-} /* osi_decode_CC */
+ return( str );
+}
-static int osi_decode_DC(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree)
+gchar *print_area(const u_char *buffer, int length)
{
- proto_tree *cotp_tree;
- proto_item *ti;
- u_short src_ref, checksum = 0;
- u_char length = 0, code = 0;
-
- if (li > LI_MAX_DC)
- return -1;
-
- src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
-
- switch(li) {
- case LI_DC_WITHOUT_CHECKSUM :
- break;
- case LI_DC_WITH_CHECKSUM :
- if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
- return -1;
- length = pd[offset + P_VAR_PART_DC + 1];
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
- break;
- default :
- return -1;
- /*NOTREACHED*/
- break;
- } /* li */
+ /* to do : all real area decoding now: NET is assumed if id len is 1 more byte
+ * and take away all these stupid resource consuming local statics
+ */
+
+ static gchar str[MAX_AREA_LEN * 3 + 20]; /* reserve space for nice layout */
+ gchar *cur;
+ u_int tmp = 0;
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
- src_ref,
- dst_ref);
+ cur = str;
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (DC)", tpdu);
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
- proto_tree_add_text(cotp_tree, offset + 4, 2,
- "Source reference: 0x%04x", src_ref);
- if (code) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_DC + 0, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_DC + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_DC + 2, 2,
- "Checksum: 0x%04x", checksum);
- }
+ if (length <= 0 || length > MAX_AREA_LEN) {
+ sprintf( str, "<Invalid length of AREA>");
+ return( str );
}
-
- offset += li + 1;
-
- return offset;
-
-} /* osi_decode_DC */
-
-static int osi_decode_AK(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree)
-{
- proto_tree *cotp_tree = NULL;
- proto_item *ti;
- u_int tpdu_nr,i =0, r_lower_window_edge ;
- u_short cdt_in_ak;
- u_short checksum, seq_nr, r_seq_nr, r_cdt;
- u_char code, length;
-
- if (li > LI_MAX_AK)
- return -1;
-
- if (!is_LI_NORMAL_AK(li)) {
- tpdu_nr = pd[offset + P_TPDU_NR_234];
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
- tpdu_nr, dst_ref);
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (AK)", tpdu);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "Credit: %d", cdt);
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "Your TPDU number: 0x%02x", tpdu_nr);
- }
-
- while(li > P_VAR_PART_NAK + i - 1) {
- switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
- case VP_CHECKSUM :
- length = pd[offset + P_VAR_PART_NAK + i + 1];
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
- if (tree) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 0, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 2, 2,
- "Checksum: 0x%04x", checksum);
- }
- i += length + 2;
- break;
- case VP_FLOW_CNTL :
- length = pd[offset + P_VAR_PART_NAK + i + 1];
- r_lower_window_edge =
- EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
- r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
- r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
- if (tree) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 0, 1,
- "Parameter code: 0x%02x (flow control)",
- code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 2, 4,
- "Lower window edge: 0x%08x",
- r_lower_window_edge);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 6, 2,
- "Sequence number: 0x%04x",
- r_seq_nr);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 8, 2,
- "Credit: 0x%04x",
- r_cdt);
- }
- i += length + 2;
- break;
- case VP_SEQ_NR :
- length = pd[offset + P_VAR_PART_NAK + i + 1];
- seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
- if (tree) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 0, 1,
- "Parameter code: 0x%02x (seq number)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 2, 2,
- "Sequence number: 0x%04x", seq_nr);
- }
- i += length + 2;
- break;
- default :
- length = pd[offset + P_VAR_PART_NAK + i + 1];
- if (tree) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 0, 1,
- "Parameter code: 0x%02x (unknown)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_NAK + i + 2, length,
- "Parameter value: <not shown>");
- }
- i += length + 2;
- break;
- } /* code */
- }
- } else { /* extended format */
-
- tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
- cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
- tpdu_nr, dst_ref);
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (AK)", tpdu);
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
- proto_tree_add_text(cotp_tree, offset + 4, 4,
- "Your TPDU number: 0x%08x", tpdu_nr);
- proto_tree_add_text(cotp_tree, offset + 8, 2,
- "Credit: 0x%04x", cdt_in_ak);
+
+ if ( ( ( NSAP_IDI_ISODCC == *buffer )
+ || ( NSAP_IDI_GOSIP2 == *buffer )
+ )
+ &&
+ ( ( RFC1237_FULLAREA_LEN == length )
+ || ( RFC1237_FULLAREA_LEN + 1 == length )
+ )
+ ) { /* AFI is good and length is long enough */
+
+ if ( length > RFC1237_FULLAREA_LEN + 1 ) { /* Special Case Designated IS */
+ sprintf( str, "<Invalid length of AREA for DCC / GOSIP AFI>");
+ return( str );
}
-
- while(li > P_VAR_PART_EAK + i - 1) {
- switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
- case VP_CHECKSUM :
- length = pd[offset + P_VAR_PART_EAK + i + 1];
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
- if (tree) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 0, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 2, 2,
- "Checksum: 0x%04x", checksum);
- }
- i += length + 2;
- break;
- case VP_FLOW_CNTL :
- length = pd[offset + P_VAR_PART_EAK + i + 1];
- r_lower_window_edge =
- EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
- r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
- r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
- if (tree) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 0, 1,
- "Parameter code: 0x%02x (flow control)",
- code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 2, 4,
- "Lower window edge: 0x%08x",
- r_lower_window_edge);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 6, 2,
- "Sequence number: 0x%04x",
- r_seq_nr);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 8, 2,
- "Credit: 0x%04x",
- r_cdt);
- }
- i += length + 2;
- break;
- case VP_SEQ_NR :
- length = pd[offset + P_VAR_PART_EAK + i + 1];
- seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
- if (tree) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 0, 1,
- "Parameter code: 0x%02x (seq number)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 2, 2,
- "Sequence number: 0x%04x", seq_nr);
- }
- i += length + 2;
- break;
- default :
- length = pd[offset + P_VAR_PART_EAK + i + 1];
- if (tree) {
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 0, 1,
- "Parameter code: 0x%02x (unknown)", code);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 1, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree,
- offset + P_VAR_PART_EAK + i + 2, length,
- "Parameter value: <not shown>");
- }
- i += length + 2;
- break;
- } /* code */
+
+ cur += sprintf( cur, "[%02x|%02x:%02x][%02x|%02x:%02x:%02x|%02x:%02x]",
+ buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],
+ buffer[5], buffer[6], buffer[7], buffer[8] );
+ cur += sprintf( cur, "[%02x:%02x|%02x:%02x]",
+ buffer[9], buffer[10], buffer[11], buffer[12] );
+ if ( RFC1237_FULLAREA_LEN + 1 == length ) {
+ sprintf( cur, "-[%02x]", buffer[20] );
}
-
- } /* is_LI_NORMAL_AK */
-
- offset += li + 1;
-
- return offset;
-
-} /* osi_decode_AK */
-
-static int osi_decode_EA(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree)
-{
- proto_tree *cotp_tree;
- proto_item *ti;
- u_int tpdu_nr ;
- u_short checksum = 0;
- u_char code = 0;
- u_char length = 0;
-
- if (li > LI_MAX_EA)
- return -1;
-
- switch (li) {
- case LI_NORMAL_EA_WITH_CHECKSUM :
- tpdu_nr = pd[offset + P_TPDU_NR_234];
- code = pd[offset + P_VAR_PART_NDT];
- length = pd[offset + P_VAR_PART_NDT + 1];
- if (code != VP_CHECKSUM || length != 1)
- return -1;
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
- break;
- case LI_NORMAL_EA_WITHOUT_CHECKSUM :
- tpdu_nr = pd[offset + P_TPDU_NR_234];
- break;
- case LI_EXTENDED_EA_WITH_CHECKSUM :
- tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
- code = pd[offset + P_VAR_PART_EDT];
- length = pd[offset + P_VAR_PART_EDT + 1];
- if (code != VP_CHECKSUM || length != 1)
- return -1;
- checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
- break;
- case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
- tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
- break;
- default : /* bad TPDU */
- return -1;
- /*NOTREACHED*/
- break;
- } /* li */
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO,
- "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (EA)", tpdu);
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
-
- switch (li) {
- case LI_NORMAL_EA_WITH_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "Your TPDU number: 0x%02x", tpdu_nr);
- proto_tree_add_text(cotp_tree, offset + 5, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree, offset + 6, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree, offset + 7, 2,
- "Checksum: 0x%04x", checksum);
- break;
- case LI_NORMAL_EA_WITHOUT_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "Your TPDU number: 0x%02x", tpdu_nr);
- break;
- case LI_EXTENDED_EA_WITH_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 4,
- "Your TPDU number: 0x%08x", tpdu_nr);
- proto_tree_add_text(cotp_tree, offset + 8, 1,
- "Parameter code: 0x%02x (checksum)", code);
- proto_tree_add_text(cotp_tree, offset + 9, 1,
- "Parameter length: %u", length);
- proto_tree_add_text(cotp_tree, offset + 10, 2,
- "Checksum: 0x%04x", checksum);
- break;
- case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
- proto_tree_add_text(cotp_tree, offset + 4, 4,
- "Your TPDU number: 0x%08x", tpdu_nr);
- break;
- default :
- break;
- } /* li */
- } /* tree */
-
- offset += li + 1;
-
- return offset;
-
-} /* osi_decode_EA */
-
-static int osi_decode_ER(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree)
-{
- proto_tree *cotp_tree;
- proto_item *ti;
- u_char *str;
-
- if (li > LI_MAX_ER)
- return -1;
-
- switch(pd[offset + P_REJECT_ER]) {
- case 0 :
- str = "Reason not specified";
- break;
- case 1 :
- str = "Invalid parameter code";
- break;
- case 2 :
- str = "Invalid TPDU type";
- break;
- case 3 :
- str = "Invalid parameter value";
- break;
- default:
- return -1;
- /*NOTREACHED*/
- break;
+ return str;
}
-
- if (check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
- cotp_tree = proto_item_add_subtree(ti, ett_cotp);
- proto_tree_add_text(cotp_tree, offset, 1,
- "Length indicator: %d", li);
- proto_tree_add_text(cotp_tree, offset + 1, 1,
- "TPDU code: 0x%x (ER)", tpdu);
- proto_tree_add_text(cotp_tree, offset + 2, 2,
- "Destination reference: 0x%04x", dst_ref);
- proto_tree_add_text(cotp_tree, offset + 4, 1,
- "Reject cause: %s", str);
- }
-
- offset += li + 1;
-
- return offset;
-
-} /* osi_decode_ER */
-
-/* Returns TRUE if we found at least one valid COTP PDU, FALSE
- otherwise. */
-static gboolean dissect_cotp_internal(const u_char *pd, int offset,
- frame_data *fd, proto_tree *tree,
- gboolean uses_inactive_subset)
-{
- gboolean first_tpdu = TRUE;
- int new_offset;
- gboolean found_cotp = FALSE;
- gboolean subdissector_found = FALSE;
-
- /* Initialize the COL_INFO field; each of the TPDUs will have its
- information appended. */
- if (check_col(fd, COL_INFO))
- col_add_str(fd, COL_INFO, "");
-
- while (IS_DATA_IN_FRAME(offset)) {
- if (!first_tpdu) {
- if (check_col(fd, COL_INFO))
- col_append_str(fd, COL_INFO, ", ");
- }
- if ((li = pd[offset + P_LI]) == 0) {
- if (check_col(fd, COL_INFO))
- col_append_str(fd, COL_INFO, "Length indicator is zero");
- if (!first_tpdu)
- dissect_data(pd, offset, fd, tree);
- return found_cotp;
- }
- if (!BYTES_ARE_IN_FRAME(offset, P_LI + li + 1)) {
- if (check_col(fd, COL_INFO))
- col_append_str(fd, COL_INFO, "Captured data in frame doesn't include entire frame");
- if (!first_tpdu)
- dissect_data(pd, offset, fd, tree);
- return found_cotp;
- }
-
- tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
- cdt = pd[offset + P_CDT] & 0x0F;
- dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
-
- switch (tpdu) {
- case CC_TPDU :
- case CR_TPDU :
- new_offset = osi_decode_CC(pd, offset, fd, tree);
- break;
- case DR_TPDU :
- new_offset = osi_decode_DR(pd, offset, fd, tree);
- break;
- case DT_TPDU :
- if (osi_decode_DT(pd, offset, fd, tree, uses_inactive_subset))
- subdissector_found = TRUE;
- new_offset = pi.captured_len; /* DT PDUs run to the end of the packet */
- break;
- case ED_TPDU :
- new_offset = osi_decode_ED(pd, offset, fd, tree);
- break;
- case RJ_TPDU :
- new_offset = osi_decode_RJ(pd, offset, fd, tree);
- break;
- case DC_TPDU :
- new_offset = osi_decode_DC(pd, offset, fd, tree);
- break;
- case AK_TPDU :
- new_offset = osi_decode_AK(pd, offset, fd, tree);
- break;
- case EA_TPDU :
- new_offset = osi_decode_EA(pd, offset, fd, tree);
- break;
- case ER_TPDU :
- new_offset = osi_decode_ER(pd, offset, fd, tree);
- break;
- default :
- if (first_tpdu && check_col(fd, COL_INFO))
- col_append_fstr(fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
- new_offset = -1; /* bad PDU type */
- break;
- }
-
- if (new_offset == -1) { /* incorrect TPDU */
- if (!first_tpdu)
- dissect_data(pd, offset, fd, tree);
- break;
- }
-
- if (first_tpdu) {
- /* Well, we found at least one valid COTP PDU, so I guess this
- is COTP. */
- if (!subdissector_found && check_col(fd, COL_PROTOCOL))
- col_add_str(fd, COL_PROTOCOL, "COTP");
- found_cotp = TRUE;
+ else { /* print standard format */
+ if ( 4 < length ) {
+ while ( tmp < length / 4 ) { /* 16/4==4 four Octets left to print */
+ cur += sprintf( str, "%02x%02x%02x%02x.", buffer[tmp++], buffer[tmp++],
+ buffer[tmp++], buffer[tmp++] );
+ }
+ if ( 1 == tmp ) { /* Special case for Designated IS */
+ sprintf( --cur, "-%02x", buffer[tmp] );
+ }
+ else {
+ for ( ; tmp < length; ) { /* print the rest without dot */
+ cur += sprintf( cur, "%02x", buffer[tmp++] );
+ }
+ }
}
-
- offset = new_offset;
- first_tpdu = FALSE;
+ return( str );
}
- return found_cotp;
-} /* dissect_cotp_internal */
+} /* print_area */
-void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
- proto_tree *tree)
-{
- if (!dissect_cotp_internal(pd, offset, fd, tree, FALSE))
- dissect_data(pd, offset, fd, tree);
-}
-
-
-/*
- * CLNP part
- */
-
-#define MAX_NSAP_LEN 20
-static gchar *print_nsap(const u_char *nsap, int length)
+gchar *print_nsap_net( const u_char *buffer, int length)
{
+ /* to do : NSAP / NET decoding */
- /* to do : real NSAP decoding */
+ static gchar str[MAX_NSAP_LEN * 3 + 50]; /* reserve space for nice layout */
+ gchar *cur;
- static gchar str[3][MAX_NSAP_LEN * 3 + 1];
- static gchar *cur;
- gchar tmp[5];
+ cur = str;
- if (cur == &str[0][0]) {
- cur = &str[1][0];
- } else if (cur == &str[1][0]) {
- cur = &str[2][0];
- } else {
- cur = &str[0][0];
+ if ( (length <= 0 ) || ( length > MAX_NSAP_LEN ) ) {
+ sprintf( str, "<Invalid length of NSAP>");
+ return( str );
}
-
- cur[0] = '\0';
- if (length <= 0 || length > MAX_NSAP_LEN)
- sprintf(cur, "<invalid NSAP>");
- else
- while (length != 1) {
- sprintf(tmp, "%02x:", *nsap ++);
- strcat(cur, tmp);
- length --;
+ if ( ( length == RFC1237_NSAP_LEN ) || ( length == RFC1237_NSAP_LEN + 1 ) ) {
+ cur += sprintf( cur, "%s", print_area( buffer, RFC1237_FULLAREA_LEN ) );
+ cur += sprintf( cur, "%s", print_system_id( buffer + RFC1237_FULLAREA_LEN,
+ RFC1237_SYSTEMID_LEN ) );
+ cur += sprintf( cur, "[%02x]",
+ buffer[ RFC1237_FULLAREA_LEN + RFC1237_SYSTEMID_LEN ] );
+ if ( length == RFC1237_NSAP_LEN + 1 ) {
+ cur += sprintf( cur, "-%02x", buffer[ length -1 ] );
}
- sprintf(tmp, "%02x", *nsap);
- strcat(cur, tmp);
- return cur;
-
-} /* print_nsap */
-
-void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
- proto_tree *tree)
-{
-
- struct clnp_header clnp;
- proto_tree *clnp_tree = NULL;
- proto_item *ti;
- u_char src_len, dst_len, nsel;
- u_int first_offset = offset;
- char flag_string[6+1];
- char *pdu_type_string;
- guint16 segment_length;
- guint16 segment_offset = 0;
- guint len;
-
- if (check_col(fd, COL_PROTOCOL))
- col_add_str(fd, COL_PROTOCOL, "CLNP");
-
- /* avoid alignment problem */
- memcpy(&clnp, &pd[offset], sizeof(clnp));
-
- if (clnp.cnf_proto_id == NLPID_NULL) {
- if (check_col(fd, COL_INFO))
- col_add_str(fd, COL_INFO, "Inactive subset");
- if (tree) {
- ti = proto_tree_add_item(tree, proto_clnp, offset, 1, NULL);
- clnp_tree = proto_item_add_subtree(ti, ett_clnp);
- proto_tree_add_uint_format(clnp_tree, hf_clnp_id, offset, 1,
- clnp.cnf_proto_id,
- "Inactive subset");
- }
- dissect_cotp_internal(pd, offset+1, fd, tree, TRUE);
- return;
- }
-
- if (!BYTES_ARE_IN_FRAME(offset, sizeof(clnp))) {
- dissect_data(pd, offset, fd, tree);
- return;
+ return ( str );
}
-
- /* return if version not known */
- if (clnp.cnf_vers != ISO8473_V1) {
- dissect_data(pd, offset, fd, tree);
- return;
+ else { /* probably format as standard */
+ return( print_area( buffer, length ) );
}
+} /* print_nsap */
- /* fixed part decoding */
- segment_length = EXTRACT_SHORT(&clnp.cnf_seglen_msb);
- flag_string[0] = '\0';
- if (clnp.cnf_type & CNF_SEG_OK)
- strcat(flag_string, "S ");
- if (clnp.cnf_type & CNF_MORE_SEGS)
- strcat(flag_string, "M ");
- if (clnp.cnf_type & CNF_ERR_OK)
- strcat(flag_string, "E ");
- pdu_type_string = val_to_str(clnp.cnf_type & CNF_TYPE, npdu_type_vals,
- "Unknown (0x%02x)");
- if (tree) {
- ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL);
- clnp_tree = proto_item_add_subtree(ti, ett_clnp);
- proto_tree_add_item(clnp_tree, hf_clnp_id, offset, 1,
- clnp.cnf_proto_id);
- proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1,
- clnp.cnf_hdr_len);
- proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1,
- clnp.cnf_vers);
- proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, offset + 3, 1,
- clnp.cnf_ttl,
- "TTL: %d (%d secs)",
- clnp.cnf_ttl, clnp.cnf_ttl / 2);
- proto_tree_add_uint_format(clnp_tree, hf_clnp_type, offset + 4, 1,
- clnp.cnf_type,
- "Type code: 0x%02x (%s%s)",
- clnp.cnf_type,
- flag_string,
- pdu_type_string);
- proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2,
- segment_length);
- proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, offset + 7, 2,
- EXTRACT_SHORT(&clnp.cnf_cksum_msb),
- "Checksum: 0x%04x",
- EXTRACT_SHORT(&clnp.cnf_cksum_msb));
- } /* tree */
+gchar *calc_checksum( const u_char *buffer, u_int len, u_int checksum) {
+ u_int calc_sum = 0;
+ u_int count = 0;
- /* stop here if header is not complete */
+ static char *checksum_string[] = { "Not Used",
+ "Is good",
+ "Is wrong" };
+ if ( 0 == checksum )
+ return( checksum_string[0] );
- if (!BYTES_ARE_IN_FRAME(offset, clnp.cnf_hdr_len)) {
- if (check_col(fd, COL_INFO))
- col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
- dissect_data(pd, offset, fd, tree);
- return;
+ for ( count = 0; count < len; count++ ) {
+ calc_sum += (u_int) buffer[count];
}
-
- /* address part */
+ calc_sum %= 255; /* modulo 255 divison */
- offset += P_ADDRESS_PART;
- dst_len = pd[offset];
- nsel = pd[offset + dst_len];
- src_len = pd[offset + dst_len + 1];
-
- if (tree) {
- proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1,
- dst_len);
- proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len,
- &pd[offset + 1],
- "Destination address: %s",
- print_nsap(&pd[offset + 1], dst_len));
- proto_tree_add_item(clnp_tree, hf_clnp_src_length,
- offset + 1 + dst_len, 1, src_len);
- proto_tree_add_bytes_format(clnp_tree, hf_clnp_src,
- offset + dst_len + 2, src_len,
- &pd[offset + dst_len + 2],
- "Source address: %s",
- print_nsap(&pd[offset + dst_len + 2], src_len));
- }
-
- if (check_col(fd, COL_RES_NET_SRC))
- col_add_fstr(fd, COL_RES_NET_SRC, "%s",
- print_nsap(&pd[offset + dst_len + 2], src_len));
- if (check_col(fd, COL_RES_NET_DST))
- col_add_fstr(fd, COL_RES_NET_DST, "%s",
- print_nsap(&pd[offset + 1], dst_len));
-
- /* Segmentation Part */
-
- offset += dst_len + src_len + 2;
-
- if (clnp.cnf_type & CNF_SEG_OK) {
- struct clnp_segment seg; /* XXX - not used */
- memcpy(&seg, &pd[offset], sizeof(seg)); /* XXX - not used */
-
- segment_offset = EXTRACT_SHORT(&pd[offset + 2]);
- if (tree) {
- proto_tree_add_text(clnp_tree, offset, 2,
- "Data unit identifier: 0x%04x",
- EXTRACT_SHORT(&pd[offset]));
- proto_tree_add_text(clnp_tree, offset + 2 , 2,
- "Segment offset: %u",
- segment_offset);
- proto_tree_add_text(clnp_tree, offset + 4 , 2,
- "Total length: %u",
- EXTRACT_SHORT(&pd[offset + 4]));
- }
-
- offset += 6;
- }
-
- if (tree) {
- /* To do : decode options */
-
- proto_tree_add_text(clnp_tree, offset,
- clnp.cnf_hdr_len + first_offset - offset,
- "Options/Data: <not shown>");
- }
-
- /* Length of CLNP datagram plus headers above it. */
- len = segment_length + first_offset;
-
- /* Set the payload and captured-payload lengths to the minima of (the
- datagram length plus the length of the headers above it) and the
- frame lengths. */
- if (pi.len > len)
- pi.len = len;
- if (pi.captured_len > len)
- pi.captured_len = len;
-
- offset = first_offset + clnp.cnf_hdr_len;
-
- /* For now, dissect the payload of segments other than the initial
- segment as data, rather than handing them off to the transport
- protocol, just as we do with fragments other than the first
- fragment in a fragmented IP datagram; in the future, we will
- probably reassemble fragments for IP, and may reassemble segments
- for CLNP. */
- if ((clnp.cnf_type & CNF_SEG_OK) && segment_offset != 0) {
- if (check_col(fd, COL_INFO))
- col_add_fstr(fd, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
- pdu_type_string, flag_string, segment_offset);
- dissect_data(pd, offset, fd, tree);
- return;
- }
-
- if (IS_DATA_IN_FRAME(offset)) {
- switch (clnp.cnf_type & CNF_TYPE) {
-
- case DT_NPDU:
- case MD_NPDU:
- /* Continue with COTP if any data.
- XXX - if this isn't the first Derived PDU of a segmented Initial
- PDU, skip that? */
-
- if (nsel == NSEL_TP) { /* just guessing here - valid for DECNet-OSI */
- if (dissect_cotp_internal(pd, offset, fd, tree, FALSE))
- return; /* yes, it appears to be COTP */
- }
- break;
-
- case ER_NPDU:
- /* The payload is the header and "none, some, or all of the data
- part of the discarded PDU", i.e. it's like an ICMP error;
- just as we don't yet trust ourselves to be able to dissect
- the payload of an ICMP error packet, we don't yet trust
- ourselves to dissect the payload of a CLNP ER packet. */
- break;
-
- case ERQ_NPDU:
- case ERP_NPDU:
- /* XXX - dissect this */
- break;
- }
- }
- if (check_col(fd, COL_INFO))
- col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
- dissect_data(pd, offset, fd, tree);
-
-} /* dissect_clnp */
+ if ( 0 == calc_sum )
+ return( checksum_string[1] );
+ else
+ return( checksum_string[2] );
+}
/* main entry point */
@@ -1747,7 +217,7 @@ const value_string nlpid_vals[] = {
{ NLPID_ISO8473_CLNP, "CLNP" },
{ NLPID_ISO9542_ESIS, "ESIS" },
{ NLPID_ISO10589_ISIS, "ISIS" },
- { NLPID_ISO10747, "ISO 10747" },
+ { NLPID_ISO10747_IDRP, "IDRP" },
{ NLPID_ISO9542X25_ESIS, "ESIS (X.25)" },
{ NLPID_ISO10030, "ISO 10030" },
{ NLPID_ISO11577, "ISO 11577" },
@@ -1759,20 +229,16 @@ const value_string nlpid_vals[] = {
void dissect_osi(const u_char *pd, int offset, frame_data *fd,
proto_tree *tree)
{
-
switch (pd[offset]) {
- /* ESIS is not currently decoded */
+ /* ESIS (X.25) is not currently decoded */
case NLPID_ISO8473_CLNP:
case NLPID_NULL: /* "Inactive Subset" of ISO 8473 CLNP */
dissect_clnp(pd, offset, fd, tree);
break;
case NLPID_ISO9542_ESIS:
- if (check_col(fd, COL_PROTOCOL)) {
- col_add_str(fd, COL_PROTOCOL, "ESIS");
- }
- dissect_data(pd, offset, fd, tree);
+ dissect_esis(pd, offset, fd, tree);
break;
case NLPID_ISO9542X25_ESIS:
if (check_col(fd, COL_PROTOCOL)) {
@@ -1783,6 +249,12 @@ void dissect_osi(const u_char *pd, int offset, frame_data *fd,
case NLPID_ISO10589_ISIS:
dissect_isis(pd, offset, fd, tree);
break;
+ case NLPID_ISO10747_IDRP:
+ if (check_col(fd, COL_PROTOCOL)) {
+ col_add_str(fd, COL_PROTOCOL, "IDRP");
+ }
+ dissect_data(pd, offset, fd, tree);
+ break;
default:
if (check_col(fd, COL_PROTOCOL)) {
col_add_str(fd, COL_PROTOCOL, "ISO");
@@ -1793,76 +265,4 @@ void dissect_osi(const u_char *pd, int offset, frame_data *fd,
dissect_data(pd, offset, fd, tree);
break;
}
-
} /* dissect_osi */
-
-void proto_register_clnp(void)
-{
- static hf_register_info hf[] = {
- { &hf_clnp_id,
- { "Protocol identifier", "clnp.id", FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0,
- "" }},
-
- { &hf_clnp_length,
- { "Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0,
- "" }},
-
- { &hf_clnp_version,
- { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
- "" }},
-
- { &hf_clnp_ttl,
- { "TTL", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
- "" }},
-
- { &hf_clnp_type,
- { "Type code", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
- "" }},
-
- { &hf_clnp_pdu_length,
- { "PDU segment length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0,
- "" }},
-
- { &hf_clnp_checksum,
- { "Checksum", "clnp.checksum",FT_UINT16, BASE_DEC, NULL, 0x0,
- "" }},
-
- { &hf_clnp_dest_length,
- { "Destination address length", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0,
- "" }},
-
- { &hf_clnp_dest,
- { "Destination address", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0,
- "" }},
-
- { &hf_clnp_src_length,
- { "Source address length","clnp.ssap.len",FT_UINT8, BASE_DEC, NULL, 0x0,
- "" }},
-
- { &hf_clnp_src,
- { "Source address", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0,
- "" }},
- };
- static gint *ett[] = {
- &ett_clnp,
- };
-
- proto_clnp = proto_register_protocol("ISO CLNP", "clnp");
- proto_register_field_array(proto_clnp, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-}
-
-void proto_register_cotp(void)
-{
- /* static hf_register_info hf[] = {
- { &variable,
- { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
- };*/
- static gint *ett[] = {
- &ett_cotp,
- };
-
- proto_cotp = proto_register_protocol("ISO COTP", "cotp");
- /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
- proto_register_subtree_array(ett, array_length(ett));
-}
diff --git a/packet-osi.h b/packet-osi.h
index 31ebed81a2..985a74ea66 100644
--- a/packet-osi.h
+++ b/packet-osi.h
@@ -1,6 +1,6 @@
/* packet-osi.h
*
- * $Id: packet-osi.h,v 1.1 2000/02/15 21:02:48 gram Exp $
+ * $Id: packet-osi.h,v 1.2 2000/04/15 22:11:12 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -20,8 +20,92 @@
* 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.
+*/
+
+#ifndef _PACKET_OSI_H
+#define _PACKET_OSI_H
+
+/* OSI Global defines, common for all OSI protocols */
+
+#define MAX_NSAP_LEN 30
+#define MAX_SYSTEMID_LEN 15
+#define MAX_AREA_LEN 30
+
+#define RFC1237_NSAP_LEN 20
+#define RFC1237_FULLAREA_LEN 13
+#define RFC1237_SYSTEMID_LEN 6
+#define RFC1237_SELECTOR_LEN 1
+
+#define RFC1237_IDI_LEN 2
+#define RFC1237_AFI_LEN 1
+#define RFC1237_DFI_LEN 1
+#define RFC1237_ORG_LEN 3
+#define RFC1237_AA_LEN 3
+#define RFC1237_RSVD_LEN 2
+#define RFC1237_RD_LEN 2
+#define RFC1237_AREA_LEN 3
+
+
+#define NSAP_IDI_ISODCC 0x39
+#define NSAP_IDI_GOSIP2 0x47
+
+#define PDU_TYPE_ESIS_ESH 100
+#define PDU_TYPE_ESIS_ISH 101
+#define PDU_TYPE_ESIS_RD 102
+
+#define PDU_TYPE_ISIS_L1_HELLO 201
+#define PDU_TYPE_ISIS_L2_HELLO 202
+#define PDU_TYPE_ISIS_PTP_HELLO 203
+#define PDU_TYPE_ISIS_L1_CSNP 204
+#define PDU_TYPE_ISIS_L1_PSNP 205
+#define PDU_TYPE_ISIS_L2_CSNP 206
+#define PDU_TYPE_ISIS_L2_PSNP 207
+
+
+
+
+
+#define PROTO_STRING_ISIS "ISO 10598 ISIS InTRA Domain Routeing Information Exchange Protocol"
+#define PROTO_STRING_IDRP "ISO 10747 IDRP InTER Domain Routeing Information Exchange Protocol"
+#define PROTO_STRING_ESIS "ISO 9542 ESIS Routeing Information Exchange Protocol"
+#define PROTO_STRING_CLNP "ISO 8473 CLNP ConnectionLess Network Protocol"
+#define PROTO_STRING_COTP "ISO 8073 COTP Connection-Oriented Transport Protocol"
+#define PROTO_STRING_LSP "ISO 10598 ISIS Link State Protocol Data Unit"
+#define PROTO_STRING_CSNP "ISO 10598 ISIS Complete Sequence Numbers Protocol Data Unit"
+#define PROTO_STRING_PSNP "ISO 10598 ISIS Partial Sequence Numbers Protocol Data Unit"
+
+#define OSI_PDU_TYPE_MASK 0x1f
+#define BIS_PDU_TYPE MASK 0xff
+
+
+#define BIT_1 0x01
+#define BIT_2 0x02
+#define BIT_3 0x04
+#define BIT_4 0x08
+#define BIT_5 0x10
+#define BIT_6 0x20
+#define BIT_7 0x40
+#define BIT_8 0x80
+
+#define BIT_9 0x0100
+#define BIT_10 0x0200
+#define BIT_11 0x0400
+#define BIT_12 0x0800
+#define BIT_13 0x1000
+#define BIT_14 0x2000
+#define BIT_15 0x4000
+#define BIT_16 0x8000
+
+
+/*
+ * published API functions
*/
+extern void dissect_osi( const u_char *, int, frame_data *, proto_tree *);
+extern gchar *print_nsap_net ( const u_char *, int );
+extern gchar *print_area ( const u_char *, int );
+extern gchar *print_system_id( const u_char *, int );
+extern gchar *calc_checksum ( const u_char *, u_int, u_int );
+
+#endif /* _PACKET_OSI_H */
-void dissect_cotp(const u_char *, int, frame_data *, proto_tree *);
-void dissect_osi(const u_char *, int, frame_data *, proto_tree *);
diff --git a/packet-x25.c b/packet-x25.c
index 51141f7969..e6977c2c60 100644
--- a/packet-x25.c
+++ b/packet-x25.c
@@ -2,7 +2,7 @@
* Routines for x25 packet disassembly
* Olivier Abad <abad@daba.dhis.net>
*
- * $Id: packet-x25.c,v 1.23 2000/04/13 18:18:53 gram Exp $
+ * $Id: packet-x25.c,v 1.24 2000/04/15 22:11:12 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -40,6 +40,7 @@
#include "packet.h"
#include "packet-ip.h"
#include "packet-osi.h"
+#include "packet-clnp.h"
#include "nlpid.h"
#define FROM_DCE 0x80