Author: deri Date: 2010-09-09 11:13:15 +0200 (Thu, 09 Sep 2010) New Revision: 4358
Modified: trunk/PF_RING/kernel/pf_ring.c Log: Fix for the bug below courtesy of Dan Kruchinin <[email protected]> 1) The bug: libpcap with PF_RING enabled improperly determines type of net device. It works well with pure ethernet devices but when I give it an IP-tunnel device it reports that tunnel has type "EN10MB (Ethernet)" instead of "RAW (Raw IP)". 2) How to reproduce: I attached a small and simple C application that creates a TUN(using /dev/net/tun) tunnel device (tun.tar.gz). It takes the only one argument - the name of tunnel. % ./tun vtun0 & Creating tun device... tun device vtun0 was successfully created. Entering main loop. Press Ctrl-D to exit... % ifconfig vtun0 10.10.0.1 up So the TUN tunnel should have RAW linktype. Let's ask what type vtun0 actually has: % tcpdump -i vtun0 -L Data link types for vtun0 (use option -y to set): EN10MB (Ethernet) An the same command on another machine where libpcap has not PF_RING support: % tcpdump -i vtun0 -L Data link types for vtun0 (use option -y to set): RAW (Raw IP) As you can see, tcpdump determines invalid link type of the IP tunnel. tcpdump uses libpcap which contains an error. 3) The error: Take a look at userland/libpcap-1.0.0-ring/pcap-linux.c, function pcap_activate_linux() There is a chunk of code: #ifdef HAVE_PF_RING if(!getenv("PCAP_NO_PF_RING")) handle->ring = pfring_open((char*)device, handle->opt.promisc, handle->snapshot, 1); else handle->ring = NULL; if(handle->ring != NULL) { handle->fd = handle->ring->fd; handle->bufsize = handle->snapshot; handle->linktype = DLT_EN10MB; handle->offset = 2; /* printf("Open HAVE_PF_RING(%s)\n", device); */ } else { /* printf("Open HAVE_PF_RING(%s) failed. Fallback to pcap\n", device); */ #endif ... here activate_new() function called that asks kernel about linktype of given device. ... #ifdef HAVE_PF_RING } #endif As you can see from the code above, libpcap sets linktype to DLT_EN10MB(ethernet) if pfring_open was called without error. If we look at pfring_open and related kernel code at kernel/pf_ring.c we'll find out that pfring_open fails only if no memory is available for allocation or if it receives bad device name. Thus libpcap will set DLT_EN10MB for any device: for IP tunnel and for ppp device. It's not good because tcpdump produces invalid output(i.e. calls invalid printer function). For example if IP tunnel is determined as DLT_EN10MB it dumps something like this: % tcpdump -i vtun0 -pns 0 -XX tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on vtun0, link-type EN10MB (Ethernet), capture size 65535 bytes 15:10:21.571132 40:00:40:01:73:54 > 45:00:00:54:00:00, ethertype Unknown (0xc0a8), length 84: 0x0000: 4500 0054 0000 4000 4001 7354 c0a8 2802 e.....@[email protected]..(. 0x0010: c0a8 1e02 0800 38ec b80f 0000 09cc fd37 ......8........7 0x0020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0x0030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0x0050: 0000 0000 .... 4) Solution: The easiest solution I found is to check linktype of device userspace application is going to bind via PF_RING sockets. If it's type isn't ARPHRD_ETHER then an error is returned. (I attached the patch: pf_ring.patch) It's a quick and dirty solution and I don't think it's the best one. -- W.B.R. Dan Kruchinin Index: kernel/pf_ring.c =================================================================== --- kernel/pf_ring.c (revision 4357) +++ kernel/pf_ring.c (working copy) @@ -77,6 +77,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/proc_fs.h> +#include <linux/if_arp.h> #include <net/xfrm.h> #include <net/sock.h> #include <asm/io.h> /* needed for virt_to_phys() */ @@ -3168,7 +3169,7 @@ { struct ring_opt *pfr = ring_sk(sk); - if(!dev) + if(!dev || (dev->type != ARPHRD_ETHER)) return(-1); #if defined(RING_DEBUG _______________________________________________ Ntop-dev mailing list [email protected] http://listgateway.unipi.it/mailman/listinfo/ntop-dev
