Ralf Schneider's changes to enhance to OSI CLNP, CLTP, and ISIS support
authorGuy Harris <guy@alum.mit.edu>
Sat, 15 Apr 2000 22:11:26 +0000 (22:11 -0000)
committerGuy Harris <guy@alum.mit.edu>
Sat, 15 Apr 2000 22:11:26 +0000 (22:11 -0000)
and to add OSI ESIS support.

svn path=/trunk/; revision=1865

19 files changed:
AUTHORS
Makefile.am
doc/ethereal.pod.template
nlpid.h
packet-clnp.c [new file with mode: 0644]
packet-clnp.h [new file with mode: 0644]
packet-esis.c [new file with mode: 0644]
packet-esis.h [new file with mode: 0644]
packet-isis-clv.c
packet-isis-hello.c
packet-isis-lsp.c
packet-isis-snp.c
packet-isis.c
packet-isis.h
packet-osi-options.c [new file with mode: 0644]
packet-osi-options.h [new file with mode: 0644]
packet-osi.c
packet-osi.h
packet-x25.c

diff --git a/AUTHORS b/AUTHORS
index 7ed2fedf732e04f09dc39e71fb23c21fc6a7e5c4..c79c2793cfdefe60e1abae043d9fee356a862efe 100644 (file)
--- 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.
 
index 813c2ec05ec2320964003fb06406b27af50abb22..245910c5a323f8a8a72305bac6460bb1512cc480 100644 (file)
@@ -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   \
index 896800d88a5a513eacd87e965d71fe36fda1d863..0d4615666db35f249bdecb1e7cdede0a0bc563c6 100644 (file)
@@ -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 2ddc5994ae381a0776931ac0c4c460f1eec957d0..cec1e25df000273c91c575fae0482503f137cefd 100644 (file)
--- 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 (file)
index 0000000..7a7478a
--- /dev/null
@@ -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 (file)
index 0000000..9d76fd0
--- /dev/null
@@ -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 (file)
index 0000000..8186990
--- /dev/null
@@ -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 (file)
index 0000000..c6e49b2
--- /dev/null
@@ -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 */
index 8cbfc6f53999d76648df082025fdf88f32938685..1de98279c925a5652e98e7a8eef1984eda616aa2 100644 (file)
@@ -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,  
index a9ae715ffe3597ffb5f34500d78c3911b918a2ae..3c53125469a7057d9e40103b01ea63ce60e6bbb7 100644 (file)
@@ -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
 #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));
 }
index ef8793ace49fd825a14fa8c9003b5b6183d6a7c9..296123d7f0669e34d6bcc874b1e568810f995031 100644 (file)
@@ -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));
 }
index b5853f3528608d847d12059f619e7ec0b14df3a1..6b37ac5f0da9989df1fb63161e53d891a65b6674 100644 (file)
@@ -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));
 }
index ead27120e94f6fba698b920464aaa73767494089..ef764fbeb297e36ba78291a03bce18e94863c783 100644 (file)
@@ -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
 #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));
 }
index 9ebc600a288db83ce2525f8977c8058497a00647..1c49542a9cacff6d8a8f3bb87ffe4eed59dd86e0 100644 (file)
@@ -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
 /*
  * 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 (file)
index 0000000..9db8f89
--- /dev/null
@@ -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 (file)
index 0000000..fdd54d8
--- /dev/null
@@ -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 */
index ebd5c015a48067291b4aeae9eb0cd146c61ff9b7..2b242597b6984f14f8fa5016b4c0f7aa8de8ee1d 100644 (file)
@@ -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)
+ * 
  *
  */
 
 #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));
-}
index 31ebed81a21d2d4d0b72e2728461a568a9a8b3bd..985a74ea6685dae12eeda5ba964c59e94b22c6ba 100644 (file)
@@ -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>
  * 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 *);
index 51141f796916464372ac8badbf3499d775c4061c..e6977c2c60c4c4ddef75e6e58fad147e68670752 100644 (file)
@@ -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