Commit e1c4cb7a authored by chris's avatar chris
Browse files

""

parent 4ef789be
......@@ -21,19 +21,43 @@ CFLAGS += -I/usr/include/pcap
# LDFLAGS += -pg -a
#
# Uncomment to use libresolv
# Name resolution. Sensible systems have gethostbyaddr_r, which is reentrant
# and can be called from several threads of a multithreaded program. Other
# systems don't, or their implementations don't work ([cough] FreeBSD). For
# these you can use gethostbyaddr (not recommended, since then only one thread
# can resolve a name at once), libresolv (not recommended and may not work
# depending on which header files you have), or ares, an asynchronous DNS
# resolution library from
# ftp://athena-dist.mit.edu/pub/ATHENA/ares/
# For systems without a working gethostbyaddr_r, this is recommended.
#
#CFLAGS += -DUSELIBRESOLV
# Leave exactly one of these uncommented, or comment all of them out if you
# don't care about name resolution at all.
#
CFLAGS += -DUSE_GETHOSTBYADDR_R
#CFLAGS += -DUSE_GETHOSTBYADDR
#CFLAGS += -DUSE_LIBRESOLV
#CFLAGS += -DUSE_ARES
#
# Uncomment if you are using libresolv.
#
#LDLIBS += -lresolv # or /usr/lib/libresolv.a on Linux?
# This may be needed to use libresolv on Linux.
#LDLIBS += /usr/lib/libresolv.a
#
# Uncomment if you are using ares.
#
#LDLIBS += -lares
# ... and uncomment these if your libares is in an unusual place.
#CFLAGS += -I/software/include
#LDFLAGS += -L/software/lib
# PREFIX specifies the base directory for the installation.
PREFIX = /usr/local
#PREFIX = /software
# BINDIR is where the binary lives. No leading /.
# BINDIR is where the binary lives relative to PREFIX (no leading /).
BINDIR = sbin
# MANDIR is where the manual page goes.
......
......@@ -14,11 +14,6 @@
#include <errno.h>
#include <string.h>
#ifdef USELIBRESOLV
#include <arpa/nameser.h>
#include <resolv.h>
#endif
#include "ns_hash.h"
#include "iftop.h"
......@@ -39,7 +34,14 @@ int head;
int tail;
#ifndef USELIBRESOLV
/*
* We have a choice of resolver methods. Real computers have gethostbyaddr_r,
* which is reentrant and therefore thread safe. Other machines don't, and so
* we can use non-reentrant gethostbyaddr and have only one resolver thread.
* Alternatively, we can use the MIT ares asynchronous DNS library to do this.
*/
#if defined(USE_GETHOSTBYADDR_R)
/**
* Implementation of do_resolve for platforms with working gethostbyaddr_r
*/
......@@ -75,7 +77,29 @@ char* do_resolve(struct in_addr * addr) {
return ret;
}
#else
#elif defined(USE_GETHOSTBYADDR)
/**
* Implementation using gethostbyname. 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) {
static pthread_mutex_t ghba_mtx = PTHREAD_MUTEX_INITIALIZER;
char *s = NULL;
struct hostent *he;
pthread_mutex_lock(&ghba_mtx);
he = gethostbyaddr((char*)addr, sizeof *addr, AF_INET);
if (he)
s = xstrdup(he->h_name);
pthread_mutex_unlock(&ghba_mtx);
return s;
}
#elif defined(USE_LIBRESOLV)
#include <arpa/nameser.h>
#include <resolv.h>
/**
* libresolv implementation
......@@ -106,13 +130,107 @@ char* do_resolve(struct in_addr * addr) {
ns_name_uncompress(msg, msg + l, ns_rr_rdata(rr), buf, 256);
ret = xstrdup(buf);
}
}
}
}
}
return ret;
}
#elif defined(USE_ARES)
/**
* ares implementation
*/
#include <sys/time.h>
#include <ares.h>
#include <arpa/nameser.h>
/* callback function for ares */
struct ares_callback_comm {
struct in_addr *addr;
int result;
char *name;
};
static void do_resolve_ares_callback(void *arg, int status, unsigned char *abuf, int alen) {
struct hostent *he;
struct ares_callback_comm *C;
C = (struct ares_callback_comm*)arg;
if (status == ARES_SUCCESS) {
C->result = 1;
ares_parse_ptr_reply(abuf, alen, C->addr, sizeof *C->addr, AF_INET, &he);
C->name = xstrdup(he->h_name);;
ares_free_hostent(he);
} else {
C->result = -1;
}
}
char *do_resolve(struct in_addr * addr) {
struct ares_callback_comm C;
char s[35];
unsigned char *a;
ares_channel *chan;
static pthread_mutex_t ares_init_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t ares_key;
static int gotkey;
/* Make sure we have an ARES channel for this thread. */
pthread_mutex_lock(&ares_init_mtx);
if (!gotkey) {
pthread_key_create(&ares_key, NULL);
gotkey = 1;
}
pthread_mutex_unlock(&ares_init_mtx);
chan = pthread_getspecific(ares_key);
if (!chan) {
chan = xmalloc(sizeof *chan);
pthread_setspecific(ares_key, chan);
if (ares_init(chan) != ARES_SUCCESS) return NULL;
}
a = (unsigned char*)addr;
sprintf(s, "%d.%d.%d.%d.in-addr.arpa.", a[3], a[2], a[1], a[0]);
C.result = 0;
C.addr = addr;
ares_query(*chan, s, C_IN, T_PTR, do_resolve_ares_callback, &C);
while (C.result == 0) {
int n;
fd_set readfds, writefds;
struct timeval tv;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
n = ares_fds(*chan, &readfds, &writefds);
ares_timeout(*chan, NULL, &tv);
select(n, &readfds, &writefds, NULL, &tv);
ares_process(*chan, &readfds, &writefds);
}
/* At this stage, the query should be complete. */
switch (C.result) {
case -1:
case 0: /* shouldn't happen */
return NULL;
default:
return C.name;
}
}
#else
# warning No name resolution method specified; name resolution will not work
char *do_resolve(struct in_addr *addr) {
return NULL;
}
#endif
void resolver_worker(void* ptr) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment