/* packet-icmpv6.c
* Routines for ICMPv6 packet disassembly
*
- * $Id: packet-icmpv6.c,v 1.74 2003/12/19 23:20:53 guy Exp $
+ * $Id: packet-icmpv6.c,v 1.78 2004/04/22 08:22:07 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
static int hf_icmpv6_code = -1;
static int hf_icmpv6_checksum = -1;
static int hf_icmpv6_checksum_bad = -1;
+static int hf_icmpv6_haad_ha_addrs = -1;
static gint ett_icmpv6 = -1;
static gint ett_icmpv6opt = -1;
case ND_OPT_SOURCE_LINKADDR:
case ND_OPT_TARGET_LINKADDR:
{
- char *t;
int len, i, p;
+ const guint8 *a;
+ char *t;
+
+ p = offset + sizeof(*opt);
len = (opt->nd_opt_len << 3) - sizeof(*opt);
+ a = tvb_get_ptr(tvb, p, len);
t = g_malloc(len * 3);
memset(t, 0, len * 3);
- p = offset + sizeof(*opt);
for (i = 0; i < len; i++) {
if (i)
t[i * 3 - 1] = ':';
- sprintf(&t[i * 3], "%02x", tvb_get_guint8(tvb, p + i) & 0xff);
+ sprintf(&t[i * 3], "%02x", a[i]);
}
proto_tree_add_text(icmp6opt_tree, tvb,
offset + sizeof(*opt), len, "Link-layer address: %s", t);
*/
static const char *
-bitrange0(v, s, buf, buflen)
- guint32 v;
- int s;
- char *buf;
- int buflen;
+bitrange0(guint32 v, int s, char *buf, int buflen)
{
guint32 v0;
char *p, *ep;
}
/*
- * See I-D draft-vida-mld-v2-03
+ * See I-D draft-vida-mld-v2-08
*/
static const value_string mldrv2ModesNames[] = {
{ 1, "Include" },
}
}
+static void
+dissect_mldqv2(tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree)
+{
+ struct e_in6_addr addr;
+
+ for ( ; count; count--, offset += 16) {
+ tvb_memcpy(tvb, (guint8 *)&addr, offset, sizeof(addr));
+ proto_tree_add_text(tree, tvb, offset, 16,
+ "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr));
+ }
+}
+
static void
dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
case ICMP6_MEMBERSHIP_QUERY:
case ICMP6_MEMBERSHIP_REPORT:
case ICMP6_MEMBERSHIP_REDUCTION:
+#define MLDV2_MINLEN 28
+#define MLDV1_MINLEN 24
+ if (dp->icmp6_type == ICMP6_MEMBERSHIP_QUERY) {
+ if (length >= MLDV2_MINLEN) {
+ guint32 mrc;
+ guint16 qqi;
+ guint8 flag;
+ guint16 nsrcs;
+
+ mrc = g_ntohs(dp->icmp6_maxdelay);
+ flag = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16);
+ qqi = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16 + 1);
+ nsrcs = tvb_get_ntohs(tvb, offset + sizeof(*dp) + 16 + 2);
+
+ if (mrc >= 32768)
+ mrc = ((mrc & 0x0fff) | 0x1000) <<
+ (((mrc & 0x7000) >> 12) + 3);
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_maxdelay), 2,
+ "Maximum response delay[ms]: %u", mrc);
+
+ proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp),
+ 16, "Multicast Address: %s",
+ ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb,
+ offset + sizeof *dp, sizeof (struct e_in6_addr)))));
+
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + sizeof(*dp) + 16, 1, "S Flag: %s",
+ flag & 0x08 ? "ON" : "OFF");
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + sizeof(*dp) + 16, 1, "Robustness: %d",
+ flag & 0x07);
+ if (qqi >= 128)
+ qqi = ((qqi & 0x0f) | 0x10) << (((qqi & 0x70) >> 4) + 3);
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + sizeof(*dp) + 17, 1, "QQI: %d", qqi);
+
+ dissect_mldqv2(tvb, offset + sizeof(*dp) + 20, nsrcs,
+ icmp6_tree);
+ break;
+ } else if (length > MLDV1_MINLEN) {
+ next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+ /* MLDv1 Query -> FALLTHOUGH */
+ }
+#undef MLDV2_MINLEN
+#undef MLDV1_MINLEN
proto_tree_add_text(icmp6_tree, tvb,
offset + offsetof(struct icmp6_hdr, icmp6_maxdelay), 2,
"Maximum response delay: %u",
proto_tree_add_text(icmp6_tree, tvb,
offset + 6, 2, "Reserved: %d",
tvb_get_ntohs(tvb, offset + 6));
- /* TODO Show all Home Agent Addresses */
+ /* Show all Home Agent Addresses */
+ {
+ int i, suboffset;
+ int ha_num = (length - 8)/16;
+
+ for (i = 0; i < ha_num; i++) {
+ suboffset = 16 * i;
+ proto_tree_add_ipv6(icmp6_tree, hf_icmpv6_haad_ha_addrs,
+ tvb, offset + 8 + suboffset, 16,
+ tvb_get_ptr(tvb, offset + 8 + suboffset, 16));
+ }
+ }
break;
case ICMP6_MIP6_MPS:
proto_tree_add_text(icmp6_tree, tvb,
tvb_get_ntohs(tvb, offset + 4),
tvb_get_ntohs(tvb, offset + 4));
proto_tree_add_text(icmp6_tree, tvb,
- offset + 6, 2,
+ offset + 6, 1,
decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
- 0x8000, 16,
+ 0x80, 8,
"Managed Address Configuration",
"No Managed Address Configuration"));
proto_tree_add_text(icmp6_tree, tvb,
- offset + 6, 2,
+ offset + 6, 1,
decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
- 0x4000, 16,
+ 0x40, 8,
"Other Stateful Configuration",
"No Other Stateful Configuration"));
- /* TODO Show all options */
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 7, 1, "Reserved: %d",
+ tvb_get_guint8(tvb, offset + 7));
+ /* Show all options */
+ dissect_icmpv6opt(tvb, offset + 8, pinfo, icmp6_tree);
break;
default:
next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
{ &hf_icmpv6_checksum_bad,
{ "Bad Checksum", "icmpv6.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"", HFILL }},
+ { &hf_icmpv6_haad_ha_addrs,
+ { "Home Agent Addresses", "icmpv6.haad.ha_addrs",
+ FT_IPv6, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
};
static gint *ett[] = {
&ett_icmpv6,