Skip to content
Advertisement

Identify virtual network interface in c

I am trying to find which interface my device is running on with C. I scanned all interfaces with ioctl, I arranged the result as :

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 

I used getifaddrs() to get list of interfces, then ioctl (IP using SIOCGIFADDR), (flags using SIOCGIFFLAGS) enum net_device_flags, and (mac using SIOCGIFHWADDR).

From the list, I can identify the loopback, non-working interfaces that do not have IP. I still have two interfaces that are identical FLAGS and have IP (apcli0 & br-lan). The br-lan is a virtual interface.

Is there away to identify if the interface is virtual (with C)?

Here is my code:

    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 ==> %sn", 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 = %sn", (char *)inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
            } else {
                printf("iface no IPn");
            }

            // flags
            if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
                printf("FLAGS = %08Xn", ifr.ifr_flags);
            } else {
                printf("iface no flagsn");

            }

            // 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 macn");

            }

            cnt++;
        }
        tmp = tmp->ifa_next;
    }
    freeifaddrs(addrs);

Thanks.

Advertisement

Answer

I don’t believe this is possible with information returned by getifaddrs(), because there are no SIOCGIFFLAGS which indicate that a device is virtual. You can find some of the virtual devices by, for example, checking for the IFF_LOOPBACK flag in iface->ifa_flags (loopback is a virtual interface), but there isn’t information in the struct which says specifically whether the device is physical or virtual.

With reasonably recent Linux kernels (not sure starting one, but it has to at least provide a sysfs), I believe this can be determined by examining /sys/class/net — the directories here will represent the interfaces reported by ifconfig and getifaddrs(), and will either be symlinked to a device in /sys/devices/platform (physical devices) or /sys/devices/virtual (virtual devices). I don’t know of a clean way to do this in “regular C” (with nice sane function calls and then checking a flag for physical or virtual), but it seems possible to do it by examining the directory structure in /sys.

edit: looks like pci devices, which are physical devices, can also show up under /sys/devices/pci0000:00 or similar, so not all physical devices are going to be in /sys/devices/physical, so a better check is that /sys/class/net directories aren’t symlinked to /sys/devices/virtual directories…

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement