From fff0784ee84632b9b41c500db74509511a664c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= Date: Thu, 7 Dec 2017 16:14:42 +0100 Subject: [PATCH] aix interface patch --- lib/replace/getifaddrs.c | 130 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 91 insertions(+), 39 deletions(-) diff --git a/lib/replace/getifaddrs.c b/lib/replace/getifaddrs.c index 9e377e5..0a4efdb 100644 --- a/lib/replace/getifaddrs.c +++ b/lib/replace/getifaddrs.c @@ -56,16 +56,17 @@ void rep_freeifaddrs(struct ifaddrs *ifp) } } -static struct sockaddr *sockaddr_dup(struct sockaddr *sa) +static struct sockaddr *sockaddr_dup(const struct sockaddr *sa) { struct sockaddr *ret; - socklen_t socklen; + socklen_t socklen, size; #ifdef HAVE_SOCKADDR_SA_LEN socklen = sa->sa_len; #else socklen = sizeof(struct sockaddr_storage); #endif - ret = calloc(1, socklen); + size = MAX(socklen, sizeof(struct sockaddr_storage)); + ret = calloc(1, size); if (ret == NULL) return NULL; memcpy(ret, sa, socklen); @@ -282,16 +283,17 @@ int rep_getifaddrs(struct ifaddrs **ifap) #ifdef HAVE_IFACE_AIX /**************************************************************************** -this one is for AIX (tested on 4.2) +this one is for AIX (tested on 5.3 / 6.1 / 7.1) ****************************************************************************/ int rep_getifaddrs(struct ifaddrs **ifap) { - char buff[8192]; - int fd, i; + int fd, size; struct ifconf ifc; - struct ifreq *ifr=NULL; - struct ifaddrs *curif; + struct ifaddrs *firstif = NULL; struct ifaddrs *lastif = NULL; + const uint8_t *current, *end; + int ret = -1; + struct ifaddrs *curif = NULL; *ifap = NULL; @@ -299,77 +301,127 @@ int rep_getifaddrs(struct ifaddrs **ifap) return -1; } - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - - if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { - close(fd); - return -1; + if (ioctl(fd, SIOCGSIZIFCONF, &size) != 0) { + ret = -1; + goto done; } - ifr = ifc.ifc_req; + ifc.ifc_len = size; + ifc.ifc_req = (struct ifreq *)cmalloc(1, size); - /* Loop through interfaces */ - i = ifc.ifc_len; + if (ifc.ifc_req == NULL) + { + ret = -1; + goto done; + } - while (i > 0) { - unsigned int inc; + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + ret = -1; + goto done; + } - inc = ifr->ifr_addr.sa_len; + current = (const uint8_t *)ifc.ifc_req; + end = current + ifc.ifc_len; - if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { - freeaddrinfo(*ifap); - return -1; - } + while (current < end) { + const struct ifreq *ifr = (const struct ifreq *)current; + struct sockaddr *sa = (struct sockaddr *)&(ifr->ifr_addr); + sa_family_t fam = ((struct sockaddr_in *)sa)->sin_family; + size_t inc = ifr->ifr_addr.sa_len; + if (fam == AF_INET || fam == AF_INET6) { curif = calloc(1, sizeof(struct ifaddrs)); - if (lastif == NULL) { - *ifap = curif; - } else { - lastif->ifa_next = curif; + if (curif == NULL) { + ret = -1; + goto done; } curif->ifa_name = strdup(ifr->ifr_name); + if (curif->ifa_name == NULL) { + ret = -1; + goto done; + } curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr); + if (curif->ifa_addr == NULL) { + ret = -1; + goto done; + } curif->ifa_dstaddr = NULL; curif->ifa_data = NULL; curif->ifa_netmask = NULL; curif->ifa_next = NULL; if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { - freeaddrinfo(*ifap); - return -1; + ret = -1; + goto done; } curif->ifa_flags = ifr->ifr_flags; if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { - freeaddrinfo(*ifap); - return -1; + if (errno == EADDRNOTAVAIL) { + curif->ifa_netmask = NULL; } - + else + { + fprintf(stderr,"Failed SIOCGIFNETMASK %d (%s)\n",errno,strerror(errno)); + ret = -1; + goto done; + } + } + else + { curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr); + if (curif->ifa_netmask == NULL) { + ret = -1; + goto done; + } + } + /* + * If we are sucessful then save our entry + */ + if (lastif == NULL) { + firstif = curif; + } else { + lastif->ifa_next = curif; + } lastif = curif; + curif = NULL; + } - next: /* * Patch from Archie Cobbs (archie@whistle.com). The * addresses in the SIOCGIFCONF interface list have a * minimum size. Usually this doesn't matter, but if * your machine has tunnel interfaces, etc. that have - * a zero length "link address", this does matter. */ + * a zero length "link address", this does matter. + */ - if (inc < sizeof(ifr->ifr_addr)) + if (inc < sizeof(ifr->ifr_addr)) { inc = sizeof(ifr->ifr_addr); + } inc += IFNAMSIZ; - ifr = (struct ifreq*) (((char*) ifr) + inc); - i -= inc; + current += inc; + } + + *ifap = firstif; + firstif = NULL; + ret = 0; +done: + if (curif != NULL) { + free(curif); } + if (firstif != NULL) { + rep_freeifaddrs(firstif); + } + if (ifc.ifc_req != NULL) { + free(ifc.ifc_req); + } close(fd); - return 0; + return ret; } #define _FOUND_IFACE_ANY -- 2.7.4