📄 lookup.c
字号:
/* This file is part of sniffer, a packet capture utility and network moniter The author can be contacted at <mistral@stev.org> the lastest version is avilable from http://stev.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <pthread.h>#include <netdb.h>#include <arpa/inet.h>#include "list.h"#include "locks.h"#include "in_ntoa.h"#include "log.h"#include "lookup.h"/* we also have the lookup code in here */#define MAX_WORK 10pthread_t lookup_thread;pthread_mutex_t lookup_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t lookup_failed_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t lookup_todo_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t lookup_active_mutex = PTHREAD_MUTEX_INITIALIZER;struct list_t *lookup_list;struct list_t *lookup_failed;struct list_t *lookup_todo;struct list_t *lookup_active;/* this is the start of a thread */void *lookup_init(void *arg) { struct lookup *tmp; int i, work; SLOCK(&lookup_mutex); SLOCK(&lookup_todo_mutex); SLOCK(&lookup_failed_mutex); SLOCK(&lookup_active_mutex); lookup_list = list_init(); list_setcmp(lookup_list, (void *) lookup_cmp); lookup_failed = list_init(); lookup_todo = list_init(); lookup_active = list_init(); list_setcmp(lookup_active, (void *) lookup_cmp); SUNLOCK(&lookup_active_mutex); SUNLOCK(&lookup_failed_mutex); SUNLOCK(&lookup_todo_mutex); SUNLOCK(&lookup_mutex); for(;;) { work = 0; SLOCK(&lookup_todo_mutex); for(i=0;i<list_len(lookup_todo);i++) { tmp = list_get(lookup_todo, i); if (!tmp) { log_unreach(); goto end_todo; } if (tmp->name == NULL && tmp->working == 0) { /* if we fail it will go onto a failed list a fererance is always stored in the main list anyway */ list_del(lookup_todo, i); SUNLOCK(&lookup_todo_mutex); if (lookup_dns(tmp) < 0) { SLOCK(&lookup_failed_mutex); list_add(lookup_failed, tmp); SUNLOCK(&lookup_failed_mutex); work++; goto end_todo; } SLOCK(&lookup_todo_mutex); } } SUNLOCK(&lookup_todo_mutex);end_todo: /* FIXME re que failed lookups */ if (work == 0) sleep(1); } /* end of for(;;) */ return 0;}void lookup_tidy() { int work = 0, i; struct lookup *tmp; SLOCK(&lookup_active_mutex); for(i=0;list_len(lookup_active);i++) { tmp = list_get(lookup_active, i); if (!tmp) { SUNLOCK(&lookup_active_mutex); return; } if (tmp->score > 0) { tmp->score--; } else { if (list_del(lookup_active, i)) i--; } if (work > MAX_WORK) { SLOCK(&lookup_active_mutex); work = 0; SUNLOCK(&lookup_active_mutex); } } SUNLOCK(&lookup_active_mutex); return;}int lookup_dns(struct lookup *p) { struct hostent *hostent; hostent = gethostbyaddr((char *) &p->ip, sizeof(struct in_addr), AF_INET); if (!hostent) { p->failed++; return -1; } else { /* the lookup worked */ p->name = malloc(strlen(hostent->h_name) + 1); if (!p->name) { log_errno("malloc"); return -1; } else { strcpy(p->name, hostent->h_name); } p->time = time(NULL); p->working = 0; p->failed = 0; } return 0;}int lookup_cmp(struct lookup *c1, struct lookup *c2) { unsigned long d1, d2; d1 = htonl(c1->ip); d2 = htonl(c2->ip); if (d1 > d2) return -1; if (d1 < d2) return 1; return 0;}struct lookup *lookup_get(unsigned long ip) { struct lookup *tmp; struct lookup check; int i = 0; check.ip = ip; SLOCK(&lookup_active_mutex); i = list_search(lookup_active, &check); if (i >= 0) { tmp = list_get(lookup_active, i); if (tmp) { if (tmp->score < 100) tmp->score++; SUNLOCK(&lookup_active_mutex); return tmp; } } SLOCK(&lookup_mutex); /* grab the lock */ i = list_search(lookup_list, &check); if (i >= 0) { tmp = list_get(lookup_list, i); if (tmp) { tmp->score = 50; list_add_sort(lookup_active, tmp); SUNLOCK(&lookup_mutex); SUNLOCK(&lookup_active_mutex); return tmp; } log_unreach(); return NULL; } /* we dont know about that host so lets create a new entry */ tmp = lookup_create(ip); if (!tmp) { SUNLOCK(&lookup_mutex); SUNLOCK(&lookup_active_mutex); return NULL; } list_add_sort(lookup_list, tmp); list_add_sort(lookup_active, tmp); SUNLOCK(&lookup_mutex); SUNLOCK(&lookup_active_mutex); SLOCK(&lookup_todo_mutex); list_add(lookup_todo, tmp); SUNLOCK(&lookup_todo_mutex); return tmp; /* we never did get a name to still return null */}/* the ip address passed to this should be in network byte order *//* this will not copy the ip / name *//* if fail is set return null not an ip address */char *lookup(unsigned long ip, int fail) { struct lookup *tmp; tmp = lookup_get(ip); if (!tmp) return NULL; if (tmp->name) return tmp->name; if (!fail) return tmp->ip_str; return NULL;}inline void lookup_stats(unsigned long daddr, unsigned long dbytes, unsigned long saddr, unsigned long sbytes) { struct lookup *tmp; tmp = lookup_get(daddr); if (tmp) { tmp->in.packets++; tmp->in.bytes += dbytes; } tmp = lookup_get(saddr); if (tmp) { tmp->out.packets++; tmp->out.bytes += sbytes; } return;}/* the whole list is already locked when we are in the function !! */inline struct lookup *lookup_create(unsigned long ip) { struct lookup *tmp; tmp = malloc(sizeof(struct lookup)); if (!tmp) { log_errno("malloc"); return NULL; } tmp->ip_str = in_ntoa(ip); if (!tmp->ip_str) { free(tmp); return NULL; } tmp->ip = ip; tmp->name = NULL; tmp->time = 0; tmp->working = 0; tmp->failed = 0; tmp->score = 100; init_stat(&tmp->in, "IN"); init_stat(&tmp->out, "OUT"); return tmp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -