aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Valverde <joao.valverde@tecnico.ulisboa.pt>2015-09-06 13:08:08 +0100
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2015-09-28 17:58:54 +0000
commitf693b4d27fb40a26c5c8d1663df989f474d26ab8 (patch)
tree7d278c75eb67a9fbf3b0677280ccc458dcf2fc1a
parentd4d03113e171feaa724e60c4d55bf888eb2bb2e4 (diff)
Improve IPv6 routing header dissection
Remove size limitation of 23 addresses to Type 0. Add validity checks to Type 0 and Type 2. Add address count vs segments left check to RPL. Use hf_ipv6_routing_* for shared routing header fields and hf_ipv6_routing_<type>_* for the rest. Change-Id: I98796504a0f7643476c4c3550586b5da2cf70f6d Reviewed-on: https://code.wireshark.org/review/10470 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
-rw-r--r--epan/dissectors/packet-ipv6.c315
-rw-r--r--epan/dissectors/packet-ipv6.h3
2 files changed, 190 insertions, 128 deletions
diff --git a/epan/dissectors/packet-ipv6.c b/epan/dissectors/packet-ipv6.c
index c13ce57858..3bbfd5db34 100644
--- a/epan/dissectors/packet-ipv6.c
+++ b/epan/dissectors/packet-ipv6.c
@@ -58,6 +58,7 @@ void proto_register_ipv6(void);
void proto_reg_handoff_ipv6(void);
#define IPv6_HDR_SIZE 40
+#define IPv6_ADDR_SIZE 16
#define IPv6_HDR_TCLS(ipv6) ((guint8)(g_ntohl((ipv6)->ip6_flow) >> 20))
@@ -168,6 +169,7 @@ static int hf_ipv6_opt_qs_ttl_diff = -1;
static int hf_ipv6_opt_qs_unused = -1;
static int hf_ipv6_opt_qs_nonce = -1;
static int hf_ipv6_opt_qs_reserved = -1;
+static int hf_ipv6_opt_mipv6_home_address = -1;
static int hf_ipv6_opt_rpl_flag = -1;
static int hf_ipv6_opt_rpl_flag_o = -1;
static int hf_ipv6_opt_rpl_flag_r = -1;
@@ -194,12 +196,11 @@ static int hf_ipv6_hopopts_length = -1;
static int hf_ipv6_unknown_hdr = -1;
static int hf_ipv6_unknown_hdr_nxt = -1;
static int hf_ipv6_unknown_hdr_length = -1;
-static int hf_ipv6_routing_hdr_opt = -1;
-static int hf_ipv6_routing_hdr_nxt = -1;
-static int hf_ipv6_routing_hdr_length = -1;
-static int hf_ipv6_routing_hdr_type = -1;
-static int hf_ipv6_routing_hdr_left = -1;
-static int hf_ipv6_routing_hdr_addr = -1;
+static int hf_ipv6_routing = -1;
+static int hf_ipv6_routing_nxt = -1;
+static int hf_ipv6_routing_length = -1;
+static int hf_ipv6_routing_type = -1;
+static int hf_ipv6_routing_segleft = -1;
static int hf_ipv6_fraghdr = -1;
static int hf_ipv6_fraghdr_nxt = -1;
static int hf_ipv6_fraghdr_reserved_octet = -1;
@@ -220,15 +221,19 @@ static int hf_ipv6_reassembled_length = -1;
static int hf_ipv6_reassembled_data = -1;
static int hf_ipv6_padding = -1;
-static int hf_ipv6_mipv6_home_address = -1;
+static int hf_ipv6_routing_src_reserved = -1;
+static int hf_ipv6_routing_src_addr = -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_routing_mipv6_reserved = -1;
+static int hf_ipv6_routing_mipv6_home_address = -1;
+
+static int hf_ipv6_routing_rpl_cmprI = -1;
+static int hf_ipv6_routing_rpl_cmprE = -1;
+static int hf_ipv6_routing_rpl_pad = -1;
+static int hf_ipv6_routing_rpl_reserved = -1;
+static int hf_ipv6_routing_rpl_segments = -1;
+static int hf_ipv6_routing_rpl_addr = -1;
+static int hf_ipv6_routing_rpl_fulladdr = -1;
static int hf_ipv6_shim6 = -1;
static int hf_ipv6_shim6_nxt = -1;
@@ -300,6 +305,7 @@ static gint ett_ipv6_opt = -1;
static gint ett_ipv6_opt_rpl = -1;
static gint ett_ipv6_opt_mpl = -1;
static gint ett_ipv6_fraghdr = -1;
+static gint ett_ipv6_routing = -1;
static gint ett_ipv6_shim6 = -1;
static gint ett_ipv6_shim6_option = -1;
static gint ett_ipv6_shim6_locators = -1;
@@ -318,13 +324,16 @@ static gint ett_ipv6_traffic_class = -1;
static gint ett_geoip_info = -1;
#endif /* HAVE_GEOIP_V6 */
+static expert_field ei_ipv6_routing_invalid_length = EI_INIT;
+static expert_field ei_ipv6_routing_invalid_segleft = EI_INIT;
static expert_field ei_ipv6_dst_addr_not_multicast = EI_INIT;
static expert_field ei_ipv6_src_route_list_mult_inst_same_addr = EI_INIT;
static expert_field ei_ipv6_src_route_list_src_addr = EI_INIT;
static expert_field ei_ipv6_src_route_list_dst_addr = EI_INIT;
static expert_field ei_ipv6_src_route_list_multicast_addr = EI_INIT;
-static expert_field ei_ipv6_cmpri_cmpre_pad = EI_INIT;
-static expert_field ei_ipv6_routing_hdr_rpl_reserved = EI_INIT;
+static expert_field ei_ipv6_routing_rpl_cmpri_cmpre_pad = EI_INIT;
+static expert_field ei_ipv6_routing_rpl_segments_ge0 = EI_INIT;
+static expert_field ei_ipv6_routing_rpl_reserved = EI_INIT;
static expert_field ei_ipv6_opt_tel_invalid_len = EI_INIT;
static expert_field ei_ipv6_opt_jumbo_invalid_len = EI_INIT;
static expert_field ei_ipv6_opt_jumbo_missing = EI_INIT;
@@ -337,7 +346,6 @@ static expert_field ei_ipv6_opt_unknown_data = EI_INIT;
static expert_field ei_ipv6_mipv6_home_address_invalid_len = EI_INIT;
static expert_field ei_ipv6_shim6_opt_elemlen_invalid = EI_INIT;
static expert_field ei_ipv6_shim6_checksum_bad = EI_INIT;
-static expert_field ei_ipv6_routing_hdr_rpl_segments_ge0 = EI_INIT;
static expert_field ei_ipv6_hopopts_not_first = EI_INIT;
static expert_field ei_ipv6_bogus_ipv6_length = EI_INIT;
static expert_field ei_ipv6_bogus_payload_length = EI_INIT;
@@ -805,11 +813,12 @@ static const value_string routing_header_type[] = {
static int
dissect_routing6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
struct ip6_rthdr rt;
- guint len, seg_left;
+ guint len;
proto_tree *rthdr_tree;
- proto_item *ti, *ti_len;
+ proto_item *pi, *ti, *ti_len, *ti_seg;
int offset = 0;
- guint8 buf[sizeof(struct ip6_rthdr0) + sizeof(struct e_in6_addr) * 23];
+ struct e_in6_addr addr;
+ guint8 addr_count;
ipv6_meta_t *ipv6_info;
ipv6_info = (ipv6_meta_t *)p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, IPV6_PROTO_META);
@@ -819,59 +828,84 @@ dissect_routing6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
tvb_memcpy(tvb, (guint8 *)&rt, offset, sizeof(rt));
len = (rt.ip6r_len + 1) << 3;
- /* Assigning seg_left and the if (seg_left) {} blocks of code that follow,
+ /* The if (segleft) {} blocks of code that follow,
* along with any expert_add_info() calls, all need to execute when
* appropriate, regardless of whether the tree is NULL or not. */
if (1) {
/* !!! specify length */
- ti = proto_tree_add_uint_format(tree, hf_ipv6_routing_hdr_opt, tvb,
- offset, len, rt.ip6r_type,
- "Routing Header, Type: %s (%u)",
- val_to_str_const(rt.ip6r_type, routing_header_type, "Unknown"),
- rt.ip6r_type);
- rthdr_tree = proto_item_add_subtree(ti, ett_ipv6);
-
- proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_nxt, tvb,
- offset + (int)offsetof(struct ip6_rthdr, ip6r_nxt), 1, ENC_BIG_ENDIAN);
-
- ti_len = proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_length, tvb,
- offset + (int)offsetof(struct ip6_rthdr, ip6r_len), 1, ENC_BIG_ENDIAN);
- proto_item_append_text(ti_len, " (%d byte%s)", len, plurality(len, "", "s"));
+ pi = proto_tree_add_item(tree, hf_ipv6_routing, tvb, offset, len, ENC_NA);
+ proto_item_append_text(pi, " (%s)", val_to_str(rt.ip6r_type, routing_header_type, "Unknown type %u"));
- proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_type, tvb,
- offset + (int)offsetof(struct ip6_rthdr, ip6r_type), 1, ENC_BIG_ENDIAN);
+ rthdr_tree = proto_item_add_subtree(pi, ett_ipv6_routing);
- proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_left, tvb,
- offset + (int)offsetof(struct ip6_rthdr, ip6r_segleft), 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(rthdr_tree, hf_ipv6_routing_nxt, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
- seg_left = tvb_get_guint8(tvb, offset + (int)offsetof(struct ip6_rthdr, ip6r_segleft));
+ ti_len = proto_tree_add_item(rthdr_tree, hf_ipv6_routing_length, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_item_append_text(ti_len, " (%d bytes)", len);
+ offset += 1;
- if (rt.ip6r_type == IPv6_RT_HEADER_SOURCE_ROUTING && len <= sizeof(buf)) {
- struct e_in6_addr *a;
- int n;
- struct ip6_rthdr0 *rt0;
+ proto_tree_add_item(rthdr_tree, hf_ipv6_routing_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
- tvb_memcpy(tvb, buf, offset, len);
- rt0 = (struct ip6_rthdr0 *)buf;
+ ti_seg = proto_tree_add_item(rthdr_tree, hf_ipv6_routing_segleft, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ /* IPv6 Source Routing Header (Type 0) */
+ if (rt.ip6r_type == IPv6_RT_HEADER_SOURCE_ROUTING) {
+ int offlim;
- for (a = rt0->ip6r0_addr, n = 0;
- a < (struct e_in6_addr *)(buf + len); a++, n++) {
+ proto_tree_add_item(rthdr_tree, hf_ipv6_routing_src_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
- proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_addr, tvb,
- offset + (int)(offsetof(struct ip6_rthdr0, ip6r0_addr)
- + n * sizeof(struct e_in6_addr)),
- (int)sizeof(struct e_in6_addr), ENC_NA);
- if (seg_left)
- TVB_SET_ADDRESS(&pinfo->dst, AT_IPv6, tvb,
- offset + (int)offsetof(struct ip6_rthdr0, ip6r0_addr) + n * (int)sizeof(struct e_in6_addr), 16);
+ if (rt.ip6r_len % 2 != 0) {
+ expert_add_info_format(pinfo, ti_len, &ei_ipv6_routing_invalid_length,
+ "IPv6 Routing Header extension header length must not be odd");
+ } else {
+ addr_count = rt.ip6r_len / 2;
+ if (rt.ip6r_segleft > addr_count) {
+ expert_add_info_format(pinfo, ti_seg, &ei_ipv6_routing_invalid_segleft,
+ "IPv6 Type 0 Routing Header segments left field must not exceed address count (%u)", addr_count);
+ }
+ offlim = offset + addr_count * IPv6_ADDR_SIZE;
+ for (; offset < offlim; offset += IPv6_ADDR_SIZE) {
+ ti = proto_tree_add_item(rthdr_tree, hf_ipv6_routing_src_addr, tvb,
+ offset, IPv6_ADDR_SIZE, ENC_NA);
+ tvb_get_ipv6(tvb, offset, &addr);
+ if (in6_is_addr_multicast(&addr)) {
+ expert_add_info(pinfo, ti, &ei_ipv6_src_route_list_multicast_addr);
+ }
+ }
+ if (rt.ip6r_segleft)
+ SET_ADDRESS(&pinfo->dst, AT_IPv6, IPv6_ADDR_SIZE, &addr);
}
}
+
+ /* Mobile IPv6 Routing Header (Type 2) */
if (rt.ip6r_type == IPv6_RT_HEADER_MobileIP) {
- proto_tree_add_item(rthdr_tree, hf_ipv6_mipv6_home_address, tvb,
- offset + 8, 16, ENC_NA);
- if (seg_left)
- TVB_SET_ADDRESS(&pinfo->dst, AT_IPv6, tvb, offset + 8, 16);
+ proto_tree_add_item(rthdr_tree, hf_ipv6_routing_mipv6_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ if (rt.ip6r_len != 2) {
+ expert_add_info_format(pinfo, ti_len, &ei_ipv6_routing_invalid_length,
+ "IPv6 Type 2 Routing Header extension header length must equal 2");
+ } else {
+ if (rt.ip6r_segleft != 1) {
+ expert_add_info_format(pinfo, ti_seg, &ei_ipv6_routing_invalid_segleft,
+ "IPv6 Type 2 Routing Header segments left field must equal 1");
+ }
+ ti = proto_tree_add_item(rthdr_tree, hf_ipv6_routing_mipv6_home_address, tvb,
+ offset, IPv6_ADDR_SIZE, ENC_NA);
+ tvb_get_ipv6(tvb, offset, &addr);
+ if (in6_is_addr_multicast(&addr)) {
+ expert_add_info(pinfo, ti, &ei_ipv6_src_route_list_multicast_addr);
+ }
+ if (rt.ip6r_segleft)
+ SET_ADDRESS(&pinfo->dst, AT_IPv6, IPv6_ADDR_SIZE, &addr);
+ }
}
+
+ /* RPL Source Routing Header (Type 3) */
if (rt.ip6r_type == IPv6_RT_HEADER_RPL) {
guint8 cmprI;
guint8 cmprE;
@@ -883,18 +917,18 @@ dissect_routing6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
struct e_in6_addr dstAddr;
/* IPv6 source address used for strict checking */
struct e_in6_addr srcAddr;
- offset += 4;
+
memcpy((guint8 *)&dstAddr, pinfo->dst.data, pinfo->dst.len);
memcpy((guint8 *)&srcAddr, pinfo->src.data, pinfo->src.len);
/* from RFC6554: Multicast addresses MUST NOT appear in the IPv6 Destination Address field */
if(g_ipv6_rpl_srh_strict_rfc_checking && in6_is_addr_multicast(&dstAddr)){
- expert_add_info(pinfo, ti, &ei_ipv6_dst_addr_not_multicast);
+ expert_add_info(pinfo, pi, &ei_ipv6_dst_addr_not_multicast);
}
- 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_rpl_cmprI, tvb, offset, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(rthdr_tree, hf_ipv6_routing_rpl_cmprE, tvb, offset, 4, ENC_BIG_ENDIAN);
+ ti = proto_tree_add_item(rthdr_tree, hf_ipv6_routing_rpl_pad, tvb, offset, 4, ENC_BIG_ENDIAN);
cmprI = tvb_get_guint8(tvb, offset) & 0xF0;
cmprE = tvb_get_guint8(tvb, offset) & 0x0F;
@@ -906,38 +940,41 @@ dissect_routing6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
/* from RFC6554: when CmprI and CmprE are both 0, Pad MUST carry a value of 0 */
if(g_ipv6_rpl_srh_strict_rfc_checking && (cmprI == 0 && cmprE == 0 && pad != 0)){
- expert_add_info_format(pinfo, ti, &ei_ipv6_cmpri_cmpre_pad, "When cmprI equals 0 and cmprE equals 0, pad MUST equal 0 but instead was %d", pad);
+ expert_add_info_format(pinfo, ti, &ei_ipv6_routing_rpl_cmpri_cmpre_pad, "When cmprI equals 0 and cmprE equals 0, pad MUST equal 0 but instead was %d", pad);
}
- proto_tree_add_item(rthdr_tree, hf_ipv6_routing_hdr_rpl_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
+ ti = proto_tree_add_item(rthdr_tree, hf_ipv6_routing_rpl_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
reserved = tvb_get_bits32(tvb, ((offset + 1) * 8) + 4, 20, ENC_BIG_ENDIAN);
if(g_ipv6_rpl_srh_strict_rfc_checking && reserved != 0){
- expert_add_info_format(pinfo, ti, &ei_ipv6_routing_hdr_rpl_reserved, "Reserved field must equal 0 but instead was %d", reserved);
+ expert_add_info_format(pinfo, ti, &ei_ipv6_routing_rpl_reserved, "Reserved field must equal 0 but instead was %d", reserved);
}
/* from RFC6554:
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);
+ ti = proto_tree_add_int(rthdr_tree, hf_ipv6_routing_rpl_segments, tvb, offset, 2, segments);
PROTO_ITEM_SET_GENERATED(ti);
if (segments < 0) {
/* This error should always be reported */
- expert_add_info_format(pinfo, ti, &ei_ipv6_routing_hdr_rpl_segments_ge0, "Calculated total segments must be greater than or equal to 0, instead was %d", segments);
+ expert_add_info_format(pinfo, ti, &ei_ipv6_routing_rpl_segments_ge0, "Calculated total address count must be greater than or equal to 0, instead was %d", segments);
} else {
+ if (rt.ip6r_segleft > (guint)segments) {
+ expert_add_info_format(pinfo, ti_seg, &ei_ipv6_routing_invalid_segleft,
+ "IPv6 RPL Routing Header segments left field must not exceed address count (%u)", (guint)segments);
+ }
+
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);
+ proto_tree_add_item(rthdr_tree, hf_ipv6_routing_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);
+ ti = proto_tree_add_ipv6(rthdr_tree, hf_ipv6_routing_rpl_fulladdr, tvb, offset, (16-cmprI), (guint8 *)&addr);
PROTO_ITEM_SET_GENERATED(ti);
offset += (16-cmprI);
segments--;
@@ -992,13 +1029,11 @@ dissect_routing6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
/* 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-cmprE), ENC_NA);
+ proto_tree_add_item(rthdr_tree, hf_ipv6_routing_rpl_addr, tvb, offset, (16-cmprE), 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);
+ ti = proto_tree_add_ipv6(rthdr_tree, hf_ipv6_routing_rpl_fulladdr, tvb, offset, (16-cmprE), (guint8 *)&addr);
PROTO_ITEM_SET_GENERATED(ti);
/* offset += (16-cmprE); */
@@ -1250,15 +1285,17 @@ dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info * pinfo, c
break;
}
case IP6OPT_HOME_ADDRESS:
+ {
if (opt_len != 16) {
expert_add_info_format(pinfo, ti_opt_len, &ei_ipv6_mipv6_home_address_invalid_len,
"Home Address: Invalid length (%u bytes)", opt_len);
}
- proto_tree_add_item(opt_tree, hf_ipv6_mipv6_home_address, tvb,
+ proto_tree_add_item(opt_tree, hf_ipv6_opt_mipv6_home_address, tvb,
offset, 16, ENC_NA);
TVB_SET_ADDRESS(&pinfo->src, AT_IPv6, tvb, offset, 16);
offset += 16;
break;
+ }
case IP6OPT_CALIPSO:
{
guint8 cmpt_length;
@@ -2739,6 +2776,10 @@ proto_register_ipv6(void)
{ "Reserved", "ipv6.opt.qs_reserved",
FT_UINT32, BASE_HEX, NULL, 0x0003,
NULL, HFILL }},
+ { &hf_ipv6_opt_mipv6_home_address,
+ { "MIPv6 Home Address", "ipv6.opt.mipv6.home_address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
{ &hf_ipv6_opt_rpl_flag,
{ "Flag", "ipv6.opt.rpl.flag",
FT_UINT8, BASE_HEX, NULL, 0x0,
@@ -2806,30 +2847,6 @@ proto_register_ipv6(void)
{ "Unknown Option Payload","ipv6.opt.unknown",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
- { &hf_ipv6_routing_hdr_opt,
- { "Routing Header, Type","ipv6.routing_hdr",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Routing Header Option", HFILL }},
- { &hf_ipv6_routing_hdr_type,
- { "Type", "ipv6.routing_hdr.type",
- FT_UINT8, BASE_DEC, VALS(routing_header_type), 0x0,
- "Routing Header Type", HFILL }},
- { &hf_ipv6_routing_hdr_nxt,
- { "Next Header", "ipv6.routing_hdr.nxt",
- FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0x0,
- NULL, HFILL }},
- { &hf_ipv6_routing_hdr_length,
- { "Length", "ipv6.routing_hdr.length",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- NULL, HFILL }},
- { &hf_ipv6_routing_hdr_left,
- { "Segments Left", "ipv6.routing_hdr.left",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Routing Header Segments Left", HFILL }},
- { &hf_ipv6_routing_hdr_addr,
- { "Address", "ipv6.routing_hdr.addr",
- FT_IPv6, BASE_NONE, NULL, 0x0,
- "Routing Header Address", HFILL }},
{ &hf_ipv6_fraghdr,
{ "Fragment Header", "ipv6.fraghdr",
FT_NONE, BASE_NONE, NULL, 0x0,
@@ -2919,48 +2936,90 @@ proto_register_ipv6(void)
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
+ /* IPv6 Routing Header */
+ { &hf_ipv6_routing,
+ { "Routing Header", "ipv6.routing",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_ipv6_routing_nxt,
+ { "Next Header", "ipv6.routing.nxt",
+ FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0x0,
+ NULL, HFILL }},
+
+ { &hf_ipv6_routing_length,
+ { "Length", "ipv6.routing.length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Extension Header Length", HFILL }},
+
+ { &hf_ipv6_routing_type,
+ { "Type", "ipv6.routing.type",
+ FT_UINT8, BASE_DEC, VALS(routing_header_type), 0x0,
+ "Routing Header Type", HFILL }},
+
+ { &hf_ipv6_routing_segleft,
+ { "Segments Left", "ipv6.routing.segleft",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Routing Header Segments Left", HFILL }},
+
+ /* Source Routing Header */
+ { &hf_ipv6_routing_src_reserved,
+ { "Reserved", "ipv6.routing.src.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Must be zero", HFILL }},
+
+ { &hf_ipv6_routing_src_addr,
+ { "Address", "ipv6.routing.src.addr",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Source Routing Header Address", HFILL }},
+
+ /* Mobile IPv6 */
+ { &hf_ipv6_routing_mipv6_reserved,
+ { "Reserved", "ipv6.routing.mipv6.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Must be zero", HFILL }},
+
+ { &hf_ipv6_routing_mipv6_home_address,
+ { "Home Address", "ipv6.routing.mipv6.home_address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
/* RPL Routing Header */
- { &hf_ipv6_routing_hdr_rpl_cmprI,
- { "Compressed Internal Octets (CmprI)", "ipv6.routing_hdr.rpl.cmprI",
+ { &hf_ipv6_routing_rpl_cmprI,
+ { "Compressed Internal Octets (CmprI)", "ipv6.routing.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",
+ { &hf_ipv6_routing_rpl_cmprE,
+ { "Compressed Final Octets (CmprE)", "ipv6.routing.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",
+ { &hf_ipv6_routing_rpl_pad,
+ { "Padding Bytes", "ipv6.routing.rpl.pad",
FT_UINT32, BASE_DEC, NULL, IP6RRPL_BITMASK_PAD,
NULL, HFILL }},
- { &hf_ipv6_routing_hdr_rpl_reserved,
- { "Reserved", "ipv6.routing_hdr.rpl.reserved",
+ { &hf_ipv6_routing_rpl_reserved,
+ { "Reserved", "ipv6.routing.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",
+ { &hf_ipv6_routing_rpl_segments,
+ { "Total Address Count", "ipv6.routing.rpl.segments",
FT_INT32, BASE_DEC, NULL, 0,
NULL, HFILL }},
- { &hf_ipv6_routing_hdr_rpl_addr,
- { "Address", "ipv6.routing_hdr.rpl.address",
+ { &hf_ipv6_routing_rpl_addr,
+ { "Address", "ipv6.routing.rpl.address",
FT_BYTES, BASE_NONE, NULL, 0,
NULL, HFILL }},
- { &hf_ipv6_routing_hdr_rpl_fulladdr,
- { "Full Address", "ipv6.routing_hdr.rpl.full_address",
+ { &hf_ipv6_routing_rpl_fulladdr,
+ { "Full Address", "ipv6.routing.rpl.full_address",
FT_IPv6, BASE_NONE, NULL, 0,
"Uncompressed IPv6 Address", HFILL }},
- /* Mobile IPv6 */
- { &hf_ipv6_mipv6_home_address,
- { "Home Address", "ipv6.mipv6_home_address",
- FT_IPv6, BASE_NONE, NULL, 0x0,
- NULL, HFILL }},
-
/* SHIM6 */
{ &hf_ipv6_shim6,
{ "SHIM6", "ipv6.shim6",
@@ -3168,6 +3227,7 @@ proto_register_ipv6(void)
&ett_ipv6_opt_rpl,
&ett_ipv6_opt_mpl,
&ett_ipv6_fraghdr,
+ &ett_ipv6_routing,
&ett_ipv6_shim6,
&ett_ipv6_shim6_option,
&ett_ipv6_shim6_locators,
@@ -3191,8 +3251,9 @@ proto_register_ipv6(void)
{ &ei_ipv6_src_route_list_src_addr, { "ipv6.src_route_list.src_addr", PI_PROTOCOL, PI_ERROR, "Source address must not appear in the source route list", EXPFILL }},
{ &ei_ipv6_src_route_list_dst_addr, { "ipv6.src_route_list.dst_addr", PI_PROTOCOL, PI_ERROR, "Destination address must not appear in the source route list", EXPFILL }},
{ &ei_ipv6_src_route_list_multicast_addr, { "ipv6.src_route_list.multicast_addr", PI_PROTOCOL, PI_ERROR, "Multicast addresses must not appear in the source route list", EXPFILL }},
- { &ei_ipv6_cmpri_cmpre_pad, { "ipv6.routing_hdr.rpl.cmprI.cmprE.pad", PI_PROTOCOL, PI_WARN, "When cmprI equals 0 and cmprE equals 0, pad MUST equal 0 but instead was X", EXPFILL }},
- { &ei_ipv6_routing_hdr_rpl_reserved, { "ipv6.routing_hdr.rpl.reserved.not0", PI_PROTOCOL, PI_WARN, "Reserved field must equal 0 but instead was X", EXPFILL }},
+ { &ei_ipv6_routing_rpl_cmpri_cmpre_pad, { "ipv6.routing.rpl.cmprI_cmprE_pad", PI_PROTOCOL, PI_WARN, "When cmprI equals 0 and cmprE equals 0, pad MUST equal 0 but instead was X", EXPFILL }},
+ { &ei_ipv6_routing_rpl_segments_ge0, { "ipv6.routing.rpl.segments_ge0", PI_MALFORMED, PI_ERROR, "Calculated total address count must be greater than or equal to 0, instead was X", EXPFILL }},
+ { &ei_ipv6_routing_rpl_reserved, { "ipv6.routing.rpl.reserved_not0", PI_PROTOCOL, PI_WARN, "Reserved field must equal 0 but instead was X", EXPFILL }},
{ &ei_ipv6_opt_tel_invalid_len, { "ipv6.opt.tel.invalid_len", PI_MALFORMED, PI_ERROR, "Tunnel Encapsulation Limit: Invalid length", EXPFILL }},
{ &ei_ipv6_opt_jumbo_invalid_len, { "ipv6.opt.jumbo.invalid_len", PI_MALFORMED, PI_ERROR, "Jumbo Payload: Invalid length", EXPFILL }},
{ &ei_ipv6_opt_jumbo_missing, { "ipv6.opt.jumbo.missing", PI_PROTOCOL, PI_ERROR, "IPv6 payload length equals 0 and Hop-By-Hop present and Jumbo Payload option missing", EXPFILL }},
@@ -3205,12 +3266,13 @@ proto_register_ipv6(void)
{ &ei_ipv6_mipv6_home_address_invalid_len, { "ipv6.mipv6_home_address.invalid_len", PI_MALFORMED, PI_ERROR, "Home Address: Invalid length", EXPFILL }},
{ &ei_ipv6_shim6_opt_elemlen_invalid, { "ipv6.shim6.opt.elemlen.invalid", PI_MALFORMED, PI_ERROR, "Invalid element length", EXPFILL }},
{ &ei_ipv6_shim6_checksum_bad, { "ipv6.shim6.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
- { &ei_ipv6_routing_hdr_rpl_segments_ge0, { "ipv6.routing_hdr.rpl.segments.ge0", PI_MALFORMED, PI_ERROR, "Calculated total segments must be greater than or equal to 0, instead was X", EXPFILL }},
{ &ei_ipv6_hopopts_not_first, { "ipv6.hopopts.not_first", PI_PROTOCOL, PI_ERROR, "IPv6 Hop-by-Hop extension header must appear immediately after IPv6 header", EXPFILL }},
{ &ei_ipv6_bogus_ipv6_length, { "ipv6.bogus_ipv6_length", PI_PROTOCOL, PI_ERROR, "Bogus IPv6 length", EXPFILL }},
{ &ei_ipv6_bogus_payload_length, { "ipv6.bogus_payload_length", PI_PROTOCOL, PI_WARN, "IPv6 payload length does not match expected framing length", EXPFILL }},
{ &ei_ipv6_bogus_ipv6_version, { "ipv6.bogus_ipv6_version", PI_PROTOCOL, PI_ERROR, "Bogus IP version", EXPFILL }},
{ &ei_ipv6_invalid_header, { "ipv6.invalid_header", PI_MALFORMED, PI_ERROR, "IPv6 header must be exactly 40 bytes", EXPFILL }},
+ { &ei_ipv6_routing_invalid_length, { "ipv6.routing.invalid_length", PI_MALFORMED, PI_ERROR, "Invalid IPv6 Routing header length", EXPFILL }},
+ { &ei_ipv6_routing_invalid_segleft, { "ipv6.routing.invalid_segleft", PI_PROTOCOL, PI_ERROR, "IPv6 Routing Header segments left field must not exceed address count", EXPFILL }},
};
/* Decode As handling */
@@ -3234,11 +3296,10 @@ proto_register_ipv6(void)
expert_register_field_array(expert_ipv6, ei, array_length(ei));
proto_ipv6_hopopts = proto_register_protocol("IPv6 Hop-by-Hop Options", "IPv6 Hop-by-Hop", "ipv6.hopopts");
- proto_ipv6_routing = proto_register_protocol("IPv6 Routing", "IPv6 Routing", "ipv6.routing_hdr");
+ proto_ipv6_routing = proto_register_protocol("IPv6 Routing", "IPv6 Routing", "ipv6.routing");
proto_ipv6_shim6 = proto_register_protocol("IPv6 SHIM6", "SHIM6", "ipv6.shim6");
proto_ipv6_dstopts = proto_register_protocol("IPv6 Destination Options", "IPv6 Destination", "ipv6.dstopts");
- ipv6_next_header_dissector_table = register_dissector_table("ipv6.nxt",
- "IPv6 Next Header", FT_UINT32, BASE_DEC);
+ ipv6_next_header_dissector_table = register_dissector_table("ipv6.nxt", "IPv6 Next Header", FT_UINT32, BASE_DEC);
/* Register configuration options */
ipv6_module = prefs_register_protocol(proto_ipv6, NULL);
diff --git a/epan/dissectors/packet-ipv6.h b/epan/dissectors/packet-ipv6.h
index c9d8264d3a..6e62fd02b3 100644
--- a/epan/dissectors/packet-ipv6.h
+++ b/epan/dissectors/packet-ipv6.h
@@ -93,7 +93,8 @@ struct ip6_rthdr0 {
guint8 ip6r0_segleft; /* segments left */
guint8 ip6r0_reserved; /* reserved field */
guint8 ip6r0_slmap[3]; /* strict/loose bit map */
- struct e_in6_addr ip6r0_addr[1]; /* up to 23 addresses */
+ /* followed by up to 127 addresses */
+ struct e_in6_addr ip6r0_addr[1];
};
/* Fragment header */