Show the address space of IPv6 addresses

This commit is contained in:
David Perry 2022-11-15 16:38:30 +00:00 committed by João Valverde
parent 6b41ad918b
commit 99d3112464
1 changed files with 133 additions and 8 deletions

View File

@ -160,6 +160,7 @@ static int hf_ipv6_plen = -1;
static int hf_ipv6_nxt = -1;
static int hf_ipv6_hlim = -1;
static int hf_ipv6_src = -1;
static int hf_ipv6_src_addr_space = -1;
static int hf_ipv6_src_host = -1;
static int hf_ipv6_src_slaac_mac = -1;
static int hf_ipv6_src_isatap_ipv4 = -1;
@ -170,6 +171,7 @@ static int hf_ipv6_src_teredo_port = -1;
static int hf_ipv6_src_teredo_client_ipv4 = -1;
static int hf_ipv6_src_embed_ipv4 = -1;
static int hf_ipv6_dst = -1;
static int hf_ipv6_dst_addr_space = -1;
static int hf_ipv6_dst_host = -1;
static int hf_ipv6_dst_slaac_mac = -1;
static int hf_ipv6_dst_isatap_ipv4 = -1;
@ -180,6 +182,7 @@ static int hf_ipv6_dst_teredo_port = -1;
static int hf_ipv6_dst_teredo_client_ipv4 = -1;
static int hf_ipv6_dst_embed_ipv4 = -1;
static int hf_ipv6_addr = -1;
static int hf_ipv6_addr_space = -1;
static int hf_ipv6_host = -1;
static int hf_ipv6_slaac_mac = -1;
static int hf_ipv6_isatap_ipv4 = -1;
@ -359,6 +362,23 @@ 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;
struct ipv6_addr_info_s {
int *hf_addr;
int *hf_addr_space;
int *hf_host;
};
static struct ipv6_addr_info_s ipv6_src_info = {
&hf_ipv6_src,
&hf_ipv6_src_addr_space,
&hf_ipv6_src_host,
};
static struct ipv6_addr_info_s ipv6_dst_info = {
&hf_ipv6_dst,
&hf_ipv6_dst_addr_space,
&hf_ipv6_dst_host,
};
static int hf_geoip_country = -1;
static int hf_geoip_country_iso = -1;
static int hf_geoip_city = -1;
@ -384,6 +404,7 @@ static int hf_geoip_dst_latitude = -1;
static int hf_geoip_dst_longitude = -1;
static gint ett_ipv6_proto = -1;
static gint ett_ipv6_detail = -1;
static gint ett_ipv6_traffic_class = -1;
static gint ett_ipv6_opt = -1;
static gint ett_ipv6_opt_type = -1;
@ -405,6 +426,8 @@ static gint ett_geoip_info = -1;
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_routing_undecoded = EI_INIT;
static expert_field ei_ipv6_dst_addr_not_unspecified = EI_INIT;
static expert_field ei_ipv6_src_addr_not_multicast = 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;
@ -701,6 +724,9 @@ static gboolean ipv6_reassemble = TRUE;
/* Place IPv6 summary in proto tree */
static gboolean ipv6_summary_in_tree = TRUE;
/* Show expanded information about IPv6 address */
static gboolean ipv6_address_detail = FALSE;
/* Look up addresses via mmdbresolve */
static gboolean ipv6_use_geoip = TRUE;
@ -2777,22 +2803,93 @@ ipv6_get_jumbo_plen(tvbuff_t *tvb, gint offset)
return 0;
}
static void
add_ipv6_address_detail(packet_info *pinfo, proto_item *vis, proto_item *invis,
tvbuff_t *tvb, int offset, struct ipv6_addr_info_s *addr_info)
{
proto_item *ti;
proto_tree *vtree; /* visible tree */
proto_tree *itree; /* invisible tree */
const guint8 unspecified[IPv6_ADDR_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
const guint8 loopback[IPv6_ADDR_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
vtree = proto_item_add_subtree(vis, ett_ipv6_detail);
itree = proto_item_add_subtree(invis, ett_ipv6_detail);
if (tvb_memeql(tvb, offset, unspecified, IPv6_ADDR_SIZE) == 0) {
/* RFC 4291 section 2.4: unspecified address */
ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, IPv6_ADDR_SIZE, "Unspecified");
proto_item_set_generated(ti);
if (addr_info == &ipv6_dst_info) {
/* "Shouldn't" see this one as a destination */
expert_add_info(pinfo, ti, &ei_ipv6_dst_addr_not_unspecified);
}
ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, IPv6_ADDR_SIZE, "Unspecified");
proto_item_set_generated(ti);
}
else if (tvb_memeql(tvb, offset, loopback, IPv6_ADDR_SIZE) == 0) {
/* RFC 4291 section 2.4: loopback address */
ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, IPv6_ADDR_SIZE, "Loopback");
proto_item_set_generated(ti);
ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, IPv6_ADDR_SIZE, "Loopback");
proto_item_set_generated(ti);
}
else if (tvb_get_guint8(tvb, offset) == 0xFF) {
/* RFC 4291 section 2.4: multicast prefix */
ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 1, "Multicast");
proto_item_set_generated(ti);
if (addr_info == &ipv6_src_info) {
/* "Shouldn't" see this one as a source */
expert_add_info(pinfo, ti, &ei_ipv6_src_addr_not_multicast);
}
ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 1, "Multicast");
proto_item_set_generated(ti);
}
else if ((tvb_get_ntohs(tvb, offset) & 0xFFC0) == 0xFE80) {
/* RFC 4291 section 2.4: Link-local unicast */
ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 2, "Link-Local Unicast");
proto_item_set_generated(ti);
ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 2, "Link-Local Unicast");
proto_item_set_generated(ti);
}
else if ((tvb_get_guint8(tvb, offset) & 0x30) == 0x20) {
/* RFC 4291 section 2.4: Global unicast */
ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 2, "Global Unicast");
proto_item_set_generated(ti);
ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 2, "Global Unicast");
proto_item_set_generated(ti);
}
else {
/* Technically anything else is also global unicast, but... */
ti = proto_tree_add_string(vtree, *addr_info->hf_addr_space, tvb, offset, 2, "Reserved by IETF");
proto_item_set_generated(ti);
ti = proto_tree_add_string(itree, hf_ipv6_addr_space, tvb, offset, 2, "Reserved by IETF");
proto_item_set_generated(ti);
}
}
static void
add_ipv6_address(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset,
gint hf_addr, gint hf_host)
struct ipv6_addr_info_s *addr_info)
{
address addr;
const char *name;
proto_item *ti;
proto_item *ti, *vis, *invis;
proto_tree_add_item(tree, hf_addr, tvb, offset, IPv6_ADDR_SIZE, ENC_NA);
ti = proto_tree_add_item(tree, hf_ipv6_addr, tvb, offset, IPv6_ADDR_SIZE, ENC_NA);
proto_item_set_hidden(ti);
vis = proto_tree_add_item(tree, *addr_info->hf_addr, tvb, offset, IPv6_ADDR_SIZE, ENC_NA);
invis = proto_tree_add_item(tree, hf_ipv6_addr, tvb, offset, IPv6_ADDR_SIZE, ENC_NA);
proto_item_set_hidden(invis);
set_address_ipv6_tvb(&addr, tvb, offset);
name = address_to_display(pinfo->pool, &addr);
ti = proto_tree_add_string(tree, hf_host, tvb, offset, IPv6_ADDR_SIZE, name);
if (ipv6_address_detail) {
add_ipv6_address_detail(pinfo, vis, invis, tvb, offset, addr_info);
}
ti = proto_tree_add_string(tree, *addr_info->hf_host, tvb, offset, IPv6_ADDR_SIZE, name);
proto_item_set_generated(ti);
proto_item_set_hidden(ti);
ti = proto_tree_add_string(tree, hf_ipv6_host, tvb, offset, IPv6_ADDR_SIZE, name);
@ -3129,13 +3226,13 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
ip6_hlim = tvb_get_guint8(tvb, offset + IP6H_CTL_HLIM);
/* Source address */
add_ipv6_address(pinfo, ipv6_tree, tvb, offset + IP6H_SRC, hf_ipv6_src, hf_ipv6_src_host);
add_ipv6_address(pinfo, ipv6_tree, tvb, offset + IP6H_SRC, &ipv6_src_info);
ip6_src = tvb_get_ptr_ipv6(tvb, offset + IP6H_SRC);
alloc_address_wmem_ipv6(pinfo->pool, &pinfo->net_src, ip6_src);
copy_address_shallow(&pinfo->src, &pinfo->net_src);
/* Destination address */
add_ipv6_address(pinfo, ipv6_tree, tvb, offset + IP6H_DST, hf_ipv6_dst, hf_ipv6_dst_host);
add_ipv6_address(pinfo, ipv6_tree, tvb, offset + IP6H_DST, &ipv6_dst_info);
ip6_dst = tvb_get_ptr_ipv6(tvb, offset + IP6H_DST);
alloc_address_wmem_ipv6(pinfo->pool, &pinfo->net_dst, ip6_dst);
copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
@ -3347,6 +3444,11 @@ proto_register_ipv6(void)
FT_IPv6, BASE_NONE, NULL, 0x0,
"Source IPv6 Address", HFILL }
},
{ &hf_ipv6_src_addr_space,
{ "Source Address Space", "ipv6.src_addr_space",
FT_STRING, BASE_NONE, NULL, 0x0,
"Source IPv6 Address Space", HFILL }
},
{ &hf_ipv6_src_host,
{ "Source Host", "ipv6.src_host",
FT_STRING, BASE_NONE, NULL, 0x0,
@ -3397,6 +3499,11 @@ proto_register_ipv6(void)
FT_IPv6, BASE_NONE, NULL, 0x0,
"Destination IPv6 Address", HFILL }
},
{ &hf_ipv6_dst_addr_space,
{ "Destination Address Space", "ipv6.dst_addr_space",
FT_STRING, BASE_NONE, NULL, 0x0,
"Destination IPv6 Address Space", HFILL }
},
{ &hf_ipv6_dst_host,
{ "Destination Host", "ipv6.dst_host",
FT_STRING, BASE_NONE, NULL, 0x0,
@ -3447,6 +3554,11 @@ proto_register_ipv6(void)
FT_IPv6, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_ipv6_addr_space,
{ "Source or Destination Address Space", "ipv6.addr_space",
FT_STRING, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_ipv6_host,
{ "Source or Destination Host", "ipv6.host",
FT_STRING, BASE_NONE, NULL, 0x0,
@ -4456,6 +4568,7 @@ proto_register_ipv6(void)
static gint *ett_ipv6[] = {
&ett_ipv6_proto,
&ett_ipv6_detail,
&ett_ipv6_traffic_class,
&ett_geoip_info,
&ett_ipv6_opt,
@ -4554,6 +4667,10 @@ proto_register_ipv6(void)
{ &ei_ipv6_embed_ipv4_u_value,
{ "ipv6.embed_ipv4.u.nonzero", PI_PROTOCOL, PI_WARN,
"IPv4-Embedded IPv6 address bit 64 to 71 must be zero", EXPFILL }
},
{ &ei_ipv6_dst_addr_not_unspecified,
{ "ipv6.addr.not_unspecified", PI_PROTOCOL, PI_WARN,
"Unspecified address cannot appear as a destination", EXPFILL }
}
};
@ -4565,6 +4682,10 @@ proto_register_ipv6(void)
};
static ei_register_info ei_ipv6_routing[] = {
{ &ei_ipv6_src_addr_not_multicast,
{ "ipv6.src_addr.not_multicast", PI_PROTOCOL, PI_WARN,
"Source address must not be a multicast address", EXPFILL }
},
{ &ei_ipv6_dst_addr_not_multicast,
{ "ipv6.dst_addr.not_multicast", PI_PROTOCOL, PI_WARN,
"Destination address must not be a multicast address", EXPFILL }
@ -4684,6 +4805,10 @@ proto_register_ipv6(void)
"Show IPv6 summary in protocol tree",
"Whether the IPv6 summary line should be shown in the protocol tree",
&ipv6_summary_in_tree);
prefs_register_bool_preference(ipv6_module, "address_detail" ,
"Show details about IPv6 addresses",
"Whether to show extended information about IPv6 addresses",
&ipv6_address_detail);
prefs_register_bool_preference(ipv6_module, "use_geoip" ,
"Enable IPv6 geolocation",
"Whether to look up IPv6 addresses in each MaxMind database we have loaded",