aboutsummaryrefslogtreecommitdiffstats
path: root/packet-icmpv6.c
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@itojun.org>2000-08-22 08:30:00 +0000
committerJun-ichiro itojun Hagino <itojun@itojun.org>2000-08-22 08:30:00 +0000
commit35a3dd5ab4b39f1b24475ad977d6486c88110796 (patch)
tree63f1c17838c1db4e6d4fe40e722a3379555d3869 /packet-icmpv6.c
parent52101799a77e0daa7e0ea5236e1d9802516a96e1 (diff)
more support for icmp6 node information query.
- DNS name decode (uses function in packet-dns.c) - supported bitmap svn path=/trunk/; revision=2338
Diffstat (limited to 'packet-icmpv6.c')
-rw-r--r--packet-icmpv6.c175
1 files changed, 167 insertions, 8 deletions
diff --git a/packet-icmpv6.c b/packet-icmpv6.c
index 651793c87a..f071a8867c 100644
--- a/packet-icmpv6.c
+++ b/packet-icmpv6.c
@@ -1,7 +1,7 @@
/* packet-icmpv6.c
* Routines for ICMPv6 packet disassembly
*
- * $Id: packet-icmpv6.c,v 1.22 2000/08/18 15:52:02 itojun Exp $
+ * $Id: packet-icmpv6.c,v 1.23 2000/08/22 08:30:00 itojun Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -53,6 +53,7 @@
#include "packet.h"
#include "packet-ipv6.h"
#include "packet-ip.h"
+#include "packet-dns.h"
#include "resolv.h"
#ifndef offsetof
@@ -72,6 +73,8 @@ static gint ett_nodeinfo_subject4 = -1;
static gint ett_nodeinfo_subject6 = -1;
static gint ett_nodeinfo_node4 = -1;
static gint ett_nodeinfo_node6 = -1;
+static gint ett_nodeinfo_nodebitmap = -1;
+static gint ett_nodeinfo_nodedns = -1;
static const value_string names_nodeinfo_qtype[] = {
{ NI_QTYPE_NOOP, "NOOP" },
@@ -213,6 +216,88 @@ again:
* draft-ietf-ipngwg-icmp-name-lookups-06.txt
* Note that the packet format was changed several times in the past.
*/
+
+static const char *
+bitrange0(v, s, buf, buflen)
+ u_int32_t v;
+ int s;
+ char *buf;
+ int buflen;
+{
+ u_int32_t v0;
+ char *p, *ep;
+ int off;
+ int i, l;
+
+ if (buflen < 1)
+ return NULL;
+ if (buflen == 1) {
+ buf[0] = '\0';
+ return NULL;
+ }
+
+ v0 = v;
+ p = buf;
+ ep = buf + buflen - 1;
+ memset(buf, 0, buflen);
+ off = 0;
+ while (off < 32) {
+ /* shift till we have 0x01 */
+ if ((v & 0x01) == 0) {
+ switch (v & 0x0f) {
+ case 0x00:
+ v >>= 4; off += 4; continue;
+ case 0x08:
+ v >>= 3; off += 3; continue;
+ case 0x04: case 0x0c:
+ v >>= 2; off += 2; continue;
+ default:
+ v >>= 1; off += 1; continue;
+ }
+ }
+
+ /* we have 0x01 with us */
+ for (i = 0; i < 32 - off; i++) {
+ if ((v & (0x01 << i)) == 0)
+ break;
+ }
+ if (i == 1)
+ l = snprintf(p, ep - p, ",%d", s + off);
+ else {
+ l = snprintf(p, ep - p, ",%d-%d", s + off,
+ s + off + i - 1);
+ }
+ if (l > ep - p) {
+ buf[0] = '\0';
+ return NULL;
+ }
+ v >>= i; off += i;
+ }
+
+ return buf;
+}
+
+static const char *
+bitrange(u_char *p, int l, int s)
+{
+ static char buf[1024];
+ char *q, *eq;
+ int i;
+
+ memset(buf, 0, sizeof(buf));
+ q = buf;
+ eq = buf + sizeof(buf) - 1;
+ for (i = 0; i < l; i++) {
+ if (bitrange0(pntohl(p + i * 4), s + i * 4, q, eq - q) == NULL) {
+ if (q != buf && q + 5 < buf + sizeof(buf))
+ strncpy(q, ",...", 5);
+ return buf;
+ }
+ }
+
+ return buf + 1;
+}
+
static void
dissect_nodeinfo(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
{
@@ -220,9 +305,10 @@ dissect_nodeinfo(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
proto_item *tf;
struct icmp6_nodeinfo *ni;
int off;
- int i, n;
+ int i, n, l;
guint16 flags;
u_char *p;
+ char dname[MAXDNAME];
ni = (struct icmp6_nodeinfo *)&pd[offset];
@@ -308,6 +394,9 @@ dissect_nodeinfo(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
/* offset for "the rest of data" */
off = sizeof(*ni);
+ /* rest of data */
+ if (!IS_DATA_IN_FRAME(offset + sizeof(*ni)))
+ goto nodata;
if (ni->ni_type == ICMP6_NI_QUERY) {
switch (ni->ni_code) {
case ICMP6_NI_SUBJ_IPV6:
@@ -326,10 +415,18 @@ dissect_nodeinfo(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
off = pi.captured_len - offset;
break;
case ICMP6_NI_SUBJ_FQDN:
- tf = proto_tree_add_text(tree, NullTVB,
- offset + sizeof(*ni), sizeof(gint32),
- "TTL: %d", (gint32)pntohl(ni + 1));
- /* XXX TBD */
+ l = get_dns_name(pd, offset + sizeof(*ni), offset + sizeof(*ni),
+ dname, sizeof(dname));
+ if (IS_DATA_IN_FRAME(offset + sizeof(*ni) + l) &&
+ pd[offset + sizeof(*ni) + l] == 0) {
+ l++;
+ proto_tree_add_text(tree, NullTVB, offset + sizeof(*ni), l,
+ "DNS label: %s (truncated)", dname);
+ } else {
+ proto_tree_add_text(tree, NullTVB, offset + sizeof(*ni), l,
+ "DNS label: %s", dname);
+ }
+ off = offset + sizeof(*ni) + l;
break;
case ICMP6_NI_SUBJ_IPV4:
n = pi.captured_len - (offset + sizeof(*ni));
@@ -349,10 +446,69 @@ dissect_nodeinfo(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
} else {
switch (pntohs(&ni->ni_qtype)) {
case NI_QTYPE_NOOP:
+ break;
case NI_QTYPE_SUPTYPES:
- /* XXX TBD */
+ p = (u_char *)(ni + 1);
+ tf = proto_tree_add_text(tree, NullTVB,
+ offset + sizeof(*ni), END_OF_FRAME,
+ "Supported type bitmap%s",
+ (flags & 0x0001) ? ", compressed" : "");
+ field_tree = proto_item_add_subtree(tf,
+ ett_nodeinfo_nodebitmap);
+ n = 0;
+ while (IS_DATA_IN_FRAME(p - pd)) {
+ if ((flags & 0x0001) == 0) {
+ l = pi.captured_len - (offset + sizeof(*ni));
+ l /= sizeof(guint32);
+ i = 0;
+ } else {
+ if (!IS_DATA_IN_FRAME(p + sizeof(guint32) - 1 - pd))
+ break;
+ l = pntohs(p);
+ i = pntohs(p + sizeof(guint16)); /*skip*/
+ }
+ if (n + l * 32 > (1 << 16))
+ break;
+ if (n + (l + i) * 32 > (1 << 16))
+ break;
+ if ((flags & 0x0001) == 0) {
+ proto_tree_add_text(field_tree, NullTVB, p - pd,
+ l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
+ bitrange(p, l, n));
+ p += l * 4;
+ } else {
+ proto_tree_add_text(field_tree, NullTVB, p - pd,
+ 4 + l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
+ bitrange(p + 4, l, n));
+ p += (4 + l * 4);
+ }
+ n += l * 32 + i * 32;
+ }
+ off = pi.captured_len - offset;
+ break;
case NI_QTYPE_DNSNAME:
- /* XXX TBD */
+ proto_tree_add_text(tree, NullTVB, offset + sizeof(*ni),
+ sizeof(gint32), "TTL: %d", (gint32)pntohl(ni + 1));
+ tf = proto_tree_add_text(tree, NullTVB,
+ offset + sizeof(*ni) + sizeof(guint32), END_OF_FRAME,
+ "DNS labels");
+ field_tree = proto_item_add_subtree(tf, ett_nodeinfo_nodedns);
+ n = pi.captured_len;
+ i = offset + sizeof(*ni) + sizeof(guint32);
+ while (i < pi.captured_len) {
+ l = get_dns_name(pd, i, offset + sizeof(*ni), dname,
+ sizeof(dname));
+ if (IS_DATA_IN_FRAME(i + l) && pd[i + l] == 0) {
+ l++;
+ proto_tree_add_text(field_tree, NullTVB, i, l,
+ "DNS label: %s (truncated)", dname);
+ } else {
+ proto_tree_add_text(field_tree, NullTVB, i, l,
+ "DNS label: %s", dname);
+ }
+ i += l;
+ }
+ off = pi.captured_len - offset;
break;
case NI_QTYPE_NODEADDR:
n = pi.captured_len - (offset + sizeof(*ni));
@@ -385,6 +541,7 @@ dissect_nodeinfo(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
break;
}
}
+nodata:;
/* the rest of data */
old_dissect_data(pd, offset + off, fd, tree);
@@ -846,6 +1003,8 @@ proto_register_icmpv6(void)
&ett_nodeinfo_subject6,
&ett_nodeinfo_node4,
&ett_nodeinfo_node6,
+ &ett_nodeinfo_nodebitmap,
+ &ett_nodeinfo_nodedns,
};
proto_icmpv6 = proto_register_protocol("Internet Control Message Protocol v6",