From c1f017231c5a6b5314804ea390512e336a53c2ea Mon Sep 17 00:00:00 2001 From: pdw <> Date: Thu, 10 Oct 2002 14:11:12 +0000 Subject: [PATCH] Added service hash for resolving port/protocol numbers to names. Minor fix to handling of netmasks end /32. --- Makefile | 5 ++-- addr_hash.c | 3 ++- addr_hash.h | 1 + iftop.c | 6 +++-- options.c | 27 ++++++++++++++++------ serv_hash.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ serv_hash.h | 22 ++++++++++++++++++ ui.c | 30 +++++++++++++++--------- 8 files changed, 137 insertions(+), 23 deletions(-) create mode 100644 serv_hash.c create mode 100644 serv_hash.h diff --git a/Makefile b/Makefile index e0d69a6..81e0dcc 100644 --- a/Makefile +++ b/Makefile @@ -33,8 +33,9 @@ LDFLAGS += -g LDLIBS += -lpcap -lpthread -lcurses -lm SRCS = iftop.c addr_hash.c hash.c ns_hash.c resolver.c ui.c util.c sorted_list.c\ - options.c -HDRS = addr_hash.h hash.h iftop.h ns_hash.h resolver.h sorted_list.h ui.h options.h sll.h + options.c serv_hash.c +HDRS = addr_hash.h hash.h iftop.h ns_hash.h resolver.h sorted_list.h ui.h options.h sll.h\ + serv_hash.h TXTS = README CHANGES INSTALL TODO iftop.8 COPYING SPECFILE = iftop.spec diff --git a/addr_hash.c b/addr_hash.c index c92e0f1..bfb823f 100644 --- a/addr_hash.c +++ b/addr_hash.c @@ -14,7 +14,8 @@ int compare(void* a, void* b) { return (aa->src.s_addr == bb->src.s_addr && aa->src_port == bb->src_port && aa->dst.s_addr == bb->dst.s_addr - && aa->dst_port == bb->dst_port); + && aa->dst_port == bb->dst_port + && aa->protocol == bb->protocol); } int hash(void* key) { diff --git a/addr_hash.h b/addr_hash.h index 214d3a2..1289790 100644 --- a/addr_hash.h +++ b/addr_hash.h @@ -12,6 +12,7 @@ #include "hash.h" typedef struct { + unsigned short int protocol; unsigned short int src_port; struct in_addr src; unsigned short int dst_port; diff --git a/iftop.c b/iftop.c index 44a2a34..921bb6b 100644 --- a/iftop.c +++ b/iftop.c @@ -193,12 +193,12 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) /* * Net filter on, assign direction according to netmask */ - if(in_filter_net(iptr->ip_src) & !in_filter_net(iptr->ip_dst)) { + if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) { /* out of network */ assign_addr_pair(&ap, iptr, 0); direction = 1; } - else if(in_filter_net(iptr->ip_dst) & !in_filter_net(iptr->ip_src)) { + else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) { /* into network */ assign_addr_pair(&ap, iptr, 1); direction = 0; @@ -209,6 +209,8 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) } } + ap.protocol = iptr->ip_p; + /* Add the addresses to be resolved */ resolve(&iptr->ip_dst, NULL, 0); resolve(&iptr->ip_src, NULL, 0); diff --git a/options.c b/options.c index 5f1fcd3..7802a56 100644 --- a/options.c +++ b/options.c @@ -87,18 +87,31 @@ static void set_net_filter(char* arg) { if (inet_aton(arg, &options.netfilternet) == 0) die("Invalid network address\n"); /* Accept a netmask like /24 or /255.255.255.0. */ - if (!mask[strspn(mask, "0123456789")]) { + if (mask[strspn(mask, "0123456789")] == '\0') { + /* Whole string is numeric */ int n; n = atoi(mask); - if (n > 32) + if (n > 32) { die("Invalid netmask"); - else { - uint32_t mm = 0xffffffffl; - mm >>= n; - options.netfiltermask.s_addr = htonl(~mm); } - } else if (inet_aton(mask, &options.netfiltermask) == 0) + else { + if(n == 32) { + /* This needs to be special cased, although I don't fully + * understand why -pdw + */ + options.netfiltermask.s_addr = htonl(0xffffffffl); + } + else { + uint32_t mm = 0xffffffffl; + mm >>= n; + options.netfiltermask.s_addr = htonl(~mm); + } + } + } + else if (inet_aton(mask, &options.netfiltermask) == 0) { die("Invalid netmask\n"); + } + options.netfilternet.s_addr = options.netfilternet.s_addr & options.netfiltermask.s_addr; options.netfilter = 1; diff --git a/serv_hash.c b/serv_hash.c new file mode 100644 index 0000000..f32e4e9 --- /dev/null +++ b/serv_hash.c @@ -0,0 +1,66 @@ +/* hash table */ + +#include +#include +#include +#include "serv_hash.h" +#include "hash.h" +#include "iftop.h" + +// Deliberately not a power of 2 or 10 +#define hash_table_size 123 + +int serv_hash_compare(void* a, void* b) { + ip_service* aa = (ip_service*)a; + ip_service* bb = (ip_service*)b; + return (aa->port == bb->port && + aa->protocol == bb->protocol); +} + +int serv_hash_hash(void* key) { + ip_service* serv = (ip_service*)key; + return serv->protocol; +} + +void* serv_hash_copy_key(void* orig) { + ip_service* copy; + copy = xmalloc(sizeof *copy); + *copy = *(ip_service*)orig; + return copy; +} + +void serv_hash_delete_key(void* key) { + free(key); +} + +/* + * Allocate and return a hash + */ +hash_type* serv_hash_create() { + hash_type* hash_table; + hash_table = xcalloc(hash_table_size, sizeof *hash_table); + hash_table->size = hash_table_size; + hash_table->compare = &serv_hash_compare; + hash_table->hash = &serv_hash_hash; + hash_table->delete_key = &serv_hash_delete_key; + hash_table->copy_key = &serv_hash_copy_key; + hash_initialise(hash_table); + return hash_table; +} + +void serv_hash_initialise(hash_type* sh) { + struct servent* ent; + struct protoent* pent; + ip_service* service; + setprotoent(1); + while((ent = getservent()) != NULL) { + pent = getprotobyname(ent->s_proto); + if(pent != NULL) { + service = xmalloc(sizeof(ip_service)); + service->port = ntohs(ent->s_port); + service->protocol = pent->p_proto; + hash_insert(sh, service, xstrdup(ent->s_name)); + } + } + endprotoent(); +} diff --git a/serv_hash.h b/serv_hash.h new file mode 100644 index 0000000..6241134 --- /dev/null +++ b/serv_hash.h @@ -0,0 +1,22 @@ +/* + * addr_hash.h: + * + */ + +#ifndef __SERV_HASH_H_ /* include guard */ +#define __SERV_HASH_H_ + +#include +#include +#include +#include "hash.h" + +typedef struct { + int port; + int protocol; +} ip_service; + +hash_type* serv_hash_create(); +void serv_hash_initialise(hash_type* sh); + +#endif /* __SERV_HASH_H_ */ diff --git a/ui.c b/ui.c index e3605ce..a4c10cd 100644 --- a/ui.c +++ b/ui.c @@ -13,6 +13,7 @@ #include #include "addr_hash.h" +#include "serv_hash.h" #include "iftop.h" #include "resolver.h" #include "sorted_list.h" @@ -43,6 +44,7 @@ extern options_t options ; void ui_finish(); hash_type* screen_hash; +hash_type* service_hash; sorted_list_type screen_list; host_pair_line totals; int peaksent, peakrecv, peaktotal; @@ -274,10 +276,11 @@ void analyse_data() { } -void sprint_host(char * line, struct in_addr* addr, unsigned int port, int L) { +void sprint_host(char * line, struct in_addr* addr, unsigned int port, unsigned int protocol, int L) { char hostname[HOSTNAME_LENGTH]; - char service[10]; - struct servent* sent; + char service[HOSTNAME_LENGTH]; + char* s_name; + ip_service skey; int left; if(addr->s_addr == 0) { sprintf(hostname, " * "); @@ -292,13 +295,16 @@ void sprint_host(char * line, struct in_addr* addr, unsigned int port, int L) { //TODO: Replace this with in-memory hash for speed. //sent = getservbyport(port, "tcp"); + + if(port != 0) { - sent = NULL; - if(sent == NULL) { - snprintf(service, 10, ":%d", port); + skey.port = port; + skey.protocol = protocol; + if(hash_find(service_hash, &skey, (void**)&s_name) == HASH_STATUS_OK) { + snprintf(service, HOSTNAME_LENGTH, ":%s", s_name); } else { - snprintf(service, 10, ":%s", sent->s_name); + snprintf(service, HOSTNAME_LENGTH, ":%d", port); } } else { @@ -372,14 +378,12 @@ void ui_print() { host_pair_line* screen_line = (host_pair_line*)nn->data; if(y < LINES - 4) { - fprintf(stderr, "Drawing at %d \r\n", y); - L = (COLS - 8 * HISTORY_DIVISIONS - 4) / 2; if(L > sizeof hostname) { L = sizeof hostname; } - sprint_host(line, &(screen_line->ap.src), screen_line->ap.src_port, L); + sprint_host(line, &(screen_line->ap.src), screen_line->ap.src_port, screen_line->ap.protocol, L); //sprintf(line, "%-*s", L, hostname); mvaddstr(y, x, line); @@ -390,7 +394,7 @@ void ui_print() { x += 4; - sprint_host(line, &(screen_line->ap.dst), screen_line->ap.dst_port, L); + sprint_host(line, &(screen_line->ap.dst), screen_line->ap.dst_port, screen_line->ap.protocol, L); mvaddstr(y, x, line); @@ -460,6 +464,10 @@ void ui_init() { screen_list_init(); screen_hash = addr_hash_create(); + service_hash = serv_hash_create(); + serv_hash_initialise(service_hash); + + } void ui_loop() {