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…