在c中识别虚拟网络接口

时间:2018-05-25 23:49:31

标签: linux network-programming ioctl

我正在尝试使用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()获取interfces列表,然后使用ioctl(使用SIOCGIFADDR的IP),(使用SIOCGIFFLAGS的标志)enum 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);

感谢。

1 个答案:

答案 0 :(得分:0)

我不认为使用getifaddrs()返回的信息是可行的,因为没有SIOCGIFFLAGS表示设备是虚拟的。例如,可以通过检查IFF_LOOPBACK中的iface->ifa_flags标志(环回是一个虚拟接口)来找到一些虚拟设备,但是结构中没有专门说明是否设备是物理设备还是虚拟设备。

对于相当新近的Linux内核(不确定是否启动一个,但必须至少提供一个sysfs),我相信可以通过检查/sys/class/net来确定-这里的目录将代表{ {1}}和ifconfig,并将被链接到getifaddrs()(物理设备)或/sys/devices/platform(虚拟设备)中的设备。我不知道在“常规C”中执行此操作的干净方法(使用不错的健全函数调用,然后检查物理或虚拟标志),但似乎可以通过检查{{1 }}。

edit:看起来像pci设备(它们是物理设备)也可以显示在/sys/devices/virtual或类似的下面,因此并非所有物理设备都位于/sys中,因此更好的检查是/sys/devices/pci0000:00目录未与/sys/devices/physical目录建立符号链接...