Hello,

I also hit this bug and had to rebuild libpcap0.8, which fixed the issue
(since I'm using 2.6.28).
I had to work around this interface problem for older kernels in my
application, and came up with the following solution.  We may wish to
consider a this workaround to avoid breakage on kernels older than
2.6.27.

Tested on 2.6.28 with HAVE_TPACKET2 purposely undeffed.  Verified with
strace that it is working as expected from 32 bit userland to 64 bit
kernel even with TPACKET_V1.

Simon-
diff --git a/pcap-linux.c b/pcap-linux.c
index 8161af0..1fe5d41 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -2198,7 +2198,7 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
 		struct sockaddr_ll *sll;
 		struct pcap_pkthdr pcaphdr;
 		unsigned char *bp;
-		union thdr h;
+		union thdr h,h32;
 		unsigned int tp_len;
 		unsigned int tp_mac;
 		unsigned int tp_snaplen;
@@ -2211,11 +2211,24 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
 
 		switch (handle->md.tp_version) {
 		case TPACKET_V1:
-			tp_len	   = h.h1->tp_len;
-			tp_mac	   = h.h1->tp_mac;
-			tp_snaplen = h.h1->tp_snaplen;
-			tp_sec	   = h.h1->tp_sec;
-			tp_usec	   = h.h1->tp_usec;
+			/*
+			 * Work around the "unsigned long tp_status"
+			 * problem 32 bit userland and 64 bit kernel by
+			 * offsetting the rest of the reads if tp_len
+			 * reads as zero.  On little-endian machines,
+			 * tp_status will still update and everything
+			 * will work with this workaround.  TPACKET_V2
+			 * was introduced to solve this in 2.6.27.
+			 * -Simon, 2009-03-19
+			 */
+			h32.raw = h.raw;
+			if (h32.h1->tp_len == 0)
+				h32.raw = (unsigned char *)h.raw + 4;
+			tp_len	   = h32.h1->tp_len;
+			tp_mac	   = h32.h1->tp_mac;
+			tp_snaplen = h32.h1->tp_snaplen;
+			tp_sec	   = h32.h1->tp_sec;
+			tp_usec	   = h32.h1->tp_usec;
 			break;
 #ifdef HAVE_TPACKET2
 		case TPACKET_V2:

Reply via email to