Linux 用c语言识别虚拟网络接口

Linux 用c语言识别虚拟网络接口,linux,network-programming,ioctl,Linux,Network Programming,Ioctl,我试图找到我的设备运行在哪个接口上。 我用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

我试图找到我的设备运行在哪个接口上。 我用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(使用siocgiffaddr的IP),(使用SIOCGIFFLAGS的标志)enum net_device_标志,以及(使用siocgiffhwaddr的mac)

从列表中,我可以确定没有IP的环回、非工作接口。我仍然有两个具有相同标志和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);
inti;
int-fd;
int-cnt=0;
结构ifaddrs*addrs,*tmp;
char-ibuf[256];
结构ifreq-ifr;
fd=插座(AF INET,插座DGRAM,0);
getifaddrs(和addrs);
tmp=地址;
while(tmp)
{
if((tmp->ifa\U地址)和&(tmp->ifa\U地址->sa\U系列==AF\U数据包)){
printf(“iface%i==>%s\n”,cnt,tmp->ifa\u名称);
//获取ip
ifr.ifr\u addr.sa\u family=AF\u INET;
strncpy(ifr.ifr\U名称,tmp->ifa\U名称,IFNAMSIZ);
如果(ioctl(fd、SIOCGIFADDR和ifr)==0){
printf(“IP=%s\n”,(char*)inet\u ntoa(((struct sockaddr\u in*)和ifr.ifr\u addr)->sin\u addr));
}否则{
printf(“iface无IP\n”);
}
//旗帜
如果(ioctl(fd、SIOCGIFFLAGS和ifr)==0){
printf(“标志=%08X\n”,ifr.ifr\u标志);
}否则{
printf(“iface无标志\n”);
}
//mac地址
如果(ioctl(fd、SIOCGIFHWADDR和ifr)==0){
memcpy(ibuf,ifr.ifr_hwaddr.sa_数据,6);
printf(“MAC:”);
对于(i=0;iifa_next;
}
freeifaddrs(addrs);

谢谢。

我不相信使用
getifaddrs()
返回的信息就可以做到这一点,因为没有
SIOCGIFFLAGS
表示设备是虚拟的。您可以通过检查
iface->ifa\u标志中的
IFF\u环回
标志来找到一些虚拟设备(环回是一个虚拟接口),但结构中没有明确说明设备是物理设备还是虚拟设备的信息

对于相当新的Linux内核(不确定是否启动一个,但它必须至少提供一个sysfs),我相信这可以通过检查
/sys/class/net
——这里的目录将表示
ifconfig
getifaddrs()报告的接口来确定
,并将被符号链接到
/sys/devices/platform
(物理设备)或
/sys/devices/virtual
(虚拟设备)中的设备。我不知道在“常规C”中有什么干净的方法可以做到这一点(使用良好的sane函数调用,然后检查物理或虚拟设备的标志),但通过检查
/sys
中的目录结构似乎可以做到这一点


编辑:看起来pci设备是物理设备,也可以显示在
/sys/devices/pci0000:00
或类似目录下,因此并非所有物理设备都将位于
/sys/devices/physical
,因此更好的检查是
/sys/class/net
目录未与
/sys/devices/virtual
目录进行符号链接。。.

请出示您的代码。是的。是的。深入研究/sys/class/net会更好。我认为如果我单独使用C语言,会非常复杂。