--- embedaddon/iftop/addrs_ioctl.c 2012/02/21 16:57:34 1.1.1.1 +++ embedaddon/iftop/addrs_ioctl.c 2016/10/18 14:04:50 1.1.1.2 @@ -18,12 +18,17 @@ #include #include -#if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ +#if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ \ + || ( defined __GLIBC__ && ! defined __linux__ ) #include #include #include #endif +#ifdef USE_GETIFADDRS +#include +#endif + #include "iftop.h" /* @@ -40,16 +45,20 @@ */ int -get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr) +get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr, struct in6_addr *if_ip6_addr) { int s; struct ifreq ifr = {}; int got_hw_addr = 0; int got_ip_addr = 0; + int got_ip6_addr = 0; +#ifdef USE_GETIFADDRS + struct ifaddrs *ifa, *ifas; +#endif /* -- */ - s = socket(PF_INET, SOCK_DGRAM, 0); /* any sort of IP socket will do */ + s = socket(AF_INET, SOCK_DGRAM, 0); /* any sort of IP socket will do */ if (s == -1) { perror("socket"); @@ -71,7 +80,8 @@ get_addrs_ioctl(char *interface, char if_hw_addr[], st got_hw_addr = 1; } #else -#if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ +#if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ \ + || ( defined __GLIBC__ && ! defined __linux__ ) { int sysctlparam[6] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; size_t needed = 0; @@ -80,28 +90,23 @@ get_addrs_ioctl(char *interface, char if_hw_addr[], st sysctlparam[5] = if_nametoindex(interface); if (sysctlparam[5] == 0) { fprintf(stderr, "Error getting hardware address for interface: %s\n", interface); - goto ENDHWADDR; } - if (sysctl(sysctlparam, 6, NULL, &needed, NULL, 0) < 0) { + else if (sysctl(sysctlparam, 6, NULL, &needed, NULL, 0) < 0) { fprintf(stderr, "Error getting hardware address for interface: %s\n", interface); - goto ENDHWADDR; } - if ((buf = malloc(needed)) == NULL) { + else if ((buf = malloc(needed)) == NULL) { fprintf(stderr, "Error getting hardware address for interface: %s\n", interface); - goto ENDHWADDR; } - if (sysctl(sysctlparam, 6, buf, &needed, NULL, 0) < 0) { + else if (sysctl(sysctlparam, 6, buf, &needed, NULL, 0) < 0) { fprintf(stderr, "Error getting hardware address for interface: %s\n", interface); free(buf); - goto ENDHWADDR; } - msghdr = (struct if_msghdr *) buf; - memcpy(if_hw_addr, LLADDR((struct sockaddr_dl *)(buf + sizeof(struct if_msghdr) - sizeof(struct if_data) + sizeof(struct if_data))), 6); - free(buf); - got_hw_addr = 1; - - ENDHWADDR: - 1; /* compiler whines if there is a label at the end of a block...*/ + else { + msghdr = (struct if_msghdr *) buf; + memcpy(if_hw_addr, LLADDR((struct sockaddr_dl *)(buf + sizeof(struct if_msghdr) - sizeof(struct if_data) + sizeof(struct if_data))), 6); + free(buf); + got_hw_addr = 1; + } } #else fprintf(stderr, "Cannot obtain hardware address on this platform\n"); @@ -109,7 +114,48 @@ get_addrs_ioctl(char *interface, char if_hw_addr[], st #endif /* Get the IP address of the interface */ -#ifdef SIOCGIFADDR +#ifdef USE_GETIFADDRS + if (getifaddrs(&ifas) == -1) { + fprintf(stderr, "Unable to get IP address for interface: %s\n", interface); + perror("getifaddrs()"); + } + else { + for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) { + if (got_ip_addr && got_ip6_addr) + break; /* Search is already complete. */ + + if (strcmp(ifa->ifa_name, interface)) + continue; /* Not our interface. */ + + if (ifa->ifa_addr == NULL) + continue; /* Skip NULL interface address. */ + + if ( (ifa->ifa_addr->sa_family != AF_INET) + && (ifa->ifa_addr->sa_family != AF_INET6) ) + continue; /* AF_PACKET is beyond our scope. */ + + if ( (ifa->ifa_addr->sa_family == AF_INET) + && !got_ip_addr ) { + got_ip_addr = 2; + memcpy(if_ip_addr, + &(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr), + sizeof(*if_ip_addr)); + continue; + } + /* Must be a IPv6 address at this point. */ + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) ifa->ifa_addr; + + if ( IN6_IS_ADDR_LINKLOCAL(&(sa6->sin6_addr)) + || IN6_IS_ADDR_SITELOCAL(&(sa6->sin6_addr)) ) + continue; + + /* A useful IPv6 address. */ + memcpy(if_ip6_addr, &(sa6->sin6_addr), sizeof(*if_ip6_addr)); + got_ip6_addr = 4; + } + freeifaddrs(ifas); + } /* getifaddrs() */ +#elif defined(SIOCGIFADDR) (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET; if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { fprintf(stderr, "Unable to get IP address for interface: %s\n", interface); @@ -125,5 +171,5 @@ get_addrs_ioctl(char *interface, char if_hw_addr[], st close(s); - return got_hw_addr + got_ip_addr; + return got_hw_addr + got_ip_addr + got_ip6_addr; }