Remove "text2pcap-scanner.obj" and "tools\lemon\lemon.obj" when a "nmake
[obnox/wireshark/wip.git] / packet-osi.c
index 53c7bc527496561756cc949739ea197e4ddf2614..1cbf57bc7627aca0a368929789f8704ef21ec567 100644 (file)
@@ -2,14 +2,13 @@
  * Routines for ISO/OSI network and transport protocol packet disassembly
  * Main entrance point and common functions
  *
- * $Id: packet-osi.c,v 1.40 2001/03/29 08:05:06 guy Exp $
+ * $Id: packet-osi.c,v 1.46 2001/09/14 07:10:05 guy Exp $
  * Laurent Deniel <deniel@worldnet.fr>
  * Ralf Schneider <Ralf.Schneider@t-online.de>
  *
  * 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 "llcsaps.h"
 #include "aftypes.h"
 #include "nlpid.h"
+#include "ppptypes.h"
 #include "packet-osi.h"
 #include "packet-isis.h"
 #include "packet-esis.h"
 
 
-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] );
-    }
-  }
-  else {
-    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++] );
-    }
-    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++] );
-      }
-    }
-  }
-  return( str );
-}
-
-gchar *print_area(const u_char *buffer, int length)
-{
-  /* 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;
-
-  cur = str;
-
-  if (length <= 0 || length > MAX_AREA_LEN) {
-    sprintf( str, "<Invalid length of AREA>");
-    return( str );
-  }
-  
-  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 );
-    }
-    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] );
-    }
-    return str;
-  }
-  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++] );
-        }
-      } 
-    }
-    return( str );
-  }
-} /* print_area */
-
-
-gchar *print_nsap_net( const u_char *buffer, int length)
-{
-  /* to do : NSAP / NET decoding */
-
-  static gchar  str[MAX_NSAP_LEN * 3 + 50]; /* reserve space for nice layout */
-  gchar *cur;
-
-  cur = str;
-
-  if ( (length <= 0 ) || ( length > MAX_NSAP_LEN ) ) {
-    sprintf( str, "<Invalid length of NSAP>");
-    return( str );
-  }
-  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 ] );
-    }
-    return ( str );
-  }
-  else {    /* probably format as standard */
-    return( print_area( buffer, length ) );
-  }
-} /* print_nsap */
-
-
-gchar *calc_checksum( tvbuff_t *tvb, int offset, u_int len, u_int checksum) {
-  u_int   calc_sum = 0;
-  u_int   count    = 0;
+cksum_status_t
+calc_checksum( tvbuff_t *tvb, int offset, u_int len, u_int checksum) {
   const gchar *buffer;
   guint   available_len;
+  const guint8 *p;
+  guint32 c0, c1;
+  u_int   seglen;
+  u_int   i;
 
   if ( 0 == checksum )
-    return( "Not Used" );
+    return( NO_CKSUM );
 
   available_len = tvb_length_remaining( tvb, offset );
   if ( available_len < len )
-    return( "Not checkable - not all of packet was captured" );
+    return( DATA_MISSING );
 
   buffer = tvb_get_ptr( tvb, offset, len );
-  for ( count = 0; count < len; count++ ) {
-    calc_sum += (u_int) buffer[count];
+
+  /*
+   * The maximum values of c0 and c1 will occur if all bytes have the
+   * value 255; if so, then c0 will be len*255 and c1 will be
+   * (len*255 + (len-1)*255 + ... + 255), which is
+   * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2.
+   * This means it can overflow if "len" is 5804 or greater.
+   *
+   * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so
+   * we can solve this by taking c0 and c1 mod 255 every
+   * 5803 bytes.
+   */
+  p = buffer;
+  c0 = 0;
+  c1 = 0;
+  while (len != 0) {
+    seglen = len;
+    if (seglen > 5803)
+      seglen = 5803;
+    for (i = 0; i < seglen; i++) {
+      c0 = c0 + *(p++);
+      c1 += c0;
+    }
+
+    c0 = c0 % 255;
+    c1 = c1 % 255;
+
+    len -= seglen;
   }
-  calc_sum %= 255;  /* modulo 255 divison */
-  
-  if ( 0 == calc_sum )
-    return( "Is good" );
+  if (c0 != 0 || c1 != 0)
+    return( CKSUM_NOT_OK );    /* XXX - what should the checksum be? */
   else
-    return( "Is wrong" );      /* XXX - what should the checksum be? */
+    return( CKSUM_OK );
 }
 
 
@@ -220,13 +120,14 @@ const value_string nlpid_vals[] = {
        { NLPID_ISO11577,        "ISO 11577" },
        { NLPID_COMPRESSED,      "Data compression protocol" },
        { NLPID_IP,              "IP" },
+       { NLPID_IP6,             "IPv6" },
        { NLPID_PPP,             "PPP" },
        { 0,                     NULL },
 };
 
-static dissector_table_t subdissector_table;
+dissector_table_t osinl_subdissector_table;
 
-void dissect_osi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
+static void dissect_osi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
 {
   guint8 nlpid;
 
@@ -235,7 +136,7 @@ void dissect_osi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   nlpid = tvb_get_guint8(tvb, 0);
 
   /* do lookup with the subdissector table */
-  if (dissector_try_port(subdissector_table, nlpid, tvb, pinfo, tree))
+  if (dissector_try_port(osinl_subdissector_table, nlpid, tvb, pinfo, tree))
       return;
 
   switch (nlpid) {
@@ -272,12 +173,13 @@ proto_register_osi(void)
        /* There's no "OSI" protocol *per se*, but we do register a
           dissector table so various protocols running at the
           network layer can register themselves. */
-       subdissector_table = register_dissector_table("osinl");
+       osinl_subdissector_table = register_dissector_table("osinl");
 }
 
 void
 proto_reg_handoff_osi(void)
 {
        dissector_add("llc.dsap", SAP_OSINL, dissect_osi, -1);
+        dissector_add("ppp.protocol", PPP_OSI, dissect_osi, -1);
        dissector_add("null.type", BSD_AF_ISO, dissect_osi, -1);
 }