summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlastair Houghton <alastair@coriolis-systems.com>2011-11-04 17:02:54 +0000
committerAlastair Houghton <alastair@coriolis-systems.com>2011-11-04 17:02:54 +0000
commitc71567fa04e1e724f5abcdddba8ca97c40b3f98d (patch)
treed747a3a6206acfea99d57744a27a026e81ebfb9d
parent3ec8a8da849d5c59e5ba6ab532fa1bddb80b804c (diff)
downloadnetifaces-c71567fa04e1e724f5abcdddba8ca97c40b3f98d.tar.gz
commit fad362f75136e2fe22f39d97c6c0177309586fec
Author: Leonid Evdokimov <leon@darkk.net.ru> 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
-rw-r--r--netifaces.c40
1 files 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 <netinet/in.h>
# if HAVE_NETASH_ASH_H
# include <netash/ash.h>
# 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;