diff --git a/README b/README index 7171e74..2f3efa7 100644 --- a/README +++ b/README @@ -3,6 +3,8 @@ $Id$ Read the INSTALL file, manual page and source code for more information. +iftop must be run as root. + RedHat 7.2 users: There is a bug in the version of ncurses distibuted with RedHat 7.2 that will cause iftop to segfault. The RPM in RedHat's Rawhide distribution diff --git a/TODO b/TODO index 1673241..cde3c89 100644 --- a/TODO +++ b/TODO @@ -12,10 +12,6 @@ $Id$ * Aggregate traffic by source host / dest host rather than just by host pair. -* Cummulative byte counters. - * Configurable sort criteria. * Configurable refresh rates. - -* Ability to turn bar graphs on and off. diff --git a/iftop.c b/iftop.c index 244f73d..81e36fd 100644 --- a/iftop.c +++ b/iftop.c @@ -87,7 +87,7 @@ void history_rotate() { } -void tick() { +void tick(int print) { time_t t; pthread_mutex_lock(&tick_mutex); @@ -95,10 +95,14 @@ void tick() { t = time(NULL); if(t - last_timestamp >= RESOLUTION) { //printf("TICKING\n"); + analyse_data(); ui_print(); history_rotate(); last_timestamp = t; } + else if(print) { + ui_print(); + } pthread_mutex_unlock(&tick_mutex); } @@ -115,7 +119,7 @@ static void handle_packet(char* args, const struct pcap_pkthdr* pkthdr,const cha int direction = 0; /* incoming */ eptr = (struct ether_header*)packet; - tick(); + tick(0); if(ntohs(eptr->ether_type) == ETHERTYPE_IP) { struct ip* iptr; @@ -285,6 +289,8 @@ int main(int argc, char **argv) { init_history(); + ui_init(); + pthread_create(&thread, NULL, (void*)&packet_loop, NULL); ui_loop(); diff --git a/ui.c b/ui.c index 0f6f995..03f5113 100644 --- a/ui.c +++ b/ui.c @@ -41,6 +41,10 @@ extern options_t options ; void ui_finish(); +sorted_list_type screen_list; +host_pair_line totals; +int peaksent, peakrecv, peaktotal; + int screen_line_compare(void* a, void* b) { int i; host_pair_line* aa = (host_pair_line*)a; @@ -149,43 +153,28 @@ void draw_totals(host_pair_line* totals) { extern history_type history_totals; - -void ui_print() { - hash_node_type* n = NULL; - sorted_list_node* nn = NULL; - char hostname[HOSTNAME_LENGTH]; - static char *line; - static int lcols; - int peaksent = 0, peakrecv = 0, peaktotal = 0; - int y = 1; - int i; - sorted_list_type screen_list; - host_pair_line totals; - - if (!line || lcols != COLS) { - xfree(line); - line = calloc(COLS + 1, 1); - } - +void screen_list_init() { screen_list.compare = &screen_line_compare; sorted_list_initialise(&screen_list); +} - clear(); - //erase(); - move(0, 0); - attron(A_REVERSE); - addstr(" Q "); - attroff(A_REVERSE); - addstr(" quit "); - attron(A_REVERSE); - addstr(" R "); - attroff(A_REVERSE); - addstr(options.dnsresolution ? " name resolution off " - : " name resolution on "); - draw_bar_scale(&y); +void screen_data_clear() { + sorted_list_node* nn = NULL; + peaksent = peakrecv = peaktotal = 0; + while((nn = sorted_list_next_item(&screen_list, nn)) != NULL) { + free(nn->data); + } + sorted_list_destroy(&screen_list); +} + +void analyse_data() { + hash_node_type* n = NULL; + int i; memset(&totals, 0, sizeof totals); + screen_data_clear(); + while(hash_next_item(history, &n) == HASH_STATUS_OK) { history_type* d = (history_type*)n->rec; host_pair_line* screen_line; @@ -235,6 +224,36 @@ void ui_print() { } } +} + +void ui_print() { + sorted_list_node* nn = NULL; + char hostname[HOSTNAME_LENGTH]; + static char *line; + static int lcols; + int y = 1; + + if (!line || lcols != COLS) { + xfree(line); + line = calloc(COLS + 1, 1); + } + + + clear(); + //erase(); + move(0, 0); + attron(A_REVERSE); + addstr(" Q "); + attroff(A_REVERSE); + addstr(" quit "); + attron(A_REVERSE); + addstr(" R "); + attroff(A_REVERSE); + addstr(options.dnsresolution ? " name resolution off " + : " name resolution on "); + draw_bar_scale(&y); + + /* Screen layout: we have 2 * HISTORY_DIVISIONS 6-character wide history * items, and so can use COLS - 12 * HISTORY_DIVISIONS to print the two @@ -274,7 +293,6 @@ void ui_print() { } y += 2; - free(screen_line); } @@ -316,14 +334,9 @@ void ui_print() { refresh(); - sorted_list_destroy(&screen_list); } -void ui_loop() { - pthread_mutex_t tick_wait_mutex; - pthread_cond_t tick_wait_cond; - extern sig_atomic_t foad; - +void ui_init() { (void) initscr(); /* initialize the curses library */ keypad(stdscr, TRUE); /* enable keyboard mapping */ (void) nonl(); /* tell curses not to do NL->CR/NL on output */ @@ -332,9 +345,12 @@ void ui_loop() { halfdelay(2); erase(); - - pthread_mutex_init(&tick_wait_mutex, NULL); - pthread_cond_init(&tick_wait_cond, NULL); + + screen_list_init(); +} + +void ui_loop() { + extern sig_atomic_t foad; while(foad == 0) { int i; i = toupper(getch()); @@ -345,13 +361,15 @@ void ui_loop() { case 'R': options.dnsresolution = !options.dnsresolution; + tick(1); break; case 'B': options.showbars = !options.showbars; + tick(1); break; } - tick(); + tick(0); } }