mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-27 08:48:58 +02:00
614 lines
16 KiB
Diff
614 lines
16 KiB
Diff
|
diff -urN libpcap.old/pcap-int.h libpcap.dev/pcap-int.h
|
||
|
--- libpcap.old/pcap-int.h 2003-12-15 02:42:24.000000000 +0100
|
||
|
+++ libpcap.dev/pcap-int.h 2005-10-22 23:20:12.220060500 +0200
|
||
|
@@ -30,7 +30,7 @@
|
||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
*
|
||
|
- * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.55.2.4 2003/12/15 01:42:24 guy Exp $ (LBL)
|
||
|
+ * @(#) $Header: /export/home/ntop/PF_RING/userland/libpcap-0.8.1-ring/pcap-int.h,v 1.2 2004/11/25 09:58:00 deri Exp $ (LBL)
|
||
|
*/
|
||
|
|
||
|
#ifndef pcap_int_h
|
||
|
@@ -46,6 +46,8 @@
|
||
|
#include <packet32.h>
|
||
|
#endif /* WIN32 */
|
||
|
|
||
|
+#define RING /* L.Deri */
|
||
|
+
|
||
|
/*
|
||
|
* Savefile
|
||
|
*/
|
||
|
@@ -93,6 +95,57 @@
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
+/* **************************** */
|
||
|
+
|
||
|
+#ifdef RING
|
||
|
+
|
||
|
+#include <unistd.h>
|
||
|
+#include <sys/mman.h>
|
||
|
+#include <errno.h>
|
||
|
+#include <sys/poll.h>
|
||
|
+
|
||
|
+#define PAGE_SIZE 4096
|
||
|
+
|
||
|
+#define HAVE_PCAP
|
||
|
+#include <linux/ring.h>
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifdef RING
|
||
|
+
|
||
|
+#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
|
||
|
+
|
||
|
+struct e1000_rx_desc {
|
||
|
+ u_int64_t buffer_addr; /* Address of the descriptor's data buffer */
|
||
|
+ u_int16_t length; /* Length of data DMAed into data buffer */
|
||
|
+ u_int16_t csum; /* Packet checksum */
|
||
|
+ u_int8_t status; /* Descriptor status */
|
||
|
+ u_int8_t errors; /* Descriptor Errors */
|
||
|
+ u_int16_t special;
|
||
|
+};
|
||
|
+
|
||
|
+/* Transmit Descriptor */
|
||
|
+struct e1000_tx_desc {
|
||
|
+ u_int64_t buffer_addr; /* Address of the descriptor's data buffer */
|
||
|
+ union {
|
||
|
+ u_int32_t data;
|
||
|
+ struct {
|
||
|
+ u_int16_t length; /* Data buffer length */
|
||
|
+ u_int8_t cso; /* Checksum offset */
|
||
|
+ u_int8_t cmd; /* Descriptor control */
|
||
|
+ } flags;
|
||
|
+ } lower;
|
||
|
+ union {
|
||
|
+ u_int32_t data;
|
||
|
+ struct {
|
||
|
+ u_int8_t status; /* Descriptor status */
|
||
|
+ u_int8_t css; /* Checksum start */
|
||
|
+ u_int16_t special;
|
||
|
+ } fields;
|
||
|
+ } upper;
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
struct pcap {
|
||
|
#ifdef WIN32
|
||
|
ADAPTER *adapter;
|
||
|
@@ -121,6 +174,14 @@
|
||
|
u_char *bp;
|
||
|
int cc;
|
||
|
|
||
|
+#ifdef RING
|
||
|
+ /* PF_RING */
|
||
|
+ char *ring_buffer, *ring_slots;
|
||
|
+ int ring_fd;
|
||
|
+ FlowSlotInfo *slots_info;
|
||
|
+ u_int page_id, slot_id, pkts_per_page;
|
||
|
+ u_int poll_sleep;
|
||
|
+#endif
|
||
|
/*
|
||
|
* Place holder for pcap_next().
|
||
|
*/
|
||
|
diff -urN libpcap.old/pcap-linux.c libpcap.dev/pcap-linux.c
|
||
|
--- libpcap.old/pcap-linux.c 2003-11-21 11:20:46.000000000 +0100
|
||
|
+++ libpcap.dev/pcap-linux.c 2005-10-22 23:43:59.726120250 +0200
|
||
|
@@ -27,7 +27,7 @@
|
||
|
|
||
|
#ifndef lint
|
||
|
static const char rcsid[] _U_ =
|
||
|
- "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.98.2.4 2003/11/21 10:20:46 guy Exp $ (LBL)";
|
||
|
+ "@(#) $Header: /export/home/ntop/PF_RING/userland/libpcap-0.8.1-ring/pcap-linux.c,v 1.2 2004/11/25 09:58:00 deri Exp $ (LBL)";
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
@@ -83,7 +83,7 @@
|
||
|
#ifdef HAVE_DAG_API
|
||
|
#include "pcap-dag.h"
|
||
|
#endif /* HAVE_DAG_API */
|
||
|
-
|
||
|
+
|
||
|
#include <errno.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
@@ -217,6 +217,83 @@
|
||
|
= { 1, &total_insn };
|
||
|
#endif
|
||
|
|
||
|
+#define RING /* L.Deri */
|
||
|
+#define SAFE_RING_MODE /*
|
||
|
+ Copy the bucket in order to avoid kernel
|
||
|
+ crash if the application faults
|
||
|
+ */
|
||
|
+
|
||
|
+#ifdef RING
|
||
|
+unsigned char *write_register;
|
||
|
+static struct pcap_stat ringStats;
|
||
|
+u_long numPollCalls = 0, numReadCalls = 0;
|
||
|
+
|
||
|
+#define POLL_SLEEP_STEP 10 /* ns = 0.1 ms */
|
||
|
+#define POLL_SLEEP_MIN POLL_SLEEP_STEP
|
||
|
+#define POLL_SLEEP_MAX 1000 /* ns */
|
||
|
+#define POLL_QUEUE_MIN_LEN 500 /* # packets */
|
||
|
+
|
||
|
+#ifdef SAFE_RING_MODE
|
||
|
+static char staticBucket[2048];
|
||
|
+#endif
|
||
|
+
|
||
|
+
|
||
|
+/* ******************************* */
|
||
|
+
|
||
|
+int pcap_set_cluster(pcap_t *handle, u_int clusterId) {
|
||
|
+ return(handle->ring_fd ? setsockopt(handle->ring_fd, 0, SO_ADD_TO_CLUSTER,
|
||
|
+ &clusterId, sizeof(clusterId)): -1);
|
||
|
+}
|
||
|
+
|
||
|
+/* ******************************* */
|
||
|
+
|
||
|
+int pcap_remove_from_cluster(pcap_t *handle) {
|
||
|
+ return(handle->ring_fd ?
|
||
|
+ setsockopt(handle->ring_fd, 0, SO_REMOVE_FROM_CLUSTER, NULL, 0) : -1);
|
||
|
+}
|
||
|
+
|
||
|
+/* ******************************* */
|
||
|
+
|
||
|
+int pcap_set_reflector(pcap_t *handle, char *reflectorDevice) {
|
||
|
+ return(handle->ring_fd ?
|
||
|
+ setsockopt(handle->ring_fd, 0, SO_SET_REFLECTOR,
|
||
|
+ &reflectorDevice, strlen(reflectorDevice)) : -1);
|
||
|
+}
|
||
|
+
|
||
|
+/* ******************************* */
|
||
|
+
|
||
|
+static int set_if_promisc(const char *device, int set_promisc) {
|
||
|
+ int sock_fd;
|
||
|
+ struct ifreq ifr;
|
||
|
+
|
||
|
+ if(device == NULL) return(-3);
|
||
|
+
|
||
|
+ sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||
|
+ if(sock_fd <= 0) return(-1);
|
||
|
+
|
||
|
+ memset(&ifr, 0, sizeof(ifr));
|
||
|
+ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
|
||
|
+ if(ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
|
||
|
+ close(sock_fd);
|
||
|
+ return(-2);
|
||
|
+ }
|
||
|
+
|
||
|
+ if(set_promisc) {
|
||
|
+ if((ifr.ifr_flags & IFF_PROMISC) == 0) ifr.ifr_flags |= IFF_PROMISC;
|
||
|
+ } else {
|
||
|
+ /* Remove promisc */
|
||
|
+ if((ifr.ifr_flags & IFF_PROMISC) != 0) ifr.ifr_flags &= ~IFF_PROMISC;
|
||
|
+ }
|
||
|
+
|
||
|
+ if(ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1)
|
||
|
+ return(-1);
|
||
|
+
|
||
|
+ close(sock_fd);
|
||
|
+ return(0);
|
||
|
+}
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
/*
|
||
|
* Get a handle for a live capture from the given device. You can
|
||
|
* pass NULL as device to get all packages (without link level
|
||
|
@@ -258,6 +335,138 @@
|
||
|
handle->snapshot = snaplen;
|
||
|
handle->md.timeout = to_ms;
|
||
|
|
||
|
+#ifdef RING
|
||
|
+ handle->ring_fd = handle->fd = socket(PF_RING, SOCK_RAW, htons(ETH_P_ALL));
|
||
|
+
|
||
|
+ printf("Open RING [fd=%d]\n", handle->ring_fd);
|
||
|
+
|
||
|
+ if(handle->ring_fd > 0) {
|
||
|
+ struct sockaddr sa;
|
||
|
+ int rc;
|
||
|
+ u_int memSlotsLen;
|
||
|
+
|
||
|
+ err = 0;
|
||
|
+ sa.sa_family = PF_RING;
|
||
|
+ snprintf(sa.sa_data, sizeof(sa.sa_data), "%s", device);
|
||
|
+ rc = bind(handle->ring_fd, (struct sockaddr *)&sa, sizeof(sa));
|
||
|
+
|
||
|
+ if(rc == 0) {
|
||
|
+
|
||
|
+
|
||
|
+ handle->md.device = strdup(device);
|
||
|
+ handle->ring_buffer = (char *)mmap(NULL, PAGE_SIZE,
|
||
|
+ PROT_READ|PROT_WRITE,
|
||
|
+ MAP_SHARED,
|
||
|
+ handle->ring_fd, 0);
|
||
|
+
|
||
|
+ if(handle->ring_buffer == MAP_FAILED) {
|
||
|
+ sprintf(ebuf, "mmap() failed");
|
||
|
+ return (NULL);
|
||
|
+ }
|
||
|
+
|
||
|
+ handle->slots_info = (FlowSlotInfo *)handle->ring_buffer;
|
||
|
+ if(handle->slots_info->version != RING_FLOWSLOT_VERSION) {
|
||
|
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "Wrong RING version: "
|
||
|
+ "kernel is %i, libpcap was compiled with %i\n",
|
||
|
+ handle->slots_info->version, RING_FLOWSLOT_VERSION);
|
||
|
+ return (NULL);
|
||
|
+ }
|
||
|
+ memSlotsLen = handle->slots_info->tot_mem;
|
||
|
+ munmap(handle->ring_buffer, PAGE_SIZE);
|
||
|
+
|
||
|
+ handle->ring_buffer = (char *)mmap(NULL, memSlotsLen,
|
||
|
+ PROT_READ|PROT_WRITE,
|
||
|
+ MAP_SHARED, handle->ring_fd, 0);
|
||
|
+
|
||
|
+ if(handle->ring_buffer == MAP_FAILED) {
|
||
|
+ sprintf(ebuf, "mmap() failed");
|
||
|
+ return (NULL);
|
||
|
+ }
|
||
|
+
|
||
|
+ handle->slots_info = (FlowSlotInfo *)handle->ring_buffer;
|
||
|
+ handle->ring_slots = (char *)(handle->ring_buffer+sizeof(FlowSlotInfo));
|
||
|
+
|
||
|
+ /* Safety check */
|
||
|
+ if(handle->slots_info->remove_idx >= handle->slots_info->tot_slots)
|
||
|
+ handle->slots_info->remove_idx = 0;
|
||
|
+
|
||
|
+ handle->page_id = PAGE_SIZE, handle->slot_id = 0,
|
||
|
+ handle->pkts_per_page = 0;
|
||
|
+
|
||
|
+ if(0) {
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for(i=0; i<handle->slots_info->tot_slots; i++) {
|
||
|
+ unsigned long idx = i*handle->slots_info->slot_len;
|
||
|
+ FlowSlot *slot = (FlowSlot*)&handle->ring_slots[idx];
|
||
|
+
|
||
|
+ printf("RING: Setting RING_MAGIC_VALUE into slot %d [displacement=%lu]\n", i, idx);
|
||
|
+ slot->magic = RING_MAGIC_VALUE; slot->slot_state = 0;
|
||
|
+ printf("RING: slot[%d]: magic=%d, slot_state=%d\n",
|
||
|
+ slot->magic, slot->slot_state);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
+ /* Set defaults */
|
||
|
+ handle->linktype = DLT_EN10MB;
|
||
|
+ handle->offset = 2;
|
||
|
+
|
||
|
+ printf("RING (%s): tot_slots=%d/slot_len=%d/"
|
||
|
+ "insertIdx=%d/remove_idx=%d/dropped=%d\n",
|
||
|
+ device,
|
||
|
+ handle->slots_info->tot_slots,
|
||
|
+ handle->slots_info->slot_len,
|
||
|
+ handle->slots_info->insert_idx,
|
||
|
+ handle->slots_info->remove_idx,
|
||
|
+ handle->slots_info->tot_lost);
|
||
|
+
|
||
|
+ ringStats.ps_recv = handle->slots_info->tot_read;
|
||
|
+ ringStats.ps_drop = handle->slots_info->tot_lost;
|
||
|
+
|
||
|
+ if(promisc) {
|
||
|
+ struct ifreq ifr;
|
||
|
+
|
||
|
+ err = 0;
|
||
|
+ memset(&ifr, 0, sizeof(ifr));
|
||
|
+ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
|
||
|
+ if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
|
||
|
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
|
||
|
+ "ioctl: %s", pcap_strerror(errno));
|
||
|
+ err = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ if(err == 0) {
|
||
|
+ if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
|
||
|
+ /*
|
||
|
+ * Promiscuous mode isn't currently on,
|
||
|
+ * so turn it on, and remember that
|
||
|
+ * we should turn it off when the
|
||
|
+ * pcap_t is closed.
|
||
|
+ */
|
||
|
+
|
||
|
+ ifr.ifr_flags |= IFF_PROMISC;
|
||
|
+ if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
|
||
|
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
|
||
|
+ "ioctl: %s", pcap_strerror(errno));
|
||
|
+ err = 1;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if(err == 0)
|
||
|
+ handle->md.clear_promisc = 1;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if(err == 0)
|
||
|
+ goto open_open_live_final;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Don't put 'else' above... */
|
||
|
+ close(handle->ring_fd);
|
||
|
+ /* Continue without ring support */
|
||
|
+ }
|
||
|
+#endif
|
||
|
/*
|
||
|
* NULL and "any" are special devices which give us the hint to
|
||
|
* monitor all devices.
|
||
|
@@ -397,6 +606,9 @@
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
+#ifdef RING
|
||
|
+ open_open_live_final:
|
||
|
+#endif
|
||
|
/*
|
||
|
* "handle->fd" is a socket, so "select()" and "poll()"
|
||
|
* should work on it.
|
||
|
@@ -449,6 +661,120 @@
|
||
|
int packet_len, caplen;
|
||
|
struct pcap_pkthdr pcap_header;
|
||
|
|
||
|
+#ifdef RING
|
||
|
+ if(handle->ring_buffer != NULL) {
|
||
|
+ u_int idx, numRuns = 0, ptrAddr;
|
||
|
+ FlowSlot *slot;
|
||
|
+
|
||
|
+ slot = (FlowSlot*)&handle->ring_slots[handle->slots_info->remove_idx*handle->slots_info->slot_len];
|
||
|
+
|
||
|
+ while(1) {
|
||
|
+ u_int32_t queuedPkts;
|
||
|
+
|
||
|
+ if(handle->slots_info->tot_insert >= handle->slots_info->tot_read)
|
||
|
+ queuedPkts = handle->slots_info->tot_insert - handle->slots_info->tot_read;
|
||
|
+ else
|
||
|
+ queuedPkts = handle->slots_info->tot_slots + handle->slots_info->tot_insert - handle->slots_info->tot_read;
|
||
|
+
|
||
|
+ if(queuedPkts && (slot->slot_state == 1)) {
|
||
|
+ char *bucket = &slot->bucket;
|
||
|
+
|
||
|
+#ifdef RING_MAGIC
|
||
|
+ if(slot->magic != RING_MAGIC_VALUE) {
|
||
|
+ printf("==>> Bad Magic [remove_idx=%u][insert_idx=%u][ptrAddr=%u]\n",
|
||
|
+ handle->slots_info->remove_idx,
|
||
|
+ handle->slots_info->insert_idx,
|
||
|
+ ptrAddr);
|
||
|
+ slot->magic = RING_MAGIC_VALUE;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
+
|
||
|
+ handle->md.stat.ps_recv++;
|
||
|
+
|
||
|
+#ifdef SAFE_RING_MODE
|
||
|
+ {
|
||
|
+ struct pcap_pkthdr *hdr = (struct pcap_pkthdr*)bucket;
|
||
|
+ int bktLen = hdr->caplen;
|
||
|
+
|
||
|
+ if(bktLen > sizeof(staticBucket))
|
||
|
+ bktLen = sizeof(staticBucket);
|
||
|
+
|
||
|
+ memcpy(staticBucket, &bucket[sizeof(struct pcap_pkthdr)], bktLen);
|
||
|
+
|
||
|
+#ifdef RING_DEBUG
|
||
|
+ printf("==>> [remove_idx=%u][insert_idx=%u][ptrAddr=%u]\n",
|
||
|
+ handle->slots_info->remove_idx,
|
||
|
+ handle->slots_info->insert_idx,
|
||
|
+ ptrAddr);
|
||
|
+#endif
|
||
|
+
|
||
|
+ callback(userdata, hdr, staticBucket);
|
||
|
+ }
|
||
|
+#else
|
||
|
+ callback(userdata,
|
||
|
+ (const struct pcap_pkthdr*)bucket,
|
||
|
+ (const u_char*)&bucket[sizeof(struct pcap_pkthdr)]);
|
||
|
+#endif
|
||
|
+
|
||
|
+ if(handle->slots_info->remove_idx >= (handle->slots_info->tot_slots-1)) {
|
||
|
+ handle->slots_info->remove_idx = 0;
|
||
|
+ handle->page_id = PAGE_SIZE, handle->slot_id = 0, handle->pkts_per_page = 0;
|
||
|
+ } else {
|
||
|
+ handle->slots_info->remove_idx++;
|
||
|
+ handle->pkts_per_page++, handle->slot_id += handle->slots_info->slot_len;
|
||
|
+ }
|
||
|
+
|
||
|
+ handle->slots_info->tot_read++;
|
||
|
+ slot->slot_state = 0;
|
||
|
+
|
||
|
+ return(1);
|
||
|
+ } else {
|
||
|
+ struct pollfd pfd;
|
||
|
+ int rc;
|
||
|
+
|
||
|
+ /* Sleep when nothing is happening */
|
||
|
+ pfd.fd = handle->ring_fd;
|
||
|
+ pfd.events = POLLIN|POLLERR;
|
||
|
+ pfd.revents = 0;
|
||
|
+
|
||
|
+#ifdef RING_DEBUG
|
||
|
+ printf("==>> poll [remove_idx=%u][insert_idx=%u][loss=%d][queuedPkts=%u]"
|
||
|
+ "[slot_state=%d][tot_insert=%u][tot_read=%u]\n",
|
||
|
+ handle->slots_info->remove_idx,
|
||
|
+ handle->slots_info->insert_idx,
|
||
|
+ handle->slots_info->tot_lost,
|
||
|
+ queuedPkts, slot->slot_state,
|
||
|
+ handle->slots_info->tot_insert,
|
||
|
+ handle->slots_info->tot_read);
|
||
|
+ #endif
|
||
|
+
|
||
|
+#ifdef RING_DEBUG
|
||
|
+ printf("==>> poll @ [remove_idx=%u][slot_id=%u]\n", handle->slots_info->remove_idx, handle->slot_id);
|
||
|
+#endif
|
||
|
+ errno = 0;
|
||
|
+ rc = poll(&pfd, 1, -1);
|
||
|
+#ifdef RING_DEBUG
|
||
|
+ printf("==>> poll returned %d [%s][errno=%d][break_loop=%d]\n",
|
||
|
+ rc, strerror(errno), errno, handle->break_loop);
|
||
|
+#endif
|
||
|
+ numPollCalls++;
|
||
|
+
|
||
|
+ if(rc == -1) {
|
||
|
+ if(errno == EINTR) {
|
||
|
+ if(handle->break_loop) {
|
||
|
+ handle->break_loop = 0;
|
||
|
+ return(-2);
|
||
|
+ } else
|
||
|
+ return(0);
|
||
|
+ } else
|
||
|
+ return(-1);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ } /* while() */
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
#ifdef HAVE_PF_PACKET_SOCKETS
|
||
|
/*
|
||
|
* If this is a cooked device, leave extra room for a
|
||
|
@@ -688,6 +1014,22 @@
|
||
|
socklen_t len = sizeof (struct tpacket_stats);
|
||
|
#endif
|
||
|
|
||
|
+#ifdef RING
|
||
|
+ if(handle->ring_fd > 0) {
|
||
|
+ stats->ps_recv = handle->slots_info->tot_read-ringStats.ps_recv;
|
||
|
+ stats->ps_drop = handle->slots_info->tot_lost-ringStats.ps_drop;
|
||
|
+
|
||
|
+ printf("RING: numPollCalls=%d [%.1f packets/call]\n",
|
||
|
+ numPollCalls, (float)stats->ps_recv/(float)numPollCalls);
|
||
|
+ printf("RING: [tot_pkts=%u][tot_read=%u][tot_lost=%u]\n",
|
||
|
+ handle->slots_info->tot_pkts,
|
||
|
+ handle->slots_info->tot_read,
|
||
|
+ handle->slots_info->tot_lost);
|
||
|
+
|
||
|
+ return(0);
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
#ifdef HAVE_TPACKET_STATS
|
||
|
/*
|
||
|
* Try to get the packet counts from the kernel.
|
||
|
@@ -879,6 +1221,11 @@
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+
|
||
|
+#ifdef RING
|
||
|
+ if(handle->ring_fd <= 0) can_filter_in_kernel = 0;
|
||
|
+#endif
|
||
|
+
|
||
|
if (can_filter_in_kernel) {
|
||
|
if ((err = set_kernel_filter(handle, &fcode)) == 0)
|
||
|
{
|
||
|
@@ -1348,7 +1695,7 @@
|
||
|
memset(&mr, 0, sizeof(mr));
|
||
|
mr.mr_ifindex = device_id;
|
||
|
mr.mr_type = PACKET_MR_PROMISC;
|
||
|
- if (setsockopt(sock_fd, SOL_PACKET,
|
||
|
+ if (setsockopt(sock_fd, 0 /* SOL_PACKET */,
|
||
|
PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)
|
||
|
{
|
||
|
snprintf(ebuf, PCAP_ERRBUF_SIZE,
|
||
|
@@ -1425,10 +1772,11 @@
|
||
|
|
||
|
/* Any pending errors, e.g., network is down? */
|
||
|
|
||
|
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
||
|
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
|
||
|
- "getsockopt: %s", pcap_strerror(errno));
|
||
|
- return -2;
|
||
|
+ if ((getsockopt(fd, PF_RING, SO_ERROR, &err, &errlen) == -1)
|
||
|
+ && (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1)) {
|
||
|
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
|
||
|
+ "getsockopt: %s", pcap_strerror(errno));
|
||
|
+ return -2;
|
||
|
}
|
||
|
|
||
|
if (err > 0) {
|
||
|
@@ -1482,6 +1830,13 @@
|
||
|
struct pcap *p, *prevp;
|
||
|
struct ifreq ifr;
|
||
|
|
||
|
+#ifdef RING
|
||
|
+ if(handle->ring_buffer != NULL) {
|
||
|
+ munmap(handle->ring_buffer, handle->slots_info->tot_mem);
|
||
|
+ handle->ring_buffer = NULL;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
if (handle->md.clear_promisc) {
|
||
|
/*
|
||
|
* We put the interface into promiscuous mode; take
|
||
|
@@ -1698,11 +2053,11 @@
|
||
|
}
|
||
|
|
||
|
/* Any pending errors, e.g., network is down? */
|
||
|
-
|
||
|
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
||
|
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
|
||
|
- "getsockopt: %s", pcap_strerror(errno));
|
||
|
- return -1;
|
||
|
+ if((getsockopt(fd, PF_RING, SO_ERROR, &err, &errlen) == -1)
|
||
|
+ && (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1)) {
|
||
|
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
|
||
|
+ "getsockopt: %s", pcap_strerror(errno));
|
||
|
+ return -1;
|
||
|
}
|
||
|
|
||
|
if (err > 0) {
|
||
|
@@ -1924,8 +2279,11 @@
|
||
|
* the filtering done in userland even if it could have been
|
||
|
* done in the kernel.
|
||
|
*/
|
||
|
- if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
|
||
|
- &total_fcode, sizeof(total_fcode)) == 0) {
|
||
|
+ printf("pcap[setsockopt(%d)]\n", 0);
|
||
|
+ if (setsockopt(handle->fd, 0 /* SOL_SOCKET */,
|
||
|
+ SO_ATTACH_FILTER,
|
||
|
+ &total_fcode,
|
||
|
+ sizeof(total_fcode)) == 0) {
|
||
|
char drain[1];
|
||
|
|
||
|
/*
|
||
|
@@ -1933,6 +2291,9 @@
|
||
|
*/
|
||
|
total_filter_on = 1;
|
||
|
|
||
|
+#ifdef RING
|
||
|
+ if(!handle->ring_fd) {
|
||
|
+#endif
|
||
|
/*
|
||
|
* Save the socket's current mode, and put it in
|
||
|
* non-blocking mode; we drain it by reading packets
|
||
|
@@ -1955,12 +2316,15 @@
|
||
|
return -2;
|
||
|
}
|
||
|
}
|
||
|
- }
|
||
|
+#ifdef RING
|
||
|
+ }
|
||
|
+#endif
|
||
|
+}
|
||
|
|
||
|
/*
|
||
|
* Now attach the new filter.
|
||
|
*/
|
||
|
- ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
|
||
|
+ ret = setsockopt(handle->fd, 0 /* SOL_SOCKET */, SO_ATTACH_FILTER,
|
||
|
fcode, sizeof(*fcode));
|
||
|
if (ret == -1 && total_filter_on) {
|
||
|
/*
|
||
|
@@ -1993,7 +2357,8 @@
|
||
|
/* setsockopt() barfs unless it get a dummy parameter */
|
||
|
int dummy;
|
||
|
|
||
|
- return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER,
|
||
|
- &dummy, sizeof(dummy));
|
||
|
+ return setsockopt(handle->fd, handle->ring_fd > 0 ? PF_RING : SOL_SOCKET,
|
||
|
+ SO_DETACH_FILTER,
|
||
|
+ &dummy, sizeof(dummy));
|
||
|
}
|
||
|
#endif
|