识别c中的虚拟网络接口
Identify virtual network interface in c
我正在尝试查找我的设备 运行 使用 C 的接口。
我用 ioctl 扫描了所有接口,我将结果排列为:
iface 0 ==> lo IP = 127.0.0.1 FLAGS = 00000049 MAC: 00 00 00 00 00 00
iface 1 ==> eth0 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 2 ==> eth0.1 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 3 ==> ra0 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 4 ==> br-lan IP = 192.168.100.1 FLAGS = 00001043 MAC: 40 D6 3C 02 74 11
iface 5 ==> apcli0 IP = 192.168.1.17 FLAGS = 00001043 MAC: 42 D6 3C 02 74 10
iface 6 ==> mon0 iface no IP FLAGS = 00001002 MAC: 40 D6 3C 02 74 10
我使用 getifaddrs() 获取接口列表,然后是 ioctl(使用 SIOCGIFADDR 的 IP),(使用 SIOCGIFFLAGS 的标志)枚举 net_device_flags,以及(mac 使用 SIOCGIFHWADDR)。
从列表中,我可以识别没有 IP 的环回、非工作接口。我仍然有两个具有相同 FLAGS 和 IP(apcli0 和 br-lan)的接口。
br-lan 是一个虚拟接口。
有没有办法判断接口是不是虚拟接口(用C)?
这是我的代码:
int i;
int fd;
int cnt = 0;
struct ifaddrs *addrs,*tmp;
char ibuf[256];
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
getifaddrs(&addrs);
tmp = addrs;
while (tmp)
{
if ( (tmp->ifa_addr) && (tmp->ifa_addr->sa_family == AF_PACKET)) {
printf("iface %i ==> %s\n", cnt, tmp->ifa_name);
// get ip
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, tmp->ifa_name, IFNAMSIZ);
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
printf("IP = %s\n", (char *)inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
} else {
printf("iface no IP\n");
}
// flags
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
printf("FLAGS = %08X\n", ifr.ifr_flags);
} else {
printf("iface no flags\n");
}
// mac addr
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
memcpy(ibuf, ifr.ifr_hwaddr.sa_data, 6);
printf("MAC: ");
for (i=0; i<6; i++) {
printf("%02X ", ibuf[i] & 0xFF);
}
printf("\n");
} else {
printf("iface no mac\n");
}
cnt++;
}
tmp = tmp->ifa_next;
}
freeifaddrs(addrs);
谢谢。
我认为 getifaddrs()
返回的信息不可能做到这一点,因为没有 SIOCGIFFLAGS
表明设备是虚拟的。例如,您可以通过检查 iface->ifa_flags
中的 IFF_LOOPBACK
标志(loopback 是一个虚拟接口)来找到一些虚拟设备,但是结构中没有信息具体说明是否设备是物理的还是虚拟的。
使用相当新的 Linux 内核(不确定启动内核,但它至少必须提供一个 sysfs),我相信这可以通过检查 /sys/class/net
来确定——这里的目录将表示由 ifconfig
和 getifaddrs()
报告的接口,并且将符号链接到 /sys/devices/platform
(物理设备)或 /sys/devices/virtual
(虚拟设备)中的设备。我不知道在 "regular C" 中有一个干净的方法来做到这一点(通过很好的理智函数调用,然后检查物理或虚拟的标志),但似乎可以通过检查 [= 中的目录结构来做到这一点19=].
编辑:看起来像 pci 设备,它们是物理设备,也可以显示在 /sys/devices/pci0000:00
或类似的下面,所以并不是所有的物理设备都会在 /sys/devices/physical
中,所以最好检查一下是 /sys/class/net
目录没有符号链接到 /sys/devices/virtual
目录...
我正在尝试查找我的设备 运行 使用 C 的接口。 我用 ioctl 扫描了所有接口,我将结果排列为:
iface 0 ==> lo IP = 127.0.0.1 FLAGS = 00000049 MAC: 00 00 00 00 00 00
iface 1 ==> eth0 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 2 ==> eth0.1 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 3 ==> ra0 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 4 ==> br-lan IP = 192.168.100.1 FLAGS = 00001043 MAC: 40 D6 3C 02 74 11
iface 5 ==> apcli0 IP = 192.168.1.17 FLAGS = 00001043 MAC: 42 D6 3C 02 74 10
iface 6 ==> mon0 iface no IP FLAGS = 00001002 MAC: 40 D6 3C 02 74 10
我使用 getifaddrs() 获取接口列表,然后是 ioctl(使用 SIOCGIFADDR 的 IP),(使用 SIOCGIFFLAGS 的标志)枚举 net_device_flags,以及(mac 使用 SIOCGIFHWADDR)。
从列表中,我可以识别没有 IP 的环回、非工作接口。我仍然有两个具有相同 FLAGS 和 IP(apcli0 和 br-lan)的接口。 br-lan 是一个虚拟接口。
有没有办法判断接口是不是虚拟接口(用C)?
这是我的代码:
int i;
int fd;
int cnt = 0;
struct ifaddrs *addrs,*tmp;
char ibuf[256];
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
getifaddrs(&addrs);
tmp = addrs;
while (tmp)
{
if ( (tmp->ifa_addr) && (tmp->ifa_addr->sa_family == AF_PACKET)) {
printf("iface %i ==> %s\n", cnt, tmp->ifa_name);
// get ip
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, tmp->ifa_name, IFNAMSIZ);
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
printf("IP = %s\n", (char *)inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
} else {
printf("iface no IP\n");
}
// flags
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
printf("FLAGS = %08X\n", ifr.ifr_flags);
} else {
printf("iface no flags\n");
}
// mac addr
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
memcpy(ibuf, ifr.ifr_hwaddr.sa_data, 6);
printf("MAC: ");
for (i=0; i<6; i++) {
printf("%02X ", ibuf[i] & 0xFF);
}
printf("\n");
} else {
printf("iface no mac\n");
}
cnt++;
}
tmp = tmp->ifa_next;
}
freeifaddrs(addrs);
谢谢。
我认为 getifaddrs()
返回的信息不可能做到这一点,因为没有 SIOCGIFFLAGS
表明设备是虚拟的。例如,您可以通过检查 iface->ifa_flags
中的 IFF_LOOPBACK
标志(loopback 是一个虚拟接口)来找到一些虚拟设备,但是结构中没有信息具体说明是否设备是物理的还是虚拟的。
使用相当新的 Linux 内核(不确定启动内核,但它至少必须提供一个 sysfs),我相信这可以通过检查 /sys/class/net
来确定——这里的目录将表示由 ifconfig
和 getifaddrs()
报告的接口,并且将符号链接到 /sys/devices/platform
(物理设备)或 /sys/devices/virtual
(虚拟设备)中的设备。我不知道在 "regular C" 中有一个干净的方法来做到这一点(通过很好的理智函数调用,然后检查物理或虚拟的标志),但似乎可以通过检查 [= 中的目录结构来做到这一点19=].
编辑:看起来像 pci 设备,它们是物理设备,也可以显示在 /sys/devices/pci0000:00
或类似的下面,所以并不是所有的物理设备都会在 /sys/devices/physical
中,所以最好检查一下是 /sys/class/net
目录没有符号链接到 /sys/devices/virtual
目录...