summaryrefslogtreecommitdiff
path: root/resolver.c
diff options
context:
space:
mode:
authorpdw <>2003-09-06 13:52:36 +0000
committerpdw <>2003-09-06 13:52:36 +0000
commit2eeeadf6e177ea478b7f58c3d087b29f25cee6ff (patch)
tree446a9ee966d9d1d0bb739d2fdbead0f75e6b33b7 /resolver.c
parent37f7fadd8aacf89f103f7bcba74be61c7ad060a2 (diff)
downloadiftop-2eeeadf6e177ea478b7f58c3d087b29f25cee6ff.zip
Added forking resolver (chris)
Diffstat (limited to 'resolver.c')
-rw-r--r--resolver.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/resolver.c b/resolver.c
index 3762311..1cec32d 100644
--- a/resolver.c
+++ b/resolver.c
@@ -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