From c71567fa04e1e724f5abcdddba8ca97c40b3f98d Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 4 Nov 2011 17:02:54 +0000 Subject: commit fad362f75136e2fe22f39d97c6c0177309586fec Author: Leonid Evdokimov Date: Fri Oct 14 19:08:04 2011 +0400 Workaround for FreeBSD PR kern/152036. I heard, that MacOS has alike problem too. FreeBSD PR: URL: http://www.freebsd.org/cgi/query-pr.cgi?pr=152036 Title: kern/152036: [libc] getifaddrs(3) returns truncated sockaddrs for netmasks --- netifaces.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/netifaces.c b/netifaces.c index a0e3546..eebd78f 100644 --- a/netifaces.c +++ b/netifaces.c @@ -30,8 +30,9 @@ #endif /* For the benefit of stupid platforms (Linux), include all the sockaddr - definitions we can lay our hands on. */ -#if !HAVE_SOCKADDR_SA_LEN + definitions we can lay our hands on. It can also be useful for the benefit + of another stupid platform (FreeBSD, see PR 152036). */ +#include # if HAVE_NETASH_ASH_H # include # endif @@ -120,6 +121,7 @@ static int af_to_len(int af) return sizeof (struct sockaddr); } +#if !HAVE_SOCKADDR_SA_LEN #define SA_LEN(sa) af_to_len(sa->sa_family) #if HAVE_SIOCGLIFNUM #define SS_LEN(sa) af_to_len(sa->ss_family) @@ -267,13 +269,43 @@ string_from_sockaddr (struct sockaddr *addr, char *buffer, int buflen) { + struct sockaddr* bigaddr = 0; + int failure; + struct sockaddr* gniaddr; + socklen_t gnilen; + if (!addr || addr->sa_family == AF_UNSPEC) return -1; - if (getnameinfo (addr, SA_LEN(addr), + if (SA_LEN(addr) < af_to_len(addr->sa_family)) { + /* Someteims ifa_netmask can be truncated. So let's detruncate it. FreeBSD + * PR: kern/152036: getifaddrs(3) returns truncated sockaddrs for netmasks + * -- http://www.freebsd.org/cgi/query-pr.cgi?pr=152036 */ + gnilen = af_to_len(addr->sa_family); + bigaddr = calloc(1, gnilen); + if (!bigaddr) + return -1; + memcpy(bigaddr, addr, SA_LEN(addr)); +#if HAVE_SOCKADDR_SA_LEN + bigaddr->sa_len = gnilen; +#endif + gniaddr = bigaddr; + } else { + gnilen = SA_LEN(addr); + gniaddr = addr; + } + + failure = getnameinfo (gniaddr, gnilen, buffer, buflen, NULL, 0, - NI_NUMERICHOST) != 0) { + NI_NUMERICHOST); + + if (bigaddr) { + free(bigaddr); + bigaddr = 0; + } + + if (failure) { int n, len; char *ptr; const char *data; -- cgit v1.2.1