summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2010-04-06 16:01:58 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2010-04-06 16:01:58 +0000
commit216d3d4bb3769339d476f6a8a3469817083712f5 (patch)
treed5ee1f222b72dd49b30ad77f67ecdc0d49f4e5e5
parent10b632d51941a9fda8546c12c9a98f4dccecff8f (diff)
Add support for decoding MLDv2 initially from tcpdump.org via FreeBSD,
cleaned up to be less gross after some suggestions from stsp. ok stsp@
-rw-r--r--usr.sbin/tcpdump/interface.h6
-rw-r--r--usr.sbin/tcpdump/print-icmp6.c196
-rw-r--r--usr.sbin/tcpdump/print-ip6.c5
-rw-r--r--usr.sbin/tcpdump/print-ipsec.c7
4 files changed, 203 insertions, 11 deletions
diff --git a/usr.sbin/tcpdump/interface.h b/usr.sbin/tcpdump/interface.h
index 4475e742570..202b427e3c7 100644
--- a/usr.sbin/tcpdump/interface.h
+++ b/usr.sbin/tcpdump/interface.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: interface.h,v 1.60 2010/01/12 06:10:33 naddy Exp $ */
+/* $OpenBSD: interface.h,v 1.61 2010/04/06 16:01:57 jsg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -20,7 +20,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Id: interface.h,v 1.60 2010/01/12 06:10:33 naddy Exp $ (LBL)
+ * @(#) $Id: interface.h,v 1.61 2010/04/06 16:01:57 jsg Exp $ (LBL)
*/
#ifndef tcpdump_interface_h
@@ -281,7 +281,7 @@ extern void ip6_opt_print(const u_char *, int);
extern int hbhopt_print(const u_char *);
extern int dstopt_print(const u_char *);
extern int frag6_print(const u_char *, const u_char *);
-extern void icmp6_print(const u_char *, const u_char *);
+extern void icmp6_print(const u_char *, u_int, const u_char *);
extern void ripng_print(const u_char *, int);
extern int rt6_print(const u_char *, const u_char *);
extern void ospf6_print(const u_char *, u_int);
diff --git a/usr.sbin/tcpdump/print-icmp6.c b/usr.sbin/tcpdump/print-icmp6.c
index 2d5803a2d16..dffec6c35cf 100644
--- a/usr.sbin/tcpdump/print-icmp6.c
+++ b/usr.sbin/tcpdump/print-icmp6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print-icmp6.c,v 1.7 2009/10/27 23:59:55 deraadt Exp $ */
+/* $OpenBSD: print-icmp6.c,v 1.8 2010/04/06 16:01:57 jsg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
@@ -48,15 +48,52 @@
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
+#include <netinet6/mld6.h>
#include "interface.h"
#include "addrtoname.h"
void icmp6_opt_print(const u_char *, int);
void mld6_print(const u_char *);
+void mldv2_query_print(const u_char *, u_int);
+void mldv2_report_print(const u_char *, u_int);
+
+/* mldv2 report types */
+static struct tok mldv2report2str[] = {
+ { 1, "is_in" },
+ { 2, "is_ex" },
+ { 3, "to_in" },
+ { 4, "to_ex" },
+ { 5, "allow" },
+ { 6, "block" },
+ { 0, NULL }
+};
+
+#define MLDV2_QUERY_QRV 24
+#define MLDV2_QUERY_QQIC 25
+#define MLDV2_QUERY_NSRCS 26
+#define MLDV2_QUERY_SRC0 28
+
+#define MLDV2_QUERY_QRV_SFLAG (1 << 3)
+
+#define MLD_V1_QUERY_MINLEN 24
+
+#define MLDV2_REPORT_GROUP0 8
+
+#define MLDV2_REPORT_MINLEN 8
+#define MLDV2_REPORT_MINGRPLEN 20
+
+#define MLDV2_RGROUP_NSRCS 2
+#define MLDV2_RGROUP_MADDR 4
+
+#define MLDV2_MRC_FLOAT (1 << 15)
+#define MLDV2_MRD(mant, exp) ((mant | 0x1000) << (exp + 3))
+
+#define MLDV2_QQIC_FLOAT (1 << 7)
+#define MLDV2_QQI(mant, exp) ((mant | 0x10) << (exp + 3))
void
-icmp6_print(register const u_char *bp, register const u_char *bp2)
+icmp6_print(const u_char *bp, u_int length, const u_char *bp2)
{
register const struct icmp6_hdr *dp;
register const struct ip6_hdr *ip;
@@ -196,7 +233,14 @@ icmp6_print(register const u_char *bp, register const u_char *bp2)
break;
case ICMP6_MEMBERSHIP_QUERY:
printf("icmp6: multicast listener query ");
- mld6_print((const u_char *)dp);
+ if (length == MLD_V1_QUERY_MINLEN) {
+ mld6_print((const u_char *)dp);
+ } else if (length >= MLD_V2_QUERY_MINLEN) {
+ printf("v2 ");
+ mldv2_query_print((const u_char *)dp, length);
+ } else {
+ printf("unknown-version (len %u) ", length);
+ }
break;
case ICMP6_MEMBERSHIP_REPORT:
printf("icmp6: multicast listener report ");
@@ -397,6 +441,10 @@ icmp6_print(register const u_char *bp, register const u_char *bp2)
break;
}
#endif /*ICMP6_WRUREPLY*/
+ case MLDV2_LISTENER_REPORT:
+ printf("multicast listener report v2");
+ mldv2_report_print((const u_char *) dp, length);
+ break;
default:
printf("icmp6: type-#%d", dp->icmp6_type);
break;
@@ -569,4 +617,146 @@ mld6_print(register const u_char *bp)
return;
}
+
+void
+mldv2_report_print(const u_char *bp, u_int len)
+{
+ struct icmp6_hdr *icp = (struct icmp6_hdr *) bp;
+ u_int group, nsrcs, ngroups;
+ u_int i, j;
+
+ if (len < MLDV2_REPORT_MINLEN) {
+ printf(" [invalid len %d]", len);
+ return;
+ }
+
+ TCHECK(icp->icmp6_data16[1]);
+ ngroups = ntohs(icp->icmp6_data16[1]);
+ printf(", %d group record(s)", ngroups);
+ if (vflag > 0) {
+ /* Print the group records */
+ group = MLDV2_REPORT_GROUP0;
+ for (i = 0; i < ngroups; i++) {
+ /* type(1) + auxlen(1) + numsrc(2) + grp(16) */
+ if (len < group + MLDV2_REPORT_MINGRPLEN) {
+ printf(" [invalid number of groups]");
+ return;
+ }
+ TCHECK2(bp[group + MLDV2_RGROUP_MADDR],
+ sizeof(struct in6_addr));
+ printf(" [gaddr %s",
+ ip6addr_string(&bp[group + MLDV2_RGROUP_MADDR]));
+ printf(" %s", tok2str(mldv2report2str,
+ " [v2-report-#%d]", bp[group]));
+ nsrcs = (bp[group + MLDV2_RGROUP_NSRCS] << 8) +
+ bp[group + MLDV2_RGROUP_NSRCS + 1];
+ /* Check the number of sources and print them */
+ if (len < group + MLDV2_REPORT_MINGRPLEN +
+ (nsrcs * sizeof(struct in6_addr))) {
+ printf(" [invalid number of sources %d]", nsrcs);
+ return;
+ }
+ if (vflag == 1)
+ printf(", %d source(s)", nsrcs);
+ else {
+ /* Print the sources */
+ (void)printf(" {");
+ for (j = 0; j < nsrcs; j++) {
+ TCHECK2(bp[group +
+ MLDV2_REPORT_MINGRPLEN +
+ j * sizeof(struct in6_addr)],
+ sizeof(struct in6_addr));
+ printf(" %s", ip6addr_string(&bp[group +
+ MLDV2_REPORT_MINGRPLEN + j *
+ sizeof(struct in6_addr)]));
+ }
+ (void)printf(" }");
+ }
+ /* Next group record */
+ group += MLDV2_REPORT_MINGRPLEN + nsrcs *
+ sizeof(struct in6_addr);
+ printf("]");
+ }
+ }
+ return;
+trunc:
+ (void)printf("[|icmp6]");
+ return;
+}
+
+void
+mldv2_query_print(const u_char *bp, u_int len)
+{
+ struct icmp6_hdr *icp = (struct icmp6_hdr *) bp;
+ u_int mrc, qqic;
+ int mrd, qqi;
+ int mant, exp;
+ u_int nsrcs;
+ u_int i;
+
+ if (len < MLD_V2_QUERY_MINLEN) {
+ printf(" [invalid len %d]", len);
+ return;
+ }
+ TCHECK(icp->icmp6_data16[0]);
+ mrc = ntohs(icp->icmp6_data16[0]);
+ if (mrc & MLDV2_MRC_FLOAT) {
+ mant = MLD_MRC_MANT(mrc);
+ exp = MLD_MRC_EXP(mrc);
+ mrd = MLDV2_MRD(mant, exp);
+ } else {
+ mrd = mrc;
+ }
+ if (vflag) {
+ (void)printf(" [max resp delay=%d]", mrd);
+ }
+ TCHECK2(bp[8], sizeof(struct in6_addr));
+ printf(" [gaddr %s", ip6addr_string(&bp[8]));
+
+ if (vflag) {
+ TCHECK(bp[MLDV2_QUERY_QQIC]);
+ if (bp[MLDV2_QUERY_QRV] & MLDV2_QUERY_QRV_SFLAG) {
+ printf(" sflag");
+ }
+ if (MLD_QRV(bp[MLDV2_QUERY_QRV])) {
+ printf(" robustness=%d", MLD_QRV(bp[MLDV2_QUERY_QRV]));
+ }
+ qqic = bp[MLDV2_QUERY_QQIC];
+ if (qqic & MLDV2_QQIC_FLOAT) {
+ mant = MLD_QQIC_MANT(qqic);
+ exp = MLD_QQIC_EXP(qqic);
+ qqi = MLDV2_QQI(mant, exp);
+ } else {
+ qqi = bp[MLDV2_QUERY_QQIC];
+ }
+ printf(" qqi=%d", qqi);
+ }
+
+ TCHECK2(bp[MLDV2_QUERY_NSRCS], 2);
+ nsrcs = ntohs(*(u_short *)&bp[MLDV2_QUERY_NSRCS]);
+ if (nsrcs > 0) {
+ if (len < MLD_V2_QUERY_MINLEN + nsrcs * sizeof(struct in6_addr))
+ printf(" [invalid number of sources]");
+ else if (vflag > 1) {
+ printf(" {");
+ for (i = 0; i < nsrcs; i++) {
+ TCHECK2(bp[MLDV2_QUERY_SRC0 + i *
+ sizeof(struct in6_addr)],
+ sizeof(struct in6_addr));
+ printf(" %s",
+ ip6addr_string(&bp[MLDV2_QUERY_SRC0 + i *
+ sizeof(struct in6_addr)]));
+ }
+ printf(" }");
+ } else
+ printf(", %d source(s)", nsrcs);
+ }
+ printf("]");
+ return;
+trunc:
+ (void)printf("[|icmp6]");
+ return;
+}
+
+
#endif /* INET6 */
diff --git a/usr.sbin/tcpdump/print-ip6.c b/usr.sbin/tcpdump/print-ip6.c
index b9ef3df0e34..7f809c9954c 100644
--- a/usr.sbin/tcpdump/print-ip6.c
+++ b/usr.sbin/tcpdump/print-ip6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print-ip6.c,v 1.12 2009/11/27 13:14:35 bluhm Exp $ */
+/* $OpenBSD: print-ip6.c,v 1.13 2010/04/06 16:01:57 jsg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
@@ -161,7 +161,8 @@ ip6_print(register const u_char *bp, register int length)
(const u_char *)ip6);
goto end;
case IPPROTO_ICMPV6:
- icmp6_print(cp, (const u_char *)ip6);
+ icmp6_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp),
+ (const u_char *)ip6);
goto end;
case IPPROTO_PIM:
(void)printf("PIM");
diff --git a/usr.sbin/tcpdump/print-ipsec.c b/usr.sbin/tcpdump/print-ipsec.c
index 5e332fd5658..5e8eea70d26 100644
--- a/usr.sbin/tcpdump/print-ipsec.c
+++ b/usr.sbin/tcpdump/print-ipsec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print-ipsec.c,v 1.15 2009/11/11 13:23:01 jsg Exp $ */
+/* $OpenBSD: print-ipsec.c,v 1.16 2010/04/06 16:01:57 jsg Exp $ */
/*
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
@@ -190,7 +190,7 @@ esp_decrypt (const u_char *bp, u_int len, const u_char *bp2)
icmp_print(data, bp2);
break;
case IPPROTO_ICMPV6:
- icmp6_print(data, bp2);
+ icmp6_print(data, len, bp2);
break;
default:
printf("ip-proto-%d %d", nh, len);
@@ -302,7 +302,8 @@ ah_print (register const u_char *bp, register u_int len,
break;
case IPPROTO_ICMPV6:
- icmp6_print(bp + pl_len, (const u_char *) ip);
+ icmp6_print(bp + pl_len, len - pl_len,
+ (const u_char *) ip);
break;
case IPPROTO_TCP: