#! /bin/sh -e ## 60_ring.dpatch by Ken-ichirou MATSUZAWA ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: use sockopt - PACKET_RX_RING if [ $# -lt 1 ]; then echo "`basename $0`: script expects -patch|-unpatch as argument" >&2 exit 1 fi [ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts patch_opts="${patch_opts:--f --no-backup-if-mismatch} ${2:+-d $2}" case "$1" in -patch) patch -p1 ${patch_opts} < $0;; -unpatch) patch -R -p1 ${patch_opts} < $0;; *) echo "`basename $0`: script expects -patch|-unpatch as argument" >&2 exit 1;; esac exit 0 @DPATCH@ diff -ubBrN libpcap0.8-0.9.5.orig/FILES libpcap0.8-0.9.5/FILES --- libpcap0.8-0.9.5.orig/FILES 2005-06-21 06:30:14.000000000 +0900 +++ libpcap0.8-0.9.5/FILES 2008-06-17 23:02:22.000000000 +0900 @@ -82,6 +82,8 @@ pcap-enet.c pcap-int.h pcap-linux.c +pcap-ring.c +pcap-ring.h pcap-namedb.h pcap-nit.c pcap-nit.h diff -ubBrN libpcap0.8-0.9.5.orig/Makefile.in libpcap0.8-0.9.5/Makefile.in --- libpcap0.8-0.9.5.orig/Makefile.in 2008-06-17 22:59:28.000000000 +0900 +++ libpcap0.8-0.9.5/Makefile.in 2008-06-17 23:02:23.000000000 +0900 @@ -89,17 +89,18 @@ PSRC = pcap-@V_PCAP@.c FSRC = fad-@V_FINDALLDEVS@.c SSRC = @SSRC@ +RSRC = @RSRC@ CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \ etherent.c savefile.c bpf_filter.c bpf_image.c bpf_dump.c GENSRC = scanner.c grammar.c version.c LIBOBJS = @LIBOBJS@ -SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC) +SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(RSRC) $(GENSRC) # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection -OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS) -OBJ_PIC = $(PSRC:.c=_pic.o) $(FSRC:.c=_pic.o) $(CSRC:.c=_pic.o) $(SSRC:.c=_pic.o) $(GENSRC:.c=_pic.o) +OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(RSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS) +OBJ_PIC = $(PSRC:.c=_pic.o) $(FSRC:.c=_pic.o) $(CSRC:.c=_pic.o) $(SSRC:.c=_pic.o) $(RSRC:.c=_pic.o) $(GENSRC:.c=_pic.o) HDR = pcap.h pcap-int.h pcap-namedb.h pcap-nit.h pcap-pf.h \ ethertype.h gencode.h gnuc.h GENHDR = \ @@ -178,6 +179,12 @@ version_pic.o: version.c $(CC) -fPIC $(CFLAGS) -c version.c -o $@ +pcap-ring.o: pcap-ring.c pcap-ring.h + $(CC) $(CFLAGS) -c pcap-ring.c + +pcap-ring_pic.o: pcap-ring.c pcap-ring.h + $(CC) -fPIC $(CFLAGS) -o $@ -c pcap-ring.c + snprintf.o: $(srcdir)/missing/snprintf.c $(CC) $(CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c diff -ubBrN libpcap0.8-0.9.5.orig/config.h.in libpcap0.8-0.9.5/config.h.in --- libpcap0.8-0.9.5.orig/config.h.in 2006-04-07 16:08:50.000000000 +0900 +++ libpcap0.8-0.9.5/config.h.in 2008-06-17 23:02:22.000000000 +0900 @@ -131,6 +131,9 @@ /* IPv6 */ #undef INET6 +/* PACKET_RX_RING sockopt */ +#undef DO_RING + /* if unaligned access fails */ #undef LBL_ALIGN diff -ubBrN libpcap0.8-0.9.5.orig/configure libpcap0.8-0.9.5/configure --- libpcap0.8-0.9.5.orig/configure 2008-06-17 22:59:28.000000000 +0900 +++ libpcap0.8-0.9.5/configure 2008-06-17 23:02:22.000000000 +0900 @@ -310,7 +310,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SHLICC2 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP LIBOBJS V_LEX V_YACC RANLIB ac_ct_RANLIB V_CCOPT V_DEFS V_INCLS V_LIBS V_PCAP V_FINDALLDEVS V_RANLIB SSRC DYEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SHLICC2 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP LIBOBJS V_LEX V_YACC RANLIB ac_ct_RANLIB V_CCOPT V_DEFS V_INCLS V_LIBS V_PCAP V_FINDALLDEVS V_RANLIB SSRC RSRC DYEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -5935,6 +5935,65 @@ _ACEOF fi + + echo "$as_me:$LINENO: checking set PACKET_RX_RING sockopt" >&5 +echo $ECHO_N "checking set PACKET_RX_RING sockopt... $ECHO_C" >&6 + if test "$cross_compiling" = yes; then + enable_packet_mmap=yes +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + #include + #include + #include + int main(int argc, char **argv) { + int fd; + struct tpacket_req req = {0, 1, 0, 1}; + req.tp_block_size = req.tp_frame_size = getpagesize(); + fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (fd < 0) return -1; + return setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req)); + } +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + enable_packet_mmap=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +enable_packet_mmap=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + if test "$enable_packet_mmap" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define DO_RING 1 +_ACEOF + + RSRC="pcap-ring.c" + fi + echo "$as_me:$LINENO: result: ${enable_packet_mmap-no}" >&5 +echo "${ECHO_T}${enable_packet_mmap-no}" >&6 ;; dag) @@ -7906,6 +7965,7 @@ s,@V_FINDALLDEVS@,$V_FINDALLDEVS,;t t s,@V_RANLIB@,$V_RANLIB,;t t s,@SSRC@,$SSRC,;t t +s,@RSRC@,$RSRC,;t t s,@DYEXT@,$DYEXT,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t diff -ubBrN libpcap0.8-0.9.5.orig/configure.in libpcap0.8-0.9.5/configure.in --- libpcap0.8-0.9.5.orig/configure.in 2008-06-17 22:59:28.000000000 +0900 +++ libpcap0.8-0.9.5/configure.in 2008-06-17 23:02:22.000000000 +0900 @@ -362,6 +362,31 @@ AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info) fi AC_LBL_TPACKET_STATS + + AC_MSG_CHECKING(set PACKET_RX_RING sockopt) + AC_TRY_RUN( + [#include + #include + #include + #include + #include + int main(int argc, char **argv) { + int fd; + struct tpacket_req req = {0, 1, 0, 1}; + req.tp_block_size = req.tp_frame_size = getpagesize(); + fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (fd < 0) return -1; + return setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req)); + }], + enable_packet_mmap=yes, + enable_packet_mmap=no, + enable_packet_mmap=yes) + + if test "$enable_packet_mmap" = "yes"; then + AC_DEFINE(DO_RING,1,[PACKT_RX_RING]) + RSRC="pcap-ring.c" + fi + AC_MSG_RESULT(${enable_packet_mmap-no}) ;; dag) @@ -782,6 +807,7 @@ AC_SUBST(V_RANLIB) AC_SUBST(V_YACC) AC_SUBST(SSRC) +AC_SUBST(RSRC) AC_SUBST(DYEXT) AC_PROG_INSTALL diff -ubBrN libpcap0.8-0.9.5.orig/pcap-int.h libpcap0.8-0.9.5/pcap-int.h --- libpcap0.8-0.9.5.orig/pcap-int.h 2006-02-23 02:09:54.000000000 +0900 +++ libpcap0.8-0.9.5/pcap-int.h 2008-06-17 23:02:23.000000000 +0900 @@ -51,6 +51,10 @@ #include #endif +#ifdef DO_RING +# include +#endif + /* * Savefile */ @@ -146,6 +150,9 @@ struct pcap_sf sf; struct pcap_md md; +#ifdef DO_RING + struct pcap_ring rg; +#endif /* DO_RING */ /* * Read buffer. diff -ubBrN libpcap0.8-0.9.5.orig/pcap-linux.c libpcap0.8-0.9.5/pcap-linux.c --- libpcap0.8-0.9.5.orig/pcap-linux.c 2006-09-19 02:34:31.000000000 +0900 +++ libpcap0.8-0.9.5/pcap-linux.c 2008-06-17 23:02:23.000000000 +0900 @@ -409,8 +409,13 @@ /* Allocate the buffer */ +#ifdef DO_RING + handle->buffer = NULL; + err = packet_tring_setup(handle, ebuf); + if (err == -1) { /* err == -2, means hard failure ring wise */ +#endif /* DO_RING */ handle->buffer = malloc(handle->bufsize + handle->offset); - if (!handle->buffer) { + if (!handle->buffer && err) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); pcap_close_linux(handle); @@ -418,6 +423,9 @@ return NULL; } +#ifdef DO_RING + } +#endif /* * "handle->fd" is a socket, so "select()" and "poll()" * should work on it. @@ -445,6 +453,11 @@ static int pcap_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { +#ifdef DO_RING + if (handle->buffer == NULL) + return pcap_ring_recv(handle, max_packets, callback, user); +#endif /* DO_RING */ + /* * Currently, on Linux only one packet is delivered per read, * so we don't loop. @@ -1701,6 +1714,10 @@ struct pcap *p, *prevp; struct ifreq ifr; +#ifdef DO_RING + packet_ring_close(handle); + fflush(stderr); +#endif /* DO_RING */ if (handle->md.clear_promisc) { /* * We put the interface into promiscuous mode; take @@ -2148,6 +2165,11 @@ * Note that we've put the total filter onto the socket. */ total_filter_on = 1; +#ifdef DO_RING + if (handle->rg.iovec) + packet_ring_discard(handle); + else { +#endif /* DO_RING */ /* * Save the socket's current mode, and put it in @@ -2171,6 +2193,9 @@ return -2; } } +#ifdef DO_RING + } +#endif /* DO_RING */ } /* diff -ubBrN libpcap0.8-0.9.5.orig/pcap-ring.c libpcap0.8-0.9.5/pcap-ring.c --- libpcap0.8-0.9.5.orig/pcap-ring.c 1970-01-01 09:00:00.000000000 +0900 +++ libpcap0.8-0.9.5/pcap-ring.c 2008-06-17 23:16:01.000000000 +0900 @@ -0,0 +1,318 @@ +/* Copyright (c) 2006, + * Regents of the University of California All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Los Alamos National Laboratory nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef lint +static const char rcsid[] _U_ = "@#( $Header: /n/CVS/sirt/libpcap/pcap-ring.c,v 0.9 2005/06/10 23:06:31 cpw Exp $ (CPW)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PACKET_HOST +#define HAVE_PF_PACKET_SOCKETS +#endif /* PACKET_HOST */ + +#include "pcap-int.h" +#include "sll.h" + +#define DEFAULT_RING_SIZE 8 * 1024 * 1024 /* 8Mbyes */ + +#define RING_DEBUG +/* #undef RING_DEBUG */ +#ifdef RING_DEBUG +#define DPRINTF(format, args...) fprintf(stderr, format,##args) +#else +#define DPRINTF(format, args...) +#endif + +unsigned clp2(unsigned x) +{ + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return x + 1; +} + +int +packet_tring_setup(pcap_t *p, char *ebuf) +{ + int i, size = p->snapshot; + struct tpacket_req req; + struct iovec *ring; + unsigned long mem = 0; + char *endptr, *str; + + str = getenv("PCAP_MMAP_MEMSIZE"); + if (str) + mem = strtoul(str, &endptr, 10); + if (mem < getpagesize() || endptr == str) + mem = DEFAULT_RING_SIZE; /* XXX: use getenv() ? */ + + if (p->md.cooked) + size += SLL_HDR_LEN; + + req.tp_block_size = getpagesize(); + req.tp_block_nr = mem / req.tp_block_size; + req.tp_frame_size = clp2(TPACKET_ALIGN(TPACKET_HDRLEN) + TPACKET_ALIGN(size)); + req.tp_frame_nr = req.tp_block_size / req.tp_frame_size * req.tp_block_nr; + + p->rg.ct = req.tp_frame_nr; + + if (setsockopt(p->fd, SOL_PACKET, PACKET_RX_RING, (void*)&req, + sizeof(req))) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "PACKET_RX_RING: %s", + pcap_strerror(errno)); + return -1; + } + + ring = (struct iovec *) malloc(p->rg.ct * sizeof(struct iovec)); + if (!ring) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + return -1; + } + + p->rg.buf = (void*)mmap(NULL, req.tp_block_nr * req.tp_block_size, + PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0); + if (p->rg.buf == MAP_FAILED) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "mmap: %s", + pcap_strerror(errno)); + + memset(&req, 0, sizeof(req)); + p->rg.buf = NULL; + if (setsockopt(p->fd, SOL_PACKET, PACKET_RX_RING, (void*)&req, + sizeof(req))) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "mmap and unset PACKET_RX_RING: %s", + pcap_strerror(errno)); + } + free(ring); + return -2; + } + + for (i = 0; i < req.tp_frame_nr; i++) { + ring[i].iov_base = (unsigned char *)((unsigned long)p->rg.buf) + i * req.tp_frame_size; + ring[i].iov_len = req.tp_frame_size; + } + + p->rg.bufsize = req.tp_block_nr * req.tp_block_size; + p->rg.iovhead = 0; + p->rg.iovmax = p->rg.ct - 1; + p->rg.iovec = ring; + + DPRINTF("use PACKET_MMAP, packet buffer size - pkts: %d\n", req.tp_frame_nr); + + return 0; +} + +int +pcap_ring_recv(pcap_t *handle, int cnt, pcap_handler callback, u_char *userdata) +{ + struct iovec *ring = handle->rg.iovec; + struct tpacket_hdr *h; + struct sockaddr_ll *sll; + unsigned char *bp; + struct pcap_pkthdr pcap_header; + struct sll_header *hdrp; + struct pollfd pfd; + int n = 0; + + if (handle->rg.iovec == NULL) + return -1; /* called inappropriately - no ring defined */ + + pfd.fd = handle->fd; + pfd.events = POLLIN | POLLERR; + pfd.revents = 0; + + while (1) { + while (*(unsigned long *) ring[handle->rg.iovhead].iov_base == 0) { + if (poll(&pfd, 1, -1) < 0) + return -1; /* XXX: in case of EINTR? */ + } + if (handle->break_loop) { + handle->break_loop = 0; + return -2; + } + + h = ring[handle->rg.iovhead].iov_base; + sll = (void*)h + TPACKET_ALIGN(sizeof(*h)); + bp = (unsigned char*)h + h->tp_mac; + +#ifdef HAVE_PF_PACKET_SOCKETS + /* + * >>>> see original pcap_read_packet() in pcap-linux.c + */ + if (!handle->md.sock_packet) { + if (handle->md.ifindex != -1 && + sll->sll_ifindex != handle->md.ifindex) + goto clear_status; + + if (sll->sll_pkttype == PACKET_OUTGOING) { + if (sll->sll_ifindex == handle->md.lo_ifindex) + goto clear_status; + + if (handle->direction == PCAP_D_IN) + goto clear_status; + } else { + if (handle->direction == PCAP_D_OUT) + goto clear_status; + } + } +#endif + +#ifdef HAVE_PF_PACKET_SOCKETS + if (handle->md.cooked) { + hdrp = (struct sll_header *)((char *)bp - sizeof(struct sll_header)); + switch (sll->sll_pkttype) { + case PACKET_HOST: + hdrp->sll_pkttype = htons(LINUX_SLL_HOST); + break; + + case PACKET_BROADCAST: + hdrp->sll_pkttype = htons(LINUX_SLL_BROADCAST); + break; + + case PACKET_MULTICAST: + hdrp->sll_pkttype = htons(LINUX_SLL_MULTICAST); + break; + + case PACKET_OTHERHOST: + hdrp->sll_pkttype = htons(LINUX_SLL_OTHERHOST); + break; + + case PACKET_OUTGOING: + hdrp->sll_pkttype = htons(LINUX_SLL_OUTGOING); + break; + + default: + hdrp->sll_pkttype = -1; + break; + } + + hdrp->sll_hatype = htons(sll->sll_hatype); + hdrp->sll_halen = htons(sll->sll_halen); + memcpy(hdrp->sll_addr, sll->sll_addr, + (sll->sll_halen > SLL_ADDRLEN) ? + SLL_ADDRLEN : + sll->sll_halen); + hdrp->sll_protocol = sll->sll_protocol; + } +#endif + if (!handle->md.use_bpf && handle->fcode.bf_insns) { + /* XXX: call after bp was adjusted ? */ + if (bpf_filter(handle->fcode.bf_insns, bp, + h->tp_len, h->tp_snaplen)) + { + goto clear_status; + } + } + /* + * <<<< original pcap_read_packet() in pcap-linux.c + */ + + pcap_header.ts.tv_sec = h->tp_sec; + pcap_header.ts.tv_usec = h->tp_usec; + pcap_header.caplen = h->tp_snaplen; + pcap_header.len = h->tp_len; + if (handle->md.cooked) { + pcap_header.caplen += SLL_HDR_LEN; + pcap_header.len += SLL_HDR_LEN; + bp -= SLL_HDR_LEN; + } + + handle->md.packets_read++; + (*callback)(userdata, &pcap_header, bp); + + clear_status: + h->tp_status = 0; + /* mb(); */ + handle->rg.iovhead = handle->rg.iovhead == handle->rg.iovmax + ? 0 + : handle->rg.iovhead + 1; + + if (++n >= cnt && cnt > 0) + return n; + } + + return n; +} + +void +packet_ring_close(pcap_t * p) +{ + if (p->rg.iovec != NULL) + free(p->rg.iovec); + p->rg.iovec = NULL; + + if (p->rg.buf != NULL) { + munmap(p->rg.buf, p->rg.bufsize); + p->rg.buf = NULL; + } +} + +/* + * packet_discard (pcap_t *) + * marks any entries in the ring buffer as read + * presumably called after setting a new filter. + */ +int +packet_ring_discard (pcap_t * p) +{ + struct iovec *ring = p->rg.iovec; + struct tpacket_stats tps = { 0 }; + socklen_t olen = sizeof (tps); + int discarded = 0; + int start = p->rg.iovhead; + + if (!p->rg.iovec) + return 0; + + while (*(unsigned long *) ring[p->rg.iovhead].iov_base) { + *(unsigned long *) ring[p->rg.iovhead].iov_base = 0; + discarded++; + p->rg.iovhead = (p->rg.iovhead == p->rg.iovmax) ? 0 : p->rg.iovhead + 1; + if (p->rg.iovhead == start) /* one turn only */ + break; + } + + /* clear packet stats */ + getsockopt(p->fd, SOL_PACKET, PACKET_STATISTICS, (void *) &tps, &olen); + + return discarded; +} diff -ubBrN libpcap0.8-0.9.5.orig/pcap-ring.h libpcap0.8-0.9.5/pcap-ring.h --- libpcap0.8-0.9.5.orig/pcap-ring.h 1970-01-01 09:00:00.000000000 +0900 +++ libpcap0.8-0.9.5/pcap-ring.h 2008-06-17 23:02:23.000000000 +0900 @@ -0,0 +1,54 @@ +/* +Copyright (c) 2005, Regents of the University of California All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Los Alamos National Laboratory nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + @(#) $Header: /n/CVS/sirt/libpcap/pcap-ring.h,v 0.10 2005/07/18 16:05:12 cpw Exp $ (CPW) +*/ +#ifndef PCAP_RING_H +#define PCAP_RING_H 1 + +#include +#include +#include + +#ifndef SOL_PACKET /* */ +#define SOL_PACKET 263 /* */ +#endif /* SOL_PACKET */ + +typedef struct pcap_ring { + char *buf; + void *iovec; /* non zero implies ring use */ + unsigned int bufsize; + unsigned int iovmax; + unsigned int iovhead; + long ct; /* size of ring in packets */ +} pcap_ring; + +void packet_ring_close (pcap_t *); +int packet_tring_setup(pcap_t *, char *); +int packet_ring_discard(pcap_t *); + +#endif