Wireshark-dev: [Wireshark-dev] [PATCH] analyzing SHIM6 protocol

From: Matthijs Mekking <matthijs@xxxxxxxxxxxx>
Date: Tue, 20 Mar 2007 15:34:38 +0100
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello,

The last two months I have been working on a SHIM6 enabled version of
Wireshark. The subject of my final thesis is about SHIM6 and I needed to
analyze the SHIM6 communication exchange. SHIM6 is an IPv6 based
solution for multihoming.(www.shim6.org)

SHIM6 is handled as an IPv6 extension header. So I have changed the
source and header files of packet-ipv6. I have added dissecting
functions for different the message formats of the SHIM6 protocol.
I also needed to change the ipproto files to add the new extension
header. The included patch is pretty clear about that.

The message formats are conform the latest draft specification of SHIM6:
http://tools.ietf.org/html/draft-ietf-shim6-proto-07
http://tools.ietf.org/html/draft-ietf-shim6-failure-detection-07

Regards,

Matthijs Mekking
matthijs@xxxxxxxxxxxx
NLNetLabs Amsterdam / Radboud University Nijmegen
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFF//D+NiaStnTWEtYRAmxUAJ4+s+KNTUkOJQY0vm+9Yr7f5KT3XgCeLrDA
Nb8iiJWcL4aZoQzgkTteSHc=
=HW21
-----END PGP SIGNATURE-----
diff -r -u -N --strip-trailing-cr wireshark-0.99.5/epan/dissectors/packet-ipv6.c wireshark-0.99.5-shim6/epan/dissectors/packet-ipv6.c
--- wireshark-0.99.5/epan/dissectors/packet-ipv6.c	2007-02-02 00:00:57.000000000 +0100
+++ wireshark-0.99.5-shim6/epan/dissectors/packet-ipv6.c	2007-03-20 10:30:01.000000000 +0100
@@ -7,6 +7,8 @@
  * By Gerald Combs <gerald@xxxxxxxxxxxxx>
  * Copyright 1998 Gerald Combs
  *
+ * SHIM6 support added by Matthijs Mekking <matthijs@xxxxxxxxxxxx>
+ *
  * MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@xxxxxxxxxx>
  *
  * This program is free software; you can redistribute it and/or
@@ -29,6 +31,7 @@
 #endif
 
 #include <string.h>
+#include <math.h>
 #include <stdio.h>
 #include <glib.h>
 #include <epan/packet.h>
@@ -39,11 +42,13 @@
 #include <epan/prefs.h>
 #include <epan/reassemble.h>
 #include <epan/ipproto.h>
+#include <epan/ipv6-utils.h>
 #include <epan/etypes.h>
 #include <epan/ppptypes.h>
 #include <epan/aftypes.h>
 #include <epan/nlpid.h>
 #include <epan/arcnet_pids.h>
+#include <epan/in_cksum.h>
 
 /*
  * NOTE: ipv6.nxt is not very useful as we will have chained header.
@@ -77,6 +82,10 @@
 static int hf_ipv6_mipv6_length = -1;
 static int hf_ipv6_mipv6_home_address = -1;
 
+static int hf_ipv6_shim6 = -1;
+static int hf_ipv6_shim6_nxt = -1;
+static int hf_ipv6_shim6_len = -1;
+
 static gint ett_ipv6 = -1;
 static gint ett_ipv6_fragments = -1;
 static gint ett_ipv6_fragment  = -1;
@@ -168,6 +177,19 @@
      }
      offset += advance;
      goto again;
+   case IP_PROTO_SHIM6:
+     if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
+       ld->other++;
+       return;
+     }
+     nxt = pd[offset];
+     advance = (pd[offset+1] + 1) << 3;
+     if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
+       ld->other++;
+       return;
+     }
+     offset += advance;
+     goto again;
    }
 
   switch(nxt) {
@@ -557,16 +579,562 @@
     return dissect_opts(tvb, offset, tree, "Destination Option");
 }
 
+/* START SHIM6 PART */
+static guint16 shim_checksum(const guint8 *ptr, int len)
+{
+	vec_t cksum_vec[1];
+
+	cksum_vec[0].ptr = ptr;
+	cksum_vec[0].len = len;
+	return in_cksum(&cksum_vec[0], 1);
+}
+
+static int 
+dissect_shim_ip_addr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *itemname, ...) 
+{
+    int count;
+    struct e_in6_addr addr;
+
+    for(count=0;count<16;count++) {
+	addr.bytes[count] = tvb_get_guint8(tvb, offset+count); 
+    }
+
+    proto_tree_add_text(tree, tvb, offset, 16, "%s %s", 
+	itemname, ip6_to_str(&addr));
+
+    return 16;
+}
+
+static int 
+dissect_hex_val(tvbuff_t *tvb, int offset, int len, const char *itemname, guint8 bitmask, proto_tree *tree) 
+{
+    proto_item *ti;
+    int count;
+    gint p;
+
+    p = offset;
+
+    ti = proto_tree_add_text(tree, tvb, offset, len, itemname); 
+
+    for (count=0; count<len; count++) 
+    {
+	if (count==0) {
+	    proto_item_append_text(ti, " 0x%02x", tvb_get_guint8(tvb, p+count) & bitmask);
+	}
+	else {
+	    proto_item_append_text(ti, "%02x", tvb_get_guint8(tvb, p+count));
+	}
+    }
+
+    return len;
+}
+
+static const value_string shimoptvals[] = {
+    { SHIM6_OPT_RESPVAL, "Responder Validator" },
+    { SHIM6_OPT_LOCLIST, "Locator List" },
+    { SHIM6_OPT_LOCPREF, "Locator Preferences" },
+    { SHIM6_OPT_CGAPDM, "CGA Parameter Data Structure" },
+    { SHIM6_OPT_CGASIG, "CGA Signature" },
+    { SHIM6_OPT_ULIDPAIR, "ULID Pair" },
+    { SHIM6_OPT_FII, "Forked Instance Identifier" },
+    { 0, NULL },
+};
+
+static const value_string shimverifmethods[] = {
+    { SHIM6_VERIF_HBA, "HBA" },
+    { SHIM6_VERIF_CGA, "CGA" },
+    { 0, NULL },
+};
+
+static const value_string shimflags[] = {
+    { SHIM6_FLAG_BROKEN, "BROKEN" },
+    { SHIM6_FLAG_TEMPORARY, "TEMPORARY" },
+    { 0, NULL },
+};
+
+static const value_string shimreapstates[] = {
+    { SHIM6_REAP_OPERATIONAL, "Operational" },
+    { SHIM6_REAP_EXPLORING, "Exploring" },
+    { SHIM6_REAP_INBOUNDOK, "InboundOK" },
+    { 0, NULL },
+};
+
+static int
+dissect_shimopts(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+    int len, total_len;
+    gint p;
+    proto_tree *opt_tree;
+    proto_item *ti;
+    guint8 tmp[4]; 
+
+    p = offset;
+
+    tmp[0] = tvb_get_guint8(tvb, p++);
+    tmp[1] = tvb_get_guint8(tvb, p++);
+    tmp[2] = tvb_get_guint8(tvb, p++);
+    tmp[3] = tvb_get_guint8(tvb, p++);
+
+    len = tmp[2]*256 + tmp[3];
+    total_len = (11+len) - ((len+3)%8);
+
+    if (tree) 
+    {
+	char *ctype;
+	char locnum[6];
+	int count;
+	guint32 tmp32;			
+	guint8 optlen;
+
+	ctype = val_to_str( (tvb_get_ntohs(tvb, offset) & SHIM6_BITMASK_OPT_TYPE) >> 1, 
+	    shimoptvals, "Unknown Option Type");
+	ti = proto_tree_add_text(tree, tvb, offset, total_len, "%s Option", ctype);
+	opt_tree = proto_item_add_subtree(ti, ett_ipv6);
+
+	/* Option Type */
+	proto_tree_add_text(opt_tree, tvb, offset, 2, "Type: %s", ctype);
+
+	/* Critical */
+	proto_tree_add_text(opt_tree, tvb, offset+1, 1, "Critical: %s", 
+	    tmp[1] & SHIM6_BITMASK_CRITICAL ? "Yes" : "No");	
+
+	/* Content Length */
+	proto_tree_add_text(opt_tree, tvb, offset+2, 2, "Content Length: %u (Total Length: %u)", 
+	    len, total_len);
+
+	/* Option Type Specific */
+	switch (tvb_get_ntohs(tvb, offset) >> 1) 
+	{
+	    case SHIM6_OPT_RESPVAL:
+		p += dissect_hex_val(tvb, p, len, "Validator:", 0xff, opt_tree); 
+
+		if (total_len-(len+4) > 0)
+		    proto_tree_add_text(opt_tree, tvb, p, total_len-(len+4), "Padding");
+
+		break;
+	    case SHIM6_OPT_LOCLIST:
+		tmp32 = tvb_get_ntohl(tvb, p);
+		proto_tree_add_text(opt_tree, tvb, p, 4, "Locator List Generation: %u", 
+		    tmp32);
+		p += 4;
+
+		optlen = tvb_get_guint8(tvb, p);
+		proto_tree_add_text(opt_tree, tvb, p, 1, "Num Locators: %u", 
+		    optlen);
+		p++;
+
+		/* Verification Methods */
+		proto_tree_add_text(opt_tree, tvb, p, optlen, "Locator Verification Methods:");
+
+		for (count=0;count<optlen;count++) {
+		    proto_tree_add_text(opt_tree, tvb, p+count, 1, "(%u): %s", count+1, 
+			val_to_str(tvb_get_guint8(tvb, p+count), shimverifmethods, "Unknown"));
+		}
+		p += optlen;
+
+		/* Padding, included in length field */
+		if ((7-optlen % 8) > 0) {
+		    proto_tree_add_text(opt_tree, tvb, p, (7-optlen % 8), "Padding");
+		    p += (7-optlen % 8);
+		}
+
+		/* Locators */
+		proto_tree_add_text(opt_tree, tvb, p, 16*optlen, "Locators");
+
+		for (count=0;count<optlen;count++) {
+		    g_snprintf(locnum, sizeof locnum, "(%u)", count+1);
+		    p += dissect_shim_ip_addr(tvb, p, opt_tree, locnum); 
+		}
+
+		break;
+	    case SHIM6_OPT_LOCPREF:
+		tmp32 = tvb_get_ntohl(tvb, p);
+		proto_tree_add_text(opt_tree, tvb, p, 4, "Locator List Generation: %u", 
+		    tmp32);
+		p += 4;
+
+		optlen = tvb_get_guint8(tvb, p);
+		proto_tree_add_text(opt_tree, tvb, p, 1, "Element Length: %u", optlen);
+		p++;
+
+		/* Locator Preferences */
+		count = 0;
+		while (p < offset+len+4) {
+		    count++;
+		    if (optlen > 0) {
+			/* Flags */
+			proto_tree_add_text(opt_tree, tvb, p, 1, "Locator Flag %u: %s", count, 
+			    val_to_str(tvb_get_guint8(tvb, p), shimflags, "Unknown")); 
+			p++;
+
+			if (optlen > 1) {
+			    /* Priority */
+			    proto_tree_add_text(opt_tree, tvb, p, 1, "Locator Priority %u: %u", 
+				count, tvb_get_guint8(tvb, p)); 
+			    p++;
+
+			    if (optlen > 2) {
+				/*
+	 			 * This document doesn't specify the format when the Element length is
+				 * more than three, except that any such formats MUST be defined so that
+				 * the first three octets are the same as in the above case, that is, a
+				 * of a 1 octet flags field followed by a 1 octet priority field, and a
+				 * 1 octet weight field.
+				 */
+
+				/* Weight */
+				proto_tree_add_text(opt_tree, tvb, p, 1, "Locator Weight %u: %u", 
+				    count, tvb_get_guint8(tvb, p)); 
+			   	p++;
+			    }
+			}
+		    }
+		}
+
+		if (total_len-(len+4) > 0)
+		    proto_tree_add_text(opt_tree, tvb, p, total_len-(len+4), "Padding");
+
+		break;
+	    case SHIM6_OPT_CGAPDM:
+		p += dissect_hex_val(tvb, p, len, "CGA Parameter Data Structure:", 0xff, opt_tree); 
+
+		if (total_len-(len+4) > 0)
+		    proto_tree_add_text(opt_tree, tvb, p, total_len-(len+4), "Padding");
+
+		break;
+	    case SHIM6_OPT_CGASIG:
+		p += dissect_hex_val(tvb, p, len, "CGA Signature:", 0xff, opt_tree); 
+
+		if (total_len-(len+4) > 0)
+		    proto_tree_add_text(opt_tree, tvb, p, total_len-(len+4), "Padding");
+
+		break;
+	    case SHIM6_OPT_ULIDPAIR:
+		proto_tree_add_text(opt_tree, tvb, p, 4, "Reserved");
+		p += 4;
+
+		p += dissect_shim_ip_addr(tvb, p, opt_tree, "Sender ULID:"); 
+		p += dissect_shim_ip_addr(tvb, p, opt_tree, "Receiver ULID:"); 
+
+		break;
+	    case SHIM6_OPT_FII:
+		tmp32 = tvb_get_ntohl(tvb, p);
+		proto_tree_add_text(opt_tree, tvb, p, 4, 
+		    "Forked Instance Identifier: %u (0x%02x)", tmp32, tmp32);
+		p += 4;
+		break;
+	    default:
+		break;
+	}
+    }
+
+    return total_len;
+}
+
+/* Dissect SHIM6 data: control messages */
+static int
+dissect_shimctrl(tvbuff_t *tvb, int offset, guint type, proto_tree *shim_tree)
+{
+    gint p;
+    guint32 tmp32;
+    guint8 tmp8;
+    const char *sta;
+    int count;
+
+    p = offset; 
+
+    switch (type) 
+    {
+	case SHIM6_TYPE_I1:
+	    p += dissect_hex_val(tvb, p, 6, "Initiator Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree); 
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Initiator Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+
+	    break;
+	case SHIM6_TYPE_R1:
+	    proto_tree_add_text(shim_tree, tvb, p, 2, "Reserved2");
+	    p += 2;
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Initiator Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Responder Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+	
+	    break;
+	case SHIM6_TYPE_I2:
+	    p += dissect_hex_val(tvb, p, 6, "Initiator Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree); 
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Initiator Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Responder Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Reserved2");
+	    p += 4;
+
+	    break;
+	case SHIM6_TYPE_R2:
+	    p += dissect_hex_val(tvb, p, 6, "Responder Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree); 
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Initiator Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+
+	    break;
+	case SHIM6_TYPE_R1BIS:
+	    p += dissect_hex_val(tvb, p, 6, "Packet Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree); 
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Responder Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+
+	    break;
+	case SHIM6_TYPE_I2BIS:
+	    p += dissect_hex_val(tvb, p, 6, "Initiator Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree); 
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Initiator Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Responder Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+	    
+	    proto_tree_add_text(shim_tree, tvb, p, 6, "Reserved2");
+	    p += 6;
+	    
+	    p += dissect_hex_val(tvb, p, 6, "Packet Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree);
+
+	    break;
+	case SHIM6_TYPE_UPD_REQ:
+	case SHIM6_TYPE_UPD_ACK:
+	    p += dissect_hex_val(tvb, p, 6, "Receiver Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree); 
+
+	    tmp32 = tvb_get_ntohl(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Request Nonce: %u (0x%02x)", 
+		tmp32, tmp32);
+	    p += 4;
+
+	    break;
+	case SHIM6_TYPE_KEEPALIVE:
+	    p += dissect_hex_val(tvb, p, 6, "Receiver Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree); 
+
+	    proto_tree_add_text(shim_tree, tvb, p, 4, "Reserved2");
+	    p += 4;
+	    break;
+	case SHIM6_TYPE_PROBE:
+	    p += dissect_hex_val(tvb, p, 6, "Receiver Context Tag:", 
+		SHIM6_BITMASK_CT, shim_tree); 
+
+	    tmp8 = tvb_get_guint8(tvb, p);
+	    proto_tree_add_text(shim_tree, tvb, p, 1, "Probes Received: %u", 
+		(tmp8 & SHIM6_BITMASK_PRECVD) >> 4);
+	    proto_tree_add_text(shim_tree, tvb, p, 1, "Probes Sent: %u", 
+		tmp8 & SHIM6_BITMASK_PSENT);
+	    p++;
+
+	    sta = val_to_str((tvb_get_guint8(tvb, p) & SHIM6_BITMASK_STA) >> 6,
+		shimreapstates, "Unknown REAP State");
+	    proto_tree_add_text(shim_tree, tvb, p, 1, "State: %s", sta);
+
+	    proto_tree_add_text(shim_tree, tvb, p, 3, "Reserved2");
+	    p += 3;
+	    
+	    /* Probes Sent */
+	    for (count=0;count<(tmp8 & SHIM6_BITMASK_PSENT);count++) {
+		proto_tree_add_text(shim_tree, tvb, p, 40, "Probe Sent %u:", count+1);
+
+		p += dissect_shim_ip_addr(tvb, p, shim_tree, "- Source address:"); 
+		p += dissect_shim_ip_addr(tvb, p, shim_tree, "- Destination address:"); 
+
+		tmp32 = tvb_get_ntohl(tvb, p);
+		proto_tree_add_text(shim_tree, tvb, p, 4, "- Nonce: %u (0x%02x)", 
+		    tmp32, tmp32);
+		p += 4;
+
+		tmp32 = tvb_get_ntohl(tvb, p);
+		proto_tree_add_text(shim_tree, tvb, p, 4, "- Data: 0x%02x", 
+		    tmp32);
+		p += 4;
+	   }
+
+	   /* Probes Received */
+	   for (count=0;count<((tmp8 & SHIM6_BITMASK_PRECVD)>>4);count++) {
+		proto_tree_add_text(shim_tree, tvb, p, 40, "Probe Received %u:", count+1);
+
+		p += dissect_shim_ip_addr(tvb, p, shim_tree, "- Source address:"); 
+		p += dissect_shim_ip_addr(tvb, p, shim_tree, "- Destination address:"); 
+
+		tmp32 = tvb_get_ntohl(tvb, p);
+		proto_tree_add_text(shim_tree, tvb, p, 4, "- Nonce: %u (0x%02x)", 
+		    tmp32, tmp32);
+		p += 4;
+
+		tmp32 = tvb_get_ntohl(tvb, p);
+		proto_tree_add_text(shim_tree, tvb, p, 4, "- Data: 0x%02x", 
+		    tmp32);
+		p += 4;
+	   }
+
+	   break;
+	default:
+	   break;
+    }
+
+    return p-offset;
+}
+
+/* Dissect SHIM6 data: payload, common part, options */
+static const value_string shimctrlvals[] = {
+    { SHIM6_TYPE_I1, "I1" },
+    { SHIM6_TYPE_R1, "R1" },
+    { SHIM6_TYPE_I2, "I2" },
+    { SHIM6_TYPE_R2, "R2" },
+    { SHIM6_TYPE_R1BIS, "R1bis" },
+    { SHIM6_TYPE_I2BIS, "I2bis" },
+    { SHIM6_TYPE_UPD_REQ, "Update Request" },
+    { SHIM6_TYPE_UPD_ACK, "Update Acknowledgement" },
+    { SHIM6_TYPE_KEEPALIVE, "Keepalive" },
+    { SHIM6_TYPE_PROBE, "Probe" },
+    { 0, NULL },
+};
+
+static int
+dissect_shim6(tvbuff_t *tvb, int offset, proto_tree *tree) 
+{
+    struct ip6_shim shim;		
+    int len;
+    gint p;
+    proto_tree *shim_tree, *opt_tree;
+    proto_item *ti;
+    guint8 tmp[5]; 
+
+    tvb_memcpy(tvb, (guint8 *)&shim, offset, sizeof(shim));
+    len = (shim.ip6s_len + 1) << 3;
+
+    if (tree) 
+    {
+    	ti = proto_tree_add_item(tree, hf_ipv6_shim6, tvb, offset, len, FALSE);
+	shim_tree = proto_item_add_subtree(ti, ett_ipv6);
+
+	/* Next Header */
+	proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_nxt, tvb,
+	    offset + offsetof(struct ip6_shim, ip6s_nxt), 1, shim.ip6s_nxt,
+	    "Next header: %s (0x%02x)", ipprotostr(shim.ip6s_nxt), shim.ip6s_nxt); 
+
+	/* Header Extension Length */
+	proto_tree_add_uint_format(shim_tree, hf_ipv6_shim6_len, tvb,
+	    offset + offsetof(struct ip6_shim, ip6s_len), 1, shim.ip6s_len,
+	    "Header Ext Length: %u (%d bytes)", shim.ip6s_len, len); 
+
+	/* P Field */
+	proto_tree_add_text(shim_tree, tvb,
+	    offset + offsetof(struct ip6_shim, ip6s_p), 1, "P field: %s", 
+	    shim.ip6s_p & SHIM6_BITMASK_P ? "Payload extension" : "Control message");
+
+	/* skip the first 3 bytes (nxt hdr, hdr ext len, p field + 7 bits) */
+	p = offset + 3; 
+
+	if (shim.ip6s_p & SHIM6_BITMASK_P) 
+	{ 
+	    /* Payload Extension Header */
+	    p += dissect_hex_val(tvb, offset + offsetof(struct ip6_shim, ip6s_p), 
+		6, "Initiator Context Tag:", SHIM6_BITMASK_CT, shim_tree); 
+	}
+	else 
+        { 
+	    /* Control Message */
+	    const char *ctype;
+	    proto_item *ti_shim;
+	    guint16 csum, tmp16;
+	    int advance;
+
+	    /* Message Type */
+	    ctype = val_to_str(shim.ip6s_p & SHIM6_BITMASK_TYPE, shimctrlvals,
+		"Unknown Message Type");
+
+	    proto_tree_add_text(shim_tree, tvb, offset + offsetof(struct ip6_shim, ip6s_p), 
+		1, "Message Type: %s", ctype);
+
+	    /* Type Specific field (Reserved) and zero bit */
+	    tmp[0] = tvb_get_guint8(tvb, p++);
+
+	    /* Protocol bit (Must be zero for SHIM6 */
+	    proto_tree_add_text(shim_tree, tvb, p-1, 1, "Protocol: %s", 
+		tmp[0] & SHIM6_BITMASK_PROTOCOL ? "HIP" : "SHIM6");
+
+	    /* Checksum */ 
+	    csum = shim_checksum(tvb_get_ptr(tvb, offset, len), len);
+	    tmp16 = tvb_get_ntohs(tvb, p); 
+	    p += 2;
+
+	    if (csum == 0)
+		proto_tree_add_text(shim_tree, tvb, p-2, 2, "Checksum: 0x%04x [correct]", tmp16);
+	    else
+		proto_tree_add_text(shim_tree, tvb, p-2, 2, "Checksum: 0x%04x [incorrect: should be 0x%04x]", 
+		    tmp16, in_cksum_shouldbe(tmp16, csum)); 
+
+	    /* Type specific data */
+	    advance = dissect_shimctrl(tvb, p, shim.ip6s_p & SHIM6_BITMASK_TYPE, shim_tree);
+		
+	    p += advance;
+
+	    /* Options */
+
+	    if (p < offset+len && shim_tree) {
+		ti_shim = proto_tree_add_text(shim_tree, tvb, p, len-(advance+6), 
+		    "Options (%u bytes)", len-(advance+6));
+		
+		opt_tree = proto_item_add_subtree(ti_shim, ett_ipv6);
+
+		while (p < offset+len) {
+		    p += dissect_shimopts(tvb, p, opt_tree);
+		}
+	    }
+
+	}
+    }
+
+    return len;
+}
+
+/* END SHIM6 PART */
+
 static void
 dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
   proto_tree *ipv6_tree = NULL;
   proto_item *ti;
-  guint8 nxt;
+  guint8 nxt, stype;
   int advance;
   int poffset;
   guint16 plen;
-  gboolean hopopts, routing, frag, ah, dstopts;
+  gboolean hopopts, routing, frag, ah, shim6, dstopts;
   guint16 offlg;
   guint32 ident;
   int offset;
@@ -677,6 +1245,7 @@
   routing = FALSE;
   frag = FALSE;
   ah = FALSE;
+  shim6 = FALSE;
   dstopts = FALSE;
 
 again:
@@ -716,6 +1285,15 @@
 			offset += advance;
 			plen -= advance;
 			goto again;
+    case IP_PROTO_SHIM6:
+			shim6 = TRUE;
+			advance = dissect_shim6(tvb, offset, tree);
+			nxt = tvb_get_guint8(tvb, offset);
+			stype = tvb_get_guint8(tvb, offset+2); 
+			poffset = offset;
+			offset += advance;
+			plen -= advance;
+			goto again;
     case IP_PROTO_DSTOPTS:
 			dstopts = TRUE;
 			advance = dissect_dstopts(tvb, offset, tree);
@@ -795,7 +1373,7 @@
         /* If we had an Authentication Header, the AH dissector already
            put something in the Info column; leave it there. */
       	if (!ah) {
-          if (hopopts || routing || dstopts) {
+          if (hopopts || routing || dstopts || shim6) {
             const char *sep = "IPv6 ";
             if (hopopts) {
               col_append_fstr(pinfo->cinfo, COL_INFO, "%shop-by-hop options",
@@ -810,6 +1388,15 @@
               col_append_fstr(pinfo->cinfo, COL_INFO, "%sdestination options",
                               sep);
             }
+            if (shim6) {
+		if (stype & SHIM6_BITMASK_P) {
+              	  col_append_fstr(pinfo->cinfo, COL_INFO, "Shim6 (Payload)");
+		}
+		else {
+              	  col_append_fstr(pinfo->cinfo, COL_INFO, "Shim6 (%s)", 
+		    val_to_str(stype & SHIM6_BITMASK_TYPE, shimctrlvals, "Unknown"));
+		}
+            }
           } else
             col_set_str(pinfo->cinfo, COL_INFO, "IPv6 no next header");
 	}
@@ -912,6 +1499,22 @@
 				FT_IPv6, BASE_HEX, NULL, 0x0,
 				"", HFILL }},
 
+    /* SHIM6 */
+    { &hf_ipv6_shim6,
+      { "SHIM6 ",		"ipv6.shim6",
+				FT_NONE, BASE_NONE, NULL, 0x0,
+				"", HFILL }},
+
+    { &hf_ipv6_shim6_nxt,
+      { "SHIM6 Next Header",	"ipv6.shim6.nxt",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				"", HFILL }},
+
+    { &hf_ipv6_shim6_len,
+      { "SHIM6 Header Ext Length", "ipv6.shim6.len",
+				FT_UINT8, BASE_DEC, NULL, 0x0,
+				"", HFILL }},
+
 #ifdef TEST_FINALHDR
     { &hf_ipv6_final,
       { "Final next header",	"ipv6.final",
diff -r -u -N --strip-trailing-cr wireshark-0.99.5/epan/dissectors/packet-ipv6.h wireshark-0.99.5-shim6/epan/dissectors/packet-ipv6.h
--- wireshark-0.99.5/epan/dissectors/packet-ipv6.h	2007-02-02 00:00:57.000000000 +0100
+++ wireshark-0.99.5-shim6/epan/dissectors/packet-ipv6.h	2007-03-20 10:30:02.000000000 +0100
@@ -150,6 +150,61 @@
 	guint32 ip6f_ident;		/* identification */
 };
 
+/* SHIM6 control message types */
+#define SHIM6_TYPE_I1 		0x01	/* 0 000 0001 */
+#define SHIM6_TYPE_R1 		0x02	/* 0 000 0010 */
+#define SHIM6_TYPE_I2		0x03	/* 0 000 0011 */
+#define SHIM6_TYPE_R2 		0x04	/* 0 000 0100 */
+#define SHIM6_TYPE_R1BIS	0x05	/* 0 000 0101 */
+#define SHIM6_TYPE_I2BIS	0x06	/* 0 000 0110 */
+#define SHIM6_TYPE_UPD_ACK	0x40	/* 0 100 0000 = 64 */
+#define SHIM6_TYPE_UPD_REQ	0x41	/* 0 100 0001 = 65 */
+#define SHIM6_TYPE_KEEPALIVE	0x42	/* 0 100 0010 = 66 */
+#define SHIM6_TYPE_PROBE 	0x43	/* 0 100 0011 = 67 */
+
+/* SHIM6 Options */
+#define SHIM6_OPT_RESPVAL       0x01    /* 0 000 0001 */
+#define SHIM6_OPT_LOCLIST       0x02    /* 0 000 0010 */
+#define SHIM6_OPT_LOCPREF       0x03    /* 0 000 0011 */
+#define SHIM6_OPT_CGAPDM        0x04    /* 0 000 0100 */
+#define SHIM6_OPT_CGASIG        0x05    /* 0 000 0101 */
+#define SHIM6_OPT_ULIDPAIR      0x06    /* 0 000 0110 */
+#define SHIM6_OPT_FII           0x07    /* 0 000 0111 */
+
+/* SHIM6 Bitmasks */
+#define SHIM6_BITMASK_P		0x80	/* 1 000 0000 */
+#define SHIM6_BITMASK_TYPE	0x7F	/* 0 111 1111 */
+#define SHIM6_BITMASK_PROTOCOL	0x01	/* 0 000 0001 */
+#define SHIM6_BITMASK_SPECIFIC	0xFE	/* 1 111 1110 */
+#define SHIM6_BITMASK_R		0x80	/* 1 000 0000 */
+#define SHIM6_BITMASK_CT	0x7F	/* 0 111 1111 */
+#define SHIM6_BITMASK_OPT_TYPE	0xFFFE	/* 1 111 1111    1 111 1110 */
+#define SHIM6_BITMASK_CRITICAL	0x01	/* 0 000 0001 */
+#define SHIM6_BITMASK_PRECVD	0xF0	/* 1 111 0000 */
+#define SHIM6_BITMASK_PSENT	0x0F	/* 0 000 1111 */
+#define SHIM6_BITMASK_STA	0xC0	/* 1 100 0000 */
+
+/* SHIM6 Verification Methods */
+#define SHIM6_VERIF_HBA		0x01	/* 0 000 0001 */
+#define SHIM6_VERIF_CGA		0x02	/* 0 000 0010 */
+
+/* SHIM6 Flags */
+#define SHIM6_FLAG_BROKEN	0x01	/* 0 000 0001 */
+#define SHIM6_FLAG_TEMPORARY	0x02	/* 0 000 0010 */
+
+/* SHIM6 REAP States */
+#define SHIM6_REAP_OPERATIONAL	0x00	/* 0 000 0000 */
+#define SHIM6_REAP_EXPLORING	0x01	/* 0 000 0001 */
+#define SHIM6_REAP_INBOUNDOK	0x02	/* 0 000 0010 */
+
+/* SHIM6 header */
+struct ip6_shim {
+	guint8  ip6s_nxt;		/* next header */
+	guint8  ip6s_len;		/* header extension length */
+	guint8  ip6s_p;			/* P field and first 7 bits of remainder */
+	/* followed by shim6 specific data*/
+};
+
 #define IP6F_OFF_MASK		0xfff8	/* mask out offset from _offlg */
 #define IP6F_RESERVED_MASK	0x0006	/* reserved bits in ip6f_offlg */
 #define IP6F_MORE_FRAG		0x0001	/* more-fragments flag */
diff -r -u -N --strip-trailing-cr wireshark-0.99.5/epan/ipproto.c wireshark-0.99.5-shim6/epan/ipproto.c
--- wireshark-0.99.5/epan/ipproto.c	2007-02-02 00:01:02.000000000 +0100
+++ wireshark-0.99.5-shim6/epan/ipproto.c	2007-03-20 10:30:03.000000000 +0100
@@ -107,6 +107,7 @@
     { IP_PROTO_ICMPV6,	"ICMPv6" },
     { IP_PROTO_NONE,	"IPv6 no next header" },
     { IP_PROTO_DSTOPTS,	"IPv6 destination option" },
+    { IP_PROTO_SHIM6,	"SHIM6 header" },
     { IP_PROTO_MIPV6_OLD, "Mobile IPv6 (old)" },
     { IP_PROTO_SATEXPAK,"SATNET EXPAK" },
     { IP_PROTO_KRYPTOLAN, "Kryptolan" },
diff -r -u -N --strip-trailing-cr wireshark-0.99.5/epan/ipproto.h wireshark-0.99.5-shim6/epan/ipproto.h
--- wireshark-0.99.5/epan/ipproto.h	2007-02-02 00:01:03.000000000 +0100
+++ wireshark-0.99.5-shim6/epan/ipproto.h	2007-03-20 10:30:03.000000000 +0100
@@ -96,6 +96,9 @@
 #define IP_PROTO_NONE		59		/* IP6 no next header - RFC1883 */
 #define IP_PROTO_DSTOPTS	60		/* IP6 destination options - RFC1883 */
 /* 61 is reserved by IANA for any host internal protocol */
+/* 61 is used by UCL's SHIM6 implementation as Next Header for SHIM6 */
+#define IP_PROTO_SHIM6		61		/* SHIM6 */
+
 /*
  * The current Protocol Numbers list says that the IP protocol number for
  * mobility headers is 135; it cites draft-ietf-mobileip-ipv6-24, but