summaryrefslogtreecommitdiff
path: root/resolver.c
diff options
context:
space:
mode:
authorpdw <>2002-03-24 16:22:26 +0000
committerpdw <>2002-03-24 16:22:26 +0000
commit3004ea063cbb186a63af99a2e13d7cb09f23360d (patch)
treed617af0ad0619334f899d3405350edb9b1b2407b /resolver.c
downloadiftop-3004ea063cbb186a63af99a2e13d7cb09f23360d.zip
iftop
Diffstat (limited to 'resolver.c')
-rw-r--r--resolver.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/resolver.c b/resolver.c
new file mode 100644
index 0000000..6ceee19
--- /dev/null
+++ b/resolver.c
@@ -0,0 +1,143 @@
+/*
+ * resolver.c:
+ *
+ */
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+
+#include "ns_hash.h"
+
+#define RESOLVE_QUEUE_LENGTH 20
+
+struct in_addr resolve_queue[RESOLVE_QUEUE_LENGTH];
+
+pthread_cond_t resolver_queue_cond;
+pthread_mutex_t resolver_queue_mutex;
+pthread_mutex_t resolver_queue_access_mutex;
+
+hash_type* ns_hash;
+
+int head;
+int tail;
+
+void resolver_worker(void* ptr) {
+ struct timespec delay;
+ delay.tv_sec = 0;
+ delay.tv_nsec = 500;
+ while(1) {
+ /* Wait until we are told that an address has been added to the
+ * queue
+ */
+ pthread_cond_wait(&resolver_queue_cond, &resolver_queue_mutex);
+
+ /* Keep resolving until the queue is empty */
+ pthread_mutex_lock(&resolver_queue_access_mutex);
+ while(head != tail) {
+ struct in_addr addr = resolve_queue[tail];
+ struct hostent hostbuf, *hp;
+ size_t hstbuflen;
+ char *tmphstbuf;
+ int res;
+ int herr;
+
+ /* mutex always locked at this point */
+
+ tail = (tail + 1) % RESOLVE_QUEUE_LENGTH;
+
+ pthread_mutex_unlock(&resolver_queue_access_mutex);
+
+
+ hstbuflen = 1024;
+ /* Allocate buffer, remember to free it to avoid memory leakage. */
+ tmphstbuf = malloc (hstbuflen);
+
+ while ((res = gethostbyaddr_r (&addr, sizeof(addr), AF_INET,
+ &hostbuf, tmphstbuf, hstbuflen,
+ &hp, &herr)) == ERANGE) {
+ /* Enlarge the buffer. */
+ hstbuflen *= 2;
+ tmphstbuf = realloc (tmphstbuf, hstbuflen);
+ }
+
+ /*
+ * Store the result in ns_hash
+ */
+ pthread_mutex_lock(&resolver_queue_access_mutex);
+
+ /* Check for errors. */
+ if (res || hp == NULL) {
+ /* failed */
+ //printf("[ Did not resolve %s ]\n", inet_ntoa(addr));
+ /* Leave the unresolved IP in the hash */
+ }
+ else {
+ /* success */
+ char* hostname;
+ //printf("[ Resolved: %s ]\n", hp->h_name);
+ if(hash_find(ns_hash, &addr, (void**)&hostname) == HASH_STATUS_OK) {
+ hash_delete(ns_hash, &addr);
+ free(hostname);
+ }
+ else {
+ //printf("[ Warning: Could not find hash entry for key: %s ]\n", inet_ntoa(addr));
+ }
+ hostname = strdup(hp->h_name);
+ hash_insert(ns_hash, &addr, (void*)hostname);
+
+ }
+ free(tmphstbuf);
+ }
+ pthread_mutex_unlock(&resolver_queue_access_mutex);
+ }
+}
+
+void resolver_initialise() {
+ pthread_t thread;
+ head = tail = 0;
+
+ ns_hash = ns_hash_create();
+
+ pthread_mutex_init(&resolver_queue_mutex, NULL);
+ pthread_mutex_init(&resolver_queue_access_mutex, NULL);
+ pthread_cond_init(&resolver_queue_cond, NULL);
+
+ pthread_create(&thread, NULL, (void*)&resolver_worker, NULL);
+
+}
+
+void resolve(struct in_addr* addr, char* result, int buflen) {
+ char* hostname;
+
+ pthread_mutex_lock(&resolver_queue_access_mutex);
+
+ if(hash_find(ns_hash, addr, (void**)&hostname) == HASH_STATUS_OK) {
+ /* Found => already resolved, or on the queue */
+ }
+ else {
+ hostname = strdup(inet_ntoa(*addr));
+ hash_insert(ns_hash, addr, hostname);
+
+ if(((head + 1) % RESOLVE_QUEUE_LENGTH) == tail) {
+ /* queue full */
+ }
+ else {
+ resolve_queue[head] = *addr;
+ head = (head + 1) % RESOLVE_QUEUE_LENGTH;
+ pthread_cond_signal(&resolver_queue_cond);
+ }
+ }
+ pthread_mutex_unlock(&resolver_queue_access_mutex);
+
+ if(result != NULL && buflen > 1) {
+ strncpy(result, hostname, buflen - 1);
+ result[buflen - 1] = '\0';
+ }
+}