Commit 2eeeadf6 authored by pdw's avatar pdw
Browse files

Added forking resolver (chris)

parent 37f7fadd
......@@ -37,8 +37,9 @@ AC_ARG_WITH(resolver,
[ --with-resolver=TYPE Technique iftop should use for name resolution. Valid
options are netdb, netdb_1thread (for systems without
working gethostbyaddr_r), ares for the MIT ARES
asynchronous resolver library, or none if you don't
need any name resolution.
asynchronous resolver library, forking for the REALLY SUCKY
forking resolver, or none if you don't need any name
resolution.
[default=netdb]],
[resolver=$withval],
[resolver=netdb])
......@@ -164,7 +165,7 @@ if test x$resolver = xnetdb ; then
AC_DEFINE(USE_GETNAMEINFO, 1, [use getnameinfo for name resolution])
else
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....
if test x$resolver = xnetdb ; then
......@@ -185,8 +186,8 @@ if test x$resolver = xnetdb ; then
[7-argument gethostbyaddr_r returns struct hostent*])
], [
dnl neither
AC_MSG_RESULT([no idea; dropping back to gethostbyaddr])
resolver=netdb_1thread
AC_MSG_RESULT([no idea; dropping back to the forking resolver])
resolver=forking
])
])
......@@ -209,24 +210,33 @@ if test x$resolver = xares ; then
AC_DEFINE(USE_ARES, 1, [use ARES for name resolution])
], [
dnl no ares
AC_MSG_RESULT([can't find ARES; dropping back to gethostbyaddr])
resolver=netdb_1thread])
AC_MSG_RESULT([can't find ARES; dropping back to the forking resolver])
resolver=forking])
fi
dnl Ugh. gethostbyaddr.
if test x$resolver = xnetdb_1thread ; then
dnl Ugh. Both the single-threaded and the forking resolvers use gethostbyaddr.
if test x$resolver = xnetdb_1thread || test x$resolver = xforking ; then
AC_SEARCH_LIBS(gethostbyaddr, [nsl], , [
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
AC_MSG_WARN([using single-threaded resolver with gethostbyaddr
if test x$resolver = xnetdb_1thread ; then
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.])
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
dnl Otherwise, no resolver at all. Boo hoo.
......
......@@ -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
# warning No name resolution method specified; name resolution will not work
......
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