Hi, IP header is not always aligned since bpf copies out the mbuf chain into the contigous buffer provided by the userland. I've seen this with large packet sizes on VLANs. ip_print will then copy the packet but the Ethernet header into the internal buffer so that it can cast it to the IP header structure and update global packetp and snapend pointers hence preventing the -Xx dumping code from printing out the Ethernet header itself.
Diff below fixes it. OK? diff --git usr.sbin/tcpdump/print-ip.c usr.sbin/tcpdump/print-ip.c index 3f4194c..6d90b3d 100644 --- usr.sbin/tcpdump/print-ip.c +++ usr.sbin/tcpdump/print-ip.c @@ -252,7 +252,7 @@ ip_printroute(const char *type, register const u_char *cp, u_int length) * print IP options. */ static void -ip_optprint(register const u_char *cp, u_int length) +ip_optprint(register const u_char *cp, u_char *send, u_int length) { register u_int len; int tt; @@ -265,7 +265,7 @@ ip_optprint(register const u_char *cp, u_int length) printf("[|ip op len %d]", len); return; } - if (&cp[1] >= snapend || cp + len > snapend) { + if (&cp[1] >= send || cp + len > send) { printf("[|ip]"); return; } @@ -356,12 +356,11 @@ ip_print(register const u_char *bp, register u_int length) register const struct ip *ip; register u_int hlen, len, off; register const u_char *cp; + u_char *send = snapend; ip = (const struct ip *)bp; /* * If the IP header is not aligned, copy into abuf. - * This will never happen with BPF. It does happen with raw packet - * dumps from -r. */ if ((intptr_t)ip & (sizeof(long)-1)) { static u_char *abuf = NULL; @@ -376,8 +375,7 @@ ip_print(register const u_char *bp, register u_int length) error("ip_print: malloc"); } memmove((char *)abuf, (char *)ip, min(length, clen)); - snapend = abuf + clen; - packetp = abuf; + send = abuf + clen; ip = (struct ip *)abuf; /* We really want libpcap to give us aligned packets */ if (!didwarn) { @@ -538,7 +536,7 @@ ip_print(register const u_char *bp, register u_int length) #define IPPROTO_ETHERIP 97 #endif case IPPROTO_ETHERIP: - etherip_print(cp, snapend - cp, len, + etherip_print(cp, send - cp, len, (const u_char *)ip); break; @@ -573,7 +571,7 @@ ip_print(register const u_char *bp, register u_int length) #endif case IPPROTO_PFSYNC: pfsync_ip_print(cp, - (int)(snapend - (u_char *)ip) - hlen, + (int)(send - (u_char *)ip) - hlen, (const u_char *)ip); break; @@ -638,7 +636,7 @@ ip_print(register const u_char *bp, register u_int length) } (void)printf("%slen %u", sep, ntohs(ip->ip_len)); sep = ", "; - if ((u_char *)ip + hlen <= snapend) { + if ((u_char *)ip + hlen <= send) { u_int16_t sum, ip_sum; sum = in_cksum((const u_short *)ip, hlen, 0); if (sum != 0) { @@ -651,7 +649,7 @@ ip_print(register const u_char *bp, register u_int length) if (hlen > sizeof(struct ip)) { hlen -= sizeof(struct ip); (void)printf("%soptlen=%d", sep, hlen); - ip_optprint((u_char *)(ip + 1), hlen); + ip_optprint((u_char *)(ip + 1), send, hlen); } printf(")"); }