]> The Tcpdump Group git mirrors - libpcap/commitdiff
Not releasing a packet in Linux memory-mapped mode until we try to read
authorGuy Harris <[email protected]>
Fri, 3 Jul 2009 21:37:06 +0000 (14:37 -0700)
committerGuy Harris <[email protected]>
Fri, 3 Jul 2009 21:37:06 +0000 (14:37 -0700)
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.

pcap-int.h
pcap-linux.c

index 77612dd5c7eed0ba8c43210e3e50e6fa46ac957d..c662f848c1322e29fda024c07a9eacbc5af4a35b 100644 (file)
@@ -109,14 +109,6 @@ struct pcap_sf {
        u_char *base;
 };
 
-#ifdef linux
-union thdr {
-       struct tpacket_hdr      *h1;
-       struct tpacket2_hdr     *h2;
-       void                    *raw;
-};
-#endif
-
 /*
  * Used when doing a live capture.
  */
@@ -143,7 +135,6 @@ struct pcap_md {
        char    *mondevice;     /* mac80211 monitor device we created */
        u_int   tp_version;     /* version of tpacket_hdr for mmaped ring */
        u_int   tp_hdrlen;      /* hdrlen of tpacket_hdr for mmaped ring */
-       union thdr prev_pkt;    /* previous packet handed to the callback */
 #endif /* linux */
 
 #ifdef HAVE_DAG_API
index 0150226b31509de3060854e991bf38013a3e9430..0c6cf3d589d6f31a5ed716c9d990e0da31409e8b 100644 (file)
@@ -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;