diff --git a/dlpisubs.c b/dlpisubs.c index e1a64492d4..632b0c94c6 100644 --- a/dlpisubs.c +++ b/dlpisubs.c @@ -166,8 +166,7 @@ pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user, */ if (p->break_loop) { if (n == 0) { - p->break_loop = 0; - return (-2); + return PCAP_ERROR_BREAK; } else { p->bp = bufp; p->cc = ep - bufp; diff --git a/pcap-bpf.c b/pcap-bpf.c index 7d29be2017..5d9e72a5f9 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -1190,15 +1190,9 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* * Has "pcap_breakloop()" been called? */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates that it - * has, and return PCAP_ERROR_BREAK to indicate - * that we were told to break out of the loop. - */ - p->break_loop = 0; + if (p->break_loop) return (PCAP_ERROR_BREAK); - } + cc = p->cc; if (p->cc == 0) { /* @@ -1348,10 +1342,9 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) if (p->break_loop) { p->bp = bp; p->cc = (u_int)(ep - bp); - if (n == 0) { - p->break_loop = 0; + if (n == 0) return (PCAP_ERROR_BREAK); - } else + else return (n); } diff --git a/pcap-bt-linux.c b/pcap-bt-linux.c index 67d357c4d8..c22c9773ac 100644 --- a/pcap-bt-linux.c +++ b/pcap-bt-linux.c @@ -338,10 +338,8 @@ bt_read_linux(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char /* ignore interrupt system call error */ do { if (handle->break_loop) - { - handle->break_loop = 0; return PCAP_ERROR_BREAK; - } + ret = recvmsg(handle->fd, &msg, 0); } while ((ret == -1) && (errno == EINTR)); diff --git a/pcap-bt-monitor-linux.c b/pcap-bt-monitor-linux.c index 44d40e2efc..2e1f614e84 100644 --- a/pcap-bt-monitor-linux.c +++ b/pcap-bt-monitor-linux.c @@ -118,10 +118,8 @@ bt_monitor_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_ch do { if (handle->break_loop) - { - handle->break_loop = 0; return PCAP_ERROR_BREAK; - } + ret = recvmsg(handle->fd, &msg, 0); } while ((ret == -1) && (errno == EINTR)); diff --git a/pcap-dag.c b/pcap-dag.c index 147479ca01..20fc15e099 100644 --- a/pcap-dag.c +++ b/pcap-dag.c @@ -334,15 +334,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* * Has "pcap_breakloop()" been called? */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates that - * it has, and return PCAP_ERROR_BREAK to indicate that - * we were told to break out of the loop. - */ - p->break_loop = 0; + if (p->break_loop) return PCAP_ERROR_BREAK; - } /* dag_advance_stream() will block (unless nonblock is called) * until 64kB of data has accumulated. @@ -395,15 +388,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* * Has "pcap_breakloop()" been called? */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates that - * it has, and return PCAP_ERROR_BREAK to indicate that - * we were told to break out of the loop. - */ - p->break_loop = 0; + if (p->break_loop) return PCAP_ERROR_BREAK; - } rlen = ntohs(header->rlen); if (rlen < dag_record_size) diff --git a/pcap-dbus.c b/pcap-dbus.c index d29fb81d36..31c204d1ef 100644 --- a/pcap-dbus.c +++ b/pcap-dbus.c @@ -70,10 +70,8 @@ dbus_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *us return -1; } - if (handle->break_loop) { - handle->break_loop = 0; - return -2; - } + if (handle->break_loop) + return PCAP_ERROR_BREAK; message = dbus_connection_pop_message(handlep->conn); } diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 1cb680bb11..51bf5f8eec 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -180,16 +180,9 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* * Has "pcap_breakloop()" been called? */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates - * that it has, and return -2 to - * indicate that we were told to - * break out of the loop. - */ - p->break_loop = 0; - return (-2); - } + if (p->break_loop) + return PCAP_ERROR_BREAK; + /* * XXX - check for the DLPI primitive, which * would be DL_HP_RAWDATA_IND on HP-UX diff --git a/pcap-dpdk.c b/pcap-dpdk.c index 76de9b7690..3c2f6e6512 100644 --- a/pcap-dpdk.c +++ b/pcap-dpdk.c @@ -353,7 +353,6 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c while( pkt_cnt < max_cnt){ if (p->break_loop){ - p->break_loop = 0; return PCAP_ERROR_BREAK; } // read once in non-blocking mode, or try many times waiting for timeout_ms. @@ -365,9 +364,7 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c }else{ if (p->break_loop){ RTE_LOG(DEBUG, USER1, "dpdk: no packets available and break_loop is set in blocking mode.\n"); - p->break_loop = 0; return PCAP_ERROR_BREAK; - } RTE_LOG(DEBUG, USER1, "dpdk: no packets available for timeout %d ms in blocking mode.\n", timeout_ms); } diff --git a/pcap-haiku.c b/pcap-haiku.c index 9a2d6cf4c2..54509dc67e 100644 --- a/pcap-haiku.c +++ b/pcap-haiku.c @@ -62,7 +62,6 @@ pcap_read_haiku(pcap_t* handle, int maxPackets _U_, pcap_handler callback, ssize_t bytesReceived; do { if (handle->break_loop) { - handle->break_loop = 0; return PCAP_ERROR_BREAK; } bytesReceived = recvfrom(handle->fd, buffer, handle->bufsize, MSG_TRUNC, diff --git a/pcap-hurd.c b/pcap-hurd.c index 134a109b35..fc527c1076 100644 --- a/pcap-hurd.c +++ b/pcap-hurd.c @@ -134,10 +134,8 @@ pcap_read_hurd(pcap_t *p, int cnt _U_, pcap_handler callback, u_char *user) msg = (struct net_rcv_msg *)p->buffer; retry: - if (p->break_loop) { - p->break_loop = 0; + if (p->break_loop) return PCAP_ERROR_BREAK; - } kr = mach_msg(&msg->msg_hdr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, p->bufsize, ph->rcv_port, MACH_MSG_TIMEOUT_NONE, diff --git a/pcap-int.h b/pcap-int.h index d154f00e5d..6bce067ae6 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -183,7 +183,7 @@ typedef int (*set_datalink_op_t)(pcap_t *, int); typedef int (*getnonblock_op_t)(pcap_t *); typedef int (*setnonblock_op_t)(pcap_t *, int); typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *); -typedef void (*breakloop_op_t)(pcap_t *); +typedef void (*breakloop_op_t)(pcap_t *, int); #ifdef _WIN32 typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *); typedef int (*setbuff_op_t)(pcap_t *, int); @@ -199,6 +199,12 @@ typedef int (*live_dump_ended_op_t)(pcap_t *, int); #endif typedef void (*cleanup_op_t)(pcap_t *); +enum { + PCAPINT_BREAK_RUN = 0, + PCAPINT_BREAK_IMMEDIATE, + PCAPINT_BREAK_FLUSH, +}; + /* * We put all the stuff used in the read code path at the beginning, * to try to keep it together in the same cache line or lines. @@ -228,7 +234,8 @@ struct pcap { u_char *bp; u_int cc; - sig_atomic_t break_loop; /* flag set to force break from packet-reading loop */ + /* break packet-reading loop, will be set to one of PCAPINT_BREAK_* */ + sig_atomic_t break_loop; void *priv; /* private data for methods */ @@ -433,7 +440,7 @@ void pcapint_add_to_pcaps_to_close(pcap_t *); void pcapint_remove_from_pcaps_to_close(pcap_t *); void pcapint_cleanup_live_common(pcap_t *); int pcapint_check_activated(pcap_t *); -void pcapint_breakloop_common(pcap_t *); +void pcapint_breakloop_common(pcap_t *, int mode); /* * Internal interfaces for "pcap_findalldevs()". diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c index 67cb58580b..474b4d7c2d 100644 --- a/pcap-libdlpi.c +++ b/pcap-libdlpi.c @@ -410,15 +410,8 @@ pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user) } do { /* Has "pcap_breakloop()" been called? */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates that it has, - * and return -2 to indicate that we were told to - * break out of the loop. - */ - p->break_loop = 0; - return (-2); - } + if (p->break_loop) + return PCAP_ERROR_BREAK; msglen = p->bufsize; bufp = p->buffer + p->offset; diff --git a/pcap-linux.c b/pcap-linux.c index fc459ece10..6d407357df 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -1106,9 +1106,9 @@ set_poll_timeout(struct pcap_linux *handlep) } } -static void pcap_breakloop_linux(pcap_t *handle) +static void pcap_breakloop_linux(pcap_t *handle, int mode) { - pcapint_breakloop_common(handle); + pcapint_breakloop_common(handle, mode); struct pcap_linux *handlep = handle->priv; uint64_t value = 1; @@ -3676,10 +3676,8 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle) * It's EINTR; if we were told to break out of * the loop, do so. */ - if (handle->break_loop) { - handle->break_loop = 0; - return PCAP_ERROR_BREAK; - } + if (handle->break_loop) + return 0; } else if (ret > 0) { /* * OK, some descriptor is ready. @@ -3826,10 +3824,8 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle) * pcap_breakloop() call; if we were told * to break out of the loop, do so. */ - if (handle->break_loop) { - handle->break_loop = 0; - return PCAP_ERROR_BREAK; - } + if (handle->break_loop) + return 0; } } @@ -4344,17 +4340,24 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback, int pkts = 0; int ret; + /* Stop processing if we should break out immediately */ + if (handle->break_loop == PCAPINT_BREAK_IMMEDIATE) + return PCAP_ERROR_BREAK; + /* wait for frames availability.*/ h.raw = RING_GET_CURRENT_FRAME(handle); - if (!packet_mmap_acquire(h.h2)) { + if (!handle->break_loop && !packet_mmap_acquire(h.h2)) { /* * The current frame is owned by the kernel; wait for * a frame to be handed to us. */ ret = pcap_wait_for_frames_mmap(handle); - if (ret) { + if (ret) return ret; - } + + /* We may have received an immediate break while polling */ + if (handle->break_loop == PCAPINT_BREAK_IMMEDIATE) + return PCAP_ERROR_BREAK; } /* @@ -4422,12 +4425,15 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback, if (++handle->offset >= handle->cc) handle->offset = 0; - /* check for break loop condition*/ - if (handle->break_loop) { - handle->break_loop = 0; - return PCAP_ERROR_BREAK; - } + /* Abort processing if requested */ + if (handle->break_loop == PCAPINT_BREAK_IMMEDIATE) + break; } + + /* All packets are drained, report loop break */ + if (pkts == 0 && handle->break_loop) + return PCAP_ERROR_BREAK; + return pkts; } @@ -4451,7 +4457,7 @@ pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback, * for a frame to be handed to us. */ ret = pcap_wait_for_frames_mmap(handle); - if (ret) { + if (ret && ret != PCAP_ERROR_BREAK) { return ret; } } @@ -4557,10 +4563,8 @@ pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback, } /* check for break loop condition*/ - if (handle->break_loop) { - handle->break_loop = 0; + if (handle->break_loop) return PCAP_ERROR_BREAK; - } } if (pkts == 0 && handlep->timeout == 0) { /* Block until we see a packet. */ diff --git a/pcap-netfilter-linux.c b/pcap-netfilter-linux.c index 90296be71b..16b6738238 100644 --- a/pcap-netfilter-linux.c +++ b/pcap-netfilter-linux.c @@ -92,12 +92,6 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c * Has "pcap_breakloop()" been called? */ if (handle->break_loop) { - /* - * Yes - clear the flag that indicates that it - * has, and return PCAP_ERROR_BREAK to indicate - * that we were told to break out of the loop. - */ - handle->break_loop = 0; return PCAP_ERROR_BREAK; } cc = handle->cc; @@ -116,7 +110,6 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c do { read_ret = recv(handle->fd, handle->buffer, handle->bufsize, 0); if (handle->break_loop) { - handle->break_loop = 0; return PCAP_ERROR_BREAK; } if (read_ret == -1 && errno == ENOBUFS) @@ -165,7 +158,6 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c handle->bp = bp; handle->cc = (u_int)(ep - bp); if (count == 0) { - handle->break_loop = 0; return PCAP_ERROR_BREAK; } else return count; diff --git a/pcap-netmap.c b/pcap-netmap.c index 56a6bc4180..227a75f57c 100644 --- a/pcap-netmap.c +++ b/pcap-netmap.c @@ -97,10 +97,9 @@ pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user) pn->cb_arg = user; for (;;) { - if (p->break_loop) { - p->break_loop = 0; + if (p->break_loop) return PCAP_ERROR_BREAK; - } + /* nm_dispatch won't run forever */ ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p); diff --git a/pcap-npf.c b/pcap-npf.c index 4feee30cfd..f54ad545c4 100644 --- a/pcap-npf.c +++ b/pcap-npf.c @@ -555,15 +555,8 @@ pcap_read_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* * Has "pcap_breakloop()" been called? */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates that it - * has, and return PCAP_ERROR_BREAK to indicate - * that we were told to break out of the loop. - */ - p->break_loop = 0; + if (p->break_loop) return (PCAP_ERROR_BREAK); - } /* * Capture the packets. @@ -668,7 +661,6 @@ pcap_read_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) */ if (p->break_loop) { if (n == 0) { - p->break_loop = 0; return (PCAP_ERROR_BREAK); } else { p->bp = bp; @@ -812,9 +804,9 @@ pcap_cleanup_npf(pcap_t *p) } static void -pcap_breakloop_npf(pcap_t *p) +pcap_breakloop_npf(pcap_t *p, int mode) { - pcapint_breakloop_common(p); + pcapint_breakloop_common(p, mode); struct pcap_win *pw = p->priv; /* XXX - what if this fails? */ diff --git a/pcap-rdmasniff.c b/pcap-rdmasniff.c index ba4705b71a..022350c28f 100644 --- a/pcap-rdmasniff.c +++ b/pcap-rdmasniff.c @@ -126,7 +126,6 @@ rdmasniff_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u return PCAP_ERROR; } if (handle->break_loop) { - handle->break_loop = 0; return PCAP_ERROR_BREAK; } } @@ -179,7 +178,6 @@ rdmasniff_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u rdmasniff_post_recv(handle, wc.wr_id); if (handle->break_loop) { - handle->break_loop = 0; return PCAP_ERROR_BREAK; } } diff --git a/pcap-rpcap.c b/pcap-rpcap.c index fd3cf6abb9..a5eaf3a9f4 100644 --- a/pcap-rpcap.c +++ b/pcap-rpcap.c @@ -671,15 +671,8 @@ static int pcap_read_rpcap(pcap_t *p, int cnt, pcap_handler callback, u_char *us /* * Has "pcap_breakloop()" been called? */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates that it - * has, and return PCAP_ERROR_BREAK to indicate - * that we were told to break out of the loop. - */ - p->break_loop = 0; + if (p->break_loop) return (PCAP_ERROR_BREAK); - } /* * Read some packets. @@ -713,13 +706,9 @@ static int pcap_read_rpcap(pcap_t *p, int cnt, pcap_handler callback, u_char *us * * Were we told to break out of the loop? */ - if (p->break_loop) { - /* - * Yes. - */ - p->break_loop = 0; + if (p->break_loop) return (PCAP_ERROR_BREAK); - } + /* No - return the number of packets we've processed. */ return n; } diff --git a/pcap-snf.c b/pcap-snf.c index 72ed13d62a..2adc772867 100644 --- a/pcap-snf.c +++ b/pcap-snf.c @@ -151,7 +151,6 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) */ if (p->break_loop) { if (n == 0) { - p->break_loop = 0; return PCAP_ERROR_BREAK; } else { return (n); diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c index 4287585f15..eba19696ef 100644 --- a/pcap-usb-linux.c +++ b/pcap-usb-linux.c @@ -670,10 +670,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets _U_, pcap_handler callback, u do { ret = ioctl(handle->fd, MON_IOCX_GET, &info); if (handle->break_loop) - { - handle->break_loop = 0; - return -2; - } + return PCAP_ERROR_BREAK; } while ((ret == -1) && (errno == EINTR)); if (ret < 0) { @@ -800,10 +797,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch do { ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch); if (handle->break_loop) - { - handle->break_loop = 0; - return -2; - } + return PCAP_ERROR_BREAK; } while ((ret == -1) && (errno == EINTR)); if (ret < 0) { diff --git a/pcap.c b/pcap.c index ebb0c9e978..62fe0f7872 100644 --- a/pcap.c +++ b/pcap.c @@ -569,6 +569,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data) { struct oneshot_userdata s; + int ret; s.hdr = &p->pcap_header; s.pkt = pkt_data; @@ -615,7 +616,9 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, * The first one ('0') conflicts with the return code of 0 from * pcapint_offline_read() meaning "end of file". */ - return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s)); + ret = p->read_op(p, 1, p->oneshot_callback, (u_char *)&s); + if (ret == PCAP_ERROR_BREAK) + p->break_loop = 0; } /* @@ -2892,7 +2895,12 @@ pcapint_open_offline_common(char *ebuf, size_t total_size, size_t private_offset int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { - return (p->read_op(p, cnt, callback, user)); + int ret = p->read_op(p, cnt, callback, user); + + if (ret == PCAP_ERROR_BREAK) + p->break_loop = 0; + + return ret; } int @@ -2915,6 +2923,8 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) n = p->read_op(p, cnt, callback, user); } while (n == 0); } + if (n == PCAP_ERROR_BREAK) + p->break_loop = 0; if (n <= 0) return (n); if (!PACKET_COUNT_IS_UNLIMITED(cnt)) { @@ -2931,7 +2941,13 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) void pcap_breakloop(pcap_t *p) { - p->breakloop_op(p); + p->breakloop_op(p, PCAPINT_BREAK_IMMEDIATE); +} + +void +pcap_breakloop_flush(pcap_t *p) +{ + p->breakloop_op(p, PCAPINT_BREAK_FLUSH); } int @@ -4064,9 +4080,9 @@ pcapint_remove_from_pcaps_to_close(pcap_t *p) } void -pcapint_breakloop_common(pcap_t *p) +pcapint_breakloop_common(pcap_t *p, int mode) { - p->break_loop = 1; + p->break_loop = mode; } @@ -4283,7 +4299,7 @@ pcap_read_dead(pcap_t *p, int cnt _U_, pcap_handler callback _U_, } static void -pcap_breakloop_dead(pcap_t *p _U_) +pcap_breakloop_dead(pcap_t *p _U_, int mode) { /* * A "dead" pcap_t is just a placeholder to use in order to diff --git a/pcap/pcap.h b/pcap/pcap.h index a023fde6c6..ac30e048b3 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -608,6 +608,9 @@ PCAP_API int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); PCAP_AVAILABLE_0_8 PCAP_API void pcap_breakloop(pcap_t *); +PCAP_AVAILABLE_1_11 +PCAP_API void pcap_breakloop_flush(pcap_t *); + PCAP_AVAILABLE_0_4 PCAP_API int pcap_stats(pcap_t *, struct pcap_stat *) PCAP_WARN_UNUSED_RESULT; diff --git a/savefile.c b/savefile.c index 17cf98722d..ed12900050 100644 --- a/savefile.c +++ b/savefile.c @@ -645,10 +645,9 @@ pcapint_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * return the number of packets we've processed so far. */ if (p->break_loop) { - if (n == 0) { - p->break_loop = 0; - return (-2); - } else + if (n == 0) + return (PCAP_ERROR_BREAK); + else return (n); }