ioctl で NIC の情報を取得
特定NICのIPアドレスを取得する関数 - Shammerismのようにgetifaddrs 関数を使用しても取得できるが、IPv4 の情報であれば ioctl も使用できるようだ。struct ifreq が使用される。
#include <arpa/inet.h> #include <ifaddrs.h> #include <net/if.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/ioctl.h> #include <unistd.h> int getifipv4addr(char * value, const char * device) { int status, fd; struct ifreq ifreq; struct sockaddr_in addr; strcpy(ifreq.ifr_name, device); fd = socket(PF_INET, SOCK_DGRAM, 0); status = ioctl(fd, SIOCGIFADDR, &ifreq); if( status == -1 ){ perror("ioctl(SIOCGIFADDR)\n"); return 1; } else if( ifreq.ifr_addr.sa_family != AF_INET ){ // Not IPv4 } else { memcpy(&addr, &ifreq.ifr_addr, sizeof(struct sockaddr_in)); strcpy(value, inet_ntoa(addr.sin_addr)); } close(fd); return 0; } void getifipv6addr(char * value, const char * device) { struct ifaddrs * if_list = NULL; struct ifaddrs * ifa = NULL; void * tmp = NULL; getifaddrs(&if_list); for( ifa = if_list ; ifa != NULL ; ifa = ifa->ifa_next ){ if( strcmp(ifa->ifa_name, device) == 0 ){ // Target device if( !ifa->ifa_addr ){ // This interface is NOT assigned IP Address? or not linked up? continue; } else { if( ifa->ifa_addr->sa_family == AF_INET6 ) { // Check IPv6 Address tmp = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; inet_ntop(AF_INET6, tmp, value, INET6_ADDRSTRLEN); break; } else { // For example, reach here the cases // sa_family is AF_PACKET(17). // sa_family is AF_INET6(23). } } } } freeifaddrs(if_list); } int main(int argc, const char * args[]){ char ipv4_addr[INET_ADDRSTRLEN]; memset(ipv4_addr, 0, sizeof(ipv4_addr)); getifipv4addr(ipv4_addr, args[1]); printf("%s IPv4 address is %s.\n", args[1], ipv4_addr); char ipv6_addr[INET6_ADDRSTRLEN]; memset(ipv6_addr, 0, sizeof(ipv6_addr)); getifipv6addr(ipv6_addr, args[1]); printf("%s IPv6 address is %s.\n", args[1], ipv6_addr); return 0; }
実行結果は以下。
$ ./a.out eth0 eth0 IPv4 address is 192.168.128.101. eth0 IPv6 address is fe80::863a:4bff:fedc:280. $
ioctl はもっといろいろできるようだ。