* 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 );
}
{ 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;
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) {
/* 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);
}