diff -uNr libpcap-0.8.1/pcap-int.h libpcap-0.8.1-pfring/pcap-int.h
--- libpcap-0.8.1/pcap-int.h	2003-12-15 02:42:24.000000000 +0100
+++ libpcap-0.8.1-pfring/pcap-int.h	2004-04-26 17:51:34.000000000 +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-priv/ring/userland/libpcap-0.8.1-ring/pcap-int.h,v 1.3 2004/04/05 13:29:11 deri Exp $ (LBL)
  */
 
 #ifndef pcap_int_h
@@ -46,6 +46,8 @@
 #include <packet32.h>
 #endif /* WIN32 */
 
+#define RING /* L.Deri */
+
 /*
  * Savefile
  */
@@ -93,6 +95,22 @@
 #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
+
+
 struct pcap {
 #ifdef WIN32
 	ADAPTER *adapter;
@@ -121,6 +139,12 @@
 	u_char *bp;
 	int cc;
 
+#ifdef RING
+	char *ring_buffer, *slots_buffer;
+	int  ring_fd;
+	FlowSlotInfo *slots_info;
+        u_int page_id, slot_id, pkts_per_page;
+#endif
 	/*
 	 * Place holder for pcap_next().
 	 */
diff -uNr libpcap-0.8.1/pcap-linux.c libpcap-0.8.1-pfring/pcap-linux.c
--- libpcap-0.8.1/pcap-linux.c	2003-11-21 11:20:46.000000000 +0100
+++ libpcap-0.8.1-pfring/pcap-linux.c	2004-04-26 17:51:34.000000000 +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-priv/ring/userland/libpcap-0.8.1-ring/pcap-linux.c,v 1.7 2004/04/22 14:35:45 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,27 @@
 	= { 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
+static struct pcap_stat ringStats;
+u_int  numPollCalls = 0;
+#ifdef SAFE_RING_MODE
+static char staticBucket[2048];
+#endif
+
+unsigned long long rdtsc() {
+  unsigned long long a;
+  asm volatile("rdtsc":"=A" (a));
+  return(a);
+}
+
+#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 +279,115 @@
 	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;
+	    memSlotsLen = handle->slots_info->tot_num_pages*PAGE_SIZE;
+	    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;
+
+	    /* 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;
+
+	    /* Set defaults */
+	    handle->linktype = DLT_EN10MB;
+	    handle->offset = 2;
+
+	    printf("RING: tot_slots=%d/slot_len=%d/"
+		   "insertIdx=%d/remove_idx=%d/dropped=%d\n",
+		   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_pkts;
+	    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 +527,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 +582,73 @@
 	int			packet_len, caplen;
 	struct pcap_pkthdr	pcap_header;
 
+#ifdef RING
+	if(handle->ring_buffer != NULL) {
+	  u_int idx, numRuns = 0;
+	  FlowSlot *slot;
+
+	  /*
+	    printf("page_id=%d - slot_id=%d\n", handle->page_id, handle->slot_id);
+	  */
+
+	  slot = (FlowSlot*)&handle->ring_buffer[handle->page_id+handle->slot_id];
+
+	  while(1) {
+	    if(slot->slot_state == 1) {
+	      char *bucket = &slot->bucket;
+
+	      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);
+		callback(userdata, hdr, staticBucket);		
+	      }
+#else
+	      callback(userdata,
+		       (const struct pcap_pkthdr*)bucket,
+		       (const u_char*)&bucket[sizeof(struct pcap_pkthdr)]);	      
+#endif
+	      slot->slot_state = 0;
+
+	      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;
+
+		if(handle->pkts_per_page >= handle->slots_info->pkts_per_page) {
+		  handle->page_id += PAGE_SIZE, handle->slot_id = 0,
+		    handle->pkts_per_page = 0;
+		}
+	      }
+
+	      return(1);
+	    } else {
+	      struct pollfd pfd;
+
+	      /* Sleep when nothing is happening */
+	      pfd.fd      = handle->ring_fd;
+	      pfd.events  = POLLIN|POLLERR;
+	      pfd.revents = 0;
+
+	      poll(&pfd, 1, -1);
+	      numPollCalls++;
+	    }
+	  } /* while() */
+	}
+#endif
+
 #ifdef HAVE_PF_PACKET_SOCKETS
 	/*
 	 * If this is a cooked device, leave extra room for a
@@ -688,6 +888,17 @@
 	socklen_t len = sizeof (struct tpacket_stats);
 #endif
 
+#ifdef RING
+	if(handle->ring_fd > 0) {
+	  stats->ps_recv = handle->slots_info->tot_pkts-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);
+	  return(0);
+	}
+#endif
+
 #ifdef HAVE_TPACKET_STATS
 	/*
 	 * Try to get the packet counts from the kernel.
@@ -879,6 +1090,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 +1564,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 +1641,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 +1699,14 @@
 	struct pcap	*p, *prevp;
 	struct ifreq	ifr;
 
+#ifdef RING
+	if(handle->ring_buffer != NULL) {
+	  u_int memSlotsLen = handle->slots_info->tot_num_pages*PAGE_SIZE;
+	  munmap(handle->ring_buffer, PAGE_SIZE);
+	  handle->ring_buffer = NULL;
+	}
+#endif
+
 	if (handle->md.clear_promisc) {
 		/*
 		 * We put the interface into promiscuous mode; take
@@ -1698,11 +1923,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 +2149,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 +2161,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 +2186,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 +2227,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
