c - 使用 pcap 自动检索有线以太网接口(interface)名称

标签 c pcap raw-ethernet

我有一个在数据链路层级别发送/接收数据包的应用程序,即通过有线以太网连接从 MAC 地址发送到 MAC 地址的帧。

我正在使用 pcap 库来执行此操作。

从终端运行 ip a 返回:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether 50:7b:9d:84:34:93 brd ff:ff:ff:ff:ff:ff
3: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 18:5e:0f:8f:d1:3f brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 brd 192.168.1.255 scope global dynamic wlp3s0
       valid_lft 57882sec preferred_lft 57882sec
    inet6 fe80::c215:9ad2:a358:6d3d/64 scope link 
       valid_lft forever preferred_lft forever

我的操作系统是 ubuntu 16.04,它使用 systemd 可预测的网络接口(interface)命名。此实例中的有线以太网接口(interface)名称为 enp0s25

目前我在我的应用程序中有这个硬编码,即

pcap=pcap_open_live("enp0s25", ETH_SNAPLEN, ETH_PROMISCUOUS, ETH_TIMEOUT, pcap_errbuf);

我想做的是动态检索有线以太网接口(interface)的名称,这样它仍然可以在以太网接口(interface)名称可能不同于 enp0s25

的设备上工作

我已经实现了:

/* automatically retrieve the ethernet interface name */
n = pcap_findalldevs(&alldevs, pcap_errbuf);

/* scan the list for a suitable device to capture from */
for (dev = alldevs; dev != NULL; dev = dev->next) {

    /* Name */
    printf("%s\n",dev->name);
}
pcap_freealldevs(alldevs);

这使我可以遍历所有接口(interface)名称。

我的问题是如何选择有线以太网接口(interface)对应的名称?

我还没有在多个设备上测试我的代码,所以我不确定接口(interface)名称与 enp0s25 有何不同。

有线以太网接口(interface)是否总是以 enp 开头?

在这种情况下,也许解决方案是对检索到的接口(interface)名称的第一个 3 个字符执行 strcmp

最佳答案

ioctl(fd, SIOCGIWNAME) 将返回无线扩展协议(protocol)版本,该版本仅在无线接口(interface)上可用。

下面的函数检查接口(interface)是否是无线的

bool check_type(const char* ifname) {
  int sock = -1;
  // set the name of the interface in the ioctl request struct
  struct ifreq ifr;
  memset(&ifr, 0, sizeof(struct ifreq));
  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);

  //Create a throw-away socket
  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    return FALSE;
  }


  // First check if the interface is up
  // also proves that the interface exists
  int r = ioctl(sock, SIOCGIFFLAGS, &ifr);
  if (r != 0) {
    close(sock);
    return FALSE;
  }

  if (!(ifr.ifr_flags & IFF_UP)) {
    close(sock);
    return FALSE;
  }
  if (ioctl(sock, SIOCGIWNAME, &ifr) != -1) {
    close(sock);
    return TRUE;
  }

  close(sock);
  return FALSE;
}

关于c - 使用 pcap 自动检索有线以太网接口(interface)名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49447049/

相关文章:

c - 在 C 中仅打印数组中的某些位置

在c中为捕获的数据包创建PCAP文件

node.js - windows下用nodejs抓包

network-programming - 编程中以太网和 TCP/IP 协议(protocol)的区别?

c - 获取从 C 中的函数返回的奇怪数字

c++ - 使用 g++ 进行编译时 undefined reference

c - 查找数组中的最大元素

pcap - pcap魔数(Magic Number)0xc3d4a1b2是什么?

原始以太网的 Java 库

sockets - 使用 Go 语言发送带有以太网 header 的原始数据包