libpcap: как получить активный сетевой интерфейс (Mac OSX) - PullRequest
2 голосов
/ 05 декабря 2010

Я использую libpcap для прослушивания трафика.Я хотел бы сделать это на текущем активном сетевом устройстве (например, на котором назначен IP-адрес и т. Д.).Какой лучший способ сделать это?Я предполагаю, что мне нужно будет сделать следующее:

pcap_findalldevs(&alldevs, errbuf)

, чтобы получить все сетевые устройства, затем выполнить цикл и проверить, какое из них активно в данный момент.


Редактировать: Следующая функция

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

возвращает сетевой адрес и маску подсети для сетевого устройства.Я провел несколько тестов с различными адаптерами Ethernet на моем компьютере, и он возвращает -1, когда я вызываю его на адаптере, который не подключен к сети.Будет ли это пуленепробиваемый способ получить активный интерфейс?Есть ли какие-нибудь крайние случаи, которые он пропустит?

Ответы [ 4 ]

2 голосов
/ 05 декабря 2010

API pcap для поиска интерфейсов, соответствующих определенным пользователем правилам, тривиально. Вы действительно можете использовать pcap_findalldevs () для взаимодействия со всеми подходящими сетевыми устройствами или использовать pcap_lookupdev () для получения следующего сетевого устройства, которое вы можете использовать с pcap. Определение того, какой интерфейс вы хотите использовать со своим анализатором, может быть проблематичным (с точки зрения кода) в системах с несколькими сетевыми устройствами, и вы захотите определить более явные правила для выбора такого интерфейса. Такие правила обычно определяются статически (например, «активный интерфейс с установленным маршрутом по умолчанию»). Однако у вас может быть несколько маршрутов по умолчанию (подумайте о балансировке нагрузки), и здесь вы можете захотеть прослушать все из них или (например) только через интерфейс ppp. Поэтому выбор целевого интерфейса, который я бы сказал, является задачей, решаемой вне анализатора, а не во время выполнения в коде анализатора.

Например:

Если под «активным интерфейсом» мы понимаем интерфейс, на котором установлен маршрут по умолчанию (я предполагаю, что система Linux здесь):

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

если вы хотите получить активный интерфейс, на котором установлен маршрут по умолчанию, из вашего кода сниффера, вы бы предпочли использовать netlink (7) или proc (5) (/ proc / net / route), а не интерфейс поиска устройств pcap, сложность высокая.

В заключение, логика поиска интерфейса может быть легко записана в какую-либо программу-оболочку в любой системе, и результат (ы) передаются в качестве параметра (ов) вашему анализатору.

0 голосов
/ 08 декабря 2010

Согласно 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.

Но, похоже, это устарело, вы должны использовать pcap_create (3)

0 голосов
/ 05 декабря 2010

Я уже несколько раз шел по этому пути и обычно возвращался к добавлению переключателя -i, чтобы пользователь мог точно идентифицировать интерфейс.

Это упрощает вашу работу и позволяет избежать любых граничных условий.

0 голосов
/ 05 декабря 2010

Почему бы вам не выполнить захват на «любом» устройстве (псевдо-устройстве, которое захватывает на всех интерфейсах)?

В любом случае, вот небольшой фрагмент, который поможет вам найти «активные» интерфейсы

#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;
}
...