diff options
author | ishaangandhi <ishaangandhi@gmail.com> | 2020-10-28 00:38:46 -0400 |
---|---|---|
committer | Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org> | 2020-11-05 05:48:07 +0000 |
commit | 9b46447bb1710563ecea8fa132818ac5ad9aa2fa (patch) | |
tree | 40b35a194d54f97b753b05571beec36c36e84849 /epan/dissectors/packet-ipv6.c | |
parent | 1dd8b133ee8062149177a317d739172663eb86bc (diff) |
IPv6: Add dissector for Compact Routing Header (CRH)
Diffstat (limited to 'epan/dissectors/packet-ipv6.c')
-rw-r--r-- | epan/dissectors/packet-ipv6.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/epan/dissectors/packet-ipv6.c b/epan/dissectors/packet-ipv6.c index f173d263b1..e959639463 100644 --- a/epan/dissectors/packet-ipv6.c +++ b/epan/dissectors/packet-ipv6.c @@ -111,6 +111,7 @@ static int proto_ipv6_routing_rt0 = -1; static int proto_ipv6_routing_mipv6 = -1; static int proto_ipv6_routing_rpl = -1; static int proto_ipv6_routing_srh = -1; +static int proto_ipv6_routing_crh = -1; static int hf_ipv6_version = -1; static int hf_ip_version = -1; @@ -265,6 +266,11 @@ static int hf_ipv6_routing_srh_flags = -1; static int hf_ipv6_routing_srh_tag = -1; static int hf_ipv6_routing_srh_addr = -1; +static int hf_ipv6_routing_crh16_current_sid = -1; +static int hf_ipv6_routing_crh32_current_sid = -1; +static int hf_ipv6_routing_crh16_segment_id = -1; +static int hf_ipv6_routing_crh32_segment_id = -1; + static int hf_geoip_country = -1; static int hf_geoip_country_iso = -1; static int hf_geoip_city = -1; @@ -651,6 +657,8 @@ enum { IPv6_RT_HEADER_MOBILE_IP = 2, IPv6_RT_HEADER_RPL = 3, IPv6_RT_HEADER_SEGMENT_ROUTING = 4, + IPv6_RT_HEADER_COMPACT_16 = 5, + IPv6_RT_HEADER_COMPACT_32 = 6, IPv6_RT_HEADER_EXP1 = 253, IPv6_RT_HEADER_EXP2 = 254 }; @@ -662,6 +670,8 @@ static const value_string routing_header_type[] = { { IPv6_RT_HEADER_MOBILE_IP, "Type 2 Routing" }, { IPv6_RT_HEADER_RPL, "RPL Source Route" }, { IPv6_RT_HEADER_SEGMENT_ROUTING, "Segment Routing" }, + { IPv6_RT_HEADER_COMPACT_16, "Compact Routing Header 16" }, + { IPv6_RT_HEADER_COMPACT_32, "Compact Routing Header 32" }, { IPv6_RT_HEADER_EXP1, "Experiment 1" }, { IPv6_RT_HEADER_EXP2, "Experiment 2" }, { 0, NULL } @@ -1110,6 +1120,82 @@ dissect_routing6_srh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * return tvb_captured_length(tvb); } +/* Compact Routing Header 16 (Type 5) and Compact Routing Header 32 (Type 6). + https://tools.ietf.org/html/draft-bonica-6man-comp-rtg-hdr-23. */ +static int dissect_routing6_crh(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) +{ + int offset, minimum_crh_length; + gint sid; + + unsigned sid_count = 0; + unsigned octets_per_sid = 0; + unsigned sids_beyond_first_word = 0; + unsigned sids_per_word = 0; + struct ws_rthdr* rt = (struct ws_rthdr*)data; + gboolean is_crh16 = rt->hdr.ip6r_type == IPv6_RT_HEADER_COMPACT_16; + guint8 segments_left = rt->hdr.ip6r_segleft; + + /* Compute the minimum CRH length measured in 8-octet units, not including + the first 8 octets */ + minimum_crh_length = -1; + switch (rt->hdr.ip6r_type) { + case IPv6_RT_HEADER_COMPACT_16: + octets_per_sid = 2; + sids_per_word = 4; + sid_count = rt->hdr.ip6r_len * 4 + 2; + if (segments_left <= 2) + minimum_crh_length = 0; + sids_beyond_first_word = segments_left - 2; + break; + case IPv6_RT_HEADER_COMPACT_32: + octets_per_sid = 4; + sids_per_word = 2; + sid_count = rt->hdr.ip6r_len * 2 + 1; + if (segments_left <= 1) + minimum_crh_length = 0; + sids_beyond_first_word = segments_left - 1; + break; + } + if (minimum_crh_length) { + minimum_crh_length = sids_beyond_first_word / sids_per_word; + if (sids_beyond_first_word % sids_per_word) + minimum_crh_length++; + } + if (minimum_crh_length > rt->hdr.ip6r_len) { + expert_add_info_format(pinfo, rt->ti_len, &ei_ipv6_routing_invalid_length, + "IPv6 Compact Routing Header minimum length must not exceed header length (%u)", + rt->hdr.ip6r_len); + } + + offset = 0; + if (is_crh16) { + proto_item* current_sid_item = proto_tree_add_item(tree, hf_ipv6_routing_crh16_current_sid, + tvb, offset + (octets_per_sid * segments_left), octets_per_sid, ENC_BIG_ENDIAN); + proto_item_set_generated(current_sid_item); + } else { + proto_item* current_sid_item = proto_tree_add_item(tree, hf_ipv6_routing_crh16_current_sid, + tvb, offset + (octets_per_sid * segments_left), octets_per_sid, ENC_BIG_ENDIAN); + proto_item_set_generated(current_sid_item); + } + sid = is_crh16 ? tvb_get_guint16(tvb, offset, ENC_BIG_ENDIAN) + : tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN); + proto_tree* segment_ids + = proto_tree_add_subtree(tree, tvb, 0, -1, 0, NULL, "Segment Identifiers"); + for (unsigned i = 0; i < sid_count && sid; i++) { + if (is_crh16) { + proto_tree_add_uint_format(segment_ids, hf_ipv6_routing_crh16_segment_id, tvb, offset, + octets_per_sid, sid, "SID[%d] = %d", i, sid); + } else { + proto_tree_add_uint_format(segment_ids, hf_ipv6_routing_crh32_segment_id, tvb, offset, + octets_per_sid, sid, "SID[%d] = %d", i, sid); + } + offset += octets_per_sid; + sid = is_crh16 ? tvb_get_guint16(tvb, offset, ENC_BIG_ENDIAN) + : tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN); + } + + return tvb_captured_length(tvb); +} /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -3341,6 +3427,28 @@ proto_register_ipv6(void) { "Address", "ipv6.routing.srh.addr", FT_IPv6, BASE_NONE, NULL, 0x0, "Segment address", HFILL } + }, + + /* Compact Routing Header */ + { &hf_ipv6_routing_crh16_current_sid, + { "Current SID", "ipv6.routing.crh16.current_sid", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Value of the current Segment ID", HFILL } + }, + { &hf_ipv6_routing_crh32_current_sid, + { "Current SID", "ipv6.routing.crh32.current_sid", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Value of the current Segment ID", HFILL } + }, + { &hf_ipv6_routing_crh16_segment_id, + { "Segment ID", "ipv6.routing.crh16.sid", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Segment address", HFILL } + }, + { &hf_ipv6_routing_crh32_segment_id, + { "Segment ID", "ipv6.routing.crh32.sid", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Segment address", HFILL } } }; @@ -3569,6 +3677,7 @@ proto_register_ipv6(void) proto_ipv6_routing_mipv6 = proto_register_protocol_in_name_only("IPv6 Routing Type - Type 2", "Type 2", "ipv6.routing.type.mipv6", proto_ipv6, FT_BYTES); proto_ipv6_routing_rpl = proto_register_protocol_in_name_only("IPv6 Routing Type - RPL Source Route", "RPL Source Route", "ipv6.routing.type.mipv6", proto_ipv6, FT_BYTES); proto_ipv6_routing_srh = proto_register_protocol_in_name_only("IPv6 Routing Types - Segment Routing", "Segment Routing", "ipv6.routing.type.srh", proto_ipv6, FT_BYTES); + proto_ipv6_routing_crh = proto_register_protocol_in_name_only("IPv6 Routing Types - Compact Routing", "Compact Routing", "ipv6.routing.type.crh", proto_ipv6, FT_BYTES); proto_ipv6_fraghdr = proto_register_protocol("Fragment Header for IPv6", "IPv6 Fragment", "ipv6.fraghdr"); proto_register_field_array(proto_ipv6_fraghdr, hf_ipv6_fraghdr, array_length(hf_ipv6_fraghdr)); @@ -3712,6 +3821,9 @@ proto_reg_handoff_ipv6(void) dissector_add_uint("ipv6.routing.type", IPv6_RT_HEADER_RPL, h); h = create_dissector_handle(dissect_routing6_srh, proto_ipv6_routing_srh); dissector_add_uint("ipv6.routing.type", IPv6_RT_HEADER_SEGMENT_ROUTING, h); + h = create_dissector_handle(dissect_routing6_crh, proto_ipv6_routing_crh); + dissector_add_uint("ipv6.routing.type", IPv6_RT_HEADER_COMPACT_16, h); + dissector_add_uint("ipv6.routing.type", IPv6_RT_HEADER_COMPACT_32, h); } /* |