如何通过pcap动态获取Ubuntu系统的有线以太网接口名称
动态获取有线以太网接口名称的几种方案
针对你用pcap库开发链路层应用、需要替换硬编码接口名的需求,这里有几个可靠的实现思路,都是适配Ubuntu 16.04这类采用systemd可预测命名的系统的:
方案1:利用pcap库自身的接口枚举(推荐,跨平台友好)
pcap本身提供了枚举系统所有网络接口的API,你可以遍历这些接口,筛选出符合有线以太网特征的接口。判断依据可以是:
- 接口处于UP状态(避免选到禁用的接口)
- 接口类型是以太网(通过检查链路层类型为
DLT_EN10MB) - 排除无线接口(比如名字包含
wlan/wlp前缀,systemd命名的无线接口大多是这类开头)
代码示例
#include <pcap.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #define ETH_SNAPLEN 65536 #define ETH_PROMISCUOUS 1 #define ETH_TIMEOUT 1000 char* get_wired_eth_interface() { pcap_if_t *alldevs, *d; char errbuf[PCAP_ERRBUF_SIZE]; char* target_iface = NULL; // 获取所有网络接口列表 if (pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf); return NULL; } // 遍历接口筛选目标 for (d = alldevs; d != NULL; d = d->next) { // 跳过非活跃接口 if (!(d->flags & PCAP_IF_UP)) continue; // 临时打开接口判断是否为以太网类型 pcap_t* temp_pcap = pcap_open_live(d->name, ETH_SNAPLEN, 0, ETH_TIMEOUT, errbuf); if (!temp_pcap) continue; if (pcap_datalink(temp_pcap) == DLT_EN10MB) { // 排除无线接口 if (strncmp(d->name, "wlp", 3) != 0 && strncmp(d->name, "wlan", 4) != 0) { target_iface = strdup(d->name); pcap_close(temp_pcap); break; } } pcap_close(temp_pcap); } pcap_freealldevs(alldevs); return target_iface; } // 调用示例 int main() { char* iface = get_wired_eth_interface(); if (iface) { printf("Found wired eth interface: %s\n", iface); // 这里替换硬编码的接口名执行后续逻辑 pcap_t* pcap = pcap_open_live(iface, ETH_SNAPLEN, ETH_PROMISCUOUS, ETH_TIMEOUT, errbuf); free(iface); // 记得释放内存 } else { fprintf(stderr, "No valid wired eth interface found\n"); } return 0; }
方案2:读取Linux sysfs文件(Linux专属,高效直接)
Linux的sysfs文件系统(/sys/class/net/)存储了所有网络接口的底层信息,我们可以遍历目录下的接口,通过以下规则判断:
/sys/class/net/<iface>/type文件内容为1(以太网的类型标识)- 不存在
/sys/class/net/<iface>/wireless目录(排除无线接口) - 可选:
/sys/class/net/<iface>/carrier文件内容为1(接口已连接网线)
代码示例
#include <dirent.h> #include <stdio.h> #include <string.h> #include <stdlib.h> char* get_wired_eth_interface_sysfs() { DIR* dir = opendir("/sys/class/net/"); struct dirent* entry; char* target_iface = NULL; if (!dir) { perror("Failed to access /sys/class/net/"); return NULL; } while ((entry = readdir(dir)) != NULL) { // 跳过.和..目录 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } // 检查是否为以太网类型 char type_path[1024]; snprintf(type_path, sizeof(type_path), "/sys/class/net/%s/type", entry->d_name); FILE* type_file = fopen(type_path, "r"); if (!type_file) continue; int type; fscanf(type_file, "%d", &type); fclose(type_file); if (type != 1) continue; // 排除无线接口 char wireless_path[1024]; snprintf(wireless_path, sizeof(wireless_path), "/sys/class/net/%s/wireless", entry->d_name); DIR* wireless_dir = opendir(wireless_path); if (wireless_dir) { closedir(wireless_dir); continue; } // 可选:检查接口是否已连接 char carrier_path[1024]; snprintf(carrier_path, sizeof(carrier_path), "/sys/class/net/%s/carrier", entry->d_name); FILE* carrier_file = fopen(carrier_path, "r"); if (carrier_file) { int carrier; fscanf(carrier_file, "%d", &carrier); fclose(carrier_file); if (carrier != 1) continue; } // 找到目标接口,复制名称 target_iface = strdup(entry->d_name); break; } closedir(dir); return target_iface; }
方案3:解析ip link命令输出(快速原型,依赖命令格式)
如果不想写复杂的系统调用,也可以执行ip link show命令,解析输出内容找到link/ether类型的接口,同时排除无线接口名称。
代码示例
#include <stdio.h> #include <string.h> #include <stdlib.h> char* get_wired_eth_interface_ipcmd() { FILE* pipe = popen("ip link show", "r"); if (!pipe) { perror("Failed to run ip link command"); return NULL; } char line[256]; char* target_iface = NULL; char current_iface[64]; while (fgets(line, sizeof(line), pipe) != NULL) { // 提取接口名称(格式:X: <iface>: ...) if (sscanf(line, "%*d: %[^:]:", current_iface) == 1) { // 检查下一行是否包含以太网标识 if (fgets(line, sizeof(line), pipe) != NULL) { if (strstr(line, "link/ether") != NULL) { // 排除无线接口 if (strncmp(current_iface, "wlp", 3) != 0 && strncmp(current_iface, "wlan", 4) != 0) { target_iface = strdup(current_iface); break; } } } } } pclose(pipe); return target_iface; }
选择建议
- 如果你的应用需要跨平台(比如后续要适配Windows/macOS),优先选方案1,pcap的API是跨平台兼容的。
- 如果只针对Linux系统,方案2最高效,不需要依赖外部命令或额外的pcap调用,直接读取系统底层文件。
- 方案3适合快速原型开发,但要注意
ip命令的输出格式可能在不同系统版本有细微变化,稳定性稍差。
内容的提问来源于stack exchange,提问作者bph
相关产品推荐
相关产品推荐

