diff options
author | pdw <> | 2002-03-24 16:22:26 +0000 |
---|---|---|
committer | pdw <> | 2002-03-24 16:22:26 +0000 |
commit | 3004ea063cbb186a63af99a2e13d7cb09f23360d (patch) | |
tree | d617af0ad0619334f899d3405350edb9b1b2407b /resolver.c | |
download | iftop-3004ea063cbb186a63af99a2e13d7cb09f23360d.zip |
iftop
Diffstat (limited to 'resolver.c')
-rw-r--r-- | resolver.c | 143 |
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'; + } +} |