From a480e5cce3ded53d4d8edd2f4030d03a524ccbd8 Mon Sep 17 00:00:00 2001 From: SATOH Fumiyasu Date: Wed, 19 Dec 2012 00:06:39 +0900 Subject: [PATCH 1/2] Bug #6970 - getifaddrs() issues on AIX Fixed by Miguel Sanders --- lib/replace/getifaddrs.c | 112 +++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/lib/replace/getifaddrs.c b/lib/replace/getifaddrs.c index 84d7906..f43a039 100644 --- a/lib/replace/getifaddrs.c +++ b/lib/replace/getifaddrs.c @@ -251,16 +251,16 @@ 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) ****************************************************************************/ int rep_getifaddrs(struct ifaddrs **ifap) { - char buff[8192]; - int fd, i; + int fd, size; struct ifconf ifc; - struct ifreq *ifr=NULL; + struct ifreq *ifr = NULL; struct ifaddrs *curif; struct ifaddrs *lastif = NULL; + void *current, *end; *ifap = NULL; @@ -268,8 +268,12 @@ int rep_getifaddrs(struct ifaddrs **ifap) return -1; } - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; + if (ioctl(fd, SIOCGSIZIFCONF, &size) != 0) { + return -1; + } + + ifc.ifc_len = size; + ifc.ifc_req = (struct ifreq *)malloc(size); if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { close(fd); @@ -277,66 +281,64 @@ int rep_getifaddrs(struct ifaddrs **ifap) } ifr = ifc.ifc_req; - - /* Loop through interfaces */ - i = ifc.ifc_len; - - while (i > 0) { - unsigned int inc; - - inc = ifr->ifr_addr.sa_len; - - if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { - freeaddrinfo(*ifap); - return -1; + current = (void *)ifr; + end = (void *)ifr + ifc.ifc_len; + + while (current < end) { + ifr = (struct ifreq *)current; + struct sockaddr *sa = (struct sockaddr *)&(ifr->ifr_addr); + sa_family_t fam = ((struct sockaddr_in *)sa)->sin_family; + + if(fam == AF_INET || fam == AF_INET6) { + curif = calloc(1, sizeof(struct ifaddrs)); + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + + curif->ifa_name = strdup(ifr->ifr_name); + curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr); + 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; + } + + curif->ifa_flags = ifr->ifr_flags; + + if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr); + + lastif = curif; } - curif = calloc(1, sizeof(struct ifaddrs)); - if (lastif == NULL) { - *ifap = curif; - } else { - lastif->ifa_next = curif; - } - - curif->ifa_name = strdup(ifr->ifr_name); - curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr); - 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; - } - - curif->ifa_flags = ifr->ifr_flags; - - if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { - freeaddrinfo(*ifap); - return -1; - } - - curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr); - - lastif = curif; - - 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)) - inc = sizeof(ifr->ifr_addr); - inc += IFNAMSIZ; + int inc = ifr->ifr_addr.sa_len; + if (inc < sizeof(ifr->ifr_addr)) { + inc = sizeof(ifr->ifr_addr); + } + inc += IFNAMSIZ; - ifr = (struct ifreq*) (((char*) ifr) + inc); - i -= inc; + current += inc; } + free(ifc.ifc_req); close(fd); return 0; } -- 1.7.10.4