FreeBSD patch from Frederic Perrin <frederic.perrin@resel.fr> plus fix for

compile error in gethostbyaddr resolver.
Order of pcap.h vs bpf.h switched, to fix compilation on Mac OS X.
This commit is contained in:
pdw
2011-10-02 21:41:47 +00:00
parent 3e90c6b547
commit 120a1b2c53
3 changed files with 42 additions and 27 deletions

View File

@@ -6,6 +6,7 @@
static const char rcsid[] = "$Id$"; static const char rcsid[] = "$Id$";
#include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>

14
iftop.c
View File

@@ -5,13 +5,6 @@
#include "integers.h" #include "integers.h"
#if defined(HAVE_PCAP_H)
# include <pcap.h>
#elif defined(HAVE_PCAP_PCAP_H)
# include <pcap/pcap.h>
#else
# error No pcap.h
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
@@ -20,6 +13,13 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <net/if.h> #include <net/if.h>
#include <net/bpf.h> #include <net/bpf.h>
#if defined(HAVE_PCAP_H)
# include <pcap.h>
#elif defined(HAVE_PCAP_PCAP_H)
# include <pcap/pcap.h>
#else
# error No pcap.h
#endif
#include <pthread.h> #include <pthread.h>
#include <curses.h> #include <curses.h>

View File

@@ -37,6 +37,22 @@ int tail;
extern options_t options; 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 * 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; struct sockaddr_in6 sin6;
char buf[NI_MAXHOST]; /* 1025 */ char buf[NI_MAXHOST]; /* 1025 */
int res, af; int res, af;
uint32_t* probe;
memset(&sin, '\0', sizeof(sin)); memset(&sin, '\0', sizeof(sin));
memset(&sin6, '\0', sizeof(sin6)); memset(&sin6, '\0', sizeof(sin6));
/* If the upper three (network byte order) uint32-parts switch (guess_af(addr)) {
* 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) {
case AF_INET: case AF_INET:
sin.sin_family = af; sin.sin_family = af;
sin.sin_port = 0; 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 * Some implementations of libc choose to implement gethostbyaddr_r as
* a non thread-safe wrapper to gethostbyaddr. An interesting choice... * 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; struct hostent hostbuf, *hp;
size_t hstbuflen = 1024; size_t hstbuflen = 1024;
char *tmphstbuf; char *tmphstbuf;
int res; int res;
int herr; int herr;
int af;
char * ret = NULL; char * ret = NULL;
/* Allocate buffer, remember to free it to avoid memory leakage. */ /* Allocate buffer, remember to free it to avoid memory leakage. */
tmphstbuf = xmalloc (hstbuflen); tmphstbuf = xmalloc (hstbuflen);
af = guess_af(addr);
/* Some machines have gethostbyaddr_r returning an integer error code; on /* Some machines have gethostbyaddr_r returning an integer error code; on
* others, it returns a struct hostent*. */ * others, it returns a struct hostent*. */
#ifdef GETHOSTBYADDR_R_RETURNS_INT #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, &hostbuf, tmphstbuf, hstbuflen,
&hp, &herr)) == ERANGE) &hp, &herr)) == ERANGE)
#else #else
/* ... also assume one fewer argument.... */ /* ... 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 &hostbuf, tmphstbuf, hstbuflen, &herr)) == NULL
&& errno == ERANGE) && errno == ERANGE)
#endif #endif
@@ -152,22 +164,24 @@ char* do_resolve(struct in_addr * addr) {
#elif defined(USE_GETHOSTBYADDR) #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. * 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; static pthread_mutex_t ghba_mtx = PTHREAD_MUTEX_INITIALIZER;
char *s = NULL; char *s = NULL;
struct hostent *he; struct hostent *he;
int af;
af = guess_af(addr);
pthread_mutex_lock(&ghba_mtx); pthread_mutex_lock(&ghba_mtx);
he = gethostbyaddr((char*)addr, sizeof *addr, AF_INET); he = gethostbyaddr((char*)addr, aflength(af), af);
if (he) if (he)
s = xstrdup(he->h_name); s = xstrdup(he->h_name);
pthread_mutex_unlock(&ghba_mtx); pthread_mutex_unlock(&ghba_mtx);
return s; return s;
} }
#elif defined(USE_LIBRESOLV) #elif defined(USE_LIBRESOLV)
#include <arpa/nameser.h> #include <arpa/nameser.h>
@@ -177,7 +191,7 @@ char *do_resolve(struct in_addr *addr) {
* libresolv implementation * libresolv implementation
* resolver functions may not be thread safe * 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 msg[PACKETSZ];
char s[35]; char s[35];
int l; 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; struct ares_callback_comm C;
char s[35]; char s[35];
unsigned char *a; unsigned char *a;
@@ -299,7 +313,7 @@ char *do_resolve(struct in_addr * addr) {
#elif defined(USE_FORKING_RESOLVER) #elif defined(USE_FORKING_RESOLVER)
/** /**
* Resolver which forks a process, then uses gethostbyname. * Resolver which forks a process, then uses gethostbyaddr.
*/ */
#include <signal.h> #include <signal.h>
@@ -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 { struct {
int fd; int fd;
pid_t child; 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 # 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; return NULL;
} }