#include "../include/traffic.h" #define lpp (LINES - 6) /* Lines per page to display IP qtatistics */ void print_field(u_short y, u_short x, struct host *h, u_char col); void help(); u_int column_width(u_char col); void show_stats(int sig) { u_int i; /* Counter variable */ struct host *host; /* Pointer host structure */ /* Initialize */ total.last_in = total.last_out = 0; total.last_pkt_in = total.last_pkt_out = 0; total.last_tcp_in = total.last_udp_in = total.last_icmp_in = 0; total.last_tcp_out = total.last_udp_out = total.last_icmp_out = 0; /* Proccess all hosts statistics */ for (i = 0; i < h_num; i++) { host = &hosts[i]; /* To make code more clear */ /* Update total transfers */ host->tot_in += host->last_in = host->in; host->tot_out += host->last_out = host->out; host->tot_tcp_in += host->last_tcp_in = host->tcp_in; host->tot_udp_in += host->last_udp_in = host->udp_in; host->tot_icmp_in += host->last_icmp_in = host->icmp_in; host->tot_tcp_out += host->last_tcp_out = host->tcp_out; host->tot_udp_out += host->last_udp_out = host->udp_out; host->tot_icmp_out += host->last_icmp_out = host->icmp_out; /* Summarize */ total.last_in += host->last_in; total.last_out += host->last_out; total.last_tcp_in += host->last_tcp_in; total.last_udp_in += host->last_udp_in; total.last_icmp_in += host->last_icmp_in; total.last_tcp_out += host->last_tcp_out; total.last_udp_out += host->last_udp_out; total.last_icmp_out += host->last_icmp_out; /* Check maximum transfers */ if (host->in > host->max_in) host->max_in = host->in; if (host->out > host->max_out) host->max_out = host->out; host->in = 0; host->out = 0; host->tcp_in = host->udp_in = host->icmp_in = 0; host->tcp_out = host->udp_out = host->icmp_out = 0; /* Update packets counters */ host->tot_pkt_in += host->last_pkt_in = host->pkt_in; host->tot_pkt_out += host->last_pkt_out = host->pkt_out; /* Summarize */ total.last_pkt_in += host->pkt_in; total.last_pkt_out += host->pkt_out; /* Check maximum packets */ if (host->pkt_in > host->max_pkt_in) host->max_pkt_in = host->pkt_in; if (host->pkt_out > host->max_pkt_out) host->max_pkt_out = host->pkt_out; host->pkt_in = 0; host->pkt_out = 0; } /* Summarize */ total.tot_in += total.last_in; total.tot_out += total.last_out; /* Summarize */ total.tot_pkt_in += total.last_pkt_in; total.tot_pkt_out += total.last_pkt_out; /* Summarize - Check maximum transfers */ if (total.last_in > total.max_in) total.max_in = total.last_in; if (total.last_out > total.max_out) total.max_out = total.last_out; /* Summarize - Check maximum packets */ if (total.last_pkt_in > total.max_pkt_in) total.max_pkt_in = total.last_pkt_in; if (total.last_pkt_out > total.max_pkt_out) total.max_pkt_out = total.last_pkt_out; opt.times++; /* Lock */ if (m_packet) m_display = 1; if ((opt.logfile != NULL) && m_packet) m_file = 1; if (m_packet) return; /* If logging enabled then log */ if ((opt.logfile != NULL) && !m_file) log_file(); /* Display on screen */ if (!opt.daemon) display(); } void display() { extern WINDOW *win; /* Pointer to ncurses window */ extern struct options opt; /* Options */ extern struct host *hosts; /* Pointer to host info array */ extern u_int h_num; /* Number of watched hosts */ u_int i; /* Counter variable */ char *buf; /* Pointer to buffor */ u_char next=1; /* Position of next column */ u_long active=0; /* Active hosts counter */ /* Erase window */ werase(win); if ( opt.mode == MODE_STAT) { /* Print info */ mvwprintw( win, 0, 0, "Traffic Analyzer (c) Krzysztof \"Msciciel\" Pawlowski 2002, 2004"); /* sort */ switch(opt.sort) { case COL_IP: qsort(hosts, h_num, sizeof(struct host), cmp_ip); break; case COL_DATA: qsort(hosts, h_num, sizeof(struct host), cmp_data_cur); break; case COL_DATA_MAX: qsort(hosts, h_num, sizeof(struct host), cmp_data_max); break; case COL_DATA_TOT: case COL_DATA_AVG: qsort(hosts, h_num, sizeof(struct host), cmp_data_tot); break; case COL_PKT: qsort(hosts, h_num, sizeof(struct host), cmp_pkt_cur); break; case COL_PKT_TOT: case COL_PKT_AVG: qsort(hosts, h_num, sizeof(struct host), cmp_pkt_tot); break; case COL_PKT_MAX: qsort(hosts, h_num, sizeof(struct host), cmp_pkt_max); break; case COL_MAC: qsort(hosts, h_num, sizeof(struct host), cmp_mac); break; case COL_HOSTNAME: qsort(hosts, h_num, sizeof(struct host), cmp_hostname); break; case COL_TCP: qsort(hosts, h_num, sizeof(struct host), cmp_tcp); break; case COL_UDP: qsort(hosts, h_num, sizeof(struct host), cmp_udp); break; case COL_ICMP: qsort(hosts, h_num, sizeof(struct host), cmp_icmp); break; case COL_TCP_TOT: qsort(hosts, h_num, sizeof(struct host), cmp_tcp_tot); break; case COL_UDP_TOT: qsort(hosts, h_num, sizeof(struct host), cmp_udp_tot); break; case COL_ICMP_TOT: qsort(hosts, h_num, sizeof(struct host), cmp_icmp_tot); break; } /* Print columns */ for(i=0; i < MAX_COL; i++) if (opt.columns[i] != 0) { next += print_col(opt.columns[i], next) + 2; if ( next >= COLS ) opt.columns[i] = 0; } /* Calculate number of active hosts */ for(i=0; i < h_num; i++) if ((hosts[i].last_in > 0) || (hosts[i].last_out > 0)) active++; /* Print footer */ mvwprintw( win, LINES - 1, 1, "Device: %s | Unit: %s / %s | Refresh: %ds | Time: %2dh %2dm %2ds | From / To | Active: %d" , opt.dev, opt.unit_name, opt.unit_t_name, opt.delay , opt.times * opt.delay / 3600 , ((opt.times * opt.delay) % 3600) / 60 , (opt.times * opt.delay) % 60 , active ); } /* Print help */ else if ( opt.mode == MODE_HELP) help(); wrefresh(win); /* Exit if timeout has been reached */ if (((opt.times * opt.delay) >= opt.timeout) && (opt.timeout > 0)) { endwin(); exit(0); } } /* Print column */ int print_col(u_char col, u_char pos) { int i,j; struct host *host; /* Pointer host structure */ u_short len; /* Column width */ /* Get column width */ len = column_width(col); /* Print header */ switch (col) { case COL_IP: mvwprintw( win, 2, pos + (len - 4 ) / 2, "Host"); break; case COL_DATA: mvwprintw( win, 2, pos + (len - 4 ) / 2, "Data"); break; case COL_DATA_MAX: mvwprintw( win, 2, pos + (len - 8 ) / 2, "Data Max"); break; case COL_DATA_AVG: mvwprintw( win, 2, pos + (len - 8 ) / 2, "Data Avg"); break; case COL_DATA_TOT: mvwprintw( win, 2, pos + (len - 8 ) / 2, "Data Total"); break; case COL_PKT: mvwprintw( win, 2, pos + (len - 7 ) / 2, "Packets"); break; case COL_PKT_TOT: mvwprintw( win, 2, pos + (len - 13 ) / 2, "Packets Total"); break; case COL_PKT_AVG: mvwprintw( win, 2, pos + (len - 11 ) / 2, "Packets Avg"); break; case COL_PKT_MAX: mvwprintw( win, 2, pos + (len - 11 ) / 2, "Packets Max"); break; case COL_MAC: mvwprintw( win, 2, pos + (len - 3 ) / 2, "MAC"); break; case COL_HOSTNAME: mvwprintw( win, 2, pos + (len - 8 ) / 2, "Hostname"); break; case COL_TCP: mvwprintw( win, 2, pos + (len - 3 ) / 2, "TCP"); break; case COL_UDP: mvwprintw( win, 2, pos + (len - 3 ) / 2, "UDP"); break; case COL_ICMP: mvwprintw( win, 2, pos + (len - 4 ) / 2, "ICMP"); break; case COL_TCP_TOT: mvwprintw( win, 2, pos + (len - 9 ) / 2, "TCP Total"); break; case COL_UDP_TOT: mvwprintw( win, 2, pos + (len - 9 ) / 2, "UDP Total"); break; case COL_ICMP_TOT: mvwprintw( win, 2, pos + (len - 10 ) / 2, "ICMP Total"); break; }; /* Print fields */ for (i = opt.page * lpp, j=0; i < h_num && i < opt.page * lpp + lpp - 2 * opt.total; i++, j++) { print_field(4 + j, pos, &hosts[i], col); } /* Print summarize line */ if (opt.total) { if (col == COL_IP) mvwprintw( win, LINES - 3, 1, "%s", "TOTAL"); else print_field(LINES - 3, pos, &total, col); } return len; } /* Print field */ void print_field(u_short y, u_short x, struct host *h, u_char col) { extern struct options opt; extern WINDOW *win; switch(col) { /* Print data column */ case COL_DATA: if (cmp(opt.unit_name,"B") || cmp(opt.unit_name,"Bit")) mvwprintw( win, y, x, "%7d / %7d ", (int)(h->last_in * opt.unit / opt.delay) , (int)(h->last_out * opt.unit / opt.delay)); else if (cmp(opt.unit_name,"KB") || cmp(opt.unit_name,"kBit")) mvwprintw( win, y, x, "%6.1f / %6.1f ", h->last_in * opt.unit / opt.delay , h->last_out * opt.unit / opt.delay ); else if (cmp(opt.unit_name,"MB") || cmp(opt.unit_name,"mBit")) mvwprintw( win, y, x, "%5.3f / %5.3f ", h->last_in * opt.unit / opt.delay , h->last_out * opt.unit / opt.delay ); else mvwprintw( win, y, x, "%8.5f / %8.5f ", h->last_in * opt.unit / opt.delay , h->last_out * opt.unit / opt.delay ); break; /* Print IP column */ case COL_IP: mvwprintw( win, y, 1, "%s", inet_ntoa(h->ip)); break; /* Print data maximum column */ case COL_DATA_MAX: if (cmp(opt.unit_name,"B") || cmp(opt.unit_name,"Bit")) mvwprintw( win, y, x, "%7d / %7d ", (int)(h->max_in * opt.unit / opt.delay) , (int)(h->max_out * opt.unit / opt.delay)); else if (cmp(opt.unit_name,"KB") || cmp(opt.unit_name,"kBit")) mvwprintw( win, y, x, "%6.1f / %6.1f ", h->max_in * opt.unit / opt.delay , h->max_out * opt.unit / opt.delay ); else if (cmp(opt.unit_name,"MB") || cmp(opt.unit_name,"mBit")) mvwprintw( win, y, x, "%5.3f / %5.3f", h->max_in * opt.unit / opt.delay , h->max_out * opt.unit / opt.delay); else mvwprintw( win, y, x, "%8.5f / %8.5f", h->max_in * opt.unit / opt.delay , h->max_out * opt.unit / opt.delay); break; /* Print data average column */ case COL_DATA_AVG: if (opt.times > 0) { if (cmp(opt.unit_name,"B") || cmp(opt.unit_name,"Bit")) mvwprintw( win, y, x, "%7d / %7d", (int)(h->tot_in * opt.unit / (opt.times * opt.delay)) , (int)(h->tot_out * opt.unit / (opt.times * opt.delay))); else if (cmp(opt.unit_name,"KB") || cmp(opt.unit_name,"kBit")) mvwprintw( win, y, x, "%6.1f / %6.1f", h->tot_in * opt.unit / (opt.times * opt.delay) , h->tot_out * opt.unit / (opt.times * opt.delay)); else if (cmp(opt.unit_name,"MB") || cmp(opt.unit_name,"mBit")) mvwprintw( win, y, x, "%5.3f / %5.3f", h->tot_in * opt.unit / (opt.times * opt.delay) , h->tot_out * opt.unit / (opt.times * opt.delay)); else mvwprintw( win, y, x, "%8.5f / %8.5f", h->tot_in * opt.unit / (opt.times * opt.delay) , h->tot_out * opt.unit / (opt.times * opt.delay)); } break; /* Print data total column */ case COL_DATA_TOT: if (cmp(opt.unit_t_name,"B") || cmp(opt.unit_t_name,"Bit")) mvwprintw( win, y, x, "%9d / %9d ", (int)(h->tot_in * opt.unit_t) , (int)(h->tot_out * opt.unit_t)); else if (cmp(opt.unit_t_name,"KB") || cmp(opt.unit_t_name,"kBit")) mvwprintw( win, y, x, "%9.1f / %9.1f ", h->tot_in * opt.unit_t , h->tot_out * opt.unit_t); else if (cmp(opt.unit_t_name,"MB") || cmp(opt.unit_t_name,"mBit")) mvwprintw( win, y, x, "%8.1f / %8.1f ", h->tot_in * opt.unit_t , h->tot_out * opt.unit_t); else mvwprintw( win, y, x, "%8.3f / %8.3f ", h->tot_in * opt.unit_t , h->tot_out * opt.unit_t); break; /* Print packet current column */ case COL_PKT: mvwprintw( win, y, x, "%5d / %5d ", (int)(h->last_pkt_in / opt.delay) , (int)(h->last_pkt_out / opt.delay)); break; /* Print packet average column */ case COL_PKT_AVG: if (opt.times > 0) mvwprintw( win, y, x, "%5d / %5d ", (int)(h->tot_pkt_in / (opt.delay * opt.times)) , (int)(h->tot_pkt_out / (opt.delay * opt.times))); break; /* Print packet maximum column */ case COL_PKT_MAX: mvwprintw( win, y, x, "%5d / %5d ", (int)(h->max_pkt_in / opt.delay) , (int)(h->max_pkt_out / opt.delay)); break; /* Print packet current column */ case COL_PKT_TOT: mvwprintw( win, y, x, "%8d / %8d ", (int)h->tot_pkt_in , (int)h->tot_pkt_out); break; /* Print MAC address column */ case COL_MAC: mvwprintw( win, y, x, "%18s ", h->mac); break; /* Print hostname column */ case COL_HOSTNAME: mvwprintw( win, y, x, "%32s ", h->hostname); break; /* Print TCP column */ case COL_TCP: if (cmp(opt.unit_name,"B") || cmp(opt.unit_name,"Bit")) mvwprintw( win, y, x, "%7d / %7d ", (int)(h->last_tcp_in * opt.unit / opt.delay) , (int)(h->last_tcp_out * opt.unit / opt.delay)); else if (cmp(opt.unit_name,"KB") || cmp(opt.unit_name,"kBit")) mvwprintw( win, y, x, "%6.1f / %6.1f ", h->last_tcp_in * opt.unit / opt.delay , h->last_tcp_out * opt.unit / opt.delay ); else mvwprintw( win, y, x, "%5.3f / %5.3f ", h->last_tcp_in * opt.unit / opt.delay , h->last_tcp_out * opt.unit / opt.delay ); break; /* Print UDP column */ case COL_UDP: if (cmp(opt.unit_name,"B") || cmp(opt.unit_name,"Bit")) mvwprintw( win, y, x, "%7d / %7d ", (int)(h->last_udp_in * opt.unit / opt.delay) , (int)(h->last_udp_out * opt.unit / opt.delay)); else if (cmp(opt.unit_name,"KB") || cmp(opt.unit_name,"kBit")) mvwprintw( win, y, x, "%6.1f / %6.1f ", h->last_udp_in * opt.unit / opt.delay , h->last_udp_out * opt.unit / opt.delay ); else mvwprintw( win, y, x, "%5.3f / %5.3f ", h->last_udp_in * opt.unit / opt.delay , h->last_udp_out * opt.unit / opt.delay ); break; /* Print ICMP column */ case COL_ICMP: if (cmp(opt.unit_name,"B") || cmp(opt.unit_name,"Bit")) mvwprintw( win, y, x, "%7d / %7d ", (int)(h->last_icmp_in * opt.unit / opt.delay) , (int)(h->last_icmp_out * opt.unit / opt.delay)); else if (cmp(opt.unit_name,"KB") || cmp(opt.unit_name,"kBit")) mvwprintw( win, y, x, "%6.1f / %6.1f ", h->last_icmp_in * opt.unit / opt.delay , h->last_icmp_out * opt.unit / opt.delay ); else mvwprintw( win, y, x, "%5.3f / %5.3f ", h->last_icmp_in * opt.unit / opt.delay , h->last_icmp_out * opt.unit / opt.delay ); break; /* Print TCP total column */ case COL_TCP_TOT: if (cmp(opt.unit_t_name,"B") || cmp(opt.unit_t_name,"Bit")) mvwprintw( win, y, x, "%9d / %9d ", (int)(h->tot_tcp_in * opt.unit_t) , (int)(h->tot_tcp_out * opt.unit_t)); else if (cmp(opt.unit_t_name,"KB") || cmp(opt.unit_t_name,"kBit")) mvwprintw( win, y, x, "%9.1f / %9.1f ", h->tot_tcp_in * opt.unit_t , h->tot_tcp_out * opt.unit_t); else mvwprintw( win, y, x, "%8.1f / %8.1f ", h->tot_tcp_in * opt.unit_t , h->tot_tcp_out * opt.unit_t); break; /* Print UDP total column */ case COL_UDP_TOT: if (cmp(opt.unit_t_name,"B") || cmp(opt.unit_t_name,"Bit")) mvwprintw( win, y, x, "%9d / %9d ", (int)(h->tot_udp_in * opt.unit_t) , (int)(h->tot_udp_out * opt.unit_t)); else if (cmp(opt.unit_t_name,"KB") || cmp(opt.unit_t_name,"kBit")) mvwprintw( win, y, x, "%9.1f / %9.1f ", h->tot_udp_in * opt.unit_t , h->tot_udp_out * opt.unit_t); else mvwprintw( win, y, x, "%8.1f / %8.1f ", h->tot_udp_in * opt.unit_t , h->tot_udp_out * opt.unit_t); break; /* Print ICMP total column */ case COL_ICMP_TOT: if (cmp(opt.unit_t_name,"B") || cmp(opt.unit_t_name,"Bit")) mvwprintw( win, y, x, "%9d / %9d ", (int)(h->tot_icmp_in * opt.unit_t) , (int)(h->tot_icmp_out * opt.unit_t)); else if (cmp(opt.unit_t_name,"KB") || cmp(opt.unit_t_name,"kBit")) mvwprintw( win, y, x, "%9.1f / %9.1f ", h->tot_icmp_in * opt.unit_t , h->tot_icmp_out * opt.unit_t); else mvwprintw( win, y, x, "%8.1f / %8.1f ", h->tot_icmp_in * opt.unit_t , h->tot_icmp_out * opt.unit_t); break; }; } /* Display help */ void help() { extern WINDOW *win; wprintw(win, "Keys:\n\ a + - add column\n\ d + - remove column\n\ u + - change data unit size\n\ U + - change total data unit size\n\ s + - sort\n\ t - total line\n\ r - reset statistics\n\ ? - help\n\ q - quit\n\ \n\ Columns:\n\ h - host ip\n\ c - current data transfer\n\ a - average data transfer\n\ m - maximum data transfer\n\ s - total data transfer\n\ p - current packets flow\n\ o - average packets flow\n\ m - maximum packets flow\n\ P - total packets flow\n\ M - MAC address\n\ H - hostname\n\ t - TCP data flow\n\ u - UDP data flow\n\ i - ICMP date flow\n\ T - Total TCP data flow\n\ U - Total UDP data flow\n\ I - Total ICMP date flow\n\ \n\ Units:\n\ b - Bits\n\ B - Bytes\n\ k - Kilobits\n\ K - Kilobytes\n\ m - Megabits\n\ M - Megabytes\n\ g - Gigabits\n\ G - Gigabytes\n"); } /* Get column width */ u_int column_width(u_char col) { extern struct options opt; switch(col) { case COL_DATA: case COL_DATA_MAX: case COL_DATA_AVG: case COL_TCP: case COL_UDP: case COL_ICMP: if (cmp(opt.unit_name,"G") || cmp(opt.unit_name,"gBit")) return 19; else if (cmp(opt.unit_name,"B") || cmp(opt.unit_name,"Bit")) return 17; else if (cmp(opt.unit_name,"KB") || cmp(opt.unit_name,"kBit")) return 15; else return 13; case COL_DATA_TOT: case COL_TCP_TOT: case COL_UDP_TOT: case COL_ICMP_TOT: if (cmp(opt.unit_t_name,"B") || cmp(opt.unit_t_name,"Bit")) return 21; else if (cmp(opt.unit_t_name,"KB") || cmp(opt.unit_t_name,"kBit")) return 21; else return 17; case COL_IP: return 15; case COL_PKT: case COL_PKT_AVG: case COL_PKT_MAX: return 13; case COL_PKT_TOT: return 19; case COL_MAC: return 19; case COL_HOSTNAME: return 32; default: return 0; } }