GIOP CosNaming support, from Frank Singleton.
[obnox/wireshark/wip.git] / packet-isis.c
index 5d635e160487e2f7d4dbc45cf34797fc04d19c06..767b594920ee495f24ada3b7f469763ccfec0085 100644 (file)
@@ -1,14 +1,13 @@
-/* packet-isis-core.c
+/* packet-isis.c
  * Routines for ISO/OSI network and transport protocol packet disassembly, core
  * bits.
  *
- * $Id: packet-isis.c,v 1.4 2000/03/12 04:47:41 gram Exp $
+ * $Id: packet-isis.c,v 1.25 2001/07/02 02:09:26 guy Exp $
  * Stuart Stanley <stuarts@mxmail.net>
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * 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
 #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()
@@ -81,79 +81,27 @@ static const value_string isis_vals[] = {
  *     that we make sure we don't go off the end of the bleedin packet here!
  *
  * Input
- *     unt offset : Current offset into packet data.
- *     int len : length of to dump.
+ *     tvbuff_t * : tvbuffer for packet data
+ *     packet_info * : info for current packet
  *     proto_tree * : tree of display data.  May be NULL.
- *     frame_data * fd : frame data
+ *     int : current offset into packet data
  *     char * : format text
  *
  * Output:
  *     void (may modify proto tree)
  */
 void
-isis_dissect_unknown(int offset,guint length,proto_tree *tree,frame_data *fd,
-               char *fmat, ...){
+isis_dissect_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, 
+       int offset, 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);
+       proto_tree_add_text_valist(tree, tvb, offset, 
+               tvb_length_remaining(tvb, offset), 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()
  * 
@@ -162,123 +110,146 @@ char
  *     main isis 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)
+ *     tvbuff_t * : tvbuffer for packet data
+ *     packet_info * : info for current packet
  *     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_isis(const u_char *pd, int offset, frame_data *fd, 
-               proto_tree *tree) {
-       isis_hdr_t *ihdr;
+static void
+dissect_isis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
        proto_item *ti;
        proto_tree *isis_tree = NULL;
+       int offset = 0;
+       guint8 isis_version;
+       guint8 isis_header_length;
+       guint8 isis_type_reserved;
+       guint8 isis_type;
+       guint8 isis_system_id_len;
 
-       if (!BYTES_ARE_IN_FRAME(offset, sizeof(*ihdr))) {
-               isis_dissect_unknown(offset, sizeof(*ihdr), tree, fd,
-                       "not enough capture data for header (%d vs %d)",
-                       sizeof(*ihdr), END_OF_FRAME);
-               return;
-       }
-
-       ihdr = (isis_hdr_t *) &pd[offset];
+       if (check_col(pinfo->fd, COL_PROTOCOL))
+               col_set_str(pinfo->fd, COL_PROTOCOL, "ISIS");
+       if (check_col(pinfo->fd, COL_INFO))
+               col_clear(pinfo->fd, COL_INFO);
 
-       if (ihdr->isis_version != ISIS_REQUIRED_VERSION){
-               isis_dissect_unknown(offset, END_OF_FRAME, tree, fd,
+       isis_version = tvb_get_guint8(tvb, 2);
+       if (isis_version != ISIS_REQUIRED_VERSION){
+               if (check_col(pinfo->fd, COL_INFO)) {
+                       col_add_fstr(pinfo->fd, COL_INFO,
+                               "Unknown ISIS version (%u vs %u)",
+                               isis_version, ISIS_REQUIRED_VERSION );
+               }
+               isis_dissect_unknown(tvb, pinfo, tree, 0,
                        "Unknown ISIS version (%d vs %d)",
-                       ihdr->isis_version, ISIS_REQUIRED_VERSION );
+                       isis_version, ISIS_REQUIRED_VERSION);
                return;
        }
        
-       
+       isis_header_length = tvb_get_guint8(tvb, 1);
        if (tree) {
-               ti = proto_tree_add_item(tree, proto_isis, offset
-                       END_OF_FRAME, NULL );
+               ti = proto_tree_add_item(tree, proto_isis, tvb, 0
+                       tvb_length(tvb), FALSE );
                isis_tree = proto_item_add_subtree(ti, ett_isis);
-               proto_tree_add_item(isis_tree, hf_isis_irpd, offset, 1,
-                       ihdr->isis_irpd );
-               proto_tree_add_item(isis_tree, hf_isis_header_length,
-                       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_uint_format(isis_tree, hf_isis_type,
-                       offset + 4, 1, ihdr->isis_type,
-                       "Type: %s (R:%s%s%s)",
-                       val_to_str(ihdr->isis_type & ISIS_TYPE_MASK, isis_vals,
-                               "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 );
        }
 
+       if (tree) {
+               proto_tree_add_item(isis_tree, hf_isis_irpd, tvb, offset, 1,
+                       FALSE );
+       }
+       offset += 1;
 
-       /*
-        * 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 ( 
-                       ihdr->isis_type&ISIS_TYPE_MASK, isis_vals,
-                       "Unknown (0x%x)" ) );
+       if (tree) {
+               proto_tree_add_uint(isis_tree, hf_isis_header_length, tvb,
+                       offset, 1, isis_header_length );
        }
+       offset += 1;
+
+       if (tree) {
+               proto_tree_add_uint(isis_tree, hf_isis_version, tvb,
+                       offset, 1, isis_version );
+       }
+       offset += 1;
+
+       isis_system_id_len = tvb_get_guint8(tvb, 3);
+       if (tree) {
+               proto_tree_add_uint(isis_tree, hf_isis_system_id_length, tvb,
+                       offset, 1, isis_system_id_len );
+       }
+       offset += 1;
+
+       isis_type_reserved = tvb_get_guint8(tvb, 4);
+       isis_type = isis_type_reserved & ISIS_TYPE_MASK;
+       if (check_col(pinfo->fd, COL_INFO)) {
+               col_add_str(pinfo->fd, COL_INFO,
+                       val_to_str ( isis_type, isis_vals, "Unknown (0x%x)" ) );
+       }
+       if (tree) {
+               proto_tree_add_uint_format(isis_tree, hf_isis_type, tvb,
+                       offset, 1, isis_type,
+                       "PDU Type           : %s (R:%s%s%s)",
+                       val_to_str(isis_type, isis_vals, "Unknown (0x%x)"),
+                       (isis_type_reserved & ISIS_R8_MASK) ? "1" : "0",
+                       (isis_type_reserved & ISIS_R7_MASK) ? "1" : "0",
+                       (isis_type_reserved & ISIS_R6_MASK) ? "1" : "0");
+       }
+       offset += 1;
+
+       if (tree) {
+               proto_tree_add_item(isis_tree, hf_isis_version2, tvb, 5, 1,
+                       FALSE );
+       }
+       offset += 1;
+
+       if (tree) {
+               proto_tree_add_item(isis_tree, hf_isis_reserved, tvb, 6, 1,
+                       FALSE );
+       }
+       offset += 1;
+
+       if (tree) {
+               proto_tree_add_item(isis_tree, hf_isis_max_area_adr, tvb, 7, 1,
+                       FALSE );
+       }
+       offset += 1;
 
        /*
-        * Advance offset (we are past the header).
+        * Interpret the system ID length.
         */
-       offset += sizeof(*ihdr);
-       switch (ihdr->isis_type) {
+       if (isis_system_id_len == 0)
+               isis_system_id_len = 6; /* zero means 6-octet ID field length */
+       else if (isis_system_id_len == 255) {
+               isis_system_id_len = 0; /* 255 means null ID field */
+               /* XXX - what about the LAN ID? */
+       }
+       /* XXX - otherwise, must be in the range 1 through 8 */
+
+       switch (isis_type) {
        case ISIS_TYPE_L1_HELLO:
-               isis_dissect_isis_hello(ISIS_TYPE_L1_HELLO, 
-                       ihdr->isis_header_length, pd, offset, fd, isis_tree);
-               break;
        case ISIS_TYPE_L2_HELLO:
-               isis_dissect_isis_hello(ISIS_TYPE_L2_HELLO, 
-                       ihdr->isis_header_length, pd, offset, fd, isis_tree);
-               break;
        case ISIS_TYPE_PTP_HELLO:
-               isis_dissect_isis_hello(ISIS_TYPE_PTP_HELLO, 
-                       ihdr->isis_header_length, pd, offset, fd, isis_tree);
+               isis_dissect_isis_hello(tvb, pinfo, isis_tree, offset,
+                       isis_type, isis_header_length, isis_system_id_len);
                break;
        case ISIS_TYPE_L1_LSP:
-               isis_dissect_isis_lsp(ISIS_TYPE_L1_LSP, ihdr->isis_header_length,
-                       pd, offset, fd, isis_tree);
-               break;
        case ISIS_TYPE_L2_LSP:
-               isis_dissect_isis_lsp(ISIS_TYPE_L2_LSP, ihdr->isis_header_length,
-                       pd, offset, fd, isis_tree);
+               isis_dissect_isis_lsp(tvb, pinfo, isis_tree, offset,
+                       isis_type, isis_header_length, isis_system_id_len);
                break;
        case ISIS_TYPE_L1_CSNP:
-               isis_dissect_isis_csnp(ISIS_TYPE_L1_CSNP, 
-                       ihdr->isis_header_length, pd, offset, fd, isis_tree);
-               break;
        case ISIS_TYPE_L2_CSNP:
-               isis_dissect_isis_csnp(ISIS_TYPE_L2_CSNP,
-                       ihdr->isis_header_length, pd, offset, fd, isis_tree);
+               isis_dissect_isis_csnp(tvb, pinfo, isis_tree, offset,
+                       isis_type, isis_header_length, isis_system_id_len);
                break;
        case ISIS_TYPE_L1_PSNP:
-               isis_dissect_isis_psnp(ISIS_TYPE_L1_PSNP, 
-                       ihdr->isis_header_length, pd, offset, fd, isis_tree);
-               break;
        case ISIS_TYPE_L2_PSNP:
-               isis_dissect_isis_psnp(ISIS_TYPE_L2_PSNP,
-                       ihdr->isis_header_length, pd, offset, fd, isis_tree);
+               isis_dissect_isis_psnp(tvb, pinfo, isis_tree, offset,
+                       isis_type, isis_header_length, isis_system_id_len);
                break;
        default:
-               isis_dissect_unknown(offset, END_OF_FRAME, tree, fd,
-                       "unknown ISIS packet type" );
+               isis_dissect_unknown(tvb, pinfo, tree, offset,
+                       "Unknown ISIS packet type");
        }
 } /* dissect_isis */
 
@@ -301,49 +272,54 @@ 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, "" }},
+  static hf_register_info hf[] = {
+    { &hf_isis_irpd,
+      { "Intra Domain Routing Protocol Discriminator", "isis.irpd",    
+        FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "", HFILL }},
 
-               { &hf_isis_header_length,
-               { "HDR Length",         "isis.hdr_len", FT_UINT8, BASE_DEC, 
-                 NULL, 0x0, "" }},
+    { &hf_isis_header_length,
+      { "PDU Header Length  ", "isis.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
 
-               { &hf_isis_version,
-               { "Version (==1)",              "isis.version", FT_UINT8, 
-                 BASE_DEC, NULL, 0x0, "" }},
+    { &hf_isis_version,
+      { "Version (==1)      ", "isis.version", FT_UINT8, 
+         BASE_DEC, NULL, 0x0, "", HFILL }},
 
-               { &hf_isis_reserved,
-               { "Reserved(==0)",                      "isis.reserved",        
-                 FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
+    { &hf_isis_system_id_length,
+      { "System ID Length   ", "isis.sysid_len",       
+        FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
 
-               { &hf_isis_type,
-               { "Type code",            "isis.type",  FT_UINT8, BASE_DEC, 
-                 VALS(isis_vals), 0xff, "" }},
+    { &hf_isis_type, 
+      { "PDU Type           ", "isis.type", FT_UINT8, BASE_DEC, 
+        VALS(isis_vals), 0xff, "", HFILL }},
 
-               { &hf_isis_version2,
-               { "Version2(==1)",   "isis.version2", FT_UINT8, BASE_DEC, NULL, 
-                  0x0, "" }},
+    { &hf_isis_version2, 
+      { "Version2 (==1)     ", "isis.version2", FT_UINT8, BASE_DEC, NULL, 
+        0x0, "", HFILL }},
 
-               { &hf_isis_eco,
-               { "ECO (==0)",          "isis.eco",FT_UINT8, BASE_DEC, NULL, 
-                 0x0, "" }},
+    { &hf_isis_reserved,
+      { "Reserved (==0)     ", "isis.reserved", FT_UINT8, BASE_DEC, NULL, 
+        0x0, "", HFILL }},
 
-               { &hf_isis_user_eco,
-               { "User ECO (==0)", "isis.user_eco", 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, "", HFILL }},
 
-       };
-       /*
-        * Note, we pull in the unknown CLV handler here, since it
-        * is used by all ISIS packet types.
-        */
-       static gint *ett[] = {
-               &ett_isis,
-       };
+    };
+    /*
+     * 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));
+    proto_isis = proto_register_protocol(PROTO_STRING_ISIS, "ISIS", "isis");
+    proto_register_field_array(proto_isis, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_isis(void)
+{
+    dissector_add("osinl", NLPID_ISO10589_ISIS, dissect_isis, proto_isis);
 }