From 120a1b2c5393fc63e2c9bf81d6adb55a6acd4ed2 Mon Sep 17 00:00:00 2001 From: pdw <> Date: Sun, 2 Oct 2011 21:41:47 +0000 Subject: [PATCH] FreeBSD patch from Frederic Perrin plus fix for compile error in gethostbyaddr resolver. Order of pcap.h vs bpf.h switched, to fix compilation on Mac OS X. --- config/int_ghba_r.c | 1 + iftop.c | 14 ++++++------ resolver.c | 54 ++++++++++++++++++++++++++++----------------- 3 files changed, 42 insertions(+), 27 deletions(-) diff --git a/config/int_ghba_r.c b/config/int_ghba_r.c index 7a3a3c1..6801a94 100644 --- a/config/int_ghba_r.c +++ b/config/int_ghba_r.c @@ -6,6 +6,7 @@ static const char rcsid[] = "$Id$"; +#include #include #include diff --git a/iftop.c b/iftop.c index 97020ea..0c233cf 100644 --- a/iftop.c +++ b/iftop.c @@ -5,13 +5,6 @@ #include "integers.h" -#if defined(HAVE_PCAP_H) -# include -#elif defined(HAVE_PCAP_PCAP_H) -# include -#else -# error No pcap.h -#endif #include #include #include @@ -20,6 +13,13 @@ #include #include #include +#if defined(HAVE_PCAP_H) +# include +#elif defined(HAVE_PCAP_PCAP_H) +# include +#else +# error No pcap.h +#endif #include #include diff --git a/resolver.c b/resolver.c index 17aa9fe..3a9d191 100644 --- a/resolver.c +++ b/resolver.c @@ -37,6 +37,22 @@ int tail; extern options_t options; +int guess_af(struct in6_addr *addr) +{ + /* If the upper three (network byte order) uint32-parts + * are null, then there ought to be an IPv4 address here. + * Any such IPv6 would have to be 'xxxx::'. Neglectable? */ + uint32_t* probe; + int af; + + probe = (uint32_t *) addr; + return (probe[1] || probe[2] || probe[3]) ? AF_INET6 : AF_INET; +} + +socklen_t aflength(int af) +{ + return af == AF_INET6 ? sizeof(struct in6_addr) : sizeof(struct in_addr); +} /* * We have a choice of resolver methods. Real computers have getnameinfo or @@ -60,18 +76,11 @@ char *do_resolve(struct in6_addr *addr) { struct sockaddr_in6 sin6; char buf[NI_MAXHOST]; /* 1025 */ int res, af; - uint32_t* probe; memset(&sin, '\0', sizeof(sin)); memset(&sin6, '\0', sizeof(sin6)); - /* If the upper three (network byte order) uint32-parts - * are null, then there ought to be an IPv4 address here. - * Any such IPv6 would have to be 'xxxx::'. Neglectable? */ - probe = (uint32_t *) addr; - af = (probe[1] || probe[2] || probe[3]) ? AF_INET6 : AF_INET; - - switch (af) { + switch (guess_af(addr)) { case AF_INET: sin.sin_family = af; sin.sin_port = 0; @@ -106,26 +115,29 @@ char *do_resolve(struct in6_addr *addr) { * Some implementations of libc choose to implement gethostbyaddr_r as * a non thread-safe wrapper to gethostbyaddr. An interesting choice... */ -char* do_resolve(struct in_addr * addr) { +char* do_resolve(struct in6_addr * addr) { struct hostent hostbuf, *hp; size_t hstbuflen = 1024; char *tmphstbuf; int res; int herr; + int af; char * ret = NULL; /* Allocate buffer, remember to free it to avoid memory leakage. */ tmphstbuf = xmalloc (hstbuflen); + af = guess_af(addr); + /* Some machines have gethostbyaddr_r returning an integer error code; on * others, it returns a struct hostent*. */ #ifdef GETHOSTBYADDR_R_RETURNS_INT - while ((res = gethostbyaddr_r((char*)addr, sizeof(struct in_addr), AF_INET, + while ((res = gethostbyaddr_r((char*)addr, aflength(af), af, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr)) == ERANGE) #else /* ... also assume one fewer argument.... */ - while ((hp = gethostbyaddr_r((char*)addr, sizeof(struct in_addr), AF_INET, + while ((hp = gethostbyaddr_r((char*)addr, aflength(af), af, &hostbuf, tmphstbuf, hstbuflen, &herr)) == NULL && errno == ERANGE) #endif @@ -152,22 +164,24 @@ char* do_resolve(struct in_addr * addr) { #elif defined(USE_GETHOSTBYADDR) /** - * Implementation using gethostbyname. Since this is nonreentrant, we have to + * Implementation using gethostbyaddr. Since this is nonreentrant, we have to * wrap it in a mutex, losing all benefit of multithreaded resolution. */ -char *do_resolve(struct in_addr *addr) { +char *do_resolve(struct in6_addr *addr) { static pthread_mutex_t ghba_mtx = PTHREAD_MUTEX_INITIALIZER; char *s = NULL; struct hostent *he; + int af; + af = guess_af(addr); + pthread_mutex_lock(&ghba_mtx); - he = gethostbyaddr((char*)addr, sizeof *addr, AF_INET); + he = gethostbyaddr((char*)addr, aflength(af), af); if (he) s = xstrdup(he->h_name); pthread_mutex_unlock(&ghba_mtx); return s; } - #elif defined(USE_LIBRESOLV) #include @@ -177,7 +191,7 @@ char *do_resolve(struct in_addr *addr) { * libresolv implementation * resolver functions may not be thread safe */ -char* do_resolve(struct in_addr * addr) { +char* do_resolve(struct in6_addr * addr) { char msg[PACKETSZ]; char s[35]; int l; @@ -242,7 +256,7 @@ static void do_resolve_ares_callback(void *arg, int status, unsigned char *abuf, } } -char *do_resolve(struct in_addr * addr) { +char *do_resolve(struct in6_addr * addr) { struct ares_callback_comm C; char s[35]; unsigned char *a; @@ -299,7 +313,7 @@ char *do_resolve(struct in_addr * addr) { #elif defined(USE_FORKING_RESOLVER) /** - * Resolver which forks a process, then uses gethostbyname. + * Resolver which forks a process, then uses gethostbyaddr. */ #include @@ -323,7 +337,7 @@ int forking_resolver_worker(int fd) { } } -char *do_resolve(struct in_addr *addr) { +char *do_resolve(struct in6_addr *addr) { struct { int fd; pid_t child; @@ -388,7 +402,7 @@ char *do_resolve(struct in_addr *addr) { # warning No name resolution method specified; name resolution will not work -char *do_resolve(struct in_addr *addr) { +char *do_resolve(struct in6_addr *addr) { return NULL; }