tag 623868 + patch
thanks

Robert Edmonds wrote:
> this is fixed in upstream commit ea9432fabdf4b33cbc76d9437200e028f1c47c93,
> "Fix the calculation of the frame size in memory-mapped captures."

attached is a backport of this commit to 1.1.1, and a patch to the
debian package containing the fix.

-- 
Robert Edmonds
edmo...@debian.org
From cc4298babe767e394dc673c87ef3dbabe3fdb7c9 Mon Sep 17 00:00:00 2001
From: Julien Moutinho <j...@savines.alpes.fr.eu.org>
Date: Tue, 22 Mar 2011 23:53:15 -0700
Subject: [PATCH] Fix the calculation of the frame size in memory-mapped
 captures.

The old calculation truncated packets to a smaller value than the
snapshot length.
---
 pcap-linux.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/pcap-linux.c b/pcap-linux.c
index af12543..74ac21f 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -3057,15 +3057,58 @@ create_ring(pcap_t *handle)
 {
 	unsigned i, j, frames_per_block;
 	struct tpacket_req req;
+	socklen_t len;
+	unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff;
 
 	/* Note that with large snapshot (say 64K) only a few frames 
 	 * will be available in the ring even with pretty large ring size
 	 * (and a lot of memory will be unused). 
 	 * The snap len should be carefully chosen to achive best
 	 * performance */
-	req.tp_frame_size = TPACKET_ALIGN(handle->snapshot +
-					  TPACKET_ALIGN(handle->md.tp_hdrlen) +
-					  sizeof(struct sockaddr_ll));
+	
+	/* NOTE: calculus matching those in tpacket_rcv()
+	 * in linux-2.6/net/packet/af_packet.c
+	 */
+	len = sizeof(sk_type);
+	if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type, &len) < 0) {
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno));
+		return -1;
+	}
+	len = sizeof(tp_reserve);
+	if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve, &len) < 0) {
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno));
+		return -1;
+	}
+	maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE;
+		/* XXX: in the kernel maclen is calculated from
+		 * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len
+		 * in:  packet_snd()           in linux-2.6/net/packet/af_packet.c
+		 * then packet_alloc_skb()     in linux-2.6/net/packet/af_packet.c
+		 * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c
+		 * but I see no way to get those sizes in userspace,
+		 * like for instance with an ifreq ioctl();
+		 * the best thing I've found so far is MAX_HEADER in the kernel
+		 * part of linux-2.6/include/linux/netdevice.h
+		 * which goes up to 128+48=176; since pcap-linux.c defines
+		 * a MAX_LINKHEADER_SIZE of 256 which is greater than that,
+		 * let's use it.. maybe is it even large enough to directly
+		 * replace macoff..
+		 */
+	tp_hdrlen = TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll) ;
+	netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve;
+		/* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN of
+		 * netoff, which contradicts
+		 * linux-2.6/Documentation/networking/packet_mmap.txt
+		 * documenting that:
+		 * "- Gap, chosen so that packet data (Start+tp_net)
+		 * aligns to TPACKET_ALIGNMENT=16"
+		 */
+		/* NOTE: in linux-2.6/include/linux/skbuff.h:
+		 * "CPUs often take a performance hit
+		 *  when accessing unaligned memory locations"
+		 */
+	macoff = netoff - maclen;
+	req.tp_frame_size = TPACKET_ALIGN(macoff + handle->snapshot);
 	req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
 
 	/* compute the minumum block size that will handle this frame. 
-- 
1.7.4.4

From 3e977e81063366e5634695f99afdd7a85f63a287 Mon Sep 17 00:00:00 2001
From: Robert S. Edmonds <edmo...@debian.org>
Date: Sat, 23 Apr 2011 22:37:01 -0400
Subject: [PATCH] backport commit ea9432fabd from upstream for #623868

---
 debian/changelog                         |    4 ++
 debian/patches/60_tpacket_alignment.diff |   81 ++++++++++++++++++++++++++++++
 debian/patches/series                    |    1 +
 3 files changed, 86 insertions(+), 0 deletions(-)
 create mode 100644 debian/patches/60_tpacket_alignment.diff

diff --git a/debian/changelog b/debian/changelog
index f99c8d1..dcd4fe5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -4,6 +4,10 @@ libpcap (1.1.1-4) UNRELEASED; urgency=low
     when the bonding module is loaded (closes: #612803).
   * debian/patches/50_kfreebsd.diff: Enable zerocopy BPF again.
 
+  [ Robert S. Edmonds ]
+  * Backport commit ea9432fabd from upstream to fix corruption of snapshot
+    length on live captures (closes: #623868).
+
  -- Romain Francoise <rfranco...@debian.org>  Sat, 16 Apr 2011 15:49:38 +0200
 
 libpcap (1.1.1-3) unstable; urgency=low
diff --git a/debian/patches/60_tpacket_alignment.diff b/debian/patches/60_tpacket_alignment.diff
new file mode 100644
index 0000000..e68e2e6
--- /dev/null
+++ b/debian/patches/60_tpacket_alignment.diff
@@ -0,0 +1,81 @@
+From cc4298babe767e394dc673c87ef3dbabe3fdb7c9 Mon Sep 17 00:00:00 2001
+From: Julien Moutinho <j...@savines.alpes.fr.eu.org>
+Date: Tue, 22 Mar 2011 23:53:15 -0700
+Subject: [PATCH] Fix the calculation of the frame size in memory-mapped
+ captures.
+
+The old calculation truncated packets to a smaller value than the
+snapshot length.
+---
+ pcap-linux.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++---
+ 1 files changed, 46 insertions(+), 3 deletions(-)
+
+diff --git a/pcap-linux.c b/pcap-linux.c
+index af12543..74ac21f 100644
+--- a/pcap-linux.c
++++ b/pcap-linux.c
+@@ -3057,15 +3057,58 @@ create_ring(pcap_t *handle)
+ {
+ 	unsigned i, j, frames_per_block;
+ 	struct tpacket_req req;
++	socklen_t len;
++	unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff;
+ 
+ 	/* Note that with large snapshot (say 64K) only a few frames 
+ 	 * will be available in the ring even with pretty large ring size
+ 	 * (and a lot of memory will be unused). 
+ 	 * The snap len should be carefully chosen to achive best
+ 	 * performance */
+-	req.tp_frame_size = TPACKET_ALIGN(handle->snapshot +
+-					  TPACKET_ALIGN(handle->md.tp_hdrlen) +
+-					  sizeof(struct sockaddr_ll));
++	
++	/* NOTE: calculus matching those in tpacket_rcv()
++	 * in linux-2.6/net/packet/af_packet.c
++	 */
++	len = sizeof(sk_type);
++	if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type, &len) < 0) {
++		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno));
++		return -1;
++	}
++	len = sizeof(tp_reserve);
++	if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve, &len) < 0) {
++		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno));
++		return -1;
++	}
++	maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE;
++		/* XXX: in the kernel maclen is calculated from
++		 * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len
++		 * in:  packet_snd()           in linux-2.6/net/packet/af_packet.c
++		 * then packet_alloc_skb()     in linux-2.6/net/packet/af_packet.c
++		 * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c
++		 * but I see no way to get those sizes in userspace,
++		 * like for instance with an ifreq ioctl();
++		 * the best thing I've found so far is MAX_HEADER in the kernel
++		 * part of linux-2.6/include/linux/netdevice.h
++		 * which goes up to 128+48=176; since pcap-linux.c defines
++		 * a MAX_LINKHEADER_SIZE of 256 which is greater than that,
++		 * let's use it.. maybe is it even large enough to directly
++		 * replace macoff..
++		 */
++	tp_hdrlen = TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll) ;
++	netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve;
++		/* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN of
++		 * netoff, which contradicts
++		 * linux-2.6/Documentation/networking/packet_mmap.txt
++		 * documenting that:
++		 * "- Gap, chosen so that packet data (Start+tp_net)
++		 * aligns to TPACKET_ALIGNMENT=16"
++		 */
++		/* NOTE: in linux-2.6/include/linux/skbuff.h:
++		 * "CPUs often take a performance hit
++		 *  when accessing unaligned memory locations"
++		 */
++	macoff = netoff - maclen;
++	req.tp_frame_size = TPACKET_ALIGN(macoff + handle->snapshot);
+ 	req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
+ 
+ 	/* compute the minumum block size that will handle this frame. 
+-- 
+1.7.4.4
+
diff --git a/debian/patches/series b/debian/patches/series
index 4a9498b..80180e4 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -6,3 +6,4 @@
 50_kfreebsd.diff
 55_hurd.diff
 50_autotools-dev.diff
+60_tpacket_alignment.diff
-- 
1.7.4.4

Attachment: signature.asc
Description: Digital signature

Reply via email to