/* packet-icmpv6.c
* Routines for ICMPv6 packet disassembly
*
- * $Id: packet-icmpv6.c,v 1.43 2001/05/27 04:14:53 guy Exp $
+ * $Id: packet-icmpv6.c,v 1.65 2002/01/30 22:58:54 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
*
* MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@siemens.hr>
*
+ * HMIPv6 support added by Martti Kuparinen <martti.kuparinen@iki.fi>
+ *
* 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
# include "snprintf.h"
#endif
-#include "packet.h"
+#include <epan/packet.h>
#include "packet-ipv6.h"
#include "packet-dns.h"
#include "in_cksum.h"
-#include "resolv.h"
+#include <epan/resolv.h>
#include "ipproto.h"
#ifndef offsetof
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
#endif
+/*
+ * See, under http://www.ietf.org/internet-drafts/
+ *
+ * draft-ietf-mobileip-ipv6-15.txt
+ *
+ * and
+ *
+ * draft-ietf-ipngwg-icmp-name-lookups-08.txt
+ *
+ * and
+ *
+ * draft-ietf-mobileip-hmipv6-05.txt
+ */
+
static int proto_icmpv6 = -1;
static int hf_icmpv6_type = -1;
static int hf_icmpv6_code = -1;
static gint ett_nodeinfo_nodedns = -1;
static dissector_handle_t ipv6_handle;
+static dissector_handle_t data_handle;
static const value_string names_nodeinfo_qtype[] = {
{ NI_QTYPE_NOOP, "NOOP" },
{ 0, NULL }
};
+static const value_string names_router_pref[] = {
+ { ND_RA_FLAG_RTPREF_HIGH, "High" },
+ { ND_RA_FLAG_RTPREF_MEDIUM, "Medium" },
+ { ND_RA_FLAG_RTPREF_LOW, "Low" },
+ { ND_RA_FLAG_RTPREF_RSV, "Reserved" },
+};
+
static void
dissect_contained_icmpv6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
tvbuff_t *next_tvb;
- address save_dl_src;
- address save_dl_dst;
- address save_net_src;
- address save_net_dst;
- address save_src;
- address save_dst;
+ volatile address save_dl_src;
+ volatile address save_dl_dst;
+ volatile address save_net_src;
+ volatile address save_net_dst;
+ volatile address save_src;
+ volatile address save_dst;
+ gboolean save_in_error_pkt;
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
Set the columns non-writable, so that the packet list
shows this as an ICMPv6 packet, not as the type of packet
for which the ICMPv6 packet was generated. */
- col_set_writable(pinfo->fd, FALSE);
+ col_set_writable(pinfo->cinfo, FALSE);
/* Also, save the current values of the addresses, and restore
them when we're finished dissecting the contained packet, so
save_src = pinfo->src;
save_dst = pinfo->dst;
- /* Dissect the contained packet. */
- call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+ /* Save the current value of the "we're inside an error packet"
+ flag, and set that flag; subdissectors may treat packets
+ that are the payload of error packets differently from
+ "real" packets. */
+ save_in_error_pkt = pinfo->in_error_pkt;
+ pinfo->in_error_pkt = TRUE;
+
+ /* Dissect the contained packet.
+ Catch ReportedBoundsError, and do nothing if we see it,
+ because it's not an error if the contained packet is short;
+ there's no guarantee that all of it was included.
+
+ XXX - should catch BoundsError, and re-throw it after cleaning
+ up. */
+ TRY {
+ call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+ }
+ CATCH(ReportedBoundsError) {
+ ; /* do nothing */
+ }
+ ENDTRY;
+
+ /* Restore the "we're inside an error packet" flag. */
+ pinfo->in_error_pkt = save_in_error_pkt;
/* Restore the addresses. */
pinfo->dl_src = save_dl_src;
pinfo->src = save_src;
pinfo->dst = save_dst;
} else
- dissect_data(next_tvb, 0, pinfo, tree);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
}
static void
dissect_icmpv6opt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
proto_tree *icmp6opt_tree, *field_tree;
- proto_item *ti, *tf;
+ proto_item *ti, *tf;
struct nd_opt_hdr nd_opt_hdr, *opt;
int len;
char *typename;
again:
if ((int)tvb_reported_length(tvb) <= offset)
- return; /* No more options left */
+ return; /* No more options left */
opt = &nd_opt_hdr;
tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
ti = proto_tree_add_text(tree, tvb, offset, len, "ICMPv6 options");
icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
+ if (len == 0) {
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
+ "Invalid option length: %u",
+ opt->nd_opt_len);
+ return; /* we must not try to decode this */
+ }
+
switch (opt->nd_opt_type) {
case ND_OPT_SOURCE_LINKADDR:
typename = "Source link-layer address";
case ND_OPT_MTU:
typename = "MTU";
break;
- case ND_OPT_ADVERTISEMENT_INTERVAL:
+ case ND_OPT_ADVINTERVAL:
typename = "Advertisement Interval";
break;
- case ND_OPT_HOME_AGENT_INFORMATION:
+ case ND_OPT_HOMEAGENT_INFO:
typename = "Home Agent Information";
break;
+ case ND_OPT_MAP:
+ typename = "HMIPv6 MAP option";
+ break;
default:
-
typename = "Unknown";
break;
}
}
proto_tree_add_text(icmp6opt_tree, tvb,
offset + sizeof(*opt), len, "Link-layer address: %s", t);
+ free(t);
break;
}
case ND_OPT_PREFIX_INFORMATION:
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
- 0x80, 8, "Onlink", "Not onlink"));
+ ND_OPT_PI_FLAG_ONLINK, 8, "Onlink", "Not onlink"));
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
- 0x40, 8, "Auto", "Not auto"));
- /* BT INSERT BEGIN */
+ ND_OPT_PI_FLAG_AUTO, 8, "Auto", "Not auto"));
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
- 0x20, 8, "Router Address", "Not router address"));
- /* BT INSERT END */
+ ND_OPT_PI_FLAG_ROUTER, 8,
+ "Router Address", "Not router address"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
+ ND_OPT_PI_FLAG_SITEPREF, 8,
+ "Site prefix", "Not site prefix"));
proto_tree_add_text(icmp6opt_tree, tvb,
offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
4, "Valid lifetime: 0x%08x",
offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu), 4,
"MTU: %u", tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu)));
break;
- /* BT INSERT BEGIN */
- case ND_OPT_ADVERTISEMENT_INTERVAL:
+ case ND_OPT_ADVINTERVAL:
proto_tree_add_text(icmp6opt_tree, tvb,
offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint), 4,
- "Advertisement Interval: %d",
+ "Advertisement Interval: %u",
tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint)));
break;
- case ND_OPT_HOME_AGENT_INFORMATION:
+ case ND_OPT_HOMEAGENT_INFO:
{
- struct nd_opt_ha_info *pi = (struct nd_opt_ha_info *)opt;
+ struct nd_opt_ha_info pibuf, *pi;
+
+ pi = &pibuf;
+ tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
proto_tree_add_text(icmp6opt_tree, tvb,
offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_pref),
2, "Home Agent Preference: %d",
- pntohs(&pi->nd_opt_ha_info_ha_pref));
+ (gint16)pntohs(&pi->nd_opt_ha_info_ha_pref));
proto_tree_add_text(icmp6opt_tree, tvb,
offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_life),
- 2, "Home Agent Lifetime: %d",
+ 2, "Home Agent Lifetime: %u",
pntohs(&pi->nd_opt_ha_info_ha_life));
break;
}
- /* BT INSERT END */
- }
+ case ND_OPT_MAP:
+ {
+ struct nd_opt_map_info mapbuf, *map;
+ int flagoff;
- if (opt->nd_opt_len == 0) {
- proto_tree_add_text(icmp6opt_tree, tvb,
- offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
- "Invalid option length: %u",
- opt->nd_opt_len);
- return;
+ map = &mapbuf;
+ tvb_memcpy(tvb, (guint8 *)map, offset, sizeof *map);
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
+ 1, "Distance: %u", (map->nd_opt_map_dist_and_pref >> 4));
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
+ 1, "Preference: %u", (map->nd_opt_map_dist_and_pref & 0x0F));
+ flagoff = offset + offsetof(struct nd_opt_map_info,
+ nd_opt_map_flags);
+ tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1,
+ "Flags: 0x%02x",
+ tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_map_info,
+ nd_opt_map_flags)));
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_R, 8, "R", "No R"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_M, 8, "M", "No M"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_I, 8, "I", "No I"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_T, 8, "T", "No T"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_P, 8, "P", "No P"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_V, 8, "V", "No V"));
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_map_info, nd_opt_map_lifetime),
+ 4, "Lifetime: %u", pntohl(&map->nd_opt_map_lifetime));
+
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_map_info, nd_opt_map_address), 16,
+#ifdef INET6
+ "Address of MAP: %s (%s)",
+ get_hostname6(&map->nd_opt_map_address),
+#else
+ "Address of MAP: %s",
+#endif
+ ip6_to_str(&map->nd_opt_map_address));
+ break;
+ }
+ case ND_OPT_ROUTE_INFO:
+ {
+ struct nd_opt_route_info ribuf, *ri;
+ struct e_in6_addr in6;
+ int l;
+ guint32 lifetime;
+
+ ri = &ribuf;
+ tvb_memcpy(tvb, (guint8 *)ri, offset, sizeof *ri);
+ memset(&in6, 0, sizeof(in6));
+ switch (ri->nd_opt_rti_len) {
+ case 1:
+ l = 0;
+ break;
+ case 2:
+ tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 8);
+ break;
+ case 3:
+ tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 16);
+ break;
+ default:
+ l = -1;
+ break;
+ }
+ if (l >= 0) {
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_prefixlen),
+ 1, "Prefix length: %u", ri->nd_opt_rti_prefixlen);
+ tf = proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
+ 1, "Flags: 0x%02x", ri->nd_opt_rti_flags);
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
+ 1, "%s",
+ decode_enumerated_bitfield(ri->nd_opt_rti_flags,
+ ND_RA_FLAG_RTPREF_MASK, 8, names_router_pref,
+ "Router preference: %s"));
+ lifetime = pntohl(&ri->nd_opt_rti_lifetime);
+ if (lifetime == 0xffffffff)
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
+ sizeof(ri->nd_opt_rti_lifetime), "Lifetime: infinity");
+ else
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
+ sizeof(ri->nd_opt_rti_lifetime), "Lifetime: %u", lifetime);
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + sizeof(*ri), l, "Prefix: %s", ip6_to_str(&in6));
+ } else {
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
+ "Invalid option length: %u", opt->nd_opt_len);
+ }
+ break;
+ }
}
offset += (opt->nd_opt_len << 3);
l = snprintf(p, ep - p, ",%d-%d", s + off,
s + off + i - 1);
}
- if (l > ep - p) {
+ if (l == -1 || l > ep - p) {
buf[0] = '\0';
return NULL;
}
guint16 flags;
char dname[MAXDNAME];
guint8 ipaddr[4];
- const u_char *pd;
- int top_level_offset;
ni = &icmp6_nodeinfo;
tvb_memcpy(tvb, (guint8 *)ni, offset, sizeof *ni);
if (ni->ni_type == ICMP6_NI_QUERY) {
switch (ni->ni_code) {
case ICMP6_NI_SUBJ_IPV6:
- n = tvb_length_remaining(tvb, offset + sizeof(*ni));
+ n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
n /= sizeof(struct e_in6_addr);
tf = proto_tree_add_text(tree, tvb,
- offset + sizeof(*ni), tvb_length_remaining(tvb, offset), "IPv6 subject addresses");
+ offset + sizeof(*ni), -1, "IPv6 subject addresses");
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject6);
p = offset + sizeof *ni;
for (i = 0; i < n; i++) {
off = tvb_length_remaining(tvb, offset);
break;
case ICMP6_NI_SUBJ_FQDN:
- /* XXXX - clean this up when packet-dns.c has been tvbuffified */
- tvb_compat(tvb, &pd, &top_level_offset);
- l = get_dns_name(pd, top_level_offset + offset + sizeof(*ni),
- top_level_offset + offset + sizeof(*ni),
- dname, sizeof(dname));
+ l = get_dns_name(tvb, offset + sizeof(*ni),
+ offset + sizeof(*ni), dname, sizeof(dname));
if (tvb_bytes_exist(tvb, offset + sizeof(*ni) + l, 1) &&
tvb_get_guint8(tvb, offset + sizeof(*ni) + l) == 0) {
l++;
off = tvb_length_remaining(tvb, offset + sizeof(*ni) + l);
break;
case ICMP6_NI_SUBJ_IPV4:
- n = tvb_length_remaining(tvb, offset + sizeof(*ni));
+ n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
n /= sizeof(guint32);
tf = proto_tree_add_text(tree, tvb,
- offset + sizeof(*ni), tvb_length_remaining(tvb, offset), "IPv4 subject addresses");
+ offset + sizeof(*ni), -1, "IPv4 subject addresses");
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject4);
p = offset + sizeof *ni;
for (i = 0; i < n; i++) {
case NI_QTYPE_SUPTYPES:
p = offset + sizeof *ni;
tf = proto_tree_add_text(tree, tvb,
- offset + sizeof(*ni), tvb_length_remaining(tvb, p),
+ offset + sizeof(*ni), -1,
"Supported type bitmap%s",
(flags & 0x0001) ? ", compressed" : "");
field_tree = proto_item_add_subtree(tf,
n = 0;
while (tvb_bytes_exist(tvb, p, sizeof(guint32))) { /* XXXX Check what? */
if ((flags & 0x0001) == 0) {
- l = tvb_length_remaining(tvb, offset + sizeof(*ni));
+ l = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
l /= sizeof(guint32);
i = 0;
} else {
proto_tree_add_text(tree, tvb, offset + sizeof(*ni),
sizeof(gint32), "TTL: %d", (gint32)tvb_get_ntohl(tvb, offset + sizeof *ni));
tf = proto_tree_add_text(tree, tvb,
- offset + sizeof(*ni) + sizeof(guint32),
- tvb_length_remaining(tvb, offset),
+ offset + sizeof(*ni) + sizeof(guint32), -1,
"DNS labels");
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_nodedns);
- /* XXXX - clean this up when packet-dns.c has been tvbuffified */
- tvb_compat(tvb, &pd, &top_level_offset);
j = offset + sizeof (*ni) + sizeof(guint32);
- while (j < tvb_length(tvb)) {
- l = get_dns_name(pd, top_level_offset + j,
- top_level_offset + offset + sizeof (*ni) + sizeof(guint32),
+ while (j < tvb_reported_length(tvb)) {
+ l = get_dns_name(tvb, j,
+ offset + sizeof (*ni) + sizeof(guint32),
dname,sizeof(dname));
- if (tvb_bytes_exist(tvb, top_level_offset + j + l, 1) &&
- tvb_get_guint8(tvb, top_level_offset + j + l) == 0) {
+ if (tvb_bytes_exist(tvb, j + l, 1) &&
+ tvb_get_guint8(tvb, j + l) == 0) {
l++;
proto_tree_add_text(field_tree, tvb, j, l,
"DNS label: %s (truncated)", dname);
off = tvb_length_remaining(tvb, offset);
break;
case NI_QTYPE_NODEADDR:
- n = tvb_length_remaining(tvb, offset + sizeof(*ni));
+ n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
n /= sizeof(gint32) + sizeof(struct e_in6_addr);
tf = proto_tree_add_text(tree, tvb,
- offset + sizeof(*ni), tvb_length_remaining(tvb, offset), "IPv6 node addresses");
+ offset + sizeof(*ni), -1, "IPv6 node addresses");
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node6);
p = offset + sizeof (*ni);
for (i = 0; i < n; i++) {
off = tvb_length_remaining(tvb, offset);
break;
case NI_QTYPE_IPV4ADDR:
- n = tvb_length_remaining(tvb, offset + sizeof(*ni));
+ n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
n /= sizeof(gint32) + sizeof(guint32);
tf = proto_tree_add_text(tree, tvb,
- offset + sizeof(*ni), tvb_length_remaining(tvb, offset), "IPv4 node addresses");
+ offset + sizeof(*ni), -1, "IPv4 node addresses");
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node4);
p = offset + sizeof *ni;
for (i = 0; i < n; i++) {
nodata:;
/* the rest of data */
- dissect_data(tvb_new_subset(tvb, offset + off, -1, -1), 0, pinfo, tree);
+ call_dissector(data_handle,tvb_new_subset(tvb, offset + off, -1, -1), pinfo, tree);
}
static void
proto_tree_add_text(tree, tvb,
offset + offsetof(struct icmp6_router_renum, rr_maxdelay), 2,
"Max delay: 0x%04x", pntohs(&rr->rr_maxdelay));
- dissect_data(tvb_new_subset(tvb, offset + sizeof(*rr), -1, -1), 0, pinfo, tree); /*XXX*/
+ call_dissector(data_handle,tvb_new_subset(tvb, offset + sizeof(*rr), -1, -1), pinfo, tree); /*XXX*/
if (rr->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) {
off = offset + sizeof(*rr);
int offset;
tvbuff_t *next_tvb;
- if (check_col(pinfo->fd, COL_PROTOCOL))
- col_set_str(pinfo->fd, COL_PROTOCOL, "ICMPv6");
- if (check_col(pinfo->fd, COL_INFO))
- col_clear(pinfo->fd, COL_INFO);
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMPv6");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
offset = 0;
tvb_memcpy(tvb, (guint8 *)&icmp6_hdr, offset, sizeof icmp6_hdr);
break;
}
- if (check_col(pinfo->fd, COL_INFO)) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
char typebuf[256], codebuf[256];
if (coltypename && strcmp(coltypename, "Unknown") == 0) {
colcodename = codebuf;
}
if (colcodename) {
- col_add_fstr(pinfo->fd, COL_INFO, "%s (%s)", coltypename, colcodename);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%s)", coltypename, colcodename);
} else {
- col_add_fstr(pinfo->fd, COL_INFO, "%s", coltypename);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", coltypename);
}
}
offset + offsetof(struct icmp6_hdr, icmp6_seq), 2,
"Sequence: 0x%04x", (guint16)ntohs(dp->icmp6_seq));
next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
- dissect_data(next_tvb, 0, pinfo, icmp6_tree);
+ call_dissector(data_handle,next_tvb, pinfo, icmp6_tree);
break;
case ICMP6_MEMBERSHIP_QUERY:
case ICMP6_MEMBERSHIP_REPORT:
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
decode_boolean_bitfield(ra_flags,
- 0x80, 8, "Managed", "Not managed"));
+ ND_RA_FLAG_MANAGED, 8, "Managed", "Not managed"));
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
decode_boolean_bitfield(ra_flags,
- 0x40, 8, "Other", "Not other"));
- /* BT INSERT BEGIN */
+ ND_RA_FLAG_OTHER, 8, "Other", "Not other"));
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
decode_boolean_bitfield(ra_flags,
- 0x20, 8, "Home Agent", "Not Home Agent"));
- /* BT INSERT END */
+ ND_RA_FLAG_HOME_AGENT, 8,
+ "Home Agent", "Not Home Agent"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_enumerated_bitfield(ra_flags, ND_RA_FLAG_RTPREF_MASK, 8,
+ names_router_pref, "Router preference: %s"));
proto_tree_add_text(icmp6_tree, tvb,
offset + offsetof(struct nd_router_advert, nd_ra_router_lifetime),
2, "Router lifetime: %u",
break;
default:
next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
- dissect_data(next_tvb, 0, pinfo, tree);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
break;
}
}
static hf_register_info hf[] = {
{ &hf_icmpv6_type,
{ "Type", "icmpv6.type", FT_UINT8, BASE_DEC, NULL, 0x0,
- "" }},
+ "", HFILL }},
{ &hf_icmpv6_code,
{ "Code", "icmpv6.code", FT_UINT8, BASE_DEC, NULL, 0x0,
- "" }},
+ "", HFILL }},
{ &hf_icmpv6_checksum,
{ "Checksum", "icmpv6.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
- "" }},
+ "", HFILL }},
{ &hf_icmpv6_checksum_bad,
{ "Bad Checksum", "icmpv6.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "" }},
+ "", HFILL }},
};
static gint *ett[] = {
&ett_icmpv6,
void
proto_reg_handoff_icmpv6(void)
{
- dissector_add("ip.proto", IP_PROTO_ICMPV6, dissect_icmpv6, proto_icmpv6);
+ dissector_handle_t icmpv6_handle;
+
+ icmpv6_handle = create_dissector_handle(dissect_icmpv6, proto_icmpv6);
+ dissector_add("ip.proto", IP_PROTO_ICMPV6, icmpv6_handle);
/*
* Get a handle for the IPv6 dissector.
*/
ipv6_handle = find_dissector("ipv6");
+ data_handle = find_dissector("data");
}