aboutsummaryrefslogtreecommitdiff
path: root/print-icmp6.c
diff options
context:
space:
mode:
authorJP Abgrall <jpa@google.com>2014-02-12 14:02:41 -0800
committerJP Abgrall <jpa@google.com>2014-02-12 22:24:55 +0000
commit53f17a9db278d33517d9888dd77848f554522a38 (patch)
treebc24a01da546ba785f5996178860344345578a15 /print-icmp6.c
parent532b8f38c144da9a298260a5d8978ab9e8e3856c (diff)
downloadtcpdump-53f17a9db278d33517d9888dd77848f554522a38.tar.gz
Merge remote-tracking branch 'goog/tcpdump'
* goog/tcpdump: (3066 commits) Remove old version. Getting ready for new tcpdump 4.5 Support -Q for setting the capture direction. Clean up the TLV processing loop. With -A and -AA, don't send CRs to the standard output. Use the new libpcap <pcap/nflog.h> for NFLOG definitions and declarations. Do our own isascii(), isprint(), isgraph(), and toascii(). Fix a compiler warning. Don't use the __attribute__((packed)) on most platforms. The interval in an AODV HELLO extension is not aligned on a 4-byte boundary. As with memcpy, so with memcmp. More UNALIGNED_MEM{CPY,CMP} on IP addresses. Another case where UNALIGNED_MEMCPY() is probably necessary. No need for casting back and forth. Only do the unaligned_mem{cpy,cmp} hack if necessary. No need to declare unaligned_mem{cpy,cmp} in netdissect.h *and* interface.h. More possibly-unaligned memcpy()s and assignments - use unaligned_memcpy(). Check for compiling for IPv6; don't check whether we can create an IPv6 socket. Use unaligned_memcmp() to compare with IPv{4,6} addresses in a packet. Use EXTRACT_nBITS even when just testing against zero. Fix some more unaligned accesses. ... Change-Id: I9e98707d30c989b9e32dcd5af798bd0746ab4434
Diffstat (limited to 'print-icmp6.c')
-rw-r--r--print-icmp6.c244
1 files changed, 169 insertions, 75 deletions
diff --git a/print-icmp6.c b/print-icmp6.c
index c5039247..811e5a06 100644
--- a/print-icmp6.c
+++ b/print-icmp6.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.79.2.6 2005/09/05 09:29:28 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.86 2008-02-05 19:36:13 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -62,7 +62,10 @@ static void icmp6_rrenum_print(const u_char *, const u_char *);
#define abs(a) ((0 < (a)) ? (a) : -(a))
#endif
-static struct tok icmp6_type_values[] = {
+/* inline the various RPL definitions */
+#define ND_RPL_MESSAGE 0x9B
+
+static const struct tok icmp6_type_values[] = {
{ ICMP6_DST_UNREACH, "destination unreachable"},
{ ICMP6_PACKET_TOO_BIG, "packet too big"},
{ ICMP6_TIME_EXCEEDED, "time exceeded in-transit"},
@@ -91,10 +94,11 @@ static struct tok icmp6_type_values[] = {
{ ICMP6_NI_REPLY, "node information reply"},
{ MLD6_MTRACE, "mtrace message"},
{ MLD6_MTRACE_RESP, "mtrace response"},
+ { ND_RPL_MESSAGE, "RPL"},
{ 0, NULL }
};
-static struct tok icmp6_dst_unreach_code_values[] = {
+static const struct tok icmp6_dst_unreach_code_values[] = {
{ ICMP6_DST_UNREACH_NOROUTE, "unreachable route" },
{ ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"},
{ ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"},
@@ -103,21 +107,21 @@ static struct tok icmp6_dst_unreach_code_values[] = {
{ 0, NULL }
};
-static struct tok icmp6_opt_pi_flag_values[] = {
+static const struct tok icmp6_opt_pi_flag_values[] = {
{ ND_OPT_PI_FLAG_ONLINK, "onlink" },
{ ND_OPT_PI_FLAG_AUTO, "auto" },
{ ND_OPT_PI_FLAG_ROUTER, "router" },
{ 0, NULL }
};
-static struct tok icmp6_opt_ra_flag_values[] = {
+static const struct tok icmp6_opt_ra_flag_values[] = {
{ ND_RA_FLAG_MANAGED, "managed" },
{ ND_RA_FLAG_OTHER, "other stateful"},
{ ND_RA_FLAG_HOME_AGENT, "home agent"},
{ 0, NULL }
};
-static struct tok icmp6_nd_na_flag_values[] = {
+static const struct tok icmp6_nd_na_flag_values[] = {
{ ND_NA_FLAG_ROUTER, "router" },
{ ND_NA_FLAG_SOLICITED, "solicited" },
{ ND_NA_FLAG_OVERRIDE, "override" },
@@ -125,12 +129,14 @@ static struct tok icmp6_nd_na_flag_values[] = {
};
-static struct tok icmp6_opt_values[] = {
+static const struct tok icmp6_opt_values[] = {
{ ND_OPT_SOURCE_LINKADDR, "source link-address"},
{ ND_OPT_TARGET_LINKADDR, "destination link-address"},
{ ND_OPT_PREFIX_INFORMATION, "prefix info"},
{ ND_OPT_REDIRECTED_HEADER, "redirected header"},
{ ND_OPT_MTU, "mtu"},
+ { ND_OPT_RDNSS, "rdnss"},
+ { ND_OPT_DNSSL, "dnssl"},
{ ND_OPT_ADVINTERVAL, "advertisement interval"},
{ ND_OPT_HOMEAGENT_INFO, "homeagent information"},
{ ND_OPT_ROUTE_INFO, "route info"},
@@ -138,7 +144,7 @@ static struct tok icmp6_opt_values[] = {
};
/* mldv2 report types */
-static struct tok mldv2report2str[] = {
+static const struct tok mldv2report2str[] = {
{ 1, "is_in" },
{ 2, "is_ex" },
{ 3, "to_in" },
@@ -169,7 +175,7 @@ get_lifetime(u_int32_t v)
if (v == (u_int32_t)~0UL)
return "infinity";
else {
- snprintf(buf, sizeof(buf), "%u", v);
+ snprintf(buf, sizeof(buf), "%us", v);
return buf;
}
}
@@ -192,48 +198,110 @@ print_lladdr(const u_int8_t *p, size_t l)
static int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp,
u_int len)
{
- size_t i;
- register const u_int16_t *sp;
- u_int32_t sum;
- union {
- struct {
- struct in6_addr ph_src;
- struct in6_addr ph_dst;
- u_int32_t ph_len;
- u_int8_t ph_zero[3];
- u_int8_t ph_nxt;
- } ph;
- u_int16_t pa[20];
- } phu;
-
- /* pseudo-header */
- memset(&phu, 0, sizeof(phu));
- phu.ph.ph_src = ip6->ip6_src;
- phu.ph.ph_dst = ip6->ip6_dst;
- phu.ph.ph_len = htonl(len);
- phu.ph.ph_nxt = IPPROTO_ICMPV6;
-
- sum = 0;
- for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
- sum += phu.pa[i];
-
- sp = (const u_int16_t *)icp;
-
- for (i = 0; i < (len & ~1); i += 2)
- sum += *sp++;
-
- if (len & 1)
- sum += htons((*(const u_int8_t *)sp) << 8);
-
- while (sum > 0xffff)
- sum = (sum & 0xffff) + (sum >> 16);
- sum = ~sum & 0xffff;
-
- return (sum);
+ return (nextproto6_cksum(ip6, (const u_int8_t *)(void *)icp, len,
+ IPPROTO_ICMPV6));
+}
+
+enum ND_RPL_CODE {
+ ND_RPL_DIS =0x00,
+ ND_RPL_DIO =0x01,
+ ND_RPL_DAO =0x02,
+ ND_RPL_DAO_ACK=0x03,
+ ND_RPL_SDIS =0x80,
+ ND_RPL_SDIO =0x81,
+ ND_RPL_SDAO =0x82,
+ ND_RPL_SDAO_ACK=0x83,
+ ND_RPL_SCC =0x8A,
+};
+
+enum ND_RPL_DIO_FLAGS {
+ ND_RPL_DIO_GROUNDED = 0x80,
+ ND_RPL_DIO_DATRIG = 0x40,
+ ND_RPL_DIO_DASUPPORT= 0x20,
+ ND_RPL_DIO_RES4 = 0x10,
+ ND_RPL_DIO_RES3 = 0x08,
+ ND_RPL_DIO_PRF_MASK = 0x07, /* 3-bit preference */
+};
+
+struct nd_rpl_dio {
+ u_int8_t rpl_flags;
+ u_int8_t rpl_seq;
+ u_int8_t rpl_instanceid;
+ u_int8_t rpl_dagrank;
+ u_int8_t rpl_dagid[16];
+};
+
+static void
+rpl_print(netdissect_options *ndo,
+ const struct icmp6_hdr *hdr,
+ const u_char *bp, u_int length _U_)
+{
+ struct nd_rpl_dio *dio = (struct nd_rpl_dio *)bp;
+ int secured = hdr->icmp6_code & 0x80;
+ int basecode= hdr->icmp6_code & 0x7f;
+
+ ND_TCHECK(dio->rpl_dagid);
+
+ if(secured) {
+ ND_PRINT((ndo, ", (SEC)"));
+ } else {
+ ND_PRINT((ndo, ", (CLR)"));
+ }
+
+ switch(basecode) {
+ case ND_RPL_DIS:
+ ND_PRINT((ndo, "DODAG Information Solicitation"));
+ if(ndo->ndo_vflag) {
+ }
+ break;
+ case ND_RPL_DIO:
+ ND_PRINT((ndo, "DODAG Information Object"));
+ if(ndo->ndo_vflag) {
+ char dagid[65];
+ char *d = dagid;
+ int i;
+ for(i=0;i<16;i++) {
+ if(isprint(dio->rpl_dagid[i])) {
+ *d++ = dio->rpl_dagid[i];
+ } else {
+ int cnt=snprintf(d,4,"0x%02x",
+ dio->rpl_dagid[i]);
+ d += cnt;
+ }
+ }
+ *d++ = '\0';
+ ND_PRINT((ndo, " [seq:%u,instance:%u,rank:%u,dagid:%s]",
+ dio->rpl_seq,
+ dio->rpl_instanceid,
+ dio->rpl_dagrank,
+ dagid));
+ }
+ break;
+ case ND_RPL_DAO:
+ ND_PRINT((ndo, "Destination Advertisement Object"));
+ if(ndo->ndo_vflag) {
+ }
+ break;
+ case ND_RPL_DAO_ACK:
+ ND_PRINT((ndo, "Destination Advertisement Object Ack"));
+ if(ndo->ndo_vflag) {
+ }
+ break;
+ default:
+ ND_PRINT((ndo, "RPL message, unknown code %u",hdr->icmp6_code));
+ break;
+ }
+ return;
+trunc:
+ ND_PRINT((ndo," [|truncated]"));
+ return;
+
}
+
void
-icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
+icmp6_print(netdissect_options *ndo,
+ const u_char *bp, u_int length, const u_char *bp2, int fragmented)
{
const struct icmp6_hdr *dp;
const struct ip6_hdr *ip;
@@ -252,12 +320,15 @@ icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
TCHECK(dp->icmp6_cksum);
if (vflag && !fragmented) {
- int sum = dp->icmp6_cksum;
+ u_int16_t sum, udp_sum;
if (TTEST2(bp[0], length)) {
+ udp_sum = EXTRACT_16BITS(&dp->icmp6_cksum);
sum = icmp6_cksum(ip, dp, length);
if (sum != 0)
- (void)printf("[bad icmp6 cksum %x!] ", sum);
+ (void)printf("[bad icmp6 cksum 0x%04x -> 0x%04x!] ",
+ udp_sum,
+ in_cksum_shouldbe(udp_sum, sum));
else
(void)printf("[icmp6 sum ok] ");
}
@@ -266,14 +337,13 @@ icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
printf("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",dp->icmp6_type));
/* display cosmetics: print the packet length for printer that use the vflag now */
- if (vflag && (dp->icmp6_type ==
- ND_ROUTER_SOLICIT ||
- ND_ROUTER_ADVERT ||
- ND_NEIGHBOR_ADVERT ||
- ND_NEIGHBOR_SOLICIT ||
- ND_REDIRECT ||
- ICMP6_HADISCOV_REPLY ||
- ICMP6_MOBILEPREFIX_ADVERT ))
+ if (vflag && (dp->icmp6_type == ND_ROUTER_SOLICIT ||
+ dp->icmp6_type == ND_ROUTER_ADVERT ||
+ dp->icmp6_type == ND_NEIGHBOR_ADVERT ||
+ dp->icmp6_type == ND_NEIGHBOR_SOLICIT ||
+ dp->icmp6_type == ND_REDIRECT ||
+ dp->icmp6_type == ICMP6_HADISCOV_REPLY ||
+ dp->icmp6_type == ICMP6_MOBILEPREFIX_ADVERT ))
printf(", length %u", length);
switch (dp->icmp6_type) {
@@ -347,7 +417,7 @@ icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
TCHECK(oip->ip6_dst);
switch (dp->icmp6_code) {
case ICMP6_PARAMPROB_HEADER:
- printf(", errorneous - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr));
+ printf(", erroneous - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr));
break;
case ICMP6_PARAMPROB_NEXTHEADER:
printf(", next header - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr));
@@ -370,7 +440,7 @@ icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
if (length == MLD_MINLEN) {
mld6_print((const u_char *)dp);
} else if (length >= MLDV2_MINLEN) {
- printf("v2 ");
+ printf(" v2");
mldv2_query_print((const u_char *)dp, length);
} else {
printf(" unknown-version (len %u) ", length);
@@ -505,6 +575,9 @@ icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
length - MPADVLEN);
}
break;
+ case ND_RPL_MESSAGE:
+ rpl_print(ndo, dp, &dp->icmp6_data8[0], length);
+ break;
default:
printf(", length %u", length);
if (vflag <= 1)
@@ -596,16 +669,17 @@ static void
icmp6_opt_print(const u_char *bp, int resid)
{
const struct nd_opt_hdr *op;
- const struct nd_opt_hdr *opl; /* why there's no struct? */
const struct nd_opt_prefix_info *opp;
- const struct icmp6_opts_redirect *opr;
const struct nd_opt_mtu *opm;
+ const struct nd_opt_rdnss *oprd;
+ const struct nd_opt_dnssl *opds;
const struct nd_opt_advinterval *opa;
const struct nd_opt_homeagent_info *oph;
const struct nd_opt_route_info *opri;
- const u_char *cp, *ep;
+ const u_char *cp, *ep, *domp;
struct in6_addr in6, *in6p;
size_t l;
+ u_int i;
#define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return
@@ -632,28 +706,25 @@ icmp6_opt_print(const u_char *bp, int resid)
switch (op->nd_opt_type) {
case ND_OPT_SOURCE_LINKADDR:
- opl = (struct nd_opt_hdr *)op;
l = (op->nd_opt_len << 3) - 2;
print_lladdr(cp + 2, l);
break;
case ND_OPT_TARGET_LINKADDR:
- opl = (struct nd_opt_hdr *)op;
l = (op->nd_opt_len << 3) - 2;
print_lladdr(cp + 2, l);
break;
case ND_OPT_PREFIX_INFORMATION:
opp = (struct nd_opt_prefix_info *)op;
TCHECK(opp->nd_opt_pi_prefix);
- printf("%s/%u%s, Flags [%s], valid time %ss",
+ printf("%s/%u%s, Flags [%s], valid time %s",
ip6addr_string(&opp->nd_opt_pi_prefix),
opp->nd_opt_pi_prefix_len,
(op->nd_opt_len != 4) ? "badlen" : "",
bittok2str(icmp6_opt_pi_flag_values, "none", opp->nd_opt_pi_flags_reserved),
get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_valid_time)));
- printf(", pref. time %ss", get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time)));
+ printf(", pref. time %s", get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time)));
break;
case ND_OPT_REDIRECTED_HEADER:
- opr = (struct icmp6_opts_redirect *)op;
print_unknown_data(bp,"\n\t ",op->nd_opt_len<<3);
/* xxx */
break;
@@ -664,10 +735,33 @@ icmp6_opt_print(const u_char *bp, int resid)
EXTRACT_32BITS(&opm->nd_opt_mtu_mtu),
(op->nd_opt_len != 1) ? "bad option length" : "" );
break;
+ case ND_OPT_RDNSS:
+ oprd = (struct nd_opt_rdnss *)op;
+ l = (op->nd_opt_len - 1) / 2;
+ printf(" lifetime %us,",
+ EXTRACT_32BITS(&oprd->nd_opt_rdnss_lifetime));
+ for (i = 0; i < l; i++) {
+ TCHECK(oprd->nd_opt_rdnss_addr[i]);
+ printf(" addr: %s",
+ ip6addr_string(&oprd->nd_opt_rdnss_addr[i]));
+ }
+ break;
+ case ND_OPT_DNSSL:
+ opds = (struct nd_opt_dnssl *)op;
+ printf(" lifetime %us, domain(s):",
+ EXTRACT_32BITS(&opds->nd_opt_dnssl_lifetime));
+ domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */
+ while (domp < cp + (op->nd_opt_len << 3) && *domp != '\0')
+ {
+ printf (" ");
+ if ((domp = ns_nprint (domp, bp)) == NULL)
+ goto trunc;
+ }
+ break;
case ND_OPT_ADVINTERVAL:
opa = (struct nd_opt_advinterval *)op;
TCHECK(opa->nd_opt_adv_interval);
- printf(" %us", EXTRACT_32BITS(&opa->nd_opt_adv_interval));
+ printf(" %ums", EXTRACT_32BITS(&opa->nd_opt_adv_interval));
break;
case ND_OPT_HOMEAGENT_INFO:
oph = (struct nd_opt_homeagent_info *)op;
@@ -753,7 +847,7 @@ mldv2_report_print(const u_char *bp, u_int len)
}
TCHECK(icp->icmp6_data16[1]);
- ngroups = ntohs(icp->icmp6_data16[1]);
+ ngroups = EXTRACT_16BITS(&icp->icmp6_data16[1]);
printf(", %d group record(s)", ngroups);
if (vflag > 0) {
/* Print the group records */
@@ -812,7 +906,7 @@ mldv2_query_print(const u_char *bp, u_int len)
return;
}
TCHECK(icp->icmp6_data16[0]);
- mrc = ntohs(icp->icmp6_data16[0]);
+ mrc = EXTRACT_16BITS(&icp->icmp6_data16[0]);
if (mrc < 32768) {
mrt = mrc;
} else {
@@ -841,7 +935,7 @@ mldv2_query_print(const u_char *bp, u_int len)
}
TCHECK2(bp[26], 2);
- nsrcs = ntohs(*(u_short *)&bp[26]);
+ nsrcs = EXTRACT_16BITS(&bp[26]);
if (nsrcs > 0) {
if (len < 28 + nsrcs * sizeof(struct in6_addr))
printf(" [invalid number of sources]");
@@ -863,7 +957,7 @@ trunc:
return;
}
-void
+static void
dnsname_print(const u_char *cp, const u_char *ep)
{
int i;
@@ -1192,9 +1286,9 @@ icmp6_rrenum_print(const u_char *bp, const u_char *ep)
F(ICMP6_RR_FLAGS_PREVDONE, "P"));
}
printf("seg=%u,", rr6->rr_segnum);
- printf("maxdelay=%u", rr6->rr_maxdelay);
+ printf("maxdelay=%u", EXTRACT_16BITS(&rr6->rr_maxdelay));
if (rr6->rr_reserved)
- printf("rsvd=0x%x", EXTRACT_16BITS(&rr6->rr_reserved));
+ printf("rsvd=0x%x", EXTRACT_32BITS(&rr6->rr_reserved));
/*[*/
printf("]");
#undef F