Fix a number of proto_tree_add_item() encoding args.
[obnox/wireshark/wip.git] / epan / dissectors / packet-ipv6.c
index 303951e606fce22d9ca122a071e90c88af369eb1..d59720f20a73c9dff62a162d82f09db23268c89c 100644 (file)
 # include "config.h"
 #endif
 
-#include <string.h>
 #include <math.h>
-#include <stdio.h>
 #include <glib.h>
 #include <epan/packet.h>
-#include "packet-ipsec.h"
-#include "packet-ipv6.h"
 #include <epan/ip_opts.h>
 #include <epan/addr_resolv.h>
 #include <epan/prefs.h>
 #include <epan/nlpid.h>
 #include <epan/arcnet_pids.h>
 #include <epan/in_cksum.h>
-#include <epan/value_string.h>
 #include <epan/expert.h>
 #include <epan/emem.h>
+#include <epan/tap.h>
+#include "packet-ipsec.h"
+#include "packet-ipv6.h"
+
+#ifdef HAVE_GEOIP_V6
+#include "GeoIP.h"
+#include <epan/geoip_db.h>
+#endif /* HAVE_GEOIP_V6 */
 
 /*
  * NOTE: ipv6.nxt is not very useful as we will have chained header.
 #define TEST_FINALHDR
  */
 
+/* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
+#define IPDSFIELD_DSCP_MASK     0xFC
+#define IPDSFIELD_ECN_MASK     0x03
+#define IPDSFIELD_DSCP_SHIFT   2
+#define IPDSFIELD_DSCP(dsfield)        (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
+#define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
+#define IPDSFIELD_DSCP_DEFAULT  0x00
+#define IPDSFIELD_DSCP_CS1      0x08
+#define IPDSFIELD_DSCP_CS2      0x10
+#define IPDSFIELD_DSCP_CS3      0x18
+#define IPDSFIELD_DSCP_CS4      0x20
+#define IPDSFIELD_DSCP_CS5      0x28
+#define IPDSFIELD_DSCP_CS6      0x30
+#define IPDSFIELD_DSCP_CS7      0x38
+#define IPDSFIELD_DSCP_AF11     0x0A
+#define IPDSFIELD_DSCP_AF12     0x0C
+#define IPDSFIELD_DSCP_AF13     0x0E
+#define IPDSFIELD_DSCP_AF21     0x12
+#define IPDSFIELD_DSCP_AF22     0x14
+#define IPDSFIELD_DSCP_AF23     0x16
+#define IPDSFIELD_DSCP_AF31     0x1A
+#define IPDSFIELD_DSCP_AF32     0x1C
+#define IPDSFIELD_DSCP_AF33     0x1E
+#define IPDSFIELD_DSCP_AF41     0x22
+#define IPDSFIELD_DSCP_AF42     0x24
+#define IPDSFIELD_DSCP_AF43     0x26
+#define IPDSFIELD_DSCP_EF       0x2E
+#define IPDSFIELD_ECT_MASK      0x02
+#define IPDSFIELD_CE_MASK       0x01
+
+/* RPL Routing header */
+#define IP6RRPL_BITMASK_CMPRI     0xF0000000
+#define IP6RRPL_BITMASK_CMPRE     0x0F000000
+#define IP6RRPL_BITMASK_PAD       0x00F00000
+#define IP6RRPL_BITMASK_RESERVED  0x000FFFFF
+
+static int ipv6_tap = -1;
+
 static int proto_ipv6            = -1;
 static int hf_ipv6_version       = -1;
 static int hf_ip_version      = -1;
@@ -69,14 +110,36 @@ static int hf_ipv6_nxt               = -1;
 static int hf_ipv6_hlim                  = -1;
 static int hf_ipv6_src           = -1;
 static int hf_ipv6_src_host      = -1;
+static int hf_ipv6_src_sa_mac     = -1;
+static int hf_ipv6_src_isatap_ipv4             = -1;
+static int hf_ipv6_src_6to4_gateway_ipv4       = -1;
+static int hf_ipv6_src_6to4_sla_id             = -1;
+static int hf_ipv6_src_teredo_server_ipv4      = -1;
+static int hf_ipv6_src_teredo_port             = -1;
+static int hf_ipv6_src_teredo_client_ipv4      = -1;
 static int hf_ipv6_dst           = -1;
 static int hf_ipv6_dst_host      = -1;
+static int hf_ipv6_dst_sa_mac     = -1;
+static int hf_ipv6_dst_isatap_ipv4       = -1;
+static int hf_ipv6_dst_6to4_gateway_ipv4       = -1;
+static int hf_ipv6_dst_6to4_sla_id             = -1;
+static int hf_ipv6_dst_teredo_server_ipv4      = -1;
+static int hf_ipv6_dst_teredo_port             = -1;
+static int hf_ipv6_dst_teredo_client_ipv4      = -1;
 static int hf_ipv6_addr                  = -1;
 static int hf_ipv6_host                  = -1;
+static int hf_ipv6_sa_mac         = -1;
+static int hf_ipv6_isatap_ipv4    = -1;
+static int hf_ipv6_6to4_gateway_ipv4           = -1;
+static int hf_ipv6_6to4_sla_id                 = -1;
+static int hf_ipv6_teredo_server_ipv4          = -1;
+static int hf_ipv6_teredo_port                 = -1;
+static int hf_ipv6_teredo_client_ipv4          = -1;
 static int hf_ipv6_opt_pad1      = -1;
 static int hf_ipv6_opt_padn      = -1;
 static int hf_ipv6_dst_opt       = -1;
 static int hf_ipv6_hop_opt       = -1;
+static int hf_ipv6_unk_hdr       = -1;
 static int hf_ipv6_routing_hdr_opt       = -1;
 static int hf_ipv6_routing_hdr_type      = -1;
 static int hf_ipv6_routing_hdr_left      = -1;
@@ -94,12 +157,22 @@ static int hf_ipv6_fragment_overlap_conflict  = -1;
 static int hf_ipv6_fragment_multiple_tails    = -1;
 static int hf_ipv6_fragment_too_long_fragment = -1;
 static int hf_ipv6_fragment_error            = -1;
+static int hf_ipv6_fragment_count            = -1;
 static int hf_ipv6_reassembled_in            = -1;
+static int hf_ipv6_reassembled_length        = -1;
 
 static int hf_ipv6_mipv6_type                = -1;
 static int hf_ipv6_mipv6_length                      = -1;
 static int hf_ipv6_mipv6_home_address        = -1;
 
+static int hf_ipv6_routing_hdr_rpl_cmprI  = -1;
+static int hf_ipv6_routing_hdr_rpl_cmprE  = -1;
+static int hf_ipv6_routing_hdr_rpl_pad    = -1;
+static int hf_ipv6_routing_hdr_rpl_reserved = -1;
+static int hf_ipv6_routing_hdr_rpl_segments = -1;
+static int hf_ipv6_routing_hdr_rpl_addr = -1;
+static int hf_ipv6_routing_hdr_rpl_fulladdr = -1;
+
 static int hf_ipv6_shim6             = -1;
 static int hf_ipv6_shim6_nxt         = -1;
 static int hf_ipv6_shim6_len         = -1;
@@ -135,6 +208,33 @@ static int hf_ipv6_shim6_loc_weight   = -1;
 static int hf_ipv6_shim6_opt_locnum   = -1;
 static int hf_ipv6_shim6_opt_elemlen  = -1;
 static int hf_ipv6_shim6_opt_fii      = -1;
+static int hf_ipv6_traffic_class_dscp = -1;
+static int hf_ipv6_traffic_class_ect  = -1;
+static int hf_ipv6_traffic_class_ce   = -1;
+
+#ifdef HAVE_GEOIP_V6
+static int hf_geoip_country = -1;
+static int hf_geoip_city = -1;
+static int hf_geoip_org = -1;
+static int hf_geoip_isp = -1;
+static int hf_geoip_asnum = -1;
+static int hf_geoip_lat = -1;
+static int hf_geoip_lon = -1;
+static int hf_geoip_src_country = -1;
+static int hf_geoip_src_city = -1;
+static int hf_geoip_src_org = -1;
+static int hf_geoip_src_isp = -1;
+static int hf_geoip_src_asnum = -1;
+static int hf_geoip_src_lat = -1;
+static int hf_geoip_src_lon = -1;
+static int hf_geoip_dst_country = -1;
+static int hf_geoip_dst_city = -1;
+static int hf_geoip_dst_org = -1;
+static int hf_geoip_dst_isp = -1;
+static int hf_geoip_dst_asnum = -1;
+static int hf_geoip_dst_lat = -1;
+static int hf_geoip_dst_lon = -1;
+#endif /* HAVE_GEOIP_V6 */
 
 static gint ett_ipv6                     = -1;
 static gint ett_ipv6_version   = -1;
@@ -150,6 +250,12 @@ static gint ett_ipv6_shim6_probe_rcvd        = -1;
 static gint ett_ipv6_shim6_cksum         = -1;
 static gint ett_ipv6_fragments           = -1;
 static gint ett_ipv6_fragment            = -1;
+static gint ett_ipv6_traffic_class        = -1;
+
+#ifdef HAVE_GEOIP_V6
+static gint ett_geoip_info = -1;
+#endif /* HAVE_GEOIP_V6 */
+
 
 static const fragment_items ipv6_frag_items = {
        &ett_ipv6_fragment,
@@ -161,8 +267,10 @@ static const fragment_items ipv6_frag_items = {
        &hf_ipv6_fragment_multiple_tails,
        &hf_ipv6_fragment_too_long_fragment,
        &hf_ipv6_fragment_error,
+       &hf_ipv6_fragment_count,
        &hf_ipv6_reassembled_in,
-       "fragments"
+       &hf_ipv6_reassembled_length,
+       "IPv6 fragments"
 };
 
 static dissector_handle_t data_handle;
@@ -172,6 +280,14 @@ static dissector_table_t ip_dissector_table;
 /* Reassemble fragmented datagrams */
 static gboolean ipv6_reassemble = TRUE;
 
+/* Place IPv6 summary in proto tree */
+static gboolean ipv6_summary_in_tree = TRUE;
+
+#ifdef HAVE_GEOIP_V6
+/* Look up addresses in GeoIP */
+static gboolean ipv6_use_geoip = TRUE;
+#endif /* HAVE_GEOIP_V6 */
+
 #ifndef offsetof
 #define        offsetof(type, member)  ((size_t)(&((type *)0)->member))
 #endif
@@ -239,6 +355,7 @@ again:
      offset += advance;
      goto again;
    case IP_PROTO_SHIM6:
+   case IP_PROTO_SHIM6_OLD:
      if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
        ld->other++;
        return;
@@ -282,6 +399,153 @@ again:
   }
 }
 
+#ifdef HAVE_GEOIP_V6
+static void
+add_geoip_info(proto_tree *tree, tvbuff_t *tvb, gint offset, struct e_in6_addr src, struct e_in6_addr dst)
+{
+  guint dbnum, num_dbs;
+  int geoip_hf, geoip_src_hf, geoip_dst_hf;
+  const char *geoip_src_str, *geoip_dst_str;
+  proto_item *geoip_info_item;
+  proto_tree *geoip_info_tree;
+  proto_item *item;
+  guint item_cnt;
+
+  num_dbs = geoip_db_num_dbs();
+  if (num_dbs < 1) return;
+
+  geoip_info_item = proto_tree_add_text(tree, tvb, offset + IP6H_SRC, 16, "Source GeoIP: ");
+  geoip_info_tree = proto_item_add_subtree(geoip_info_item, ett_geoip_info);
+  PROTO_ITEM_SET_GENERATED(geoip_info_item);
+  item_cnt = 0;
+
+  for (dbnum = 0; dbnum < num_dbs; dbnum++) {
+    geoip_src_str = geoip_db_lookup_ipv6(dbnum, src, NULL);
+
+    switch (geoip_db_type(dbnum)) {
+      case GEOIP_COUNTRY_EDITION_V6:
+        geoip_hf = hf_geoip_country;
+        geoip_src_hf = hf_geoip_src_country;
+        break;
+#if NUM_DB_TYPES > 31
+      case GEOIP_CITY_EDITION_REV0_V6:
+        geoip_hf = hf_geoip_city;
+        geoip_src_hf = hf_geoip_src_city;
+        break;
+      case GEOIP_CITY_EDITION_REV1_V6:
+        geoip_hf = hf_geoip_city;
+        geoip_src_hf = hf_geoip_src_city;
+        break;
+      case GEOIP_ORG_EDITION_V6:
+        geoip_hf = hf_geoip_org;
+        geoip_src_hf = hf_geoip_src_org;
+        break;
+      case GEOIP_ISP_EDITION_V6:
+        geoip_hf = hf_geoip_isp;
+        geoip_src_hf = hf_geoip_src_isp;
+        break;
+      case GEOIP_ASNUM_EDITION_V6:
+        geoip_hf = hf_geoip_asnum;
+        geoip_src_hf = hf_geoip_src_asnum;
+        break;
+#endif /* DB_NUM_TYPES */
+      case WS_LAT_FAKE_EDITION:
+        geoip_hf = hf_geoip_lat;
+        geoip_src_hf = hf_geoip_src_lat;
+        break;
+      case WS_LON_FAKE_EDITION:
+        geoip_hf = hf_geoip_lon;
+        geoip_src_hf = hf_geoip_src_lon;
+        break;
+      default:
+        continue;
+        break;
+    }
+
+    if (geoip_src_str) {
+      item = proto_tree_add_string_format_value(geoip_info_tree, geoip_src_hf, tvb,
+        offset + IP6H_SRC, 16, geoip_src_str, "%s", geoip_src_str);
+      PROTO_ITEM_SET_GENERATED(item);
+      item  = proto_tree_add_string_format_value(geoip_info_tree, geoip_hf, tvb,
+        offset + IP6H_SRC, 16, geoip_src_str, "%s", geoip_src_str);
+      PROTO_ITEM_SET_GENERATED(item);
+      PROTO_ITEM_SET_HIDDEN(item);
+
+      item_cnt++;
+      proto_item_append_text(geoip_info_item, "%s%s", plurality(item_cnt, "", ", "), geoip_src_str);
+    }
+  }
+
+  if (item_cnt == 0)
+    proto_item_append_text(geoip_info_item, "Unknown");
+
+  geoip_info_item = proto_tree_add_text(tree, tvb, offset + IP6H_DST, 16, "Destination GeoIP: ");
+  geoip_info_tree = proto_item_add_subtree(geoip_info_item, ett_geoip_info);
+  PROTO_ITEM_SET_GENERATED(geoip_info_item);
+  item_cnt = 0;
+
+  for (dbnum = 0; dbnum < num_dbs; dbnum++) {
+    geoip_dst_str = geoip_db_lookup_ipv6(dbnum, dst, NULL);
+
+    switch (geoip_db_type(dbnum)) {
+      case GEOIP_COUNTRY_EDITION_V6:
+        geoip_hf = hf_geoip_country;
+        geoip_dst_hf = hf_geoip_dst_country;
+        break;
+#if NUM_DB_TYPES > 31
+      case GEOIP_CITY_EDITION_REV0_V6:
+        geoip_hf = hf_geoip_city;
+        geoip_dst_hf = hf_geoip_dst_city;
+        break;
+      case GEOIP_CITY_EDITION_REV1_V6:
+        geoip_hf = hf_geoip_city;
+        geoip_dst_hf = hf_geoip_dst_city;
+        break;
+      case GEOIP_ORG_EDITION_V6:
+        geoip_hf = hf_geoip_org;
+        geoip_dst_hf = hf_geoip_dst_org;
+        break;
+      case GEOIP_ISP_EDITION_V6:
+        geoip_hf = hf_geoip_isp;
+        geoip_dst_hf = hf_geoip_dst_isp;
+        break;
+      case GEOIP_ASNUM_EDITION_V6:
+        geoip_hf = hf_geoip_asnum;
+        geoip_dst_hf = hf_geoip_dst_asnum;
+        break;
+#endif /* DB_NUM_TYPES */
+      case WS_LAT_FAKE_EDITION:
+        geoip_hf = hf_geoip_lat;
+        geoip_dst_hf = hf_geoip_dst_lat;
+        break;
+      case WS_LON_FAKE_EDITION:
+        geoip_hf = hf_geoip_lon;
+        geoip_dst_hf = hf_geoip_dst_lon;
+        break;
+      default:
+        continue;
+        break;
+    }
+
+    if (geoip_dst_str) {
+      item = proto_tree_add_string_format_value(geoip_info_tree, geoip_dst_hf, tvb,
+        offset + IP6H_DST, 16, geoip_dst_str, "%s", geoip_dst_str);
+      PROTO_ITEM_SET_GENERATED(item);
+      item  = proto_tree_add_string_format_value(geoip_info_tree, geoip_hf, tvb,
+        offset + IP6H_DST, 16, geoip_dst_str, "%s", geoip_dst_str);
+      PROTO_ITEM_SET_GENERATED(item);
+      PROTO_ITEM_SET_HIDDEN(item);
+
+      item_cnt++;
+      proto_item_append_text(geoip_info_item, "%s%s", plurality(item_cnt, "", ", "), geoip_dst_str);
+    }
+  }
+
+  if (item_cnt == 0)
+    proto_item_append_text(geoip_info_item, "Unknown");
+}
+#endif /* HAVE_GEOIP_V6 */
+
 static void
 ipv6_reassemble_init(void)
 {
@@ -292,7 +556,8 @@ ipv6_reassemble_init(void)
 enum {
   IPv6_RT_HEADER_SOURCE_ROUTING=0,
   IPv6_RT_HEADER_NIMROD,
-  IPv6_RT_HEADER_MobileIP
+  IPv6_RT_HEADER_MobileIP,
+  IPv6_RT_HEADER_RPL=4
 };
 
 /* Routeing Header Types */
@@ -300,13 +565,14 @@ static const value_string routing_header_type[] = {
   { IPv6_RT_HEADER_SOURCE_ROUTING, "IPv6 Source Routing" },
   { IPv6_RT_HEADER_NIMROD, "Nimrod" },
   { IPv6_RT_HEADER_MobileIP, "Mobile IP" },
+  { IPv6_RT_HEADER_RPL, "RPL" },
   { 0, NULL }
 };
 
 static int
 dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo) {
     struct ip6_rthdr rt;
-    guint len;
+    guint len, seg_left;
     proto_tree *rthdr_tree;
     proto_item *ti;
     guint8 buf[sizeof(struct ip6_rthdr0) + sizeof(struct e_in6_addr) * 23];
@@ -319,7 +585,7 @@ dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
       ti = proto_tree_add_uint_format(tree, hf_ipv6_routing_hdr_opt, tvb,
                      offset, len, rt.ip6r_type,
                      "Routing Header, Type : %s (%u)",
-                     val_to_str(rt.ip6r_type, routing_header_type, "Unkown"),
+                     val_to_str(rt.ip6r_type, routing_header_type, "Unknown"),
                      rt.ip6r_type);
       rthdr_tree = proto_item_add_subtree(ti, ett_ipv6);
 
@@ -332,10 +598,12 @@ dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
            "Length: %u (%d bytes)", rt.ip6r_len, len);
 
        proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_type, tvb,
-                 offset + offsetof(struct ip6_rthdr, ip6r_type), 1, FALSE);
+                 offset + offsetof(struct ip6_rthdr, ip6r_type), 1, ENC_BIG_ENDIAN);
 
        proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_left, tvb,
-                 offset + offsetof(struct ip6_rthdr, ip6r_segleft), 1, FALSE);
+                 offset + offsetof(struct ip6_rthdr, ip6r_segleft), 1, ENC_BIG_ENDIAN);
+
+       seg_left = tvb_get_guint8(tvb, offset + offsetof(struct ip6_rthdr, ip6r_segleft));
 
        if (rt.ip6r_type == IPv6_RT_HEADER_SOURCE_ROUTING && len <= sizeof(buf)) {
            struct e_in6_addr *a;
@@ -351,27 +619,89 @@ dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
              proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_addr, tvb,
                              offset + offsetof(struct ip6_rthdr0, ip6r0_addr)
                                     + n * sizeof(struct e_in6_addr),
-                             sizeof(struct e_in6_addr), FALSE);
-             SET_ADDRESS(&pinfo->dst, AT_IPv6, 16, tvb_get_ptr(tvb,
+                             sizeof(struct e_in6_addr), ENC_NA);
+             if (seg_left)
+                 SET_ADDRESS(&pinfo->dst, AT_IPv6, 16, tvb_get_ptr(tvb,
                              offset + offsetof(struct ip6_rthdr0, ip6r0_addr)
                                     + n * sizeof(struct e_in6_addr), 16));
            }
        }
        if (rt.ip6r_type == IPv6_RT_HEADER_MobileIP) {
          proto_tree_add_item(rthdr_tree, hf_ipv6_mipv6_home_address, tvb,
-                             offset + 8, 16, FALSE);
+                             offset + 8, 16, ENC_NA);
          SET_ADDRESS(&pinfo->dst, AT_IPv6, 16, tvb_get_ptr(tvb, offset + 8, 16));
        }
+    if (rt.ip6r_type == IPv6_RT_HEADER_RPL) {
+        guint8 cmprI;
+        guint8 cmprE;
+        guint8 pad;
+        gint segments;
+
+        /* IPv6 destination address used for elided bytes */
+        struct e_in6_addr dstAddr;
+        offset += 4;
+        memcpy((guint8 *)&dstAddr, (guint8 *)pinfo->dst.data, pinfo->dst.len);
+
+        proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_rpl_cmprI, tvb, offset, 4, ENC_BIG_ENDIAN);
+        proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_rpl_cmprE, tvb, offset, 4, ENC_BIG_ENDIAN);
+        proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_rpl_pad, tvb, offset, 4, ENC_BIG_ENDIAN);
+        proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_rpl_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
+
+        cmprI = tvb_get_guint8(tvb, offset) & 0xF0;
+        cmprE = tvb_get_guint8(tvb, offset) & 0x0F;
+        pad   = tvb_get_guint8(tvb, offset + 1) & 0xF0;
+
+        /* Shift bytes over */
+        cmprI >>= 4;
+        pad >>= 4;
+
+        /* from draft-ietf-6man-rpl-routing-header-03:
+        n = (((Hdr Ext Len * 8) - Pad - (16 - CmprE)) / (16 - CmprI)) + 1 */
+        segments = (((rt.ip6r_len * 8) - pad - (16 - cmprE)) / (16 - cmprI)) + 1;
+        ti = proto_tree_add_int(rthdr_tree, hf_ipv6_routing_hdr_rpl_segments, tvb, offset, 2, segments);
+        PROTO_ITEM_SET_GENERATED(ti);
+
+        if ((segments < 0) || (segments > 136)) {
+            expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Calculated total segments is invalid, 0 < %d < 136 fails", segments);
+        } else {
+
+            offset += 4;
+
+            /* We use cmprI for internal (e.g.: not last) address for how many bytes to elide, so actual bytes present = 16-CmprI */
+            while(segments > 1) {
+                struct e_in6_addr addr;
+
+                proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_rpl_addr, tvb, offset, (16-cmprI), ENC_NA);
+                /* Display Full Address */
+                memcpy((guint8 *)&addr, (guint8 *)&dstAddr, sizeof(dstAddr));
+                tvb_memcpy(tvb, (guint8 *)&addr + cmprI, offset, (16-cmprI));
+                ti = proto_tree_add_ipv6(rthdr_tree, hf_ipv6_routing_hdr_rpl_fulladdr, tvb, offset, (16-cmprI), (guint8 *)&addr);
+                PROTO_ITEM_SET_GENERATED(ti);
+                offset += (16-cmprI);
+                segments--;
+            }
+
+            /* We use cmprE for last address for how many bytes to elide, so actual bytes present = 16-CmprE */
+            if (segments == 1) {
+                struct e_in6_addr addr;
+
+                proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_rpl_addr, tvb, offset, (16-cmprI), ENC_NA);
+                /* Display Full Address */
+                memcpy((guint8 *)&addr, (guint8 *)&dstAddr, sizeof(dstAddr));
+                tvb_memcpy(tvb, (guint8 *)&addr + cmprE, offset, (16-cmprE));
+                ti = proto_tree_add_ipv6(rthdr_tree, hf_ipv6_routing_hdr_rpl_fulladdr, tvb, offset, (16-cmprE), (guint8 *)&addr);
+                PROTO_ITEM_SET_GENERATED(ti);
+                offset += (16-cmprE);
+            }
+
+        }
+
+    }
     }
 
     return len;
 }
 
-static const true_false_string ipv6_more_frag = {
-  "Yes",
-  "No"
-};
-
 static int
 dissect_frag6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
     guint16 *offlg, guint32 *ident) {
@@ -410,13 +740,13 @@ dissect_frag6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
 #endif
 
           proto_tree_add_item(rthdr_tree, hf_ipv6_frag_offset, tvb,
-                   offset + offsetof(struct ip6_frag, ip6f_offlg), 2, FALSE);
+                   offset + offsetof(struct ip6_frag, ip6f_offlg), 2, ENC_BIG_ENDIAN);
 
           proto_tree_add_item(rthdr_tree, hf_ipv6_frag_more, tvb,
-                   offset + offsetof(struct ip6_frag, ip6f_offlg), 2, FALSE);
+                   offset + offsetof(struct ip6_frag, ip6f_offlg), 2, ENC_BIG_ENDIAN);
 
           proto_tree_add_item(rthdr_tree, hf_ipv6_frag_id, tvb,
-                   offset + offsetof(struct ip6_frag, ip6f_ident), 4, FALSE);
+                   offset + offsetof(struct ip6_frag, ip6f_ident), 4, ENC_BIG_ENDIAN);
     }
     return len;
 }
@@ -438,8 +768,8 @@ dissect_mipv6_hoa(tvbuff_t *tvb, proto_tree *dstopt_tree, int offset, packet_inf
        1, tvb_get_guint8(tvb, offset + len));
     len += 1;
 
-    proto_tree_add_ipv6(dstopt_tree, hf_ipv6_mipv6_home_address, tvb,
-       offset + len, 16, tvb_get_ptr(tvb, offset + len, 16));
+    proto_tree_add_item(dstopt_tree, hf_ipv6_mipv6_home_address, tvb,
+                       offset + len, 16, ENC_NA);
     SET_ADDRESS(&pinfo->src, AT_IPv6, 16, tvb_get_ptr(tvb, offset + len, 16));
     len += 16;
     return len;
@@ -548,6 +878,34 @@ dissect_ipv6_options(tvbuff_t *tvb, int offset, guint length,
   }
 }
 
+static int
+dissect_unknown_option(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+    struct ip6_ext ext;
+    int len;
+    proto_tree *unkopt_tree;
+    proto_item *ti;
+
+    tvb_memcpy(tvb, (guint8 *)&ext, offset, sizeof(ext));
+    len = (ext.ip6e_len + 1) << 3;
+
+    if (tree) {
+       /* !!! specify length */
+       ti = proto_tree_add_item(tree, hf_ipv6_unk_hdr, tvb, offset, len, ENC_NA);
+
+       unkopt_tree = proto_item_add_subtree(ti, ett_ipv6);
+
+       proto_tree_add_text(unkopt_tree, tvb,
+           offset + offsetof(struct ip6_ext, ip6e_nxt), 1,
+           "Next header: %s (0x%02x)", ipprotostr(ext.ip6e_nxt), ext.ip6e_nxt);
+
+       proto_tree_add_text(unkopt_tree, tvb,
+           offset + offsetof(struct ip6_ext, ip6e_len), 1,
+           "Length: %u (%d bytes)", ext.ip6e_len, len);
+    }
+    return len;
+}
+
 static int
 dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo, const int hf_option_item)
 {
@@ -564,7 +922,7 @@ dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo, c
 
     if (tree) {
        /* !!! specify length */
-       ti = proto_tree_add_item(tree, hf_option_item, tvb, offset, len, FALSE);
+       ti = proto_tree_add_item(tree, hf_option_item, tvb, offset, len, ENC_NA);
 
        dstopt_tree = proto_item_add_subtree(ti, ett_ipv6);
 
@@ -584,7 +942,7 @@ dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo, c
        while (p < offset + len) {
            switch (tvb_get_guint8(tvb, p)) {
            case IP6OPT_PAD1:
-               proto_tree_add_item(dstopt_tree, hf_ipv6_opt_pad1, tvb, p, 1, FALSE);
+               proto_tree_add_item(dstopt_tree, hf_ipv6_opt_pad1, tvb, p, 1, ENC_NA);
                p++;
                mip_offset++;
                break;
@@ -686,7 +1044,7 @@ dissect_shim_hex(tvbuff_t *tvb, int offset, int len, const char *itemname, guint
 
     p = offset;
 
-    ti = proto_tree_add_text(tree, tvb, offset, len, itemname);
+    ti = proto_tree_add_text(tree, tvb, offset, len, "%s", itemname);
 
     proto_item_append_text(ti, " 0x%02x", tvb_get_guint8(tvb, p) & bitmask);
     for (count=1; count<len; count++)
@@ -725,17 +1083,36 @@ static const value_string shimreapstates[] = {
     { 0, NULL }
 };
 
-static const true_false_string shim6_critical_opts = {
-    "Yes",
-    "No"
-};
-
 static const value_string shim6_protocol[] = {
   { 0, "SHIM6" },
   { 1, "HIP" },
   { 0, NULL }
 };
 
+static const value_string dscp_vals[] = {
+                 { IPDSFIELD_DSCP_DEFAULT, "Default"               },
+                 { IPDSFIELD_DSCP_CS1,     "Class Selector 1"      },
+                 { IPDSFIELD_DSCP_CS2,     "Class Selector 2"      },
+                 { IPDSFIELD_DSCP_CS3,     "Class Selector 3"      },
+                 { IPDSFIELD_DSCP_CS4,     "Class Selector 4"      },
+                 { IPDSFIELD_DSCP_CS5,     "Class Selector 5"      },
+                 { IPDSFIELD_DSCP_CS6,     "Class Selector 6"      },
+                 { IPDSFIELD_DSCP_CS7,     "Class Selector 7"      },
+                 { IPDSFIELD_DSCP_AF11,    "Assured Forwarding 11" },
+                 { IPDSFIELD_DSCP_AF12,    "Assured Forwarding 12" },
+                 { IPDSFIELD_DSCP_AF13,    "Assured Forwarding 13" },
+                 { IPDSFIELD_DSCP_AF21,    "Assured Forwarding 21" },
+                 { IPDSFIELD_DSCP_AF22,    "Assured Forwarding 22" },
+                 { IPDSFIELD_DSCP_AF23,    "Assured Forwarding 23" },
+                 { IPDSFIELD_DSCP_AF31,    "Assured Forwarding 31" },
+                 { IPDSFIELD_DSCP_AF32,    "Assured Forwarding 32" },
+                 { IPDSFIELD_DSCP_AF33,    "Assured Forwarding 33" },
+                 { IPDSFIELD_DSCP_AF41,    "Assured Forwarding 41" },
+                 { IPDSFIELD_DSCP_AF42,    "Assured Forwarding 42" },
+                 { IPDSFIELD_DSCP_AF43,    "Assured Forwarding 43" },
+                 { IPDSFIELD_DSCP_EF,      "Expedited Forwarding"  },
+                 { 0,                      NULL                    } };
+
 static void
 dissect_shim6_opt_loclist(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset)
 {
@@ -745,11 +1122,11 @@ dissect_shim6_opt_loclist(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset)
   guint optlen;
   int p = *offset;
 
-  proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_loclist, tvb, p, 4, FALSE);
+  proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_loclist, tvb, p, 4, ENC_BIG_ENDIAN);
   p += 4;
 
   optlen = tvb_get_guint8(tvb, p);
-  proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_locnum, tvb, p, 1, FALSE);
+  proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_locnum, tvb, p, 1, ENC_BIG_ENDIAN);
   p++;
 
   /* Verification Methods */
@@ -759,7 +1136,7 @@ dissect_shim6_opt_loclist(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset)
 
   for (count=0; count < optlen; count++)
     proto_tree_add_item(subtree, hf_ipv6_shim6_opt_loc_verif_methods, tvb,
-                           p+count, 1, FALSE);
+                           p+count, 1, ENC_BIG_ENDIAN);
   p += optlen;
 
   /* Padding, included in length field */
@@ -773,7 +1150,7 @@ dissect_shim6_opt_loclist(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset)
   subtree = proto_item_add_subtree(it, ett_ipv6_shim6_locators);
 
   for (count=0; count < optlen; count++) {
-      proto_tree_add_item(subtree, hf_ipv6_shim6_locator, tvb, p, 16, FALSE);
+      proto_tree_add_item(subtree, hf_ipv6_shim6_locator, tvb, p, 16, ENC_NA);
       p += 16;
   }
   *offset = p;
@@ -791,11 +1168,11 @@ dissect_shim6_opt_loc_pref(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset,
 
   p = *offset;
 
-  proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_loclist, tvb, p, 4, FALSE);
+  proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_loclist, tvb, p, 4, ENC_BIG_ENDIAN);
   p += 4;
 
   optlen = tvb_get_guint8(tvb, p);
-  proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_elemlen, tvb, p, 1, FALSE);
+  proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_elemlen, tvb, p, 1, ENC_BIG_ENDIAN);
 
   if (optlen < 1 || optlen > 3) {
     it = proto_tree_add_text(opt_tree, tvb, p, 1,
@@ -815,13 +1192,13 @@ dissect_shim6_opt_loc_pref(proto_tree * opt_tree, tvbuff_t * tvb, gint *offset,
 
     /* Flags */
     if (optlen >= 1)
-      proto_tree_add_item(subtree, hf_ipv6_shim6_loc_flag, tvb, p, 1, FALSE);
+      proto_tree_add_item(subtree, hf_ipv6_shim6_loc_flag, tvb, p, 1, ENC_BIG_ENDIAN);
     /* Priority */
     if (optlen >= 2)
-      proto_tree_add_item(subtree, hf_ipv6_shim6_loc_prio, tvb, p+1, 1, FALSE);
+      proto_tree_add_item(subtree, hf_ipv6_shim6_loc_prio, tvb, p+1, 1, ENC_BIG_ENDIAN);
     /* Weight */
     if (optlen >= 3)
-      proto_tree_add_item(subtree, hf_ipv6_shim6_loc_weight, tvb, p+2, 1, FALSE);
+      proto_tree_add_item(subtree, hf_ipv6_shim6_loc_weight, tvb, p+2, 1, ENC_BIG_ENDIAN);
     /*
      * Shim6 Draft 08 doesn't specify the format when the Element length is
      * more than three, except that any such formats MUST be defined so that
@@ -844,15 +1221,12 @@ dissect_shimopts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
     gint padding;
     proto_tree *opt_tree;
     proto_item *ti;
-    guint8 tmp[2];
     const gchar *ctype;
 
 
     p = offset;
 
-    tmp[0] = tvb_get_guint8(tvb, p++);
-    tmp[1] = tvb_get_guint8(tvb, p++);
-    p += 2;
+    p += 4;
 
     len = tvb_get_ntohs(tvb, offset+2);
     padding = 7 - ((len + 3) % 8);
@@ -865,13 +1239,13 @@ dissect_shimopts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
        ti = proto_tree_add_text(tree, tvb, offset, total_len, "%s", ctype);
        opt_tree = proto_item_add_subtree(ti, ett_ipv6_shim6_option);
 
-       proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_type, tvb, offset, 2, FALSE);
+       proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_type, tvb, offset, 2, ENC_BIG_ENDIAN);
 
        /* Critical */
-       proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_critical, tvb, offset+1, 1, FALSE);
+       proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_critical, tvb, offset+1, 1, ENC_BIG_ENDIAN);
 
        /* Content Length */
-       proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_len, tvb, offset + 2, 2, FALSE);
+       proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_len, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
        ti = proto_tree_add_uint_format(opt_tree, hf_ipv6_shim6_opt_total_len, tvb, offset+2, 2,
            total_len, "Total Length: %u", total_len);
        PROTO_ITEM_SET_GENERATED(ti);
@@ -905,13 +1279,13 @@ dissect_shimopts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
            case SHIM6_OPT_ULIDPAIR:
                proto_tree_add_text(opt_tree, tvb, p, 4, "Reserved");
                p += 4;
-               proto_tree_add_item(opt_tree, hf_ipv6_shim6_sulid, tvb, p, 16, FALSE);
+               proto_tree_add_item(opt_tree, hf_ipv6_shim6_sulid, tvb, p, 16, ENC_NA);
                p += 16;
-               proto_tree_add_item(opt_tree, hf_ipv6_shim6_rulid, tvb, p, 16, FALSE);
+               proto_tree_add_item(opt_tree, hf_ipv6_shim6_rulid, tvb, p, 16, ENC_NA);
                p += 16;
                break;
            case SHIM6_OPT_FII:
-               proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_fii, tvb, p, 4, FALSE);
+               proto_tree_add_item(opt_tree, hf_ipv6_shim6_opt_fii, tvb, p, 4, ENC_BIG_ENDIAN);
                p += 4;
                break;
            default:
@@ -922,7 +1296,7 @@ dissect_shimopts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
 }
 
 static void
-dissect_shim6_ct(proto_tree * shim_tree, gint hf_item, tvbuff_t * tvb, gint offset, guchar * label)
+dissect_shim6_ct(proto_tree * shim_tree, gint hf_item, tvbuff_t * tvb, gint offset, const guchar * label)
 {
   guint8 tmp[6];
   guchar * ct_str;
@@ -938,12 +1312,13 @@ dissect_shim6_ct(proto_tree * shim_tree, gint hf_item, tvbuff_t * tvb, gint offs
                              tmp[0] & SHIM6_BITMASK_CT, tmp[1], tmp[2],
                              tmp[3], tmp[4], tmp[5]
                            );
-  proto_tree_add_none_format(shim_tree, hf_item, tvb, offset - 6, 6, ct_str);
+  proto_tree_add_none_format(shim_tree, hf_item, tvb, offset - 6, 6, "%s", ct_str);
 }
 
 static void
 dissect_shim6_probes(proto_tree * shim_tree, tvbuff_t * tvb, gint offset,
-                     guchar * label, guint nbr_probe, gboolean probes_rcvd)
+                     const guchar * label, guint nbr_probe,
+                    gboolean probes_rcvd)
 {
   proto_tree * probes_tree;
   proto_tree * probe_tree;
@@ -959,22 +1334,22 @@ dissect_shim6_probes(proto_tree * shim_tree, tvbuff_t * tvb, gint offset,
     ett_probes = ett_ipv6_shim6_probes_sent;
     ett_probe = ett_ipv6_shim6_probe_sent;
   }
-  it = proto_tree_add_text(shim_tree, tvb, offset, 40 * nbr_probe, label);
+  it = proto_tree_add_text(shim_tree, tvb, offset, 40 * nbr_probe, "%s", label);
   probes_tree = proto_item_add_subtree(it, ett_probes);
 
   for (count=0; count < nbr_probe; count++) {
     it = proto_tree_add_text(probes_tree, tvb, offset, 40, "Probe %u", count+1);
     probe_tree = proto_item_add_subtree(it, ett_probe);
 
-    proto_tree_add_item(probe_tree, hf_ipv6_shim6_psrc, tvb, offset, 16, FALSE);
+    proto_tree_add_item(probe_tree, hf_ipv6_shim6_psrc, tvb, offset, 16, ENC_NA);
     offset += 16;
-    proto_tree_add_item(probe_tree, hf_ipv6_shim6_pdst, tvb, offset, 16, FALSE);
+    proto_tree_add_item(probe_tree, hf_ipv6_shim6_pdst, tvb, offset, 16, ENC_NA);
     offset += 16;
 
-    proto_tree_add_item(probe_tree, hf_ipv6_shim6_pnonce, tvb, offset, 4, FALSE);
+    proto_tree_add_item(probe_tree, hf_ipv6_shim6_pnonce, tvb, offset, 4, ENC_BIG_ENDIAN);
     offset += 4;
 
-    proto_tree_add_item(probe_tree, hf_ipv6_shim6_pdata, tvb, offset, 4, FALSE);
+    proto_tree_add_item(probe_tree, hf_ipv6_shim6_pdata, tvb, offset, 4, ENC_BIG_ENDIAN);
     offset += 4;
   }
 }
@@ -996,23 +1371,23 @@ dissect_shimctrl(tvbuff_t *tvb, gint offset, guint type, proto_tree *shim_tree)
        case SHIM6_TYPE_I1:
            dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Initiator Context Tag");
            p += 6;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
            break;
        case SHIM6_TYPE_R1:
            proto_tree_add_text(shim_tree, tvb, p, 2, "Reserved2");
            p += 2;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
            break;
        case SHIM6_TYPE_I2:
            dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Initiator Context Tag");
            p += 6;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
            proto_tree_add_text(shim_tree, tvb, p, 4, "Reserved2");
            p += 4;
@@ -1020,21 +1395,21 @@ dissect_shimctrl(tvbuff_t *tvb, gint offset, guint type, proto_tree *shim_tree)
        case SHIM6_TYPE_R2:
            dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Responder Context Tag");
            p += 6;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
            break;
        case SHIM6_TYPE_R1BIS:
            dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Packet Context Tag");
            p += 6;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
            break;
        case SHIM6_TYPE_I2BIS:
            dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Initiator Context Tag");
            p += 6;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_inonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
            proto_tree_add_text(shim_tree, tvb, p, 6, "Reserved2");
            p += 6;
@@ -1045,7 +1420,7 @@ dissect_shimctrl(tvbuff_t *tvb, gint offset, guint type, proto_tree *shim_tree)
        case SHIM6_TYPE_UPD_ACK:
            dissect_shim6_ct(shim_tree, hf_ipv6_shim6_ct, tvb, p, "Receiver Context Tag");
            p += 6;
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_rnonce, tvb, p, 4, ENC_BIG_ENDIAN);
            p += 4;
            break;
        case SHIM6_TYPE_KEEPALIVE:
@@ -1129,8 +1504,7 @@ static void ipv6_shim6_checkum_additional_info(tvbuff_t * tvb, packet_info * pin
         PROTO_ITEM_SET_GENERATED(item);
        if (!is_cksum_correct) {
          expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
-         if (check_col(pinfo->cinfo, COL_INFO))
-           col_append_str(pinfo->cinfo, COL_INFO, " [Shim6 CHECKSUM INCORRECT]");
+         col_append_str(pinfo->cinfo, COL_INFO, " [Shim6 CHECKSUM INCORRECT]");
        }
 }
 
@@ -1149,7 +1523,7 @@ dissect_shim6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo)
 
     if (tree)
     {
-       ti = proto_tree_add_item(tree, hf_ipv6_shim6, tvb, offset, len, FALSE);
+       ti = proto_tree_add_item(tree, hf_ipv6_shim6, tvb, offset, len, ENC_NA);
        shim_tree = proto_item_add_subtree(ti, ett_ipv6_shim6);
 
        /* Next Header */
@@ -1164,7 +1538,7 @@ dissect_shim6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo)
 
        /* P Field */
        proto_tree_add_item(shim_tree, hf_ipv6_shim6_p, tvb,
-                             offset + offsetof(struct ip6_shim, ip6s_p), 1, FALSE);
+                             offset + offsetof(struct ip6_shim, ip6s_p), 1, ENC_BIG_ENDIAN);
 
        /* skip the first 2 bytes (nxt hdr, hdr ext len, p+7bits) */
        p = offset + 3;
@@ -1192,11 +1566,11 @@ dissect_shim6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo)
            /* Message Type */
            proto_tree_add_item(shim_tree, hf_ipv6_shim6_type, tvb,
                                offset + offsetof(struct ip6_shim, ip6s_p), 1,
-                               FALSE
+                               ENC_BIG_ENDIAN
                                );
 
            /* Protocol bit (Must be zero for SHIM6) */
-           proto_tree_add_item(shim_tree, hf_ipv6_shim6_proto, tvb, p, 1, FALSE);
+           proto_tree_add_item(shim_tree, hf_ipv6_shim6_proto, tvb, p, 1, ENC_BIG_ENDIAN);
            p++;
 
            /* Checksum */
@@ -1233,7 +1607,7 @@ static void
 dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
   proto_tree *ipv6_tree = NULL;
-  proto_item *ti;
+  proto_item *ipv6_item = NULL, *ti;
   guint8 nxt;
   guint8 stype=0;
   int advance;
@@ -1246,15 +1620,14 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   fragment_data *ipfd_head;
   tvbuff_t   *next_tvb;
   gboolean update_col_info = TRUE;
-  gboolean save_fragmented;
+  gboolean save_fragmented = FALSE;
   const char *sep = "IPv6 ";
+  guint8 *mac_addr;
 
   struct ip6_hdr ipv6;
 
-  if (check_col(pinfo->cinfo, COL_PROTOCOL))
-    col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPv6");
-  if (check_col(pinfo->cinfo, COL_INFO))
-    col_clear(pinfo->cinfo, COL_INFO);
+  col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPv6");
+  col_clear(pinfo->cinfo, COL_INFO);
 
   offset = 0;
   tvb_memcpy(tvb, (guint8 *)&ipv6, offset, sizeof(ipv6));
@@ -1273,27 +1646,40 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   if (tree) {
     proto_tree* pt;
     proto_item* pi;
+    proto_tree *ipv6_tc_tree;
+    proto_item *ipv6_tc;
+    const char *name;
 
-    /* !!! specify length */
-    ti = proto_tree_add_item(tree, proto_ipv6, tvb, offset, 40, FALSE);
-    ipv6_tree = proto_item_add_subtree(ti, ett_ipv6);
+    ipv6_item = proto_tree_add_item(tree, proto_ipv6, tvb, offset, -1, ENC_NA);
+    ipv6_tree = proto_item_add_subtree(ipv6_item, ett_ipv6);
 
-    /* !!! warning: version also contains 4 Bit priority */
+    /* !!! warning: (4-bit) version, (6-bit) DSCP, (1-bit) ECN-ECT, (1-bit) ECN-CE and (20-bit) Flow */
     pi = proto_tree_add_item(ipv6_tree, hf_ipv6_version, tvb,
-                       offset + offsetof(struct ip6_hdr, ip6_vfc), 1, FALSE);
+                       offset + offsetof(struct ip6_hdr, ip6_vfc), 1, ENC_BIG_ENDIAN);
        pt = proto_item_add_subtree(pi,ett_ipv6_version);
     pi = proto_tree_add_item(pt, hf_ip_version, tvb,
-                                               offset + offsetof(struct ip6_hdr, ip6_vfc), 1, FALSE);
+                                               offset + offsetof(struct ip6_hdr, ip6_vfc), 1, ENC_BIG_ENDIAN);
        PROTO_ITEM_SET_GENERATED(pi);
 
-    proto_tree_add_item(ipv6_tree, hf_ipv6_class, tvb,
-                       offset + offsetof(struct ip6_hdr, ip6_flow), 4, FALSE);
+    ipv6_tc = proto_tree_add_item(ipv6_tree, hf_ipv6_class, tvb,
+                       offset + offsetof(struct ip6_hdr, ip6_flow), 4, ENC_BIG_ENDIAN);
+
+    ipv6_tc_tree = proto_item_add_subtree(ipv6_tc, ett_ipv6_traffic_class);
+
+    proto_tree_add_item(ipv6_tc_tree, hf_ipv6_traffic_class_dscp, tvb,
+                       offset + offsetof(struct ip6_hdr, ip6_flow), 4, ENC_BIG_ENDIAN);
+
+    proto_tree_add_item(ipv6_tc_tree, hf_ipv6_traffic_class_ect, tvb,
+                       offset + offsetof(struct ip6_hdr, ip6_flow), 4, ENC_BIG_ENDIAN);
+
+    proto_tree_add_item(ipv6_tc_tree, hf_ipv6_traffic_class_ce, tvb,
+                       offset + offsetof(struct ip6_hdr, ip6_flow), 4, ENC_BIG_ENDIAN);
 
     proto_tree_add_item(ipv6_tree, hf_ipv6_flow, tvb,
-                       offset + offsetof(struct ip6_hdr, ip6_flow), 4, FALSE);
+                       offset + offsetof(struct ip6_hdr, ip6_flow), 4, ENC_BIG_ENDIAN);
 
     proto_tree_add_item(ipv6_tree, hf_ipv6_plen, tvb,
-                       offset + offsetof(struct ip6_hdr, ip6_plen), 2, FALSE);
+                       offset + offsetof(struct ip6_hdr, ip6_plen), 2, ENC_BIG_ENDIAN);
 
     proto_tree_add_uint_format(ipv6_tree, hf_ipv6_nxt, tvb,
                offset + offsetof(struct ip6_hdr, ip6_nxt), 1,
@@ -1302,44 +1688,188 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                ipprotostr(ipv6.ip6_nxt), ipv6.ip6_nxt);
 
     proto_tree_add_item(ipv6_tree, hf_ipv6_hlim, tvb,
-                       offset + offsetof(struct ip6_hdr, ip6_hlim), 1, FALSE);
+                       offset + offsetof(struct ip6_hdr, ip6_hlim), 1, ENC_BIG_ENDIAN);
 
-    /* Adds the different items for the source address */
+    /* Add the different items for the source address */
     proto_tree_add_item(ipv6_tree, hf_ipv6_src, tvb,
-                       offset + offsetof(struct ip6_hdr, ip6_src), 16, FALSE);
+                       offset + offsetof(struct ip6_hdr, ip6_src), 16, ENC_NA);
     ti = proto_tree_add_ipv6(ipv6_tree, hf_ipv6_addr, tvb,
                              offset + offsetof(struct ip6_hdr, ip6_src),
                              16, (guint8 *)&ipv6.ip6_src);
     PROTO_ITEM_SET_HIDDEN(ti);
+    name = get_addr_name(&pinfo->src);
+    if (ipv6_summary_in_tree) {
+      proto_item_append_text(ipv6_item, ", Src: %s (%s)", name, ip6_to_str(&ipv6.ip6_src));
+    }
     ti = proto_tree_add_string(ipv6_tree, hf_ipv6_src_host, tvb,
                              offset + offsetof(struct ip6_hdr, ip6_src),
-                             16, get_addr_name(&pinfo->src));
+                             16, name);
     PROTO_ITEM_SET_GENERATED(ti);
     PROTO_ITEM_SET_HIDDEN(ti);
     ti = proto_tree_add_string(ipv6_tree, hf_ipv6_host, tvb,
                              offset + offsetof(struct ip6_hdr, ip6_src),
-                             16, get_addr_name(&pinfo->src));
+                             16, name);
     PROTO_ITEM_SET_GENERATED(ti);
     PROTO_ITEM_SET_HIDDEN(ti);
 
-    /* Adds different items for the destination address */
+    /* Extract embedded (IPv6 and MAC) address information */
+    if (tvb_get_ntohs(tvb, offset + IP6H_SRC) == 0x2002) { /* RFC 3056 section 2 */
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_src_6to4_gateway_ipv4, tvb,
+                                offset + IP6H_SRC + 2, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_src_6to4_sla_id, tvb,
+                                offset + IP6H_SRC + 6, 2, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_6to4_gateway_ipv4, tvb,
+                                offset + IP6H_SRC + 2, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_6to4_sla_id, tvb,
+                                offset + IP6H_SRC + 6, 2, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+    } else if (tvb_get_ntohl(tvb, offset + IP6H_SRC) == 0x20010000) { /* RFC 4380 section 4 */
+      guint16 mapped_port = tvb_get_ntohs(tvb, offset + IP6H_SRC + 10) ^ 0xffff;
+      guint32 client_v4 = tvb_get_ipv4(tvb, offset + IP6H_SRC + 12) ^ 0xffffffff;
+
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_src_teredo_server_ipv4, tvb,
+                                offset + IP6H_SRC + 4, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_uint(ipv6_tree, hf_ipv6_src_teredo_port, tvb,
+                                offset + IP6H_SRC + 10, 2, mapped_port);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_ipv4(ipv6_tree, hf_ipv6_src_teredo_client_ipv4, tvb,
+                                offset + IP6H_SRC + 12, 4, client_v4);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_teredo_server_ipv4, tvb,
+                                offset + IP6H_SRC + 4, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+      ti = proto_tree_add_uint(ipv6_tree, hf_ipv6_teredo_port, tvb,
+                                offset + IP6H_SRC + 10, 2, mapped_port);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+      ti = proto_tree_add_ipv4(ipv6_tree, hf_ipv6_teredo_client_ipv4, tvb,
+                                offset + IP6H_SRC + 12, 4, client_v4);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+    }
+
+    if (tvb_get_guint8(tvb, offset + IP6H_SRC + 8) & 0x02 && tvb_get_ntohs(tvb, offset + IP6H_SRC + 11) == 0xfffe) {  /* RFC 4291 appendix A */
+      mac_addr = ep_alloc(6);
+      tvb_memcpy(tvb, mac_addr, offset + IP6H_SRC + 8, 3);
+      tvb_memcpy(tvb, mac_addr+3, offset+ IP6H_SRC + 13, 3);
+      mac_addr[0] &= ~0x02;
+      ti = proto_tree_add_ether(ipv6_tree, hf_ipv6_src_sa_mac, tvb,
+                                offset + IP6H_SRC + 8, 6, mac_addr);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_ether(ipv6_tree, hf_ipv6_sa_mac, tvb,
+                                offset + IP6H_SRC + 8, 6, mac_addr);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+    } else if ((tvb_get_ntohl(tvb, offset + IP6H_SRC + 8) & 0xfcffffff) == 0x00005efe) { /* RFC 5214 section 6.1 */
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_src_isatap_ipv4, tvb,
+                                offset + IP6H_SRC + 12, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_isatap_ipv4, tvb,
+                                offset + IP6H_SRC + 12, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+    }
+
+    /* Add different items for the destination address */
     proto_tree_add_item(ipv6_tree, hf_ipv6_dst, tvb,
-                       offset + offsetof(struct ip6_hdr, ip6_dst), 16, FALSE);
+                       offset + offsetof(struct ip6_hdr, ip6_dst), 16, ENC_NA);
     ti = proto_tree_add_ipv6(ipv6_tree, hf_ipv6_addr, tvb,
                              offset + offsetof(struct ip6_hdr, ip6_dst),
                              16, (guint8 *)&ipv6.ip6_dst);
     PROTO_ITEM_SET_HIDDEN(ti);
+    name = get_addr_name(&pinfo->dst);
+    if (ipv6_summary_in_tree) {
+      proto_item_append_text(ipv6_item, ", Dst: %s (%s)", name, ip6_to_str(&ipv6.ip6_dst));
+    }
     ti = proto_tree_add_string(ipv6_tree, hf_ipv6_dst_host, tvb,
                              offset + offsetof(struct ip6_hdr, ip6_dst),
-                             16, get_addr_name(&pinfo->dst));
+                             16, name);
     PROTO_ITEM_SET_GENERATED(ti);
     PROTO_ITEM_SET_HIDDEN(ti);
     ti = proto_tree_add_string(ipv6_tree, hf_ipv6_host, tvb,
                              offset + offsetof(struct ip6_hdr, ip6_dst),
-                             16, get_addr_name(&pinfo->dst));
+                             16, name);
     PROTO_ITEM_SET_GENERATED(ti);
     PROTO_ITEM_SET_HIDDEN(ti);
+
+    /* Extract embedded (IPv6 and MAC) address information */
+    if (tvb_get_ntohs(tvb, offset + IP6H_DST) == 0x2002) { /* RFC 3056 section 2 */
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_dst_6to4_gateway_ipv4, tvb,
+                                offset + IP6H_DST + 2, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_dst_6to4_sla_id, tvb,
+                                offset + IP6H_DST + 6, 2, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_6to4_gateway_ipv4, tvb,
+                                offset + IP6H_DST + 2, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_6to4_sla_id, tvb,
+                                offset + IP6H_DST + 6, 2, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+    } else if (tvb_get_ntohl(tvb, offset + IP6H_DST) == 0x20010000) { /* RFC 4380 section 4 */
+      guint16 mapped_port = tvb_get_ntohs(tvb, offset + IP6H_DST + 10) ^ 0xffff;
+      guint32 client_v4 = tvb_get_ipv4(tvb, offset + IP6H_DST + 12) ^ 0xffffffff;
+
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_dst_teredo_server_ipv4, tvb,
+                                offset + IP6H_DST + 4, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_uint(ipv6_tree, hf_ipv6_dst_teredo_port, tvb,
+                                offset + IP6H_DST + 10, 2, mapped_port);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_ipv4(ipv6_tree, hf_ipv6_dst_teredo_client_ipv4, tvb,
+                                offset + IP6H_DST + 12, 4, client_v4);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_teredo_server_ipv4, tvb,
+                                offset + IP6H_DST + 4, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+      ti = proto_tree_add_uint(ipv6_tree, hf_ipv6_teredo_port, tvb,
+                                offset + IP6H_DST + 10, 2, mapped_port);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+      ti = proto_tree_add_ipv4(ipv6_tree, hf_ipv6_teredo_client_ipv4, tvb,
+                                offset + IP6H_DST + 12, 4, client_v4);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+    }
+
+    if (tvb_get_guint8(tvb, offset + IP6H_DST + 8) & 0x02 && tvb_get_ntohs(tvb, offset + IP6H_DST + 11) == 0xfffe) { /* RFC 4291 appendix A */
+      mac_addr = ep_alloc(6);
+      tvb_memcpy(tvb, mac_addr, offset + IP6H_DST + 8, 3);
+      tvb_memcpy(tvb, mac_addr+3, offset+ IP6H_DST + 13, 3);
+      mac_addr[0] &= ~0x02;
+      ti = proto_tree_add_ether(ipv6_tree, hf_ipv6_dst_sa_mac, tvb,
+                                offset + IP6H_DST + 8, 6, mac_addr);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_ether(ipv6_tree, hf_ipv6_sa_mac, tvb,
+                                offset + IP6H_DST + 8, 6, mac_addr);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+    } else if ((tvb_get_ntohl(tvb, offset + IP6H_DST + 8) & 0xfcffffff) == 0x00005efe) { /* RFC 5214 section 6.1 */
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_dst_isatap_ipv4, tvb,
+                                offset + IP6H_DST + 12, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      ti = proto_tree_add_item(ipv6_tree, hf_ipv6_isatap_ipv4, tvb,
+                                offset + IP6H_DST + 12, 4, ENC_BIG_ENDIAN);
+      PROTO_ITEM_SET_GENERATED(ti);
+      PROTO_ITEM_SET_HIDDEN(ti);
+    }
+  }
+
+#ifdef HAVE_GEOIP_V6
+  if (tree && ipv6_use_geoip) {
+    add_geoip_info(ipv6_tree, tvb, offset, ipv6.ip6_src, ipv6.ip6_dst);
   }
+#endif
 
   /* start of the new header (could be a extension header) */
   poffset = offset + offsetof(struct ip6_hdr, ip6_nxt);
@@ -1359,58 +1889,101 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
 again:
    switch (nxt) {
+
    case IP_PROTO_HOPOPTS:
-                       hopopts = TRUE;
-                       advance = dissect_hopopts(tvb, offset, ipv6_tree, pinfo);
-                       nxt = tvb_get_guint8(tvb, offset);
-                       poffset = offset;
-                       offset += advance;
-                       plen -= advance;
-                       goto again;
+      hopopts = TRUE;
+      advance = dissect_hopopts(tvb, offset, ipv6_tree, pinfo);
+      nxt = tvb_get_guint8(tvb, offset);
+      poffset = offset;
+      offset += advance;
+      plen -= advance;
+      goto again;
+
     case IP_PROTO_ROUTING:
-                       routing = TRUE;
-                       advance = dissect_routing6(tvb, offset, ipv6_tree, pinfo);
-                       nxt = tvb_get_guint8(tvb, offset);
-                       poffset = offset;
-                       offset += advance;
-                       plen -= advance;
-                       goto again;
+      routing = TRUE;
+      advance = dissect_routing6(tvb, offset, ipv6_tree, pinfo);
+      nxt = tvb_get_guint8(tvb, offset);
+      poffset = offset;
+      offset += advance;
+      plen -= advance;
+      goto again;
+
     case IP_PROTO_FRAGMENT:
-                       frag = TRUE;
-                       advance = dissect_frag6(tvb, offset, pinfo, ipv6_tree,
-                           &offlg, &ident);
-                       nxt = tvb_get_guint8(tvb, offset);
-                       poffset = offset;
-                       offset += advance;
-                       plen -= advance;
-                       goto again;
+      advance = dissect_frag6(tvb, offset, pinfo, ipv6_tree,
+          &offlg, &ident);
+      nxt = tvb_get_guint8(tvb, offset);
+      poffset = offset;
+      offset += advance;
+      plen -= advance;
+      frag = offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG);
+      save_fragmented |= frag;
+      if (ipv6_reassemble && frag && tvb_bytes_exist(tvb, offset, plen)) {
+        ipfd_head = fragment_add_check(tvb, offset, pinfo, ident,
+        ipv6_fragment_table,
+        ipv6_reassembled_table,
+          offlg & IP6F_OFF_MASK,
+          plen,
+          offlg & IP6F_MORE_FRAG);
+        next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv6",
+        ipfd_head, &ipv6_frag_items, &update_col_info, ipv6_tree);
+        if (next_tvb) {  /* Process post-fragment headers after reassembly... */
+          offset= 0;
+          offlg = 0;
+          frag = FALSE;
+          tvb = next_tvb;
+          goto again;
+        }
+      }
+      if (!(offlg & IP6F_OFF_MASK)) /*...or in the first fragment */
+        goto again;
+      break;
+
     case IP_PROTO_AH:
-                       ah = TRUE;
-                       advance = dissect_ah_header(
-                                 tvb_new_subset(tvb, offset, -1, -1),
-                                 pinfo, ipv6_tree, NULL, NULL);
-                       nxt = tvb_get_guint8(tvb, offset);
-                       poffset = offset;
-                       offset += advance;
-                       plen -= advance;
-                       goto again;
+      ah = TRUE;
+      advance = dissect_ah_header(tvb_new_subset_remaining(tvb, offset),
+                                  pinfo, ipv6_tree, NULL, NULL);
+      nxt = tvb_get_guint8(tvb, offset);
+      poffset = offset;
+      offset += advance;
+      plen -= advance;
+      goto again;
+
     case IP_PROTO_SHIM6:
-                       shim6 = TRUE;
-                       advance = dissect_shim6(tvb, offset, ipv6_tree, pinfo);
-                       nxt = tvb_get_guint8(tvb, offset);
-                       stype = tvb_get_guint8(tvb, offset+2);
-                       poffset = offset;
-                       offset += advance;
-                       plen -= advance;
-                       goto again;
+    case IP_PROTO_SHIM6_OLD:
+      shim6 = TRUE;
+      advance = dissect_shim6(tvb, offset, ipv6_tree, pinfo);
+      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, ipv6_tree, pinfo);
-                       nxt = tvb_get_guint8(tvb, offset);
-                       poffset = offset;
-                       offset += advance;
-                       plen -= advance;
-                       goto again;
+      dstopts = TRUE;
+      advance = dissect_dstopts(tvb, offset, ipv6_tree, pinfo);
+      nxt = tvb_get_guint8(tvb, offset);
+      poffset = offset;
+      offset += advance;
+      plen -= advance;
+      goto again;
+
+    case IP_PROTO_NONE:
+      break;
+
+    default:
+      /* Since we did not recognize this IPv6 option, check
+       * whether it is a known protocol. If not, then it
+       * is an unknown IPv6 option
+       */
+      if (!dissector_get_uint_handle(ip_dissector_table, nxt)) {
+        advance = dissect_unknown_option(tvb, offset, ipv6_tree);
+        nxt = tvb_get_guint8(tvb, offset);
+        poffset = offset;
+        offset += advance;
+        plen -= advance;
+        goto again;
+      }
     }
 
 #ifdef TEST_FINALHDR
@@ -1418,71 +1991,46 @@ again:
   PROTO_ITEM_SET_HIDDEN(ti);
 #endif
 
+  proto_item_set_len (ipv6_item, offset);
+  tap_queue_packet(ipv6_tap, pinfo, &ipv6);
+
   /* collect packet info */
   pinfo->ipproto = nxt;
   pinfo->iplen = sizeof(ipv6) + plen + offset;
   pinfo->iphdrlen = offset;
 
-  /* If ipv6_reassemble is on, this is a fragment, and we have all the data
-   * in the fragment, then just add the fragment to the hashtable.
-   */
-  save_fragmented = pinfo->fragmented;
-  if (ipv6_reassemble && frag && tvb_bytes_exist(tvb, offset, plen)) {
-    ipfd_head = fragment_add_check(tvb, offset, pinfo, ident,
-                            ipv6_fragment_table,
-                            ipv6_reassembled_table,
-                            offlg & IP6F_OFF_MASK,
-                            plen,
-                            offlg & IP6F_MORE_FRAG);
-
-    next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv6",
-          ipfd_head, &ipv6_frag_items, &update_col_info, ipv6_tree);
+  if (offlg & IP6F_OFF_MASK || (ipv6_reassemble && offlg & IP6F_MORE_FRAG)) {
+    /* Not the first fragment, or the first when we are reassembling and there are more. */
+    /* Don't dissect it; just show this as a fragment. */
+    /* COL_INFO was filled in by "dissect_frag6()" */
+    call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
+    return;
   } else {
-    /* If this is the first fragment, dissect its contents, otherwise
-       just show it as a fragment.
-
-       XXX - if we eventually don't save the reassembled contents of all
-       fragmented datagrams, we may want to always reassemble. */
-    if (offlg & IP6F_OFF_MASK) {
-      /* Not the first fragment - don't dissect it. */
-      next_tvb = NULL;
-    } else {
-      /* First fragment, or not fragmented.  Dissect what we have here. */
+    /* First fragment, not fragmented, or already reassembled.  Dissect what we have here. */
 
-      /* Get a tvbuff for the payload. */
-      next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+    /* Get a tvbuff for the payload. */
+    next_tvb = tvb_new_subset_remaining(tvb, offset);
 
-      /*
-       * If this is the first fragment, but not the only fragment,
-       * tell the next protocol that.
-       */
-      if (offlg & IP6F_MORE_FRAG)
-        pinfo->fragmented = TRUE;
-      else
-        pinfo->fragmented = FALSE;
-    }
+    /*
+     * If this is the first fragment, but not the only fragment,
+     * tell the next protocol that.
+     */
+    if (offlg & IP6F_MORE_FRAG)
+      pinfo->fragmented = TRUE;
+    else
+      pinfo->fragmented = FALSE;
   }
 
-  if (next_tvb == NULL) {
-    /* Just show this as a fragment. */
-    /* COL_INFO was filled in by "dissect_frag6()" */
-    call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
-
-    /* As we haven't reassembled anything, we haven't changed "pi", so
-       we don't have to restore it. */
-    pinfo->fragmented = save_fragmented;
-    return;
-  }
 
   /* do lookup with the subdissector table */
-  if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
+  if (!dissector_try_uint(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
     /* Unknown protocol.
        Handle "no next header" specially. */
     if (nxt == IP_PROTO_NONE) {
       if (check_col(pinfo->cinfo, COL_INFO)) {
         /* If we had an Authentication Header, the AH dissector already
            put something in the Info column; leave it there. */
-       if (!ah) {
+        if (!ah) {
           if (hopopts || routing || dstopts || shim6) {
             if (hopopts) {
               col_append_fstr(pinfo->cinfo, COL_INFO, "%shop-by-hop options",
@@ -1498,13 +2046,13 @@ again:
                               sep);
             }
             if (shim6) {
-               if (stype & SHIM6_BITMASK_P) {
-                 col_append_str(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"));
-               }
+              if (stype & SHIM6_BITMASK_P) {
+                col_append_str(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");
@@ -1525,25 +2073,25 @@ proto_register_ipv6(void)
   static hf_register_info hf[] = {
     { &hf_ipv6_version,
       { "Version",             "ipv6.version",
-                               FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }},
+                               FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
     { &hf_ip_version,
       { "This field makes the filter \"ip.version == 6\" possible",            "ip.version",
-                               FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }},
+                               FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
     { &hf_ipv6_class,
       { "Traffic class",       "ipv6.class",
-                               FT_UINT32, BASE_HEX, NULL, 0x0FF00000, "", HFILL }},
+                               FT_UINT32, BASE_HEX, NULL, 0x0FF00000, NULL, HFILL }},
     { &hf_ipv6_flow,
       { "Flowlabel",           "ipv6.flow",
-                               FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, "", HFILL }},
+                               FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, NULL, HFILL }},
     { &hf_ipv6_plen,
       { "Payload length",      "ipv6.plen",
-                               FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+                               FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
     { &hf_ipv6_nxt,
       { "Next header",         "ipv6.nxt",
-                               FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+                               FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
     { &hf_ipv6_hlim,
       { "Hop limit",           "ipv6.hlim",
-                               FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+                               FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
     { &hf_ipv6_src,
       { "Source",              "ipv6.src",
                                FT_IPv6, BASE_NONE, NULL, 0x0,
@@ -1552,6 +2100,34 @@ proto_register_ipv6(void)
       { "Source Host",         "ipv6.src_host",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                "Source IPv6 Host", HFILL }},
+    { &hf_ipv6_src_sa_mac,
+      { "Source SA MAC",               "ipv6.src_sa_mac",
+                               FT_ETHER, BASE_NONE, NULL, 0x0,
+                               "Source IPv6 Stateless Autoconfiguration MAC Address", HFILL }},
+    { &hf_ipv6_src_isatap_ipv4,
+      { "Source ISATAP IPv4",          "ipv6.src_isatap_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "Source IPv6 ISATAP Encapsulated IPv4 Address", HFILL }},
+    { &hf_ipv6_src_6to4_gateway_ipv4,
+      { "Source 6to4 Gateway IPv4",            "ipv6.src_6to4_gw_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "Source IPv6 6to4 Gateway IPv4 Address", HFILL }},
+    { &hf_ipv6_src_6to4_sla_id,
+      { "Source 6to4 SLA ID",          "ipv6.src_6to4_sla_id",
+                               FT_UINT16, BASE_DEC, NULL, 0x0,
+                               "Source IPv6 6to4 SLA ID", HFILL }},
+    { &hf_ipv6_src_teredo_server_ipv4,
+      { "Source Teredo Server IPv4",           "ipv6.src_ts_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "Source IPv6 Teredo Server Encapsulated IPv4 Address", HFILL }},
+    { &hf_ipv6_src_teredo_port,
+      { "Source Teredo Port",          "ipv6.src_tc_port",
+                               FT_UINT16, BASE_DEC, NULL, 0x0,
+                               "Source IPv6 Teredo Client Mapped Port", HFILL }},
+    { &hf_ipv6_src_teredo_client_ipv4,
+      { "Source Teredo Client IPv4",           "ipv6.src_tc_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "Source IPv6 Teredo Client Encapsulated IPv4 Address", HFILL }},
     { &hf_ipv6_dst,
       { "Destination",         "ipv6.dst",
                                FT_IPv6, BASE_NONE, NULL, 0x0,
@@ -1560,6 +2136,34 @@ proto_register_ipv6(void)
       { "Destination Host",    "ipv6.dst_host",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                "Destination IPv6 Host", HFILL }},
+    { &hf_ipv6_dst_sa_mac,
+      { "Destination SA MAC",          "ipv6.dst_sa_mac",
+                               FT_ETHER, BASE_NONE, NULL, 0x0,
+                               "Destination IPv6 Stateless Autoconfiguration MAC Address", HFILL }},
+    { &hf_ipv6_dst_isatap_ipv4,
+      { "Destination ISATAP IPv4",             "ipv6.dst_isatap_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "Destination IPv6 ISATAP Encapsulated IPv4 Address", HFILL }},
+    { &hf_ipv6_dst_6to4_gateway_ipv4,
+      { "Destination 6to4 Gateway IPv4",               "ipv6.dst_6to4_gw_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "Destination IPv6 6to4 Gateway IPv4 Address", HFILL }},
+    { &hf_ipv6_dst_6to4_sla_id,
+      { "Destination 6to4 SLA ID",             "ipv6.dst_6to4_sla_id",
+                               FT_UINT16, BASE_DEC, NULL, 0x0,
+                               "Destination IPv6 6to4 SLA ID", HFILL }},
+    { &hf_ipv6_dst_teredo_server_ipv4,
+      { "Destination Teredo Server IPv4",              "ipv6.dst_ts_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "Destination IPv6 Teredo Server Encapsulated IPv4 Address", HFILL }},
+    { &hf_ipv6_dst_teredo_port,
+      { "Destination Teredo Port",             "ipv6.dst_tc_port",
+                               FT_UINT16, BASE_DEC, NULL, 0x0,
+                               "Destination IPv6 Teredo Client Mapped Port", HFILL }},
+    { &hf_ipv6_dst_teredo_client_ipv4,
+      { "Destination Teredo Client IPv4",              "ipv6.dst_tc_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "Destination IPv6 Teredo Client Encapsulated IPv4 Address", HFILL }},
     { &hf_ipv6_addr,
       { "Address",             "ipv6.addr",
                                FT_IPv6, BASE_NONE, NULL, 0x0,
@@ -1569,6 +2173,101 @@ proto_register_ipv6(void)
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                "IPv6 Host", HFILL }},
 
+    { &hf_ipv6_sa_mac,
+      { "SA MAC",              "ipv6.sa_mac",
+                               FT_ETHER, BASE_NONE, NULL, 0x0,
+                               "IPv6 Stateless Autoconfiguration MAC Address", HFILL }},
+    { &hf_ipv6_isatap_ipv4,
+      { "ISATAP IPv4",         "ipv6.isatap_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "IPv6 ISATAP Encapsulated IPv4 Address", HFILL }},
+    { &hf_ipv6_6to4_gateway_ipv4,
+      { "6to4 Gateway IPv4",           "ipv6.6to4_gw_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "IPv6 6to4 Gateway IPv4 Address", HFILL }},
+    { &hf_ipv6_6to4_sla_id,
+      { "6to4 SLA ID",         "ipv6.6to4_sla_id",
+                               FT_UINT16, BASE_DEC, NULL, 0x0,
+                               "IPv6 6to4 SLA ID", HFILL }},
+    { &hf_ipv6_teredo_server_ipv4,
+      { "Teredo Server IPv4",          "ipv6.ts_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "IPv6 Teredo Server Encapsulated IPv4 Address", HFILL }},
+    { &hf_ipv6_teredo_port,
+      { "Teredo Port",         "ipv6.tc_port",
+                               FT_UINT16, BASE_DEC, NULL, 0x0,
+                               "IPv6 Teredo Client Mapped Port", HFILL }},
+    { &hf_ipv6_teredo_client_ipv4,
+      { "Teredo Client IPv4",          "ipv6.tc_ipv4",
+                               FT_IPv4, BASE_NONE, NULL, 0x0,
+                               "IPv6 Teredo Client Encapsulated IPv4 Address", HFILL }},
+#ifdef HAVE_GEOIP_V6
+    { &hf_geoip_country,
+      { "Source or Destination GeoIP Country", "ipv6.geoip.country", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_city,
+      { "Source or Destination GeoIP City", "ipv6.geoip.city", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_org,
+      { "Source or Destination GeoIP Organization", "ipv6.geoip.org", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_isp,
+      { "Source or Destination GeoIP ISP", "ipv6.geoip.isp", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_asnum,
+      { "Source or Destination GeoIP AS Number", "ipv6.geoip.asnum", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_lat,
+      { "Source or Destination GeoIP Latitude", "ipv6.geoip.lat", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_lon,
+      { "Source or Destination GeoIP Longitude", "ipv6.geoip.lon", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_country,
+      { "Source GeoIP Country", "ipv6.geoip.src_country", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_city,
+      { "Source GeoIP City", "ipv6.geoip.src_city", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_org,
+      { "Source GeoIP Organization", "ipv6.geoip.src_org", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_isp,
+      { "Source GeoIP ISP", "ipv6.geoip.src_isp", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_asnum,
+      { "Source GeoIP AS Number", "ipv6.geoip.src_asnum", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_lat,
+      { "Source GeoIP Latitude", "ipv6.geoip.src_lat", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_lon,
+      { "Source GeoIP Longitude", "ipv6.geoip.src_lon", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_country,
+      { "Destination GeoIP Country", "ipv6.geoip.dst_country", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_city,
+      { "Destination GeoIP City", "ipv6.geoip.dst_city", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_org,
+      { "Destination GeoIP Organization", "ipv6.geoip.dst_org", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_isp,
+      { "Destination GeoIP ISP", "ipv6.geoip.dst_isp", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_asnum,
+      { "Destination GeoIP AS Number", "ipv6.geoip.dst_asnum", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_lat,
+      { "Destination GeoIP Latitude", "ipv6.geoip.dst_lat", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_lon,
+      { "Destination GeoIP Longitude", "ipv6.geoip.dst_lon", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+#endif /* HAVE_GEOIP_V6 */
+
+
     { &hf_ipv6_opt_pad1,
       { "Pad1",                        "ipv6.opt.pad1",
                                FT_NONE, BASE_NONE, NULL, 0x0,
@@ -1578,20 +2277,24 @@ proto_register_ipv6(void)
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                "PadN Option", HFILL }},
     { &hf_ipv6_dst_opt,
-      { "Destination Option ", "ipv6.dst_opt",
+      { "Destination Option",  "ipv6.dst_opt",
                                FT_NONE, BASE_NONE, NULL, 0x0,
-                               "Destination Option", HFILL }},
+                               NULL, HFILL }},
     { &hf_ipv6_hop_opt,
       { "Hop-by-Hop Option",   "ipv6.hop_opt",
                                FT_NONE, BASE_NONE, NULL, 0x0,
-                               "Hop-by-Hop Option", HFILL }},
+                               NULL, HFILL }},
+    { &hf_ipv6_unk_hdr,
+      { "Unknown Extension Header",    "ipv6.unknown_hdr",
+                               FT_NONE, BASE_NONE, NULL, 0x0,
+                               NULL, HFILL }},
     { &hf_ipv6_routing_hdr_opt,
-      { "Routing Header, Type ","ipv6.routing_hdr",
+      { "Routing Header, Type","ipv6.routing_hdr",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                "Routing Header Option", HFILL }},
     { &hf_ipv6_routing_hdr_type,
       { "Type",                        "ipv6.routing_hdr.type",
-                               FT_UINT8, BASE_DEC, VALS(&routing_header_type), 0x0,
+                               FT_UINT8, BASE_DEC, VALS(routing_header_type), 0x0,
                                "Routeing Header Type", HFILL }},
     { &hf_ipv6_routing_hdr_left,
       { "Left Segments",       "ipv6.routing_hdr.left",
@@ -1607,7 +2310,7 @@ proto_register_ipv6(void)
                                "Fragment Offset", HFILL }},
     { &hf_ipv6_frag_more,
       { "More Fragment",       "ipv6.fragment.more",
-                               FT_BOOLEAN, BASE_DEC, TFS(&ipv6_more_frag), IP6F_MORE_FRAG,
+                               FT_BOOLEAN, 16, TFS(&tfs_yes_no), IP6F_MORE_FRAG,
                                "More Fragments", HFILL }},
     { &hf_ipv6_frag_id,
       { "Identification",      "ipv6.framgent.id",
@@ -1638,72 +2341,118 @@ proto_register_ipv6(void)
                                FT_FRAMENUM, BASE_NONE, NULL, 0x0,
                                "Defragmentation error due to illegal fragments", HFILL }},
 
+    { &hf_ipv6_fragment_count,
+      { "Fragment count", "ipv6.fragment.count",
+                               FT_UINT32, BASE_DEC, NULL, 0x0,
+                               NULL, HFILL }},
+
     { &hf_ipv6_fragment,
       { "IPv6 Fragment",       "ipv6.fragment",
                                FT_FRAMENUM, BASE_NONE, NULL, 0x0,
-                               "IPv6 Fragment", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_fragments,
       { "IPv6 Fragments",      "ipv6.fragments",
                                FT_NONE, BASE_NONE, NULL, 0x0,
-                               "IPv6 Fragments", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_reassembled_in,
       { "Reassembled IPv6 in frame", "ipv6.reassembled_in",
                                FT_FRAMENUM, BASE_NONE, NULL, 0x0,
                                "This IPv6 packet is reassembled in this frame", HFILL }},
 
+    { &hf_ipv6_reassembled_length,
+      { "Reassembled IPv6 length", "ipv6.reassembled.length",
+                               FT_UINT32, BASE_DEC, NULL, 0x0,
+                               "The total length of the reassembled payload", HFILL }},
+
+    /* RPL Routing Header */
+    { &hf_ipv6_routing_hdr_rpl_cmprI,
+      { "Compressed Internal Octets (CmprI)", "ipv6.routing_hdr.rpl.cmprI",
+        FT_UINT32, BASE_DEC, NULL, IP6RRPL_BITMASK_CMPRI,
+        "Elided octets from all but last segment", HFILL }},
+
+    { &hf_ipv6_routing_hdr_rpl_cmprE,
+      { "Compressed Final Octets (CmprE)", "ipv6.routing_hdr.rpl.cmprE",
+        FT_UINT32, BASE_DEC, NULL, IP6RRPL_BITMASK_CMPRE,
+        "Elided octets from last segment address", HFILL }},
+
+    { &hf_ipv6_routing_hdr_rpl_pad,
+      { "Padding Bytes", "ipv6.routing_hdr.rpl.pad",
+        FT_UINT32, BASE_DEC, NULL, IP6RRPL_BITMASK_PAD,
+        NULL, HFILL }},
+
+    { &hf_ipv6_routing_hdr_rpl_reserved,
+      { "Reserved", "ipv6.routing_hdr.rpl.reserved",
+        FT_UINT32, BASE_DEC, NULL, IP6RRPL_BITMASK_RESERVED,
+        "Must be Zero", HFILL }},
+
+    { &hf_ipv6_routing_hdr_rpl_segments,
+      { "Total Segments", "ipv6.routing_hdr.rpl.segments",
+        FT_INT32, BASE_DEC, NULL, 0,
+        NULL, HFILL }},
+
+    { &hf_ipv6_routing_hdr_rpl_addr,
+      { "Address", "ipv6.routing_hdr.rpl.address",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+
+    { &hf_ipv6_routing_hdr_rpl_fulladdr,
+      { "Full Address", "ipv6.routing_hdr.rpl.full_address",
+        FT_IPv6, BASE_NONE, NULL, 0,
+        "Uncompressed IPv6 Address", HFILL }},
+
     /* Mobile IPv6 */
     { &hf_ipv6_mipv6_type,
-      { "Option Type ",                "ipv6.mipv6_type",
+      { "Option Type",         "ipv6.mipv6_type",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
     { &hf_ipv6_mipv6_length,
-      { "Option Length ",      "ipv6.mipv6_length",
+      { "Option Length",       "ipv6.mipv6_length",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
     { &hf_ipv6_mipv6_home_address,
-      { "Home Address ",       "ipv6.mipv6_home_address",
-                               FT_IPv6, BASE_HEX, NULL, 0x0,
-                               "", HFILL }},
+      { "Home Address",        "ipv6.mipv6_home_address",
+                               FT_IPv6, BASE_NONE, NULL, 0x0,
+                               NULL, HFILL }},
 
     /* SHIM6 */
     { &hf_ipv6_shim6,
-      { "SHIM6 ",              "ipv6.shim6",
+      { "SHIM6",               "ipv6.shim6",
                                FT_NONE, BASE_NONE, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_nxt,
       { "Next Header",         "ipv6.shim6.nxt",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_len,
       { "Header Ext Length",   "ipv6.shim6.len",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_p,
       { "P Bit",               "ipv6.shim6.p",
-                               FT_BOOLEAN, BASE_NONE, NULL, SHIM6_BITMASK_P,
-                               "", HFILL }},
+                               FT_BOOLEAN, 8, NULL, SHIM6_BITMASK_P,
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_ct,
       { "Context Tag",                 "ipv6.shim6.ct",
                                FT_NONE, BASE_NONE, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_type,
       { "Message Type",        "ipv6.shim6.type",
                                FT_UINT8, BASE_DEC,
                                VALS(shimctrlvals), SHIM6_BITMASK_TYPE,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_proto,
       { "Protocol",            "ipv6.shim6.proto",
                                FT_UINT8, BASE_DEC,
                                VALS(shim6_protocol), SHIM6_BITMASK_PROTOCOL,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_checksum,
       { "Checksum",            "ipv6.shim6.checksum",
@@ -1717,27 +2466,27 @@ proto_register_ipv6(void)
     { &hf_ipv6_shim6_checksum_good,
       { "Good Checksum",               "ipv6.shim6.checksum_good",
                                FT_BOOLEAN, BASE_NONE, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_inonce,
       { "Initiator Nonce",     "ipv6.shim6.inonce",
                                FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_rnonce,
       { "Responder Nonce",     "ipv6.shim6.rnonce",
                                FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_precvd,
       { "Probes Received",     "ipv6.shim6.precvd",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_psent,
       { "Probes Sent",                 "ipv6.shim6.psent",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_psrc,
       { "Source Address",      "ipv6.shim6.psrc",
@@ -1772,7 +2521,7 @@ proto_register_ipv6(void)
     { &hf_ipv6_shim6_reap,
       { "REAP State",          "ipv6.shim6.reap",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_opt_type,
       { "Option Type",                 "ipv6.shim6.opt.type",
@@ -1782,11 +2531,10 @@ proto_register_ipv6(void)
 
     { &hf_ipv6_shim6_opt_critical,
       { "Option Critical Bit",         "ipv6.shim6.opt.critical",
-                               FT_BOOLEAN, BASE_NONE,
-                               TFS(&shim6_critical_opts),
+                               FT_BOOLEAN, 8,
+                               TFS(&tfs_yes_no),
                                SHIM6_BITMASK_CRITICAL,
-                               "TRUE : option is critical, "
-                               "FALSE: option is not critical",
+                               "TRUE : option is critical, FALSE: option is not critical",
                                HFILL }},
 
     { &hf_ipv6_shim6_opt_len,
@@ -1808,7 +2556,7 @@ proto_register_ipv6(void)
     { &hf_ipv6_shim6_opt_loclist,
       { "Locator List Generation", "ipv6.shim6.opt.loclist",
                                FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
     { &hf_ipv6_shim6_locator,
       { "Locator",             "ipv6.shim6.locator",
@@ -1842,13 +2590,25 @@ proto_register_ipv6(void)
     { &hf_ipv6_shim6_opt_fii,
       { "Forked Instance Identifier", "ipv6.shim6.opt.fii",
                                FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
-                               "", HFILL }},
+                               NULL, HFILL }},
 
 #ifdef TEST_FINALHDR
     { &hf_ipv6_final,
       { "Final next header",   "ipv6.final",
-                               FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+                               FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
 #endif
+
+    { &hf_ipv6_traffic_class_dscp,
+      { "Differentiated Services Field",       "ipv6.traffic_class.dscp",
+                               FT_UINT32, BASE_HEX, VALS(dscp_vals), 0x0FC00000, NULL, HFILL }},
+
+    { &hf_ipv6_traffic_class_ect,
+      { "ECN-Capable Transport (ECT)", "ipv6.traffic_class.ect",
+                               FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x0200000, NULL, HFILL }},
+
+    { &hf_ipv6_traffic_class_ce,
+      { "ECN-CE",              "ipv6.traffic_class.ce",
+                               FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x0100000, NULL, HFILL }},
   };
   static gint *ett[] = {
     &ett_ipv6,
@@ -1864,7 +2624,11 @@ proto_register_ipv6(void)
     &ett_ipv6_shim6_probe_rcvd,
     &ett_ipv6_shim6_cksum,
     &ett_ipv6_fragments,
-    &ett_ipv6_fragment
+    &ett_ipv6_fragment,
+    &ett_ipv6_traffic_class,
+#ifdef HAVE_GEOIP_V6
+    &ett_geoip_info
+#endif /* HAVE_GEOIP_V6 */
   };
   module_t *ipv6_module;
 
@@ -1878,9 +2642,20 @@ proto_register_ipv6(void)
        "Reassemble fragmented IPv6 datagrams",
        "Whether fragmented IPv6 datagrams should be reassembled",
        &ipv6_reassemble);
+  prefs_register_bool_preference(ipv6_module, "summary_in_tree",
+       "Show IPv6 summary in protocol tree",
+       "Whether the IPv6 summary line should be shown in the protocol tree",
+       &ipv6_summary_in_tree);
+#ifdef HAVE_GEOIP_V6
+       prefs_register_bool_preference(ipv6_module, "use_geoip" ,
+                 "Enable GeoIP lookups",
+                 "Whether to look up IPv6 addresses in each GeoIP database we have loaded",
+                 &ipv6_use_geoip);
+#endif /* HAVE_GEOIP_V6 */
 
   register_dissector("ipv6", dissect_ipv6, proto_ipv6);
   register_init_routine(ipv6_reassemble_init);
+  ipv6_tap = register_tap("ipv6");
 }
 
 void
@@ -1890,19 +2665,19 @@ proto_reg_handoff_ipv6(void)
 
   data_handle = find_dissector("data");
   ipv6_handle = find_dissector("ipv6");
-  dissector_add("ethertype", ETHERTYPE_IPv6, ipv6_handle);
-  dissector_add("ppp.protocol", PPP_IPV6, ipv6_handle);
-  dissector_add("ppp.protocol", ETHERTYPE_IPv6, ipv6_handle);
-  dissector_add("gre.proto", ETHERTYPE_IPv6, ipv6_handle);
-  dissector_add("ip.proto", IP_PROTO_IPV6, ipv6_handle);
-  dissector_add("null.type", BSD_AF_INET6_BSD, ipv6_handle);
-  dissector_add("null.type", BSD_AF_INET6_FREEBSD, ipv6_handle);
-  dissector_add("null.type", BSD_AF_INET6_DARWIN, ipv6_handle);
-  dissector_add("chdlctype", ETHERTYPE_IPv6, ipv6_handle);
-  dissector_add("fr.ietf", NLPID_IP6, ipv6_handle);
-  dissector_add("osinl.excl", NLPID_IP6, ipv6_handle);
-  dissector_add("x.25.spi", NLPID_IP6, ipv6_handle);
-  dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPv6, ipv6_handle);
+  dissector_add_uint("ethertype", ETHERTYPE_IPv6, ipv6_handle);
+  dissector_add_uint("ppp.protocol", PPP_IPV6, ipv6_handle);
+  dissector_add_uint("ppp.protocol", ETHERTYPE_IPv6, ipv6_handle);
+  dissector_add_uint("gre.proto", ETHERTYPE_IPv6, ipv6_handle);
+  dissector_add_uint("ip.proto", IP_PROTO_IPV6, ipv6_handle);
+  dissector_add_uint("null.type", BSD_AF_INET6_BSD, ipv6_handle);
+  dissector_add_uint("null.type", BSD_AF_INET6_FREEBSD, ipv6_handle);
+  dissector_add_uint("null.type", BSD_AF_INET6_DARWIN, ipv6_handle);
+  dissector_add_uint("chdlctype", ETHERTYPE_IPv6, ipv6_handle);
+  dissector_add_uint("fr.ietf", NLPID_IP6, ipv6_handle);
+  dissector_add_uint("osinl.excl", NLPID_IP6, ipv6_handle);
+  dissector_add_uint("x.25.spi", NLPID_IP6, ipv6_handle);
+  dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_IPv6, ipv6_handle);
 
   ip_dissector_table = find_dissector_table("ip.proto");
 }