1 diff -urN libpcap.old/pcap-int.h libpcap.dev/pcap-int.h
2 --- libpcap.old/pcap-int.h 2003-12-15 02:42:24.000000000 +0100
3 +++ libpcap.dev/pcap-int.h 2005-10-22 23:20:12.220060500 +0200
5 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8 - * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.55.2.4 2003/12/15 01:42:24 guy Exp $ (LBL)
9 + * @(#) $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)
17 +#define RING /* L.Deri */
26 +/* **************************** */
31 +#include <sys/mman.h>
33 +#include <sys/poll.h>
35 +#define PAGE_SIZE 4096
38 +#include <linux/ring.h>
43 +#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
45 +struct e1000_rx_desc {
46 + u_int64_t buffer_addr; /* Address of the descriptor's data buffer */
47 + u_int16_t length; /* Length of data DMAed into data buffer */
48 + u_int16_t csum; /* Packet checksum */
49 + u_int8_t status; /* Descriptor status */
50 + u_int8_t errors; /* Descriptor Errors */
54 +/* Transmit Descriptor */
55 +struct e1000_tx_desc {
56 + u_int64_t buffer_addr; /* Address of the descriptor's data buffer */
60 + u_int16_t length; /* Data buffer length */
61 + u_int8_t cso; /* Checksum offset */
62 + u_int8_t cmd; /* Descriptor control */
68 + u_int8_t status; /* Descriptor status */
69 + u_int8_t css; /* Checksum start */
86 + char *ring_buffer, *ring_slots;
88 + FlowSlotInfo *slots_info;
89 + u_int page_id, slot_id, pkts_per_page;
93 * Place holder for pcap_next().
95 diff -urN libpcap.old/pcap-linux.c libpcap.dev/pcap-linux.c
96 --- libpcap.old/pcap-linux.c 2003-11-21 11:20:46.000000000 +0100
97 +++ libpcap.dev/pcap-linux.c 2005-10-22 23:43:59.726120250 +0200
101 static const char rcsid[] _U_ =
102 - "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.98.2.4 2003/11/21 10:20:46 guy Exp $ (LBL)";
103 + "@(#) $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)";
109 #include "pcap-dag.h"
110 #endif /* HAVE_DAG_API */
117 = { 1, &total_insn };
120 +#define RING /* L.Deri */
121 +#define SAFE_RING_MODE /*
122 + Copy the bucket in order to avoid kernel
123 + crash if the application faults
127 +unsigned char *write_register;
128 +static struct pcap_stat ringStats;
129 +u_long numPollCalls = 0, numReadCalls = 0;
131 +#define POLL_SLEEP_STEP 10 /* ns = 0.1 ms */
132 +#define POLL_SLEEP_MIN POLL_SLEEP_STEP
133 +#define POLL_SLEEP_MAX 1000 /* ns */
134 +#define POLL_QUEUE_MIN_LEN 500 /* # packets */
136 +#ifdef SAFE_RING_MODE
137 +static char staticBucket[2048];
141 +/* ******************************* */
143 +int pcap_set_cluster(pcap_t *handle, u_int clusterId) {
144 + return(handle->ring_fd ? setsockopt(handle->ring_fd, 0, SO_ADD_TO_CLUSTER,
145 + &clusterId, sizeof(clusterId)): -1);
148 +/* ******************************* */
150 +int pcap_remove_from_cluster(pcap_t *handle) {
151 + return(handle->ring_fd ?
152 + setsockopt(handle->ring_fd, 0, SO_REMOVE_FROM_CLUSTER, NULL, 0) : -1);
155 +/* ******************************* */
157 +int pcap_set_reflector(pcap_t *handle, char *reflectorDevice) {
158 + return(handle->ring_fd ?
159 + setsockopt(handle->ring_fd, 0, SO_SET_REFLECTOR,
160 + &reflectorDevice, strlen(reflectorDevice)) : -1);
163 +/* ******************************* */
165 +static int set_if_promisc(const char *device, int set_promisc) {
169 + if(device == NULL) return(-3);
171 + sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
172 + if(sock_fd <= 0) return(-1);
174 + memset(&ifr, 0, sizeof(ifr));
175 + strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
176 + if(ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
182 + if((ifr.ifr_flags & IFF_PROMISC) == 0) ifr.ifr_flags |= IFF_PROMISC;
184 + /* Remove promisc */
185 + if((ifr.ifr_flags & IFF_PROMISC) != 0) ifr.ifr_flags &= ~IFF_PROMISC;
188 + if(ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1)
198 * Get a handle for a live capture from the given device. You can
199 * pass NULL as device to get all packages (without link level
200 @@ -258,6 +335,138 @@
201 handle->snapshot = snaplen;
202 handle->md.timeout = to_ms;
205 + handle->ring_fd = handle->fd = socket(PF_RING, SOCK_RAW, htons(ETH_P_ALL));
207 + printf("Open RING [fd=%d]\n", handle->ring_fd);
209 + if(handle->ring_fd > 0) {
210 + struct sockaddr sa;
215 + sa.sa_family = PF_RING;
216 + snprintf(sa.sa_data, sizeof(sa.sa_data), "%s", device);
217 + rc = bind(handle->ring_fd, (struct sockaddr *)&sa, sizeof(sa));
222 + handle->md.device = strdup(device);
223 + handle->ring_buffer = (char *)mmap(NULL, PAGE_SIZE,
224 + PROT_READ|PROT_WRITE,
226 + handle->ring_fd, 0);
228 + if(handle->ring_buffer == MAP_FAILED) {
229 + sprintf(ebuf, "mmap() failed");
233 + handle->slots_info = (FlowSlotInfo *)handle->ring_buffer;
234 + if(handle->slots_info->version != RING_FLOWSLOT_VERSION) {
235 + snprintf(ebuf, PCAP_ERRBUF_SIZE, "Wrong RING version: "
236 + "kernel is %i, libpcap was compiled with %i\n",
237 + handle->slots_info->version, RING_FLOWSLOT_VERSION);
240 + memSlotsLen = handle->slots_info->tot_mem;
241 + munmap(handle->ring_buffer, PAGE_SIZE);
243 + handle->ring_buffer = (char *)mmap(NULL, memSlotsLen,
244 + PROT_READ|PROT_WRITE,
245 + MAP_SHARED, handle->ring_fd, 0);
247 + if(handle->ring_buffer == MAP_FAILED) {
248 + sprintf(ebuf, "mmap() failed");
252 + handle->slots_info = (FlowSlotInfo *)handle->ring_buffer;
253 + handle->ring_slots = (char *)(handle->ring_buffer+sizeof(FlowSlotInfo));
256 + if(handle->slots_info->remove_idx >= handle->slots_info->tot_slots)
257 + handle->slots_info->remove_idx = 0;
259 + handle->page_id = PAGE_SIZE, handle->slot_id = 0,
260 + handle->pkts_per_page = 0;
265 + for(i=0; i<handle->slots_info->tot_slots; i++) {
266 + unsigned long idx = i*handle->slots_info->slot_len;
267 + FlowSlot *slot = (FlowSlot*)&handle->ring_slots[idx];
269 + printf("RING: Setting RING_MAGIC_VALUE into slot %d [displacement=%lu]\n", i, idx);
270 + slot->magic = RING_MAGIC_VALUE; slot->slot_state = 0;
271 + printf("RING: slot[%d]: magic=%d, slot_state=%d\n",
272 + slot->magic, slot->slot_state);
278 + handle->linktype = DLT_EN10MB;
279 + handle->offset = 2;
281 + printf("RING (%s): tot_slots=%d/slot_len=%d/"
282 + "insertIdx=%d/remove_idx=%d/dropped=%d\n",
284 + handle->slots_info->tot_slots,
285 + handle->slots_info->slot_len,
286 + handle->slots_info->insert_idx,
287 + handle->slots_info->remove_idx,
288 + handle->slots_info->tot_lost);
290 + ringStats.ps_recv = handle->slots_info->tot_read;
291 + ringStats.ps_drop = handle->slots_info->tot_lost;
297 + memset(&ifr, 0, sizeof(ifr));
298 + strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
299 + if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
300 + snprintf(ebuf, PCAP_ERRBUF_SIZE,
301 + "ioctl: %s", pcap_strerror(errno));
306 + if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
308 + * Promiscuous mode isn't currently on,
309 + * so turn it on, and remember that
310 + * we should turn it off when the
311 + * pcap_t is closed.
314 + ifr.ifr_flags |= IFF_PROMISC;
315 + if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
316 + snprintf(ebuf, PCAP_ERRBUF_SIZE,
317 + "ioctl: %s", pcap_strerror(errno));
323 + handle->md.clear_promisc = 1;
328 + goto open_open_live_final;
331 + /* Don't put 'else' above... */
332 + close(handle->ring_fd);
333 + /* Continue without ring support */
337 * NULL and "any" are special devices which give us the hint to
338 * monitor all devices.
344 + open_open_live_final:
347 * "handle->fd" is a socket, so "select()" and "poll()"
349 @@ -449,6 +661,120 @@
350 int packet_len, caplen;
351 struct pcap_pkthdr pcap_header;
354 + if(handle->ring_buffer != NULL) {
355 + u_int idx, numRuns = 0, ptrAddr;
358 + slot = (FlowSlot*)&handle->ring_slots[handle->slots_info->remove_idx*handle->slots_info->slot_len];
361 + u_int32_t queuedPkts;
363 + if(handle->slots_info->tot_insert >= handle->slots_info->tot_read)
364 + queuedPkts = handle->slots_info->tot_insert - handle->slots_info->tot_read;
366 + queuedPkts = handle->slots_info->tot_slots + handle->slots_info->tot_insert - handle->slots_info->tot_read;
368 + if(queuedPkts && (slot->slot_state == 1)) {
369 + char *bucket = &slot->bucket;
372 + if(slot->magic != RING_MAGIC_VALUE) {
373 + printf("==>> Bad Magic [remove_idx=%u][insert_idx=%u][ptrAddr=%u]\n",
374 + handle->slots_info->remove_idx,
375 + handle->slots_info->insert_idx,
377 + slot->magic = RING_MAGIC_VALUE;
382 + handle->md.stat.ps_recv++;
384 +#ifdef SAFE_RING_MODE
386 + struct pcap_pkthdr *hdr = (struct pcap_pkthdr*)bucket;
387 + int bktLen = hdr->caplen;
389 + if(bktLen > sizeof(staticBucket))
390 + bktLen = sizeof(staticBucket);
392 + memcpy(staticBucket, &bucket[sizeof(struct pcap_pkthdr)], bktLen);
395 + printf("==>> [remove_idx=%u][insert_idx=%u][ptrAddr=%u]\n",
396 + handle->slots_info->remove_idx,
397 + handle->slots_info->insert_idx,
401 + callback(userdata, hdr, staticBucket);
405 + (const struct pcap_pkthdr*)bucket,
406 + (const u_char*)&bucket[sizeof(struct pcap_pkthdr)]);
409 + if(handle->slots_info->remove_idx >= (handle->slots_info->tot_slots-1)) {
410 + handle->slots_info->remove_idx = 0;
411 + handle->page_id = PAGE_SIZE, handle->slot_id = 0, handle->pkts_per_page = 0;
413 + handle->slots_info->remove_idx++;
414 + handle->pkts_per_page++, handle->slot_id += handle->slots_info->slot_len;
417 + handle->slots_info->tot_read++;
418 + slot->slot_state = 0;
425 + /* Sleep when nothing is happening */
426 + pfd.fd = handle->ring_fd;
427 + pfd.events = POLLIN|POLLERR;
431 + printf("==>> poll [remove_idx=%u][insert_idx=%u][loss=%d][queuedPkts=%u]"
432 + "[slot_state=%d][tot_insert=%u][tot_read=%u]\n",
433 + handle->slots_info->remove_idx,
434 + handle->slots_info->insert_idx,
435 + handle->slots_info->tot_lost,
436 + queuedPkts, slot->slot_state,
437 + handle->slots_info->tot_insert,
438 + handle->slots_info->tot_read);
442 + printf("==>> poll @ [remove_idx=%u][slot_id=%u]\n", handle->slots_info->remove_idx, handle->slot_id);
445 + rc = poll(&pfd, 1, -1);
447 + printf("==>> poll returned %d [%s][errno=%d][break_loop=%d]\n",
448 + rc, strerror(errno), errno, handle->break_loop);
453 + if(errno == EINTR) {
454 + if(handle->break_loop) {
455 + handle->break_loop = 0;
467 #ifdef HAVE_PF_PACKET_SOCKETS
469 * If this is a cooked device, leave extra room for a
470 @@ -688,6 +1014,22 @@
471 socklen_t len = sizeof (struct tpacket_stats);
475 + if(handle->ring_fd > 0) {
476 + stats->ps_recv = handle->slots_info->tot_read-ringStats.ps_recv;
477 + stats->ps_drop = handle->slots_info->tot_lost-ringStats.ps_drop;
479 + printf("RING: numPollCalls=%d [%.1f packets/call]\n",
480 + numPollCalls, (float)stats->ps_recv/(float)numPollCalls);
481 + printf("RING: [tot_pkts=%u][tot_read=%u][tot_lost=%u]\n",
482 + handle->slots_info->tot_pkts,
483 + handle->slots_info->tot_read,
484 + handle->slots_info->tot_lost);
490 #ifdef HAVE_TPACKET_STATS
492 * Try to get the packet counts from the kernel.
493 @@ -879,6 +1221,11 @@
499 + if(handle->ring_fd <= 0) can_filter_in_kernel = 0;
502 if (can_filter_in_kernel) {
503 if ((err = set_kernel_filter(handle, &fcode)) == 0)
505 @@ -1348,7 +1695,7 @@
506 memset(&mr, 0, sizeof(mr));
507 mr.mr_ifindex = device_id;
508 mr.mr_type = PACKET_MR_PROMISC;
509 - if (setsockopt(sock_fd, SOL_PACKET,
510 + if (setsockopt(sock_fd, 0 /* SOL_PACKET */,
511 PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)
513 snprintf(ebuf, PCAP_ERRBUF_SIZE,
514 @@ -1425,10 +1772,11 @@
516 /* Any pending errors, e.g., network is down? */
518 - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
519 - snprintf(ebuf, PCAP_ERRBUF_SIZE,
520 - "getsockopt: %s", pcap_strerror(errno));
522 + if ((getsockopt(fd, PF_RING, SO_ERROR, &err, &errlen) == -1)
523 + && (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1)) {
524 + snprintf(ebuf, PCAP_ERRBUF_SIZE,
525 + "getsockopt: %s", pcap_strerror(errno));
530 @@ -1482,6 +1830,13 @@
531 struct pcap *p, *prevp;
535 + if(handle->ring_buffer != NULL) {
536 + munmap(handle->ring_buffer, handle->slots_info->tot_mem);
537 + handle->ring_buffer = NULL;
541 if (handle->md.clear_promisc) {
543 * We put the interface into promiscuous mode; take
544 @@ -1698,11 +2053,11 @@
547 /* Any pending errors, e.g., network is down? */
549 - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
550 - snprintf(ebuf, PCAP_ERRBUF_SIZE,
551 - "getsockopt: %s", pcap_strerror(errno));
553 + if((getsockopt(fd, PF_RING, SO_ERROR, &err, &errlen) == -1)
554 + && (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1)) {
555 + snprintf(ebuf, PCAP_ERRBUF_SIZE,
556 + "getsockopt: %s", pcap_strerror(errno));
561 @@ -1924,8 +2279,11 @@
562 * the filtering done in userland even if it could have been
563 * done in the kernel.
565 - if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
566 - &total_fcode, sizeof(total_fcode)) == 0) {
567 + printf("pcap[setsockopt(%d)]\n", 0);
568 + if (setsockopt(handle->fd, 0 /* SOL_SOCKET */,
571 + sizeof(total_fcode)) == 0) {
575 @@ -1933,6 +2291,9 @@
580 + if(!handle->ring_fd) {
583 * Save the socket's current mode, and put it in
584 * non-blocking mode; we drain it by reading packets
585 @@ -1955,12 +2316,15 @@
596 * Now attach the new filter.
598 - ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
599 + ret = setsockopt(handle->fd, 0 /* SOL_SOCKET */, SO_ATTACH_FILTER,
600 fcode, sizeof(*fcode));
601 if (ret == -1 && total_filter_on) {
603 @@ -1993,7 +2357,8 @@
604 /* setsockopt() barfs unless it get a dummy parameter */
607 - return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER,
608 - &dummy, sizeof(dummy));
609 + return setsockopt(handle->fd, handle->ring_fd > 0 ? PF_RING : SOL_SOCKET,
611 + &dummy, sizeof(dummy));