From Colin O'Flynn and Owen Kirby via https://bugs.wireshark.org/bugzilla/show_bug...
authormorriss <morriss@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 20 Oct 2010 01:23:32 +0000 (01:23 +0000)
committermorriss <morriss@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 20 Oct 2010 01:23:32 +0000 (01:23 +0000)
The attached patch begins to add support for RPL to the ICMPv6 file. All
locations that RPL code have been added are marked with a comment allowing this
patch to be reverted at a future time if it is decided to e.g. move all the RPL
code to it's own dissector.

A few values await IANA assignment and are also clearly marked (in
packet-ipv6.h).

Only the 'metric' option is left unsupported, as it is primarily defined in
another I-D.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@34579 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
epan/dissectors/packet-icmpv6.c
epan/dissectors/packet-ipv6.h

diff --git a/AUTHORS b/AUTHORS
index 57321324593b4c87b34c13932598132c690860a4..3cf0335490d8f0ad60dff07752999b155732e890 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3123,6 +3123,11 @@ Tom Hughes               <tom [AT] compton.nu> {
 
 Owen Kirby             <osk [AT] exegin.com> {
        SCoP dissector
+       RPL support in ICMPv6 (with Colin O'Flynn)
+}
+
+Colin O'Flynn          <coflynn [AT] newae.com> {
+       RPL support in ICMPv6 (with Owen Kirby)
 }
 
 Juha Siltanen          <juha.siltanen [AT] nsn.com> {
index e3ad24b4ed2ccab4aecee5a90daf7a7917247c28..4c9adf103e083d7e56f4cc2034bdff0f0be7c966 100644 (file)
@@ -14,6 +14,8 @@
  *
  * FMIPv6 support added by Martin Andre <andre@clarinet.u-strasbg.fr>
  *
+ * RPL support added by Colin O'Flynn & Owen Kirby.
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
@@ -43,6 +45,7 @@
 #include <epan/ipproto.h>
 #include <epan/asn1.h>
 #include <epan/strutil.h>
+#include <epan/expert.h>
 
 #include "packet-ber.h"
 #include "packet-ipv6.h"
  *
  * and
  *
+ *      draft-ieft-roll-rpl-12.txt
+ *
+ * and
+ *
  *      rfc4068.txt
  */
 
@@ -85,6 +92,69 @@ static int hf_icmpv6_ra_router_lifetime = -1;
 static int hf_icmpv6_ra_reachable_time = -1;
 static int hf_icmpv6_ra_retrans_timer = -1;
 
+/* RPL: draft-ietf-roll-rpl-12.txt: Routing over Low-Power and Lossy Networks. */
+static int hf_icmpv6_dis_reserved = -1;
+static int hf_icmpv6_dio_grounded = -1;
+static int hf_icmpv6_dio_preference = -1;
+static int hf_icmpv6_dio_rank = -1;
+static int hf_icmpv6_dio_instance = -1;
+static int hf_icmpv6_dio_version = -1;
+static int hf_icmpv6_dio_zero = -1;
+static int hf_icmpv6_dio_trigger_seqnum = -1;
+static int hf_icmpv6_dio_dagid = -1;
+static int hf_icmpv6_dio_mop = -1;
+static int hf_icmpv6_dao_instance = -1;
+static int hf_icmpv6_dao_seqnum = -1;
+static int hf_icmpv6_dao_reserved = -1;
+static int hf_icmpv6_dao_flag_k = -1;
+static int hf_icmpv6_dao_flag_d = -1;
+static int hf_icmpv6_dao_flag_rsv = -1;
+static int hf_icmpv6_dao_dodagid = -1;
+static int hf_icmpv6_daoack_instance = -1;
+static int hf_icmpv6_daoack_seqnum = -1;
+static int hf_icmpv6_daoack_status = -1;
+static int hf_icmpv6_daoack_flag_d = -1;
+static int hf_icmpv6_daoack_flag_rsv = -1;
+static int hf_icmpv6_daoack_dodagid = -1;
+static int hf_icmpv6_rpl_opt_route = -1;
+static int hf_icmpv6_rpl_opt_route_pref = -1;
+static int hf_icmpv6_rpl_opt_route_lifetime = -1;
+static int hf_icmpv6_rpl_opt_route_length = -1;
+static int hf_icmpv6_rpl_opt_config_auth = -1;
+static int hf_icmpv6_rpl_opt_config_pcs = -1;
+static int hf_icmpv6_rpl_opt_config_doublings = -1;
+static int hf_icmpv6_rpl_opt_config_min_interval = -1;
+static int hf_icmpv6_rpl_opt_config_redundancy = -1;
+static int hf_icmpv6_rpl_opt_config_rank_incr = -1;
+static int hf_icmpv6_rpl_opt_config_hop_rank_inc = -1;
+static int hf_icmpv6_rpl_opt_config_ocp = -1;
+static int hf_icmpv6_rpl_opt_config_rsv = -1;
+static int hf_icmpv6_rpl_opt_config_def_lifetime = -1;
+static int hf_icmpv6_rpl_opt_config_lifetime_unit = -1;
+static int hf_icmpv6_rpl_opt_target = -1;
+static int hf_icmpv6_rpl_opt_target_length = -1;
+static int hf_icmpv6_rpl_opt_target_reserved = -1;
+static int hf_icmpv6_rpl_opt_transit_pathseq = -1;
+static int hf_icmpv6_rpl_opt_transit_pathctl = -1;
+static int hf_icmpv6_rpl_opt_transit_pathlifetime = -1;
+static int hf_icmpv6_rpl_opt_transit_parent = -1;
+static int hf_icmpv6_rpl_opt_transit_e = -1;
+static int hf_icmpv6_rpl_opt_transit_flags = -1;
+static int hf_icmpv6_rpl_opt_solicited_instance = -1;
+static int hf_icmpv6_rpl_opt_solicited_flag_v = -1;
+static int hf_icmpv6_rpl_opt_solicited_flag_i = -1;
+static int hf_icmpv6_rpl_opt_solicited_flag_d = -1;
+static int hf_icmpv6_rpl_opt_solicited_dodagid = -1;
+static int hf_icmpv6_rpl_opt_solicited_version = -1;
+static int hf_icmpv6_rpl_opt_prefix = -1;
+static int hf_icmpv6_rpl_opt_prefix_flag_l = -1;
+static int hf_icmpv6_rpl_opt_prefix_flag_a = -1;
+static int hf_icmpv6_rpl_opt_prefix_flag_r = -1;
+static int hf_icmpv6_rpl_opt_prefix_vlifetime = -1;
+static int hf_icmpv6_rpl_opt_prefix_plifetime = -1;
+static int hf_icmpv6_rpl_opt_prefix_length = -1;
+static int hf_icmpv6_rpl_opt_targetdesc = -1;
+
 static int hf_icmpv6_option = -1;
 static int hf_icmpv6_option_type = -1;
 static int hf_icmpv6_option_length = -1;
@@ -132,6 +202,7 @@ static gint ett_nodeinfo_nodedns = -1;
 static gint ett_multicastRR = -1;
 static gint ett_icmpv6opt_name = -1;
 static gint ett_cga_param_name = -1;
+static gint ett_dao_rr_stack = -1;
 
 static dissector_handle_t ipv6_handle;
 static dissector_handle_t data_handle;
@@ -171,6 +242,7 @@ static const value_string icmpv6_type_str[] = {
     { ICMP6_MCAST_ROUTER_SOLICIT,  "Multicast Router Solicitation" },
     { ICMP6_MCAST_ROUTER_TERM,     "Multicast Router Termination" },
     { ICMP6_FMIPV6_MESSAGES,       "FMIPv6 Messages" },
+    { ICMP6_RPL_CONTROL,           "RPL Control Message" },
     { 200,                         "Private experimentation" },
     { 201,                         "Private experimentation" },
     { 255,                         "Reserved for expansion of ICMPv6 informational messages" },
@@ -299,6 +371,30 @@ static const value_string names_6lowpannd_aro_status_str[] = {
     { 0, NULL }
 };
 
+/* RPL: draft-ietf-roll-rpl-12.txt: Routing over Low-Power and Lossy Networks. */
+static const value_string names_rpl_code[] = {
+    { ICMP6_RPL_DIS,    "DODAG Information Solicitation" },
+    { ICMP6_RPL_DIO,    "DODAG Information Object" },
+    { ICMP6_RPL_DAO,    "Destination Advertisement Object" },
+    { ICMP6_RPL_DAOACK, "Destination Advertisement Object Acknowledgement" },
+    { 0, NULL }
+};
+
+/* RPL: draft-ietf-roll-rpl-12.txt: Routing over Low-Power and Lossy Networks. */
+static const value_string names_rpl_option[] = {
+    { RPL_OPT_PAD1,     "1-byte padding" },
+    { RPL_OPT_PADN,     "n-byte padding" },
+    { RPL_OPT_METRIC,   "Metric container" },
+    { RPL_OPT_ROUTING,  "Routing"},
+    { RPL_OPT_CONFIG,   "DODAG configuration" },
+    { RPL_OPT_TARGET,   "RPL Target" },
+    { RPL_OPT_TRANSIT,  "Transit Information" },
+    { RPL_OPT_SOLICITED,"Solicited Information"},
+    { RPL_OPT_PREFIX,   "Prefix Information"},
+    { RPL_OPT_TARGETDESC, "RPL Target Descriptor"},
+    { 0, NULL }
+};
+
 /* http://www.iana.org/assignments/icmpv6-parameters */
 static const value_string option_vals[] = {
     { ND_OPT_SOURCE_LINKADDR,           "Source link-layer address" },
@@ -371,6 +467,7 @@ dissect_contained_icmpv6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
        "real" packets. */
     save_in_error_pkt = pinfo->in_error_pkt;
     pinfo->in_error_pkt = TRUE;
+    pinfo->in_error_pkt = TRUE;
 
     next_tvb = tvb_new_subset_remaining(tvb, offset);
 
@@ -583,7 +680,7 @@ again:
         while (opt_offset < par_len) {
             proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_ext_type,tvb,opt_offset,2,FALSE);
             opt_offset += 2;
-            ext_data_len = tvb_get_ntohs(tvb,opt_offset); 
+            ext_data_len = tvb_get_ntohs(tvb,opt_offset);
             proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_ext_length,tvb,opt_offset,2,FALSE);
             opt_offset += 2;
             proto_tree_add_text(cga_tree,tvb,opt_offset,ext_data_len,"Ext Data");
@@ -834,7 +931,7 @@ again:
         lifetime = tvb_get_ntohl(tvb, opt_offset);
         if (lifetime == 0xffffffff){
             proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: infinity");
-        }else{ 
+        }else{
             if(lifetime==0){
                 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: RDNSS address MUST no longer be used");
             }else{
@@ -846,7 +943,7 @@ again:
         no_of_pars = opt->nd_opt_len - 1;
         no_of_pars = no_of_pars >> 2;
 
-        for (i = 0; i <= no_of_pars; i++) {                     
+        for (i = 0; i <= no_of_pars; i++) {
             proto_tree_add_item(icmp6opt_tree, hf_icmpv6_recursive_dns_serv, tvb, opt_offset, 16, FALSE);
             opt_offset = opt_offset+16;
         }
@@ -857,8 +954,8 @@ again:
         struct nd_opt_6lowpan_context nd_opt_6lowpan_context, *sco;
         struct e_in6_addr in6;
         int flagoff;
-        
-        sco = &nd_opt_6lowpan_context;       
+
+        sco = &nd_opt_6lowpan_context;
         tvb_memcpy(tvb, (guint8 *)sco, offset, sizeof *sco);
         /* Length */
         proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_opt_6co_context_length, tvb,
@@ -873,7 +970,7 @@ again:
         /* CID & Flags */
         flagoff = offset + offsetof(struct nd_opt_6lowpan_context,nd_opt_6co_CID);
         tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1,
-                                "Flags & CID: 0x%02x", tvb_get_guint8(tvb, offset + 
+                                "Flags & CID: 0x%02x", tvb_get_guint8(tvb, offset +
                                 offsetof(struct nd_opt_6lowpan_context, nd_opt_6co_CID)));
         field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
         proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
@@ -884,7 +981,7 @@ again:
                             decode_numeric_bitfield(sco->nd_opt_6co_CID,
                                                     ND_OPT_6CO_CIDMASK, 8, "CID of %d"));
 
-        /* Context */        
+        /* Context */
         if(sco->nd_opt_6co_context_length > 64){
             tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof *sco, 16);
         } else {
@@ -898,10 +995,10 @@ again:
             in6.bytes[14] = 0;
             in6.bytes[15] = 0;
         }
-     
+
         proto_tree_add_text(icmp6opt_tree, tvb, offset + sizeof *sco,
-                                16, "Context: %s", ip6_to_str(&in6));  
-    }        
+                                16, "Context: %s", ip6_to_str(&in6));
+    }
     break;
     case ND_OPT_ADDR_RESOLUTION:
     {
@@ -923,27 +1020,27 @@ again:
 
         /* EUI-64 */
         proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_aro_eui64, tvb, offset + offsetof(struct nd_opt_addr_resolution, nd_opt_aro_eui64), 8, FALSE);
-        
+
         /* Registered Address (if present only) */
         if(aro->nd_opt_aro_len == 4)
         {
-            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_aro_addr_reg, tvb, offset + sizeof *aro, 16, FALSE);    
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_aro_addr_reg, tvb, offset + sizeof *aro, 16, FALSE);
         }
-    
+
     }
     break;
     case ND_OPT_AUTH_BORDER_ROUTER:
     {
         /* Version at offset 2, Address at offset 8 */
-        guint8 version[2];     
+        guint8 version[2];
         tvb_memcpy(tvb, version, offset+2, 2);
-  
+
         proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_opt_abro_version, tvb,
                                 offset + 2, 2, pntohs(version));
-  
-        proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_abro_addr, tvb, 
-                            offset + 8, 16, FALSE);    
-                            
+
+        proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_abro_addr, tvb,
+                            offset + 8, 16, FALSE);
+
     }
         break;
     } /* switch (opt->nd_opt_type) */
@@ -1060,6 +1157,263 @@ again:
     goto again;
 }
 
+/* RPL: draft-ietf-roll-rpl-12.txt: Routing over Low-Power and Lossy Networks. */
+static void
+dissect_icmpv6rplopt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+    proto_tree *icmp6opt_tree;
+    proto_item *ti;
+    guint8      type;
+    guint16     optlen;
+    int         optoffset;
+    const char *type_name;
+    proto_item *ti_plen = NULL;
+
+    if (!tree)
+        return;
+
+again:
+    if ((int)tvb_reported_length(tvb) <= offset)
+        return; /* No more options left */
+
+    /* Make a subtree for the option. */
+    ti = proto_tree_add_item(tree, hf_icmpv6_option, tvb, offset, 1, FALSE);
+    icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
+
+    /* Get the option type. */
+    type = tvb_get_guint8(tvb, offset);
+    type_name = val_to_str(type, names_rpl_option, "Unknown");
+    proto_item_append_text(ti, " (%s)", type_name);
+    proto_tree_add_text(icmp6opt_tree, tvb, offset, 1, "Type: %u (%s)", type, type_name);
+
+    /* The Pad1 option is a special case, and contains no data. */
+    if (type == RPL_OPT_PAD1) {
+        offset++;
+        goto again;
+    }
+    optlen = tvb_get_guint8(tvb, offset + 1);
+    proto_item_set_len(ti, optlen + 2);
+    proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_option_length, tvb, offset + 1, 1, optlen);
+
+    /* Display the option contents. */
+    offset += 2;
+    optoffset = offset;
+    switch(type) {
+        case RPL_OPT_PADN:
+            /* n-byte padding */
+            proto_tree_add_text(icmp6opt_tree, tvb, offset, optlen, "Padding length is %d", optlen+2);
+            break;
+
+        case RPL_OPT_METRIC:
+            /* DAG metric container */
+            /* See draft-ietf-roll-routing-metrics for formatting. */
+            break;
+
+        case RPL_OPT_ROUTING: {
+            guint8              route_len;
+            struct e_in6_addr   route;
+
+            /* Route length */
+            route_len = tvb_get_guint8(tvb, optoffset);
+            ti_plen = proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_rpl_opt_route_length, tvb, optoffset, 1, route_len);
+            optoffset++;
+
+            if (route_len > (sizeof(route) << 3)) {
+                /* Illegal prefix length! Must prevent evil buffer overflows >:@ */
+                route_len = sizeof(route) << 3;
+                expert_add_info_format(pinfo, ti_plen, PI_MALFORMED, PI_ERROR, "Route length invalid, greather than 128 bits");
+            }
+
+            /* Flags - only preference is used anymore. */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_route_pref, tvb, optoffset, 1, FALSE);
+            optoffset++;
+
+            /* Prefix lifetime. */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_route_lifetime, tvb, optoffset, 4, FALSE);
+            optoffset += 4;
+
+            /* Prefix */
+            memset(&route, 0, sizeof(route));
+            tvb_memcpy(tvb, &route, optoffset, (route_len + 7) >> 3);         /* Round up to the nearest octet. */
+            if (route_len & 0x7)
+                route.bytes[route_len >> 3] &= 0xff << (route_len & 0x7);    /* Clear unused bits in the last octet. */
+            proto_tree_add_ipv6(icmp6opt_tree, hf_icmpv6_rpl_opt_route, tvb, optoffset, ((route_len + 7) >> 3), route.bytes);
+            optoffset += ((route_len + 7) >> 3);
+
+            break;
+        }
+
+        case RPL_OPT_CONFIG: {
+            /* flags */
+            guint8 flags = tvb_get_guint8(tvb, optoffset);
+            proto_tree_add_boolean(icmp6opt_tree, hf_icmpv6_rpl_opt_config_auth, tvb, optoffset, 1, flags & RPL_OPT_CONFIG_FLAG_AUTH);
+            proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_rpl_opt_config_pcs, tvb, optoffset, 1, flags & RPL_OPT_CONFIG_FLAG_PCS);
+            optoffset += 1;
+            /* DAG configuration */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_doublings, tvb, optoffset, 1, FALSE);
+            optoffset++;
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_min_interval, tvb, optoffset, 1, FALSE);
+            optoffset++;
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_redundancy, tvb, optoffset, 1, FALSE);
+            optoffset++;
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_rank_incr, tvb, optoffset, 2, FALSE);
+            optoffset += 2;
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_hop_rank_inc, tvb, optoffset, 2, FALSE);
+            optoffset += 2;
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_ocp, tvb, optoffset, 2, FALSE);
+            optoffset += 2;
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_rsv, tvb, optoffset, 1, FALSE);
+            optoffset++;
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_def_lifetime, tvb, optoffset, 1, FALSE);
+            optoffset++;
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_config_lifetime_unit, tvb, optoffset, 2, FALSE);
+            optoffset += 2;
+            break;
+        }
+
+        case RPL_OPT_TARGET: {
+            guint8              target_len;
+            struct e_in6_addr   target;
+
+            /* Target */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_target_reserved, tvb, optoffset, 1, FALSE);
+            optoffset++;
+
+            /* Prefix length */
+            target_len = tvb_get_guint8(tvb, optoffset);
+            ti_plen = proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_rpl_opt_target_length, tvb, optoffset, 1, target_len);
+            optoffset++;
+            if (target_len > (sizeof(target) << 3)) {
+                /* Illegal prefix length! Must prevent evil buffer overflows >:@ */
+                target_len = sizeof(target) << 3;
+                expert_add_info_format(pinfo, ti_plen, PI_MALFORMED, PI_ERROR, "Target length invalid, greather than 128 bits");
+            }
+
+            /* Prefix */
+            memset(&target, 0, sizeof(target));
+            tvb_memcpy(tvb, &target, optoffset, (target_len + 7) >> 3);         /* Round up to the nearest octet. */
+            if (target_len & 0x7)
+                target.bytes[target_len >> 3] &= 0xff << (target_len & 0x7);    /* Clear unused bits in the last octet. */
+            proto_tree_add_ipv6(icmp6opt_tree, hf_icmpv6_rpl_opt_target, tvb, optoffset, ((target_len + 7) >> 3), target.bytes);
+            optoffset += ((target_len + 7) >> 3);
+            break;
+        }
+
+        case RPL_OPT_TRANSIT: {
+
+            /* flags */
+            guint8 flags = tvb_get_guint8(tvb, optoffset);
+            proto_tree_add_boolean(icmp6opt_tree, hf_icmpv6_rpl_opt_transit_e, tvb, optoffset, 1, flags & RPL_OPT_TRANSIT_E);
+            proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_rpl_opt_transit_flags, tvb, optoffset, 1, flags & RPL_OPT_TRANSIT_FLAGS);
+            optoffset++;
+
+            /* Path Control */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_transit_pathctl, tvb, optoffset, 1, FALSE);
+            optoffset++;
+
+            /* Path Sequence */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_transit_pathseq, tvb, optoffset, 1, FALSE);
+            optoffset++;
+
+            /* Path Lifetime */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_transit_pathlifetime, tvb, optoffset, 1, FALSE);
+            optoffset++;
+
+            /* Option contains parent */
+            if(optlen > 4)
+            {
+               proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_transit_parent, tvb, optoffset, 16, FALSE);
+               optoffset += 16;
+            }
+
+            break;
+        }
+
+        case RPL_OPT_SOLICITED: {
+            guint8 flags;
+
+            /* Instance ID */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_solicited_instance, tvb, optoffset, 1, FALSE);
+            optoffset++;
+
+            /* flags */
+            flags = tvb_get_guint8(tvb, optoffset);
+            proto_tree_add_boolean(icmp6opt_tree, hf_icmpv6_rpl_opt_solicited_flag_v, tvb, optoffset, 1, flags & RPL_OPT_SOLICITED_V);
+            proto_tree_add_boolean(icmp6opt_tree, hf_icmpv6_rpl_opt_solicited_flag_i, tvb, optoffset, 1, flags & RPL_OPT_SOLICITED_I);
+            proto_tree_add_boolean(icmp6opt_tree, hf_icmpv6_rpl_opt_solicited_flag_d, tvb, optoffset, 1, flags & RPL_OPT_SOLICITED_D);
+            optoffset++;
+
+            /* DODAG ID */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_solicited_dodagid, tvb, optoffset, 16, FALSE);
+            optoffset += 16;
+
+            /* Version Number */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_solicited_version, tvb, optoffset, 1, FALSE);
+            optoffset++;
+
+            break;
+        }
+
+        case RPL_OPT_PREFIX: {
+            /* Destination prefix option. */
+            guint8              prefix_len;
+            struct e_in6_addr   prefix;
+
+            /* Prefix length */
+            prefix_len = tvb_get_guint8(tvb, optoffset);
+            ti_plen = proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_rpl_opt_prefix_length, tvb, optoffset, 1, prefix_len);
+            optoffset++;
+            if (prefix_len > (sizeof(prefix) << 3)) {
+                /* Illegal prefix length! Must prevent evil buffer overflows >:@ */
+                prefix_len = sizeof(prefix) << 3;
+                expert_add_info_format(pinfo, ti_plen, PI_MALFORMED, PI_ERROR, "Prefix length invalid, greather than 128 bits");
+            }
+
+            /* Flags. */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_prefix_flag_l, tvb, optoffset, 1, FALSE);
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_prefix_flag_a, tvb, optoffset, 1, FALSE);
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_prefix_flag_r, tvb, optoffset, 1, FALSE);
+            optoffset++;
+
+            /* Valid lifetime. */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_prefix_vlifetime, tvb, optoffset, 4, FALSE);
+            optoffset += 4;
+
+            /* Preferrred Lifetime */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_prefix_plifetime, tvb, optoffset, 4, FALSE);
+            optoffset += 4;
+
+            /* 4 reserved bytes. */
+            optoffset += 4;
+
+            /* Prefix */
+            memset(&prefix, 0, sizeof(prefix));
+            tvb_memcpy(tvb, &prefix, optoffset, (prefix_len + 7) >> 3);         /* Round up to the nearest octet. */
+            if (prefix_len & 0x7)
+                prefix.bytes[prefix_len >> 3] &= 0xff << (prefix_len & 0x7);    /* Clear unused bits in the last octet. */
+            proto_tree_add_ipv6(icmp6opt_tree, hf_icmpv6_rpl_opt_prefix, tvb, optoffset, ((prefix_len + 7) >> 3), prefix.bytes);
+            optoffset += ((prefix_len + 7) >> 3); /* Round up to the nearest 8 bytes. */
+            break;
+        }
+
+        case RPL_OPT_TARGETDESC: {
+
+            /* Descriptor */
+            proto_tree_add_item(icmp6opt_tree, hf_icmpv6_rpl_opt_targetdesc, tvb, optoffset, 4, FALSE);
+            optoffset += 4;
+            break;
+
+        }
+
+        default:
+            break;
+    } /* switch */
+
+    /* Get the next option. */
+    offset += optlen;
+    goto again;
+}
+
 /*
  * draft-ietf-ipngwg-icmp-name-lookups-07.txt
  * Note that the packet format was changed several times in the past.
@@ -1756,6 +2110,9 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             break;
         } /* switch (dp->icmp6_data8[0]) */
         break;
+    case ICMP6_RPL_CONTROL:
+        codename = colcodename = val_to_str (dp->icmp6_code, names_rpl_code, "Unknown");
+        break;
     default:
         codename = colcodename = "Unknown";
         break;
@@ -1763,15 +2120,15 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
     if (check_col(pinfo->cinfo, COL_INFO)) {
         char typebuf[256], codebuf[256];
-        
-        
+
+
         if (pinfo->destport == 0x0dd8 && dp->icmp6_type == ICMP6_ECHO_REQUEST) {
-            /* RFC 4380 
-             * 5.2.9. Direct IPv6 Connectivity Test 
+            /* RFC 4380
+             * 5.2.9. Direct IPv6 Connectivity Test
              */
-            col_set_str(pinfo->cinfo, COL_PROTOCOL, "Teredo");    
+            col_set_str(pinfo->cinfo, COL_PROTOCOL, "Teredo");
             col_set_str(pinfo->cinfo, COL_INFO, "Direct IPv6 Connectivity Test");
-        } else {   
+        } else {
             if (coltypename && strcmp(coltypename, "Unknown") == 0) {
                 g_snprintf(typebuf, sizeof(typebuf), "Unknown (0x%02x)",
                            dp->icmp6_type);
@@ -1890,8 +2247,8 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                             g_ntohs(dp->icmp6_id), g_ntohs(dp->icmp6_seq));
 
             if (pinfo->destport == 0x0dd8 && dp->icmp6_type == ICMP6_ECHO_REQUEST) {
-                /* RFC 4380 
-                 * 5.2.9. Direct IPv6 Connectivity Test 
+                /* RFC 4380
+                 * 5.2.9. Direct IPv6 Connectivity Test
                  */
                 proto_tree_add_text(icmp6_tree, tvb, offset + ICMP6_SEQ_OFFSET + 2, 4,
                                     "Nonce: 0x%08x", tvb_get_ntohl(tvb, offset + ICMP6_SEQ_OFFSET + 2));
@@ -2314,6 +2671,114 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
             dissect_icmpv6ndopt(tvb, offset, pinfo, icmp6_tree);
             break;
+        case ICMP6_RPL_CONTROL:
+            /* RPL: draft-ietf-roll-rpl-12.txt: Routing over Low-Power and Lossy Networks. */
+            offset += 4; /* Skip the type, code and checksum. */
+            if (dp->icmp6_code == ICMP6_RPL_DIS) {
+
+                /* Reserved */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dis_reserved, tvb, offset, 2, FALSE);
+                offset += 2;
+
+            }
+            else if (dp->icmp6_code == ICMP6_RPL_DIO) {
+                /* DODAG Information Object */
+                guint8  flags;
+
+                /* RPLInstanceID */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dio_instance, tvb, offset, 1, FALSE);
+                offset += 1;
+
+                /* RPLInstanceID */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dio_version, tvb, offset, 1, FALSE);
+                offset += 1;
+
+                /* Rank */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dio_rank, tvb, offset, 2, FALSE);
+                offset += 2;
+
+                /* flags */
+                flags = tvb_get_guint8(tvb, offset);
+                proto_tree_add_boolean(icmp6_tree, hf_icmpv6_dio_grounded, tvb, offset, 1, flags & RPL_DIO_FLAG_GROUNDED);
+                proto_tree_add_boolean(icmp6_tree, hf_icmpv6_dio_zero, tvb, offset, 1, flags & RPL_DIO_FLAG_ZERO);
+                proto_tree_add_uint(icmp6_tree, hf_icmpv6_dio_mop, tvb, offset, 1, flags & RPL_DIO_FLAG_MOP);
+                proto_tree_add_uint(icmp6_tree, hf_icmpv6_dio_preference, tvb, offset, 1, flags & RPL_DIO_FLAG_PREFERENCE);
+                offset += 1;
+
+                /* Destination Advertisement Trigger Sequence Number (DTSN) */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dio_trigger_seqnum, tvb, offset, 1, FALSE);
+                offset += 1;
+                offset += 2;
+
+                /* DODAGID */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dio_dagid, tvb, offset, 16, FALSE);
+                offset += 16;
+            }
+            else if (dp->icmp6_code == ICMP6_RPL_DAO) {
+                /* Destination Advertisement Object */
+                struct e_in6_addr   addr6;
+                guint8 flags;
+
+                /* DAO Instance */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dao_instance, tvb, offset, 1, FALSE);
+                offset += 1;
+
+                /* flags */
+                flags = tvb_get_guint8(tvb, offset);
+                proto_tree_add_boolean(icmp6_tree, hf_icmpv6_dao_flag_k, tvb, offset, 1, flags & RPL_DAO_FLAG_K);
+                proto_tree_add_boolean(icmp6_tree, hf_icmpv6_dao_flag_d, tvb, offset, 1, flags & RPL_DAO_FLAG_D);
+                proto_tree_add_uint(icmp6_tree, hf_icmpv6_dao_flag_rsv, tvb, offset, 1, flags & RPL_DAO_FLAG_RESERVED);
+                offset += 1;
+
+                /* DAO Reserved */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dao_reserved, tvb, offset, 1, FALSE);
+                offset += 1;
+
+                /* DAO Reserved */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_dao_seqnum, tvb, offset, 1, FALSE);
+                offset += 1;
+
+                if(flags & RPL_DAO_FLAG_D)
+                {
+                    tvb_memcpy(tvb, addr6.bytes, offset, 16);
+                    proto_tree_add_ipv6(icmp6_tree, hf_icmpv6_dao_dodagid, tvb, offset, 16, addr6.bytes);
+                    offset += 16;
+                }
+            }
+            else if (dp->icmp6_code == ICMP6_RPL_DAOACK) {
+                /* Destination Advertisement Object */
+                struct e_in6_addr   addr6;
+                guint8 flags;
+
+                /* DAO Instance */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_daoack_instance, tvb, offset, 1, FALSE);
+                offset += 1;
+
+                /* flags */
+                flags = tvb_get_guint8(tvb, offset);
+                proto_tree_add_boolean(icmp6_tree, hf_icmpv6_daoack_flag_d, tvb, offset, 1, flags & RPL_DAOACK_FLAG_D);
+                proto_tree_add_uint(icmp6_tree, hf_icmpv6_daoack_flag_rsv, tvb, offset, 1, flags & RPL_DAOACK_FLAG_RESERVED);
+                offset += 1;
+
+                /* DAO Sequence */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_daoack_seqnum, tvb, offset, 1, FALSE);
+                offset += 1;
+
+                /* DAO Status */
+                proto_tree_add_item(icmp6_tree, hf_icmpv6_daoack_status, tvb, offset, 1, FALSE);
+                offset += 1;
+
+                if(flags & RPL_DAOACK_FLAG_D)
+                {
+                    tvb_memcpy(tvb, addr6.bytes, offset, 16);
+                    proto_tree_add_ipv6(icmp6_tree, hf_icmpv6_daoack_dodagid, tvb, offset, 16, addr6.bytes);
+                    offset += 16;
+                }
+                return;
+            }
+            /* Options */
+            dissect_icmpv6rplopt(tvb, offset, pinfo, icmp6_tree);
+            break;
         default:
             next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
             call_dissector(data_handle,next_tvb, pinfo, tree);
@@ -2451,7 +2916,192 @@ proto_register_icmpv6(void)
             NULL, HFILL }},
                { &hf_icmpv6_opt_flag_reserved,
           { "Reserved", "icmpv6.opt_prefix.flag.reserved", FT_UINT8, BASE_DEC, NULL, 0x3f,
-            NULL, HFILL }}
+            NULL, HFILL }},
+        /* RPL: draft-ietf-roll-rpl-12.txt: Routing over Low-Power and Lossy Networks. */
+        { &hf_icmpv6_dis_reserved,
+           { "Grounded",          "icmpv6.rpl.dis.reserved", FT_UINT16, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_grounded,
+           { "Grounded",          "icmpv6.rpl.dio.grounded", FT_BOOLEAN, 8, NULL, RPL_DIO_FLAG_GROUNDED,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_zero,
+           { "Zero",              "icmpv6.rpl.dio.zero", FT_BOOLEAN, 8, NULL, RPL_DIO_FLAG_ZERO,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_mop,
+           { "MOP",               "icmpv6.rpl.dio.mop", FT_UINT8, BASE_HEX, NULL, RPL_DIO_FLAG_MOP,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_preference,
+           { "DAG Preference",    "icmpv6.rpl.dio.preference", FT_UINT8, BASE_DEC, NULL, RPL_DIO_FLAG_PREFERENCE,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_rank,
+           { "Rank",              "icmpv6.rpl.dio.rank", FT_UINT16, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_instance,
+           { "RPLInstanceID",     "icmpv6.rpl.dio.instance", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_version,
+           { "version",           "icmpv6.rpl.dio.version", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_trigger_seqnum,
+           { "DTSN",              "icmpv6.rpl.dio.dtsn", FT_UINT8, BASE_DEC, NULL, 0x0,
+             "Destination advertisement trigger sequence number", HFILL }},
+        { &hf_icmpv6_dao_instance,
+           { "DAO Instance",      "icmpv6.rpl.dao.instance", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_dio_dagid,
+           { "DODAGID",           "icmpv6.rpl.dio.dagid", FT_IPv6, BASE_NONE, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_dao_seqnum,
+           { "DAO Sequence",      "icmpv6.rpl.dao.sequence", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_dao_reserved,
+           { "Reserved",          "icmpv6.rpl.dao.reserved", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_dao_flag_k,
+           { "DAO-ACK Request",   "icmpv6.rpl.dao.flag_k", FT_BOOLEAN, 8, NULL, RPL_DAO_FLAG_K,
+             NULL, HFILL }},
+        { &hf_icmpv6_dao_flag_d,
+           { "DODAGID Present",   "icmpv6.rpl.dao.flag_d", FT_BOOLEAN, 8, NULL, RPL_DAO_FLAG_D,
+             NULL, HFILL }},
+        { &hf_icmpv6_dao_flag_rsv,
+           { "Reserved",          "icmpv6.rpl.dao.flag_rsv", FT_UINT8, BASE_DEC, NULL, RPL_DAO_FLAG_RESERVED,
+             NULL, HFILL }},
+        { &hf_icmpv6_dao_dodagid,
+           { "DODAGID",           "icmpv6.rpl.dao.dodagid", FT_IPv6, BASE_NONE, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_daoack_instance,
+           { "Instance",          "icmpv6.rpl.daoack.instance", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_daoack_seqnum,
+           { "DAO-ACK Sequence",  "icmpv6.rpl.daoack.sequence", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_daoack_status,
+           { "Status",            "icmpv6.rpl.daoack.status", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_daoack_flag_d,
+           { "DODAGID Present",   "icmpv6.rpl.daoack.flag_d", FT_BOOLEAN, 8, NULL, RPL_DAOACK_FLAG_D,
+             NULL, HFILL }},
+        { &hf_icmpv6_daoack_flag_rsv,
+           { "Reserved",          "icmpv6.rpl.daoack.flag_rsv", FT_UINT8, BASE_DEC, NULL, RPL_DAOACK_FLAG_RESERVED,
+             NULL, HFILL }},
+        { &hf_icmpv6_daoack_dodagid,
+           { "DODAGID",           "icmpv6.rpl.daoack.dodagid", FT_IPv6, BASE_NONE, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_route,
+           { "Route",             "icmpv6.rpl.opt.route", FT_IPv6, BASE_NONE, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_route_pref,
+           { "Routing Preference","icmpv6.rpl.opt.route.pref", FT_UINT8, BASE_DEC, NULL, RPL_OPT_ROUTE_PREFERENCE,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_route_lifetime,
+           { "Route Lifetime",    "icmpv6.rpl.opt.route.lifetime", FT_UINT32, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_route_length,
+           { "Route Length",      "icmpv6.rpl.opt.route.length", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_prefix_flag_a,
+           { "Auto Address Config","icmpv6.rpl.opt.config.A", FT_BOOLEAN, 8, NULL, RPL_OPT_PREFIX_A,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_prefix_flag_r,
+           { "Router Address",     "icmpv6.rpl.opt.config.R", FT_BOOLEAN, 8, NULL, RPL_OPT_PREFIX_R,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_auth,
+           { "Authentication Enabled","icmpv6.rpl.opt.config.auth", FT_BOOLEAN, 8, NULL, RPL_OPT_CONFIG_FLAG_AUTH,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_pcs,
+           { "Path Control Size",  "icmpv6.rpl.opt.config.pcs", FT_UINT8, BASE_DEC, NULL, RPL_OPT_CONFIG_FLAG_PCS,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_doublings,
+           { "DIOIntervalDoublings","icmpv6.rpl.opt.config.interval_double", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_min_interval,
+           { "DIOIntervalMin",     "icmpv6.rpl.opt.config.interval_min", FT_UINT16, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_redundancy,
+           { "DIORedundancyConstant", "icmpv6.rpl.opt.config.redundancy", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_rank_incr,
+           { "MaxRankInc",         "icmpv6.rpl.opt.config.max_rank_inc", FT_UINT16, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_hop_rank_inc,
+           { "MinHopRankInc",      "icmpv6.rpl.opt.config.min_hop_rank_inc", FT_UINT16, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_ocp,
+           { "Objective Code Point","icmpv6.rpl.opt.config.ocp", FT_UINT16, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_rsv,
+           { "Reserved",           "icmpv6.rpl.opt.config.rsv", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_def_lifetime,
+           { "Default Lifetime",   "icmpv6.rpl.opt.config.def_lifetime", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_config_lifetime_unit,
+           { "Lifetime Unit",      "icmpv6.rpl.opt.config.lifetime_unit", FT_UINT16, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_target,
+           { "Target",             "icmpv6.rpl.opt.target", FT_IPv6, BASE_NONE, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_target_length,
+           { "Target Length",      "icmpv6.rpl.opt.target.length", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_target_reserved,
+           { "Reserved",           "icmpv6.rpl.opt.target.reserved", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+         { &hf_icmpv6_rpl_opt_transit_e,
+           { "External",           "icmpv6.rpl.opt.transit.e", FT_BOOLEAN, 8, NULL, RPL_OPT_TRANSIT_E,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_transit_flags,
+           { "Flags",              "icmpv6.rpl.opt.transit.flags", FT_UINT8, BASE_DEC, NULL, RPL_OPT_TRANSIT_FLAGS,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_transit_pathseq,
+           { "Path Sequence",      "icmpv6.rpl.opt.transit.pathseq", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_transit_pathctl,
+           { "Path Control",       "icmpv6.rpl.opt.transit.pathctl", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_transit_pathlifetime,
+           { "Path Lifetime",      "icmpv6.rpl.opt.transit.pathlifetime", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_transit_parent,
+           { "Parent Address",     "icmpv6.rpl.opt.transit.parent", FT_IPv6, BASE_NONE, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_solicited_instance,
+           { "Instance",           "icmpv6.rpl.opt.solicited.instance", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_solicited_flag_v,
+           { "Version predicate",  "icmpv6.rpl.opt.solicited.versionflag", FT_BOOLEAN, 8, NULL, RPL_OPT_SOLICITED_V,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_solicited_flag_i,
+           { "InstanceID predicate","icmpv6.rpl.opt.solicited.instanceflag", FT_BOOLEAN, 8, NULL, RPL_OPT_SOLICITED_I,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_solicited_flag_d,
+           { "DODAGID predicate",  "icmpv6.rpl.opt.solicited.dodagidflag", FT_BOOLEAN, 8, NULL, RPL_OPT_SOLICITED_D,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_solicited_dodagid,
+           { "DODAGID",            "icmpv6.rpl.opt.solicited.dodagid", FT_IPv6, BASE_NONE, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_solicited_version,
+           { "Version",            "icmpv6.rpl.opt.solicited.version", FT_UINT8, BASE_DEC, NULL, 0x0,
+              NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_prefix_vlifetime,
+           { "Valid Lifetime",    "icmpv6.rpl.opt.prefix.valid_lifetime", FT_UINT32, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_prefix_plifetime,
+           { "Preferred Lifetime", "icmpv6.rpl.opt.prefix.preferred_lifetime", FT_UINT32, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_prefix_length,
+           { "Prefix Length",      "icmpv6.rpl.opt.prefix.length", FT_UINT8, BASE_DEC, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_prefix,
+           { "Destination Prefix", "icmpv6.rpl.opt.prefix", FT_IPv6, BASE_NONE, NULL, 0x0,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_prefix_flag_l,
+           { "On Link",            "icmpv6.rpl.opt.prefix.L", FT_BOOLEAN, 8, NULL, RPL_OPT_PREFIX_L,
+             NULL, HFILL }},
+        { &hf_icmpv6_rpl_opt_targetdesc,
+           { "Descriptor",         "icmpv6.rpl.opt.targetdesc.descriptor", FT_UINT32, BASE_HEX, NULL, 0x0,
+             NULL, HFILL }},
+
     };
 
     static gint *ett[] = {
@@ -2467,7 +3117,8 @@ proto_register_icmpv6(void)
         &ett_nodeinfo_nodedns,
         &ett_multicastRR,
         &ett_icmpv6opt_name,
-        &ett_cga_param_name
+        &ett_cga_param_name,
+        &ett_dao_rr_stack
     };
 
     proto_icmpv6 = proto_register_protocol("Internet Control Message Protocol v6",
index 3e51c3ed585140558386aaf3acf3fbdc7cc8ae31..9ba698ec45635e8f1739d69375023587fe160180 100644 (file)
@@ -282,6 +282,8 @@ struct icmp6_hdr {
 #define ICMP6_MCAST_ROUTER_SOLICIT             152 /* Multicast Router Solicitation                    [RFC4286] */
 #define ICMP6_MCAST_ROUTER_TERM                        153 /* Multicast Router Termination                     [RFC4286] */
 #define ICMP6_FMIPV6_MESSAGES                  154 /* FMIPv6 Messages       [RFC-ietf-mipshop-rfc5268bis-01.txt] */
+#define ICMP6_RPL_CONTROL              155 /* RPL control messages  [draft-ietf-roll-rpl-12.txt] */
+                                            /* (Pending IANA Assignment) */
 
 #define ICMP6_DST_UNREACH_NOROUTE              0       /* no route to destination */
 #define ICMP6_DST_UNREACH_ADMIN                        1       /* administratively prohibited */
@@ -433,7 +435,7 @@ struct nd_opt_hdr {         /* Neighbor discovery option header */
 #define ND_OPT_CERTIFICATE                     16
 
 /*
-17      IP Address Option                       [RFC4068]  
+17      IP Address Option                       [RFC4068]
 18      New Router Prefix Information Option    [RFC4068]
 19      Link-layer Address Option               [RFC4068]
 20      Neighbor Advertisement Acknowledgment   [RFC4068]
@@ -769,7 +771,7 @@ struct fmip6_opt_new_router_prefix_info {
        guint8 fmip6_opt_len;               /* size of this option in 8 octets including opt_hdr */
        guint8 fmip6_opt_optcode;           /* Opt-Code see the definition below */
        guint8 fmip6_opt_prefix_len;        /* Prefix length for the address */
-       guint32 fmip6_opt_reserved;         /* Reserved */      
+       guint32 fmip6_opt_reserved;         /* Reserved */
        struct e_in6_addr fmip6_opt_prefix; /* Could be either IPaddr or Prefix, if prefix left should be zero cleared */
 };
 
@@ -811,6 +813,54 @@ struct fmip6_opt_neighbor_advertisement_ack {
 #define FMIP6_OPT_NEIGHBOR_ADV_ACK_LEN_NO_COA          1       /* No CoA included */
 #define FMIP6_OPT_NEIGHBOR_ADV_ACK_LEN_COA             3       /* CoA included */
 
+/* RPL: draft-ietf-roll-rpl-12.txt: Routing over Low-Power and Lossy Networks. */
+/* Pending IANA Assignment */
+/* RPL ICMPv6 Codes */
+#define ICMP6_RPL_DIS       0   /* DODAG Information Solicitation */
+#define ICMP6_RPL_DIO       1   /* DODAG Information Object */
+#define ICMP6_RPL_DAO       2   /* Destination Advertisement Object */
+#define ICMP6_RPL_DAOACK    3   /* Destination Advertisement Object Ack */
+
+/* RPL Option Types */
+/* Pending IANA Assignment */
+#define RPL_OPT_PAD1        0   /* 1-byte padding */
+#define RPL_OPT_PADN        1   /* n-byte padding */
+#define RPL_OPT_METRIC      2   /* DAG metric container */
+#define RPL_OPT_ROUTING     3   /* Routing Information */
+#define RPL_OPT_CONFIG      4   /* DAG configuration */
+#define RPL_OPT_TARGET      5   /* RPL Target */
+#define RPL_OPT_TRANSIT     6   /* Transit */
+#define RPL_OPT_SOLICITED   7   /* Solicited Information */
+#define RPL_OPT_PREFIX      8   /* Destination prefix */
+#define RPL_OPT_TARGETDESC  9   /* RPL Target Descriptor */
+
+/* RPL DIO Flags */
+#define RPL_DIO_FLAG_GROUNDED           0x80
+#define RPL_DIO_FLAG_ZERO               0x40
+#define RPL_DIO_FLAG_MOP                0x38
+#define RPL_DIO_FLAG_PREFERENCE         0x07
+
+/* RPL DAO Flags */
+#define RPL_DAO_FLAG_K                  0x80
+#define RPL_DAO_FLAG_D                  0x40
+#define RPL_DAO_FLAG_RESERVED           0x3F
+
+/* RPL DAO ACK Flags */
+#define RPL_DAOACK_FLAG_D               0x80
+#define RPL_DAOACK_FLAG_RESERVED        0x7F
+
+/* RPL Option Bitfields */
+#define RPL_OPT_PREFIX_L                0x80
+#define RPL_OPT_PREFIX_A                0x40
+#define RPL_OPT_PREFIX_R                0x20
+#define RPL_OPT_ROUTE_PREFERENCE        0x18
+#define RPL_OPT_CONFIG_FLAG_AUTH        0x08
+#define RPL_OPT_CONFIG_FLAG_PCS         0x07
+#define RPL_OPT_TRANSIT_E               0x80
+#define RPL_OPT_TRANSIT_FLAGS           0x7F
+#define RPL_OPT_SOLICITED_V             0x80
+#define RPL_OPT_SOLICITED_I             0x40
+#define RPL_OPT_SOLICITED_D             0x20
 
 void capture_ipv6(const guchar *, int, int, packet_counts *);