Added forking resolver (chris)

This commit is contained in:
pdw
2003-09-06 13:52:36 +00:00
parent 37f7fadd8a
commit 2eeeadf6e1
2 changed files with 110 additions and 13 deletions

View File

@@ -37,8 +37,9 @@ AC_ARG_WITH(resolver,
[ --with-resolver=TYPE Technique iftop should use for name resolution. Valid [ --with-resolver=TYPE Technique iftop should use for name resolution. Valid
options are netdb, netdb_1thread (for systems without options are netdb, netdb_1thread (for systems without
working gethostbyaddr_r), ares for the MIT ARES working gethostbyaddr_r), ares for the MIT ARES
asynchronous resolver library, or none if you don't asynchronous resolver library, forking for the REALLY SUCKY
need any name resolution. forking resolver, or none if you don't need any name
resolution.
[default=netdb]], [default=netdb]],
[resolver=$withval], [resolver=$withval],
[resolver=netdb]) [resolver=netdb])
@@ -164,7 +165,7 @@ if test x$resolver = xnetdb ; then
AC_DEFINE(USE_GETNAMEINFO, 1, [use getnameinfo for name resolution]) AC_DEFINE(USE_GETNAMEINFO, 1, [use getnameinfo for name resolution])
else else
dnl Now see if we can use gethostbyaddr_r. dnl Now see if we can use gethostbyaddr_r.
AC_SEARCH_LIBS(gethostbyaddr_r, [nsl], , [resolver=netdb_1thread]) AC_SEARCH_LIBS(gethostbyaddr_r, [nsl], , [resolver=forking])
dnl Still want gethostbyaddr_r.... dnl Still want gethostbyaddr_r....
if test x$resolver = xnetdb ; then if test x$resolver = xnetdb ; then
@@ -185,8 +186,8 @@ if test x$resolver = xnetdb ; then
[7-argument gethostbyaddr_r returns struct hostent*]) [7-argument gethostbyaddr_r returns struct hostent*])
], [ ], [
dnl neither dnl neither
AC_MSG_RESULT([no idea; dropping back to gethostbyaddr]) AC_MSG_RESULT([no idea; dropping back to the forking resolver])
resolver=netdb_1thread resolver=forking
]) ])
]) ])
@@ -209,24 +210,33 @@ if test x$resolver = xares ; then
AC_DEFINE(USE_ARES, 1, [use ARES for name resolution]) AC_DEFINE(USE_ARES, 1, [use ARES for name resolution])
], [ ], [
dnl no ares dnl no ares
AC_MSG_RESULT([can't find ARES; dropping back to gethostbyaddr]) AC_MSG_RESULT([can't find ARES; dropping back to the forking resolver])
resolver=netdb_1thread]) resolver=forking])
fi fi
dnl Ugh. gethostbyaddr. dnl Ugh. Both the single-threaded and the forking resolvers use gethostbyaddr.
if test x$resolver = xnetdb_1thread ; then if test x$resolver = xnetdb_1thread || test x$resolver = xforking ; then
AC_SEARCH_LIBS(gethostbyaddr, [nsl], , [ AC_SEARCH_LIBS(gethostbyaddr, [nsl], , [
AC_MSG_ERROR([not even gethostbyaddr is available AC_MSG_ERROR([not even gethostbyaddr is available
What sort of UNIX system is this, anyway?]) What sort of UNIX system is this, anyway?
You will have to recompile with no name resolution at all.
])
] ]
) )
dnl Oh dear, just use gethostbyaddr; but whine about it if test x$resolver = xnetdb_1thread ; then
AC_MSG_WARN([using single-threaded resolver with gethostbyaddr dnl Oh dear, just use gethostbyaddr; but whine about it
AC_MSG_WARN([using single-threaded resolver with gethostbyaddr
Consider obtaining ARES or a machine with a working gethostbyaddr_r.]) Consider obtaining ARES or a machine with a working gethostbyaddr_r.])
AC_DEFINE(USE_GETHOSTBYADDR, 1, [use gethostbyaddr for name resolution]) AC_DEFINE(USE_GETHOSTBYADDR, 1, [use gethostbyaddr for name resolution])
else
AC_DEFINE(USE_FORKING_RESOLVER, 1, [use a REALLY SUCKY forking resolver for name resolution])
fi
fi fi
dnl Otherwise, no resolver at all. Boo hoo. dnl Otherwise, no resolver at all. Boo hoo.

View File

@@ -265,6 +265,93 @@ char *do_resolve(struct in_addr * addr) {
} }
} }
#elif defined(USE_FORKING_RESOLVER)
/**
* Resolver which forks a process, then uses gethostbyname.
*/
#include <signal.h>
#define NAMESIZE 64
int forking_resolver_worker(int fd) {
while (1) {
struct in_addr a;
struct hostent *he;
char buf[NAMESIZE] = {0};
if (read(fd, &a, sizeof a) != sizeof a)
return -1;
he = gethostbyaddr((char*)&a, sizeof a, AF_INET);
if (he)
strncpy(buf, he->h_name, NAMESIZE - 1);
if (write(fd, buf, NAMESIZE) != NAMESIZE)
return -1;
}
}
char *do_resolve(struct in_addr *addr) {
struct {
int fd;
pid_t child;
} *workerinfo;
char name[NAMESIZE];
static pthread_mutex_t worker_init_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t worker_key;
static int gotkey;
/* If no process exists, we need to spawn one. */
pthread_mutex_lock(&worker_init_mtx);
if (!gotkey) {
pthread_key_create(&worker_key, NULL);
gotkey = 1;
}
pthread_mutex_unlock(&worker_init_mtx);
workerinfo = pthread_getspecific(worker_key);
if (!workerinfo) {
int p[2];
if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, p) == -1)
return NULL;
workerinfo = xmalloc(sizeof *workerinfo);
pthread_setspecific(worker_key, workerinfo);
workerinfo->fd = p[0];
switch (workerinfo->child = fork()) {
case 0:
close(p[0]);
_exit(forking_resolver_worker(p[1]));
case -1:
close(p[0]);
close(p[1]);
return NULL;
default:
close(p[1]);
}
}
/* Now have a worker to which we can write requests. */
if (write(workerinfo->fd, addr, sizeof *addr) != sizeof *addr
|| read(workerinfo->fd, name, NAMESIZE) != NAMESIZE) {
/* Something went wrong. Just kill the child and get on with it. */
kill(workerinfo->child, SIGKILL);
wait();
close(workerinfo->fd);
xfree(workerinfo);
pthread_setspecific(worker_key, NULL);
}
if (!*name)
return NULL;
else
return xstrdup(name);
}
#else #else
# warning No name resolution method specified; name resolution will not work # warning No name resolution method specified; name resolution will not work