User selectable sort criteria.
This commit is contained in:
11
TODO
11
TODO
@@ -1,21 +1,12 @@
|
||||
Things to do for iftop
|
||||
$Id$
|
||||
|
||||
* Bandwidth display in bytes/s
|
||||
|
||||
* Search for BSD interface names - need to know what to look for.
|
||||
|
||||
* IP types other than v4?
|
||||
|
||||
* Config file.
|
||||
|
||||
* Redesign totals:
|
||||
|
||||
2sec 10sec 40sec Peak Total
|
||||
TX x x x x x
|
||||
RX x x x x x
|
||||
Total x x x x x
|
||||
|
||||
* Find someone gullible to sort out autoconf.
|
||||
|
||||
* Which average to use for the bar graph? Show several and peaks? Colours?
|
||||
@@ -23,8 +14,6 @@ Total x x x x x
|
||||
* Single keypress firewalling of troublesome connections, a la top(1)'s K
|
||||
to kill?
|
||||
|
||||
* Configurable sort criteria.
|
||||
|
||||
* Configurable refresh rates.
|
||||
|
||||
* Filtering of items included in diplay
|
||||
|
||||
4
iftop.c
4
iftop.c
@@ -242,11 +242,11 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir)
|
||||
|
||||
if(direction == 0) {
|
||||
/* incoming */
|
||||
history_totals.recv[history_pos] += ntohs(iptr->ip_len);
|
||||
history_totals.recv[history_pos] += len;
|
||||
history_totals.total_recv += len;
|
||||
}
|
||||
else {
|
||||
history_totals.sent[history_pos] += ntohs(iptr->ip_len);
|
||||
history_totals.sent[history_pos] += len;
|
||||
history_totals.total_sent += len;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ static void set_defaults() {
|
||||
options.paused = 0;
|
||||
options.showhelp = 0;
|
||||
options.bandwidth_in_bytes = 0;
|
||||
options.sort = OPTION_SORT_DIV2;
|
||||
}
|
||||
|
||||
static void die(char *msg) {
|
||||
|
||||
@@ -18,6 +18,14 @@ typedef enum {
|
||||
OPTION_PORTS_ON
|
||||
} option_port_t;
|
||||
|
||||
typedef enum {
|
||||
OPTION_SORT_DIV1,
|
||||
OPTION_SORT_DIV2,
|
||||
OPTION_SORT_DIV3,
|
||||
OPTION_SORT_SRC,
|
||||
OPTION_SORT_DEST
|
||||
} option_sort_t;
|
||||
|
||||
typedef struct {
|
||||
/* interface on which to listen */
|
||||
char *interface;
|
||||
@@ -39,6 +47,7 @@ typedef struct {
|
||||
int paused;
|
||||
int showhelp;
|
||||
int bandwidth_in_bytes;
|
||||
option_sort_t sort;
|
||||
|
||||
} options_t;
|
||||
|
||||
|
||||
88
ui.c
88
ui.c
@@ -39,6 +39,10 @@
|
||||
" S - toggle show source port \n"\
|
||||
" D - toggle show destination port\n"\
|
||||
" p - toggle port display\n"\
|
||||
"\nSorting:\n"\
|
||||
" 1/2/3 - sort by 1st/2nd/3rd column\n"\
|
||||
" < - sort by source name\n"\
|
||||
" > - sort by dest name\n"\
|
||||
"\nGeneral:\n"\
|
||||
" P - pause display\n"\
|
||||
" h - toggle this help display\n"\
|
||||
@@ -84,12 +88,13 @@ int helptimer = 0;
|
||||
char helpmsg[HELP_MSG_SIZE];
|
||||
int dontshowdisplay = 0;
|
||||
|
||||
int screen_line_compare(void* a, void* b) {
|
||||
/*
|
||||
* Compare two screen lines based on bandwidth. Start comparing from the
|
||||
* specified column
|
||||
*/
|
||||
int screen_line_bandwidth_compare(host_pair_line* aa, host_pair_line* bb, int start_div) {
|
||||
int i;
|
||||
host_pair_line* aa = (host_pair_line*)a;
|
||||
host_pair_line* bb = (host_pair_line*)b;
|
||||
/* Ignore the first division so that stuff doesn't jump around too much */
|
||||
for(i = 1; i < HISTORY_DIVISIONS; i++) {
|
||||
for(i = start_div; i < HISTORY_DIVISIONS; i++) {
|
||||
if(aa->recv[i] + aa->sent[i] != bb->recv[i] + bb->sent[i]) {
|
||||
return(aa->recv[i] + aa->sent[i] < bb->recv[i] + bb->sent[i]);
|
||||
}
|
||||
@@ -97,6 +102,59 @@ int screen_line_compare(void* a, void* b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two screen lines based on hostname / IP. Fall over to compare by
|
||||
* bandwidth.
|
||||
*/
|
||||
int screen_line_host_compare(struct in_addr* a, struct in_addr* b, host_pair_line* aa, host_pair_line* bb) {
|
||||
char hosta[HOSTNAME_LENGTH], hostb[HOSTNAME_LENGTH];
|
||||
int r;
|
||||
|
||||
/* This isn't overly efficient because we resolve again before
|
||||
display. */
|
||||
if (options.dnsresolution) {
|
||||
resolve(a, hosta, HOSTNAME_LENGTH);
|
||||
resolve(b, hostb, HOSTNAME_LENGTH);
|
||||
}
|
||||
else {
|
||||
strcpy(hosta, inet_ntoa(*a));
|
||||
strcpy(hostb, inet_ntoa(*b));
|
||||
}
|
||||
|
||||
r = strcmp(hosta, hostb);
|
||||
|
||||
if(r == 0) {
|
||||
return screen_line_bandwidth_compare(aa, bb, 2);
|
||||
}
|
||||
else {
|
||||
return (r > 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int screen_line_compare(void* a, void* b) {
|
||||
host_pair_line* aa = (host_pair_line*)a;
|
||||
host_pair_line* bb = (host_pair_line*)b;
|
||||
if(options.sort == OPTION_SORT_DIV1) {
|
||||
return screen_line_bandwidth_compare(aa, bb, 0);
|
||||
}
|
||||
else if(options.sort == OPTION_SORT_DIV2) {
|
||||
return screen_line_bandwidth_compare(aa, bb, 1);
|
||||
}
|
||||
else if(options.sort == OPTION_SORT_DIV3) {
|
||||
return screen_line_bandwidth_compare(aa, bb, 2);
|
||||
}
|
||||
else if(options.sort == OPTION_SORT_SRC) {
|
||||
return screen_line_host_compare(&(aa->ap.src), &(bb->ap.src), aa, bb);
|
||||
}
|
||||
else if(options.sort == OPTION_SORT_DEST) {
|
||||
return screen_line_host_compare(&(aa->ap.dst), &(bb->ap.dst), aa, bb);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void readable_size(float n, char* buf, int bsize, int ksize, int bytes) {
|
||||
|
||||
int i = 0;
|
||||
@@ -686,6 +744,26 @@ void ui_loop() {
|
||||
case 'P':
|
||||
options.paused = !options.paused;
|
||||
break;
|
||||
case '1':
|
||||
options.sort = OPTION_SORT_DIV1;
|
||||
showhelp("Sort by col 1");
|
||||
break;
|
||||
case '2':
|
||||
options.sort = OPTION_SORT_DIV2;
|
||||
showhelp("Sort by col 2");
|
||||
break;
|
||||
case '3':
|
||||
options.sort = OPTION_SORT_DIV3;
|
||||
showhelp("Sort by col 3");
|
||||
break;
|
||||
case '<':
|
||||
options.sort = OPTION_SORT_SRC;
|
||||
showhelp("Sort by source");
|
||||
break;
|
||||
case '>':
|
||||
options.sort = OPTION_SORT_DEST;
|
||||
showhelp("Sort by dest");
|
||||
break;
|
||||
case 'f': {
|
||||
char *s;
|
||||
dontshowdisplay = 1;
|
||||
|
||||
Reference in New Issue
Block a user