--- original/lib/replace/getifaddrs.c 2017-11-21 11:14:16.504985494 +0000 +++ patched/lib/replace/getifaddrs.c 2017-11-27 14:45:02.717633656 +0000 @@ -56,16 +56,25 @@ } } -static struct sockaddr *sockaddr_dup(struct sockaddr *sa) +static socklen_t max(socklen_t a, socklen_t b) +{ + if (a > b) { + return a; + } + return b; +} + +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 +291,17 @@ #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 +309,127 @@ 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 *)malloc(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