Fix a number of proto_tree_add_item() encoding args.
[obnox/wireshark/wip.git] / epan / dissectors / packet-ipv6.c
index ef43d6b0382ec221862b7303e135102646ff5d45..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,10 +110,31 @@ 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;
@@ -95,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;
@@ -136,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;
@@ -151,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,
@@ -162,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;
@@ -173,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
@@ -284,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)
 {
@@ -294,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 */
@@ -302,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];
@@ -334,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;
@@ -353,17 +619,84 @@ 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;
@@ -407,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;
 }
@@ -435,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;
@@ -558,7 +891,7 @@ dissect_unknown_option(tvbuff_t *tvb, int offset, proto_tree *tree)
 
     if (tree) {
        /* !!! specify length */
-       ti = proto_tree_add_item(tree, hf_ipv6_unk_hdr, tvb, offset, len, FALSE);
+       ti = proto_tree_add_item(tree, hf_ipv6_unk_hdr, tvb, offset, len, ENC_NA);
 
        unkopt_tree = proto_item_add_subtree(ti, ett_ipv6);
 
@@ -589,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);
 
@@ -609,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;
@@ -756,6 +1089,30 @@ static const value_string shim6_protocol[] = {
   { 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)
 {
@@ -765,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 */
@@ -779,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 */
@@ -793,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;
@@ -811,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,
@@ -835,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
@@ -864,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);
@@ -885,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);
@@ -925,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:
@@ -987,15 +1341,15 @@ dissect_shim6_probes(proto_tree * shim_tree, tvbuff_t * tvb, gint offset,
     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;
   }
 }
@@ -1017,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;
@@ -1041,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;
@@ -1066,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:
@@ -1169,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 */
@@ -1184,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;
@@ -1212,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 */
@@ -1253,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;
@@ -1268,6 +1622,7 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   gboolean update_col_info = TRUE;
   gboolean save_fragmented = FALSE;
   const char *sep = "IPv6 ";
+  guint8 *mac_addr;
 
   struct ip6_hdr ipv6;
 
@@ -1291,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,
@@ -1320,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);
@@ -1396,7 +1908,7 @@ again:
       plen -= advance;
       goto again;
 
-    case IP_PROTO_FRAGMENT:  
+    case IP_PROTO_FRAGMENT:
       advance = dissect_frag6(tvb, offset, pinfo, ipv6_tree,
           &offlg, &ident);
       nxt = tvb_get_guint8(tvb, offset);
@@ -1419,7 +1931,7 @@ again:
           offlg = 0;
           frag = FALSE;
           tvb = next_tvb;
-          goto again; 
+          goto again;
         }
       }
       if (!(offlg & IP6F_OFF_MASK)) /*...or in the first fragment */
@@ -1464,8 +1976,8 @@ again:
        * whether it is a known protocol. If not, then it
        * is an unknown IPv6 option
        */
-      if (!dissector_get_port_handle(ip_dissector_table, nxt)) {
-        advance = dissect_unknown_option(tvb, offset, ipv6_tree); 
+      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;
@@ -1479,6 +1991,9 @@ 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;
@@ -1508,7 +2023,7 @@ again:
 
 
   /* 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) {
@@ -1585,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,
@@ -1593,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,
@@ -1602,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,
@@ -1628,7 +2294,7 @@ proto_register_ipv6(void)
                                "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",
@@ -1675,6 +2341,11 @@ 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,
@@ -1690,6 +2361,47 @@ proto_register_ipv6(void)
                                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",
@@ -1883,8 +2595,20 @@ proto_register_ipv6(void)
 #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,
@@ -1900,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;
 
@@ -1914,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
@@ -1926,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");
 }