X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/ea3df106b57d12649e624ae6e6f935b564d47f00..ad6df73f5a6c46a409c7629f5588b1b81dff6357:/print-icmp6.c diff --git a/print-icmp6.c b/print-icmp6.c index 1cce0a8d..71323c7d 100644 --- a/print-icmp6.c +++ b/print-icmp6.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.50 2001-06-01 03:32:28 itojun Exp $"; + "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.60 2002-05-30 22:01:34 itojun Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -43,6 +43,7 @@ static const char rcsid[] = #include #include +#include #include #include "ip6.h" @@ -54,6 +55,9 @@ static const char rcsid[] = #include "udp.h" #include "ah.h" +static const char *get_rtpref(u_int); +static const char *get_lifetime(u_int32_t); +static void print_lladdr(const u_char *, size_t); void icmp6_opt_print(const u_char *, int); void mld6_print(const u_char *); static struct udphdr *get_upperlayer(u_char *, int *); @@ -65,12 +69,46 @@ void icmp6_rrenum_print(int, const u_char *, const u_char *); #define abs(a) ((0 < (a)) ? (a) : -(a)) #endif -static char *rtpref_str[] = { - "medium", /* 00 */ - "high", /* 01 */ - "rsv", /* 10 */ - "low" /* 11 */ -}; +static const char * +get_rtpref(u_int v) +{ + static const char *rtpref_str[] = { + "medium", /* 00 */ + "high", /* 01 */ + "rsv", /* 10 */ + "low" /* 11 */ + }; + + return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff]; +} + +static const char * +get_lifetime(u_int32_t v) +{ + static char buf[20]; + + if (v == (u_int32_t)~0UL) + return "infinity"; + else { + snprintf(buf, sizeof(buf), "%u", v); + return buf; + } +} + +static void +print_lladdr(const u_int8_t *p, size_t l) +{ + const u_int8_t *ep, *q; + + q = p; + ep = p + l; + while (l > 0 && q < ep) { + if (q > p) + printf(":"); + printf("%02x", *q++); + l--; + } +} void icmp6_print(const u_char *bp, const u_char *bp2) @@ -85,10 +123,6 @@ icmp6_print(const u_char *bp, const u_char *bp2) char buf[256]; int icmp6len, prot; -#if 0 -#define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc -#endif - dp = (struct icmp6_hdr *)bp; ip = (struct ip6_hdr *)bp2; oip = (struct ip6_hdr *)(dp + 1); @@ -101,12 +135,6 @@ icmp6_print(const u_char *bp, const u_char *bp2) else /* XXX: jumbo payload case... */ icmp6len = snapend - bp; -#if 0 - (void)printf("%s > %s: ", - ip6addr_string(&ip->ip6_src), - ip6addr_string(&ip->ip6_dst)); -#endif - TCHECK(dp->icmp6_code); switch (dp->icmp6_type) { case ICMP6_DST_UNREACH: @@ -231,7 +259,6 @@ icmp6_print(const u_char *bp, const u_char *bp2) printf("icmp6: router advertisement"); if (vflag) { struct nd_router_advert *p; - int rtpref; p = (struct nd_router_advert *)dp; TCHECK(p->nd_ra_retransmit); @@ -240,21 +267,15 @@ icmp6_print(const u_char *bp, const u_char *bp2) printf("M"); if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) printf("O"); -#ifndef ND_RA_FLAG_HA -#define ND_RA_FLAG_HA 0x20 -#endif - if (p->nd_ra_flags_reserved & ND_RA_FLAG_HA) + if (p->nd_ra_flags_reserved & ND_RA_FLAG_HOME_AGENT) printf("H"); -#ifndef ND_RA_FLAG_RTPREF_MASK -#define ND_RA_FLAG_RTPREF_MASK 0x18 -#endif if ((p->nd_ra_flags_reserved & ~ND_RA_FLAG_RTPREF_MASK) != 0) printf(" "); - rtpref = ((p->nd_ra_flags_reserved & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff; - printf("pref=%s, ", rtpref_str[rtpref]); + printf("pref=%s, ", + get_rtpref(p->nd_ra_flags_reserved)); printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime)); printf("reachable_time=%u, ", @@ -335,6 +356,28 @@ icmp6_print(const u_char *bp, const u_char *bp2) case ICMP6_NI_REPLY: icmp6_nodeinfo_print(icmp6len, bp, ep); break; + case ICMP6_HADISCOV_REQUEST: + case ICMP6_HADISCOV_REPLY: + { + struct in6_addr *in6; + u_int32_t *res; + u_char *cp; + printf("icmp6: ha discovery %s: ", + dp->icmp6_type == ICMP6_HADISCOV_REQUEST ? + "request" : "reply"); + TCHECK(dp->icmp6_data16[0]); + printf("id=%d", ntohs(dp->icmp6_data16[0])); + cp = (u_char *)dp + icmp6len; + res = (u_int32_t *)(dp + 1); + in6 = (struct in6_addr *)(res + 2); + for (; (u_char *)in6 < cp; in6++) { + TCHECK(*in6); + printf(", %s", ip6addr_string(in6)); + } + break; + } + case ICMP6_MOBILEPREFIX_SOLICIT: + case ICMP6_MOBILEPREFIX_ADVERT: default: printf("icmp6: type-#%d", dp->icmp6_type); break; @@ -342,9 +385,6 @@ icmp6_print(const u_char *bp, const u_char *bp2) return; trunc: fputs("[|icmp6]", stdout); -#if 0 -#undef TCHECK -#endif } static struct udphdr * @@ -429,179 +469,152 @@ icmp6_opt_print(const u_char *bp, int resid) const struct icmp6_opts_redirect *opr; const struct nd_opt_mtu *opm; const struct nd_opt_advinterval *opa; + const struct nd_opt_homeagent_info *oph; const struct nd_opt_route_info *opri; - const u_char *ep; - int opts_len; + const u_char *cp, *ep; struct in6_addr in6, *in6p; - u_int32_t lifetime; -#if 0 - const struct ip6_hdr *ip; - const char *str; - const struct ip6_hdr *oip; - const struct udphdr *ouh; - int hlen, dport; - char buf[256]; -#endif + size_t l; #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return - op = (struct nd_opt_hdr *)bp; -#if 0 - ip = (struct ip6_hdr *)bp2; - oip = &dp->icmp6_ip6; - str = buf; -#endif + cp = bp; /* 'ep' points to the end of available data. */ ep = snapend; - ECHECK(op->nd_opt_len); - if (resid <= 0) - return; - switch (op->nd_opt_type) { - case ND_OPT_SOURCE_LINKADDR: - opl = (struct nd_opt_hdr *)op; -#if 1 - if ((u_char *)opl + (opl->nd_opt_len << 3) > ep) + while (cp < ep) { + op = (struct nd_opt_hdr *)cp; + + ECHECK(op->nd_opt_len); + if (resid <= 0) + return; + if (op->nd_opt_len == 0) goto trunc; -#else - TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1); -#endif - printf("(src lladdr: %s", /*)*/ - etheraddr_string((u_char *)(opl + 1))); - if (opl->nd_opt_len != 1) - printf("!"); - /*(*/ - printf(")"); - icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), - resid - (op->nd_opt_len << 3)); - break; - case ND_OPT_TARGET_LINKADDR: - opl = (struct nd_opt_hdr *)op; -#if 1 - if ((u_char *)opl + (opl->nd_opt_len << 3) > ep) + if (cp + (op->nd_opt_len << 3) > ep) goto trunc; -#else - TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1); -#endif - printf("(tgt lladdr: %s", /*)*/ - etheraddr_string((u_char *)(opl + 1))); - if (opl->nd_opt_len != 1) - printf("!"); - /*(*/ - printf(")"); - icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), - resid - (op->nd_opt_len << 3)); - break; - case ND_OPT_PREFIX_INFORMATION: - opp = (struct nd_opt_prefix_info *)op; - TCHECK(opp->nd_opt_pi_prefix); - printf("(prefix info: "); /*)*/ - if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) - printf("L"); - if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) - printf("A"); - if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ROUTER) - printf("R"); - if (opp->nd_opt_pi_flags_reserved) - printf(" "); - printf("valid_ltime="); - if ((u_int32_t)ntohl(opp->nd_opt_pi_valid_time) == ~0U) - printf("infinity"); - else { - printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_valid_time)); - } - printf(", "); - printf("preferred_ltime="); - if ((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time) == ~0U) - printf("infinity"); - else { - printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_preferred_time)); - } - printf(", "); - printf("prefix=%s/%d", ip6addr_string(&opp->nd_opt_pi_prefix), - opp->nd_opt_pi_prefix_len); - if (opp->nd_opt_pi_len != 4) - printf("!"); - /*(*/ - printf(")"); - icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), - resid - (op->nd_opt_len << 3)); - break; - case ND_OPT_REDIRECTED_HEADER: - opr = (struct icmp6_opts_redirect *)op; - printf("(redirect)"); - /* xxx */ - icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), - resid - (op->nd_opt_len << 3)); - break; - case ND_OPT_MTU: - opm = (struct nd_opt_mtu *)op; - TCHECK(opm->nd_opt_mtu_mtu); - printf("(mtu:"); /*)*/ - printf(" mtu=%u", (u_int32_t)ntohl(opm->nd_opt_mtu_mtu)); - if (opm->nd_opt_mtu_len != 1) - printf("!"); - printf(")"); - icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), - resid - (op->nd_opt_len << 3)); - break; - case ND_OPT_ADVINTERVAL: - opa = (struct nd_opt_advinterval *)op; - TCHECK(opa->nd_opt_adv_interval); - printf("(advint:"); /*)*/ - printf(" advint=%u", - (u_int32_t)ntohl(opa->nd_opt_adv_interval)); - /*(*/ - printf(")"); - icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), - resid - (op->nd_opt_len << 3)); - break; - case ND_OPT_ROUTE_INFO: - opri = (struct nd_opt_route_info *)op; - TCHECK(opri->nd_opt_rti_lifetime); - memset(&in6, 0, sizeof(in6)); - in6p = (struct in6_addr *)(opri + 1); - switch (op->nd_opt_len) { - case 1: + + switch (op->nd_opt_type) { + case ND_OPT_SOURCE_LINKADDR: + opl = (struct nd_opt_hdr *)op; + printf("(src lladdr: "); + l = (op->nd_opt_len << 3) - 2; + print_lladdr(cp + 2, l); + /*(*/ + printf(")"); break; - case 2: - TCHECK2(*in6p, 8); - memcpy(&in6, opri + 1, 8); + case ND_OPT_TARGET_LINKADDR: + opl = (struct nd_opt_hdr *)op; + printf("(tgt lladdr: "); + l = (op->nd_opt_len << 3) - 2; + print_lladdr(cp + 2, l); + /*(*/ + printf(")"); + break; + case ND_OPT_PREFIX_INFORMATION: + opp = (struct nd_opt_prefix_info *)op; + TCHECK(opp->nd_opt_pi_prefix); + printf("(prefix info: "); /*)*/ + if (op->nd_opt_len != 4) { + printf("badlen"); + /*(*/ + printf(")"); + break; + } + if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) + printf("L"); + if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) + printf("A"); + if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ROUTER) + printf("R"); + if (opp->nd_opt_pi_flags_reserved) + printf(" "); + printf("valid_ltime=%s,", + get_lifetime((u_int32_t)ntohl(opp->nd_opt_pi_valid_time))); + printf("preferred_ltime=%s,", + get_lifetime((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time))); + printf("prefix=%s/%d", + ip6addr_string(&opp->nd_opt_pi_prefix), + opp->nd_opt_pi_prefix_len); + if (opp->nd_opt_pi_len != 4) + printf("!"); + /*(*/ + printf(")"); + break; + case ND_OPT_REDIRECTED_HEADER: + opr = (struct icmp6_opts_redirect *)op; + printf("(redirect)"); + /* xxx */ + break; + case ND_OPT_MTU: + opm = (struct nd_opt_mtu *)op; + TCHECK(opm->nd_opt_mtu_mtu); + printf("(mtu:"); /*)*/ + if (op->nd_opt_len != 1) { + printf("badlen"); + /*(*/ + printf(")"); + break; + } + printf(" mtu=%u", (u_int32_t)ntohl(opm->nd_opt_mtu_mtu)); + if (opm->nd_opt_mtu_len != 1) + printf("!"); + printf(")"); break; - case 3: - TCHECK(*in6p); - memcpy(&in6, opri + 1, sizeof(in6)); + case ND_OPT_ADVINTERVAL: + opa = (struct nd_opt_advinterval *)op; + TCHECK(opa->nd_opt_adv_interval); + printf("(advint:"); /*)*/ + printf(" advint=%u", + (u_int32_t)ntohl(opa->nd_opt_adv_interval)); + /*(*/ + printf(")"); + break; + case ND_OPT_HOMEAGENT_INFO: + oph = (struct nd_opt_homeagent_info *)op; + TCHECK(oph->nd_opt_hai_lifetime); + printf("(ha info:"); /*)*/ + printf(" pref=%d", ntohs(oph->nd_opt_hai_preference)); + printf(", lifetime=%u", ntohs(oph->nd_opt_hai_lifetime)); + printf(")"); + break; + case ND_OPT_ROUTE_INFO: + opri = (struct nd_opt_route_info *)op; + TCHECK(opri->nd_opt_rti_lifetime); + memset(&in6, 0, sizeof(in6)); + in6p = (struct in6_addr *)(opri + 1); + switch (op->nd_opt_len) { + case 1: + break; + case 2: + TCHECK2(*in6p, 8); + memcpy(&in6, opri + 1, 8); + break; + case 3: + TCHECK(*in6p); + memcpy(&in6, opri + 1, sizeof(in6)); + break; + default: + goto trunc; + } + printf("(rtinfo:"); /*)*/ + printf(" %s/%u", ip6addr_string(&in6), + opri->nd_opt_rti_prefixlen); + printf(", pref=%s", get_rtpref(opri->nd_opt_rti_flags)); + printf(", lifetime=%s", + get_lifetime((u_int32_t)ntohl(opri->nd_opt_rti_lifetime))); + /*(*/ + printf(")"); break; default: - goto trunc; + printf("(unknown opt_type=%d, opt_len=%d)", + op->nd_opt_type, op->nd_opt_len); + break; } - printf("(rtinfo:"); /*)*/ - printf(" %s/%u", ip6addr_string(&in6), - opri->nd_opt_rti_prefixlen); - printf(", pref=%s", - rtpref_str[((opri->nd_opt_rti_flags & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff]); - printf(", lifetime="); - lifetime = (u_int32_t)ntohl(opri->nd_opt_rti_lifetime); - if (lifetime == ~0UL) - printf("infinity"); - else - printf("%u", lifetime); - /*(*/ - printf(")"); - icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), - resid - (op->nd_opt_len << 3)); - break; - default: - opts_len = op->nd_opt_len; - printf("(unknwon opt_type=%d, opt_len=%d)", - op->nd_opt_type, opts_len); - if (opts_len == 0) - opts_len = 1; /* XXX */ - icmp6_opt_print((const u_char *)op + (opts_len << 3), - resid - (opts_len << 3)); - break; + + cp += op->nd_opt_len << 3; + resid -= op->nd_opt_len << 3; } return; + trunc: fputs("[ndp opt]", stdout); return;