Question

I am using libpcap to sniff traffic. I would like to do it on the currently active network device (e.g. one that has an assigned IP address, etc). What's the best way to do this? I'm assuming I would have to do the following:

pcap_findalldevs(&alldevs, errbuf)

to get all the network devices, then loop through and check which one is currently active.


Edit: The following function

(pcap_lookupnet(dev, &net, &mask, errbuf) 

returns the network address and subnet mask for a network device. I ran some tests with the different ethernet adapters on my computer and it returns -1 when I call it on an adapter that is not connected to a network. Would this be the bulletproof way to get an active interface? Are there any edge cases it would miss?

Was it helpful?

Solution

the API pcap has for looking up interfaces conforming to some user defined rules is trivial. You could indeed use pcap_findalldevs() to interate over all suitable-to-use network devices or use pcap_lookupdev() to get the next network device that you can use with pcap. Defining what is the interface you want to use with your sniffer may be problematic (code wise) on systems with multiple network devices and you would want to define more explicit rules for choosing such an interface. Such rules are usually statically defined (like "the active interface with the default route installed"). However, you may have multiple default routes (think load balancing) and here you may either want to sniff on all of them or (for example) only on the ppp interface. So choosing the target interface I would say is a task to be resolved outside the sniffer rather than at runtime in the sniffer code.

For example:

If by "active interface" we understand the interface on which the default route is installed (i assume a linux system here):

ip route show 0.0.0.0/0 | awk ' { print $5 ; } ' | xargs ./sniffer

if you want to get the active interface which has the default route installed on from your sniffer code, you would rather use netlink(7) or proc(5) (/proc/net/route) than pcap's device lookup api but the complexity is high.

In conclusion, the interface lookup logic can be easily scripted into some wrapper program on any system and the result(s) passed as parameter(s) to your sniffer.

OTHER TIPS

Why don't you capture on 'any' device (Pseudo-device that captures on all interfaces) ?

Any way, here is a little snippet that will help you find 'active' interfaces

#include <stdio.h>
#include <pcap.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

static void
dump_addresses (pcap_addr_t *addresses)
{
 pcap_addr_t *addr = addresses;
 printf("(");
 while (addr) {
  struct sockaddr_in *ip = (struct sockaddr_in *)addr->addr;
  struct sockaddr_in *nm = (struct sockaddr_in *)addr->netmask;
  if (ip && nm)
   printf("%s/%s ",
     inet_ntoa(ip->sin_addr), inet_ntoa(nm->sin_addr));
  addr = addr->next;
 }
 printf(")");
}

static void
devs_dump (pcap_if_t *devs)
{
 pcap_if_t *dev = devs;
 while (dev) {
  printf("dev: %s - %s - ",
    dev->name, dev->description);
  dump_addresses(dev->addresses);
  printf("\n");
  dev = dev->next;
 }
}

int
main(int argc, char *argv[])
{
 int r;
 char errbuf[PCAP_ERRBUF_SIZE];
 pcap_if_t *devs;

 r = pcap_findalldevs (&devs, errbuf);
 if (r) {
  printf("Findalldevs: %d (%s)\n", r, errbuf);
  return -1;
 }
 devs_dump(devs);
 pcap_freealldevs (devs);

 return 0;
}

I've been down this road several times before, and usually find myself falling back to adding a -i switch to allow the user to precisely identify the interface.

It makes your job simpler and avoids any edge conditions.

According to pcap_open_live (3):

DESCRIPTION
pcap_open_live() is used to obtain a packet capture handle to
   look at packets on the network.   device  is  a  string  that
   specifies  the  network device to open; on Linux systems with
   2.2 or later kernels, a device argument of "any" or NULL  can
   be used to capture packets from all interfaces.

But it seems it's deprecated now, you should use pcap_create(3)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top