""
This commit is contained in:
34
Makefile
34
Makefile
@@ -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
|
||||
|
||||
# This may be needed to use libresolv on Linux.
|
||||
#LDLIBS += /usr/lib/libresolv.a
|
||||
#
|
||||
# Uncomment if you are using libresolv.
|
||||
#
|
||||
#LDLIBS += -lresolv # or /usr/lib/libresolv.a on Linux?
|
||||
|
||||
#
|
||||
# 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.
|
||||
|
||||
134
resolver.c
134
resolver.c
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user