aboutsummaryrefslogtreecommitdiffstats
path: root/pcap-linux.c
diff options
context:
space:
mode:
authorGuy Harris <gharris@steve.local>2009-07-03 14:37:06 -0700
committerGuy Harris <gharris@steve.local>2009-07-03 14:37:06 -0700
commit703acf10e7b3a128c426937712cd12ae65e3b1e9 (patch)
tree2b5d4167682f44a3f184a868b9fa81af7a26346f /pcap-linux.c
parentb43a22e65e685d03e435a9edc0138a797e771009 (diff)
Not releasing a packet in Linux memory-mapped mode until we try to read
the next packet breaks select(). Back those changes out; we'll have to fix the behavior of pcap_next* by making a copy of the packet.
Diffstat (limited to 'pcap-linux.c')
-rw-r--r--pcap-linux.c77
1 files changed, 17 insertions, 60 deletions
diff --git a/pcap-linux.c b/pcap-linux.c
index 0150226..0c6cf3d 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -295,6 +295,12 @@ static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
static int pcap_setdirection_linux(pcap_t *, pcap_direction_t);
static void pcap_cleanup_linux(pcap_t *);
+union thdr {
+ struct tpacket_hdr *h1;
+ struct tpacket2_hdr *h2;
+ void *raw;
+};
+
#ifdef HAVE_PACKET_RING
#define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset])
@@ -2739,24 +2745,6 @@ pcap_get_ring_frame(pcap_t *handle, int status)
return h.raw;
}
-static inline void
-pcap_release_previous_ring_frame(pcap_t *handle)
-{
- if (handle->md.prev_pkt.raw != NULL) {
- switch (handle->md.tp_version) {
- case TPACKET_V1:
- handle->md.prev_pkt.h1->tp_status = TP_STATUS_KERNEL;
- break;
-#ifdef HAVE_TPACKET2
- case TPACKET_V2:
- handle->md.prev_pkt.h2->tp_status = TP_STATUS_KERNEL;
- break;
-#endif
- }
- handle->md.prev_pkt.raw = NULL;
- }
-}
-
static int
pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
u_char *user)
@@ -2804,44 +2792,10 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
unsigned int tp_sec;
unsigned int tp_usec;
- /*
- * Check for break loop condition; a callback might have
- * set it.
- */
- if (handle->break_loop) {
- handle->break_loop = 0;
- return -2;
- }
-
h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
if (!h.raw)
break;
- /*
- * We have a packet; release the previous packet,
- * if any.
- *
- * Libpcap has never guaranteed that, if we get a
- * packet from the underlying packet capture
- * mechanism, the data passed to callbacks for
- * any previous packets is still valid. It did
- * implicitly guarantee that the data will still
- * be available after the callback returns, by
- * virtue of implementing pcap_next() by calling
- * pcap_dispatch() with a count of 1 and a callback
- * that fills in a structure with a pointer to
- * the packet data, meaning that pointer is
- * expected to point to valid data after the
- * callback returns and pcap_next() returns,
- * so we can't release the packet when the
- * callback returns.
- *
- * Therefore, we remember the packet that
- * needs to be released after handing it
- * to the callback, and release it up here.
- */
- pcap_release_previous_ring_frame(handle);
-
switch (handle->md.tp_version) {
case TPACKET_V1:
tp_len = h.h1->tp_len;
@@ -2992,14 +2946,17 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
handle->md.packets_read++;
skip:
- /*
- * As per the comment above, we can't yet release this
- * packet, even though the callback has returned, as
- * some users of pcap_loop() and pcap_dispatch() - such
- * as pcap_next() and pcap_next_ex() - expect the packet
- * to be available until the next pcap_dispatch() call.
- */
- handle->md.prev_pkt = h;
+ /* next packet */
+ switch (handle->md.tp_version) {
+ case TPACKET_V1:
+ h.h1->tp_status = TP_STATUS_KERNEL;
+ break;
+#ifdef HAVE_TPACKET2
+ case TPACKET_V2:
+ h.h2->tp_status = TP_STATUS_KERNEL;
+ break;
+#endif
+ }
if (++handle->offset >= handle->cc)
handle->offset = 0;