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(")");
        }

Reply via email to