diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2010-04-06 16:01:58 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2010-04-06 16:01:58 +0000 |
commit | 216d3d4bb3769339d476f6a8a3469817083712f5 (patch) | |
tree | d5ee1f222b72dd49b30ad77f67ecdc0d49f4e5e5 | |
parent | 10b632d51941a9fda8546c12c9a98f4dccecff8f (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.h | 6 | ||||
-rw-r--r-- | usr.sbin/tcpdump/print-icmp6.c | 196 | ||||
-rw-r--r-- | usr.sbin/tcpdump/print-ip6.c | 5 | ||||
-rw-r--r-- | usr.sbin/tcpdump/print-ipsec.c | 7 |
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: |