/* For terms of usage/redistribution/modification see the LICENSE file */
/* For authors and contributors see the AUTHORS file */
/***
hostmon.c - Host traffic monitor
Discovers LAN hosts and displays packet statistics for them
***/
#include "iptraf-ng-compat.h"
#include "tui/labels.h"
#include "tui/winops.h"
#include "dirs.h"
#include "deskman.h"
#include "fltdefs.h"
#include "packet.h"
#include "ifaces.h"
#include "hostmon.h"
#include "attrs.h"
#include "log.h"
#include "timer.h"
#include "landesc.h"
#include "options.h"
#include "logvars.h"
#include "promisc.h"
#include "error.h"
#include "rate.h"
#define SCROLLUP 0
#define SCROLLDOWN 1
struct ethtabent {
int type;
union {
struct {
unsigned long long inpcount;
unsigned long long inbcount;
unsigned long long inippcount;
unsigned long inspanbr;
unsigned long long outpcount;
unsigned long long outbcount;
unsigned long long outippcount;
unsigned long outspanbr;
struct rate inrate;
struct rate outrate;
} figs;
struct {
char eth_addr[ETH_ALEN];
char ascaddr[18];
char desc[65];
char ifname[IFNAMSIZ];
int withdesc;
int printed;
unsigned int linktype;
} desc;
} un;
unsigned int index;
struct ethtabent *prev_entry;
struct ethtabent *next_entry;
};
struct ethtab {
struct ethtabent *head;
struct ethtabent *tail;
struct ethtabent *firstvisible;
struct ethtabent *lastvisible;
unsigned long count;
unsigned long entcount;
int units;
WINDOW *borderwin;
PANEL *borderpanel;
WINDOW *tabwin;
PANEL *tabpanel;
};
/*
* SIGUSR1 logfile rotation handler
*/
static void rotate_lanlog(int s __unused)
{
rotate_flag = 1;
strcpy(target_logname, current_logfile);
signal(SIGUSR1, rotate_lanlog);
}
static void writeethlog(struct ethtabent *list, unsigned long nsecs, FILE *fd)
{
char atime[TIME_TARGET_MAX];
struct ethtabent *ptmp = list;
genatime(time(NULL), atime);
fprintf(fd, "\n*** LAN traffic log, generated %s\n\n", atime);
while (ptmp != NULL) {
if (ptmp->type == 0) {
if (ptmp->un.desc.linktype == ARPHRD_ETHER)
fprintf(fd, "\nEthernet address: %s",
ptmp->un.desc.ascaddr);
else if (ptmp->un.desc.linktype == ARPHRD_FDDI)
fprintf(fd, "\nFDDI address: %s",
ptmp->un.desc.ascaddr);
if (ptmp->un.desc.withdesc)
fprintf(fd, " (%s)", ptmp->un.desc.desc);
fprintf(fd, "\n");
} else {
fprintf(fd,
"\tIncoming total %llu packets, %llu bytes; %llu IP packets\n",
ptmp->un.figs.inpcount, ptmp->un.figs.inbcount,
ptmp->un.figs.inippcount);
fprintf(fd,
"\tOutgoing total %llu packets, %llu bytes; %llu IP packets\n",
ptmp->un.figs.outpcount,
ptmp->un.figs.outbcount,
ptmp->un.figs.outippcount);
fprintf(fd, "\tAverage rates: ");
char buf_in[32];
char buf_out[32];
rate_print(ptmp->un.figs.inbcount / nsecs, buf_in, sizeof(buf_in));
rate_print(ptmp->un.figs.outbcount / nsecs, buf_out, sizeof(buf_out));
fprintf(fd, "%s incoming, %s outgoing\n",
buf_in, buf_out);
if (nsecs > 5) {
rate_print(rate_get_average(&ptmp->un.figs.inrate),
buf_in, sizeof(buf_in));
rate_print(rate_get_average(&ptmp->un.figs.outrate),
buf_out, sizeof(buf_out));
fprintf(fd,
"\tLast 5-second rates: %s incoming, %s outgoing\n",
buf_in, buf_out);
}
}
ptmp = ptmp->next_entry;
}
fprintf(fd, "\nRunning time: %lu seconds\n", nsecs);
fflush(fd);
}
static void initethtab(struct ethtab *table)
{
table->head = table->tail = NULL;
table->firstvisible = table->lastvisible = NULL;
table->count = table->entcount = 0;
table->borderwin = newwin(LINES - 2, COLS, 1, 0);
table->borderpanel = new_panel(table->borderwin);
table->tabwin = newwin(LINES - 4, COLS - 2, 2, 1);
table->tabpanel = new_panel(table->tabwin);
wattrset(table->borderwin, BOXATTR);
tx_box(table->borderwin, ACS_VLINE, ACS_HLINE);
wmove(table->borderwin, 0, 5 * COLS / 80);
wprintw(table->borderwin, " PktsIn ");
wmove(table->borderwin, 0, 16 * COLS / 80);
wprintw(table->borderwin, " IP In ");
wmove(table->borderwin, 0, 24 * COLS / 80);
wprintw(table->borderwin, " BytesIn ");
wmove(table->borderwin, 0, 34 * COLS / 80);
wprintw(table->borderwin, " InRate ");
wmove(table->borderwin, 0, 42 * COLS / 80);
wprintw(table->borderwin, " PktsOut ");
wmove(table->borderwin, 0, 53 * COLS / 80);
wprintw(table->borderwin, " IP Out ");
wmove(table->borderwin, 0, 61 * COLS / 80);
wprintw(table->borderwin, " BytesOut ");
wmove(table->borderwin, 0, 70 * COLS / 80);
wprintw(table->borderwin, " OutRate ");
wmove(table->borderwin, LINES - 3, 40);
wprintw(table->borderwin, " InRate and OutRate are in %s ",
dispmode(options.actmode));
wattrset(table->tabwin, STDATTR);
tx_colorwin(table->tabwin);
tx_stdwinset(table->tabwin);
wtimeout(table->tabwin, -1);
update_panels();
doupdate();
}
static struct ethtabent *addethnode(struct ethtab *table)
{
struct ethtabent *ptemp;
ptemp = xmalloc(sizeof(struct ethtabent));
if (table->head == NULL) {
ptemp->prev_entry = NULL;
table->head = ptemp;
table->firstvisible = ptemp;
} else {
ptemp->prev_entry = table->tail;
table->tail->next_entry = ptemp;
}
table->tail = ptemp;
ptemp->next_entry = NULL;
table->count++;
ptemp->index = table->count;
if (table->count <= (unsigned) LINES - 4)
table->lastvisible = ptemp;
return ptemp;
}
void convmacaddr(char *addr, char *result)
{
u_int8_t *ptmp = (u_int8_t *) addr;
sprintf(result, "%02x:%02x:%02x:%02x:%02x:%02x",
*ptmp,
*(ptmp + 1),
*(ptmp + 2),
*(ptmp + 3),
*(ptmp + 4),
*(ptmp + 5));
}
static struct ethtabent *addethentry(struct ethtab *table,
unsigned int linktype, char *ifname,
char *addr, struct eth_desc *list)
{
struct ethtabent *ptemp;
ptemp = addethnode(table);
if (ptemp == NULL)
return NULL;
ptemp->type = 0;
memcpy(&(ptemp->un.desc.eth_addr), addr, ETH_ALEN);
strcpy(ptemp->un.desc.desc, "");
convmacaddr(addr, ptemp->un.desc.ascaddr);
ptemp->un.desc.linktype = linktype;
struct eth_desc *desc = NULL;
list_for_each_entry(desc, &list->hd_list, hd_list)
if (!strcasecmp(desc->hd_mac, ptemp->un.desc.ascaddr))
strcpy(ptemp->un.desc.desc, desc->hd_desc);
strcpy(ptemp->un.desc.ifname, ifname);
if (strcmp(ptemp->un.desc.desc, "") == 0)
ptemp->un.desc.withdesc = 0;
else
ptemp->un.desc.withdesc = 1;
ptemp->un.desc.printed = 0;
ptemp = addethnode(table);
if (ptemp == NULL)
return NULL;
ptemp->type = 1;
ptemp->un.figs.inpcount = 0;
ptemp->un.figs.outpcount = 0;
ptemp->un.figs.inspanbr = ptemp->un.figs.outspanbr = 0;
ptemp->un.figs.inippcount = ptemp->un.figs.outippcount = 0;
ptemp->un.figs.inbcount = ptemp->un.figs.outbcount = 0;
rate_alloc(&ptemp->un.figs.inrate, 5);
rate_alloc(&ptemp->un.figs.outrate, 5);
table->entcount++;
wmove(table->borderwin, LINES - 3, 1);
wprintw(table->borderwin, " %u entries ", table->entcount);
return ptemp;
}
static struct ethtabent *in_ethtable(struct ethtab *table,
unsigned int linktype, char *addr)
{
struct ethtabent *ptemp = table->head;
while (ptemp != NULL) {
if ((ptemp->type == 0)
&& (memcmp(addr, ptemp->un.desc.eth_addr, ETH_ALEN) == 0)
&& (ptemp->un.desc.linktype == linktype))
return ptemp->next_entry;
ptemp = ptemp->next_entry;
}
return NULL;
}
static void updateethent(struct ethtabent *entry, int pktsize, int is_ip,
int inout)
{
if (inout == 0) {
entry->un.figs.inpcount++;
entry->un.figs.inbcount += pktsize;
entry->un.figs.inspanbr += pktsize;
if (is_ip)
entry->un.figs.inippcount++;
} else {
entry->un.figs.outpcount++;
entry->un.figs.outbcount += pktsize;
entry->un.figs.outspanbr += pktsize;
if (is_ip)
entry->un.figs.outippcount++;
}
}
static void printethent(struct ethtab *table, struct ethtabent *entry,
unsigned int idx)
{
unsigned int target_row;
if ((entry->index < idx) || (entry->index > idx + LINES - 5))
return;
target_row = entry->index - idx;
if (entry->type == 0) {
wmove(table->tabwin, target_row, 1);
wattrset(table->tabwin, STDATTR);
if (entry->un.desc.linktype == ARPHRD_ETHER)
wprintw(table->tabwin, "Ethernet");
else if (entry->un.desc.linktype == ARPHRD_FDDI)
wprintw(table->tabwin, "FDDI");
wprintw(table->tabwin, " HW addr: %s", entry->un.desc.ascaddr);
if (entry->un.desc.withdesc)
wprintw(table->tabwin, " (%s)", entry->un.desc.desc);
wprintw(table->tabwin, " on %s ", entry->un.desc.ifname);
entry->un.desc.printed = 1;
} else {
wattrset(table->tabwin, PTRATTR);
wmove(table->tabwin, target_row, 1);
waddch(table->tabwin, ACS_LLCORNER);
wattrset(table->tabwin, HIGHATTR);
/* Inbound traffic counts */
wmove(table->tabwin, target_row, 2 * COLS / 80);
printlargenum(entry->un.figs.inpcount, table->tabwin);
wmove(table->tabwin, target_row, 12 * COLS / 80);
printlargenum(entry->un.figs.inippcount, table->tabwin);
wmove(table->tabwin, target_row, 22 * COLS / 80);
printlargenum(entry->un.figs.inbcount, table->tabwin);
/* Outbound traffic counts */
wmove(table->tabwin, target_row, 40 * COLS / 80);
printlargenum(entry->un.figs.outpcount, table->tabwin);
wmove(table->tabwin, target_row, 50 * COLS / 80);
printlargenum(entry->un.figs.outippcount, table->tabwin);
wmove(table->tabwin, target_row, 60 * COLS / 80);
printlargenum(entry->un.figs.outbcount, table->tabwin);
}
}
static void destroyethtab(struct ethtab *table)
{
struct ethtabent *ptemp = table->head;
struct ethtabent *cnext = NULL;
if (table->head != NULL)
cnext = table->head->next_entry;
while (ptemp != NULL) {
if (ptemp->type == 1) {
rate_destroy(&ptemp->un.figs.outrate);
rate_destroy(&ptemp->un.figs.inrate);
}
free(ptemp);
ptemp = cnext;
if (cnext != NULL)
cnext = cnext->next_entry;
}
}
static void hostmonhelp(void)
{
move(LINES - 1, 1);
scrollkeyhelp();
sortkeyhelp();
stdexitkeyhelp();
}
static void printrates(struct ethtab *table, unsigned int target_row,
struct ethtabent *ptmp)
{
char buf[32];
rate_print_no_units(rate_get_average(&ptmp->un.figs.inrate),
buf, sizeof(buf));
wmove(table->tabwin, target_row, 32 * COLS / 80);
wprintw(table->tabwin, "%s", buf);
rate_print_no_units(rate_get_average(&ptmp->un.figs.outrate),
buf, sizeof(buf));
wmove(table->tabwin, target_row, 69 * COLS / 80);
wprintw(table->tabwin, "%s", buf);
}
static void updateethrates(struct ethtab *table, unsigned long msecs,
unsigned int idx)
{
struct ethtabent *ptmp = table->head;
unsigned int target_row = 0;
if (table->lastvisible == NULL)
return;
while (ptmp != NULL) {
if (ptmp->type == 1) {
rate_add_rate(&ptmp->un.figs.inrate, ptmp->un.figs.inspanbr, msecs);
ptmp->un.figs.inspanbr = 0;
rate_add_rate(&ptmp->un.figs.outrate, ptmp->un.figs.outspanbr, msecs);
ptmp->un.figs.outspanbr = 0;
if ((ptmp->index >= idx)
&& (ptmp->index <= idx + LINES - 5)) {
wattrset(table->tabwin, HIGHATTR);
target_row = ptmp->index - idx;
printrates(table, target_row, ptmp);
}
}
ptmp = ptmp->next_entry;
}
}
static void refresh_hostmon_screen(struct ethtab *table, unsigned int idx)
{
struct ethtabent *ptmp = table->firstvisible;
wattrset(table->tabwin, STDATTR);
tx_colorwin(table->tabwin);
while ((ptmp != NULL) && (ptmp->prev_entry != table->lastvisible)) {
printethent(table, ptmp, idx);
ptmp = ptmp->next_entry;
}
update_panels();
doupdate();
}
static void scrollethwin(struct ethtab *table, int direction, unsigned int *idx)
{
char sp_buf[10];
sprintf(sp_buf, "%%%dc", COLS - 2);
wattrset(table->tabwin, STDATTR);
if (direction == SCROLLUP) {
if (table->lastvisible != table->tail) {
wscrl(table->tabwin, 1);
table->lastvisible = table->lastvisible->next_entry;
table->firstvisible = table->firstvisible->next_entry;
(*idx)++;
wmove(table->tabwin, LINES - 5, 0);
scrollok(table->tabwin, 0);
wprintw(table->tabwin, sp_buf, ' ');
scrollok(table->tabwin, 1);
printethent(table, table->lastvisible, *idx);
if (table->lastvisible->type == 1)
printrates(table, LINES - 5,
table->lastvisible);
}
} else {
if (table->firstvisible != table->head) {
wscrl(table->tabwin, -1);
table->lastvisible = table->lastvisible->prev_entry;
table->firstvisible = table->firstvisible->prev_entry;
(*idx)--;
wmove(table->tabwin, 0, 0);
wprintw(table->tabwin, sp_buf, ' ');
printethent(table, table->firstvisible, *idx);
if (table->firstvisible->type == 1)
printrates(table, 0, table->firstvisible);
}
}
}
static void pageethwin(struct ethtab *table, int direction, unsigned int *idx)
{
int i = 1;
if (direction == SCROLLUP) {
while ((i <= LINES - 7) && (table->lastvisible != table->tail)) {
i++;
table->firstvisible = table->firstvisible->next_entry;
table->lastvisible = table->lastvisible->next_entry;
(*idx)++;
}
} else {
while ((i <= LINES - 7) && (table->firstvisible != table->head)) {
i++;
table->firstvisible = table->firstvisible->prev_entry;
table->lastvisible = table->lastvisible->prev_entry;
(*idx)--;
}
}
refresh_hostmon_screen(table, *idx);
}
static void show_hostsort_keywin(WINDOW ** win, PANEL ** panel)
{
*win = newwin(13, 35, (LINES - 10) / 2, COLS - 40);
*panel = new_panel(*win);
wattrset(*win, DLGBOXATTR);
tx_colorwin(*win);
tx_box(*win, ACS_VLINE, ACS_HLINE);
wattrset(*win, DLGTEXTATTR);
mvwprintw(*win, 2, 2, "Select sort criterion");
wmove(*win, 4, 2);
tx_printkeyhelp("P", " - total packets in", *win, DLGHIGHATTR,
DLGTEXTATTR);
wmove(*win, 5, 2);
tx_printkeyhelp("I", " - IP packets in", *win, DLGHIGHATTR,
DLGTEXTATTR);
wmove(*win, 6, 2);
tx_printkeyhelp("B", " - total bytes in", *win, DLGHIGHATTR,
DLGTEXTATTR);
wmove(*win, 7, 2);
tx_printkeyhelp("K", " - total packets out", *win, DLGHIGHATTR,
DLGTEXTATTR);
wmove(*win, 8, 2);
tx_printkeyhelp("O", " - IP packets out", *win, DLGHIGHATTR,
DLGTEXTATTR);
wmove(*win, 9, 2);
tx_printkeyhelp("Y", " - total bytes out", *win, DLGHIGHATTR,
DLGTEXTATTR);
wmove(*win, 10, 2);
tx_printkeyhelp("Any other key", " - cancel sort", *win, DLGHIGHATTR,
DLGTEXTATTR);
update_panels();
doupdate();
}
/*
* Swap two host table entries.
*/
static void swaphostents(struct ethtab *list, struct ethtabent *p1,
struct ethtabent *p2)
{
register unsigned int tmp;
struct ethtabent *p1prevsaved;
struct ethtabent *p2nextsaved;
if (p1 == p2)
return;
tmp = p1->index;
p1->index = p2->index;
p2->index = tmp;
p1->next_entry->index = p1->index + 1;
p2->next_entry->index = p2->index + 1;
if (p1->prev_entry != NULL)
p1->prev_entry->next_entry = p2;
else
list->head = p2;
if (p2->next_entry->next_entry != NULL)
p2->next_entry->next_entry->prev_entry = p1->next_entry;
else
list->tail = p1->next_entry;
p2nextsaved = p2->next_entry->next_entry;
p1prevsaved = p1->prev_entry;
if (p1->next_entry->next_entry == p2) {
p2->next_entry->next_entry = p1;
p1->prev_entry = p2->next_entry;
} else {
p2->next_entry->next_entry = p1->next_entry->next_entry;
p1->prev_entry = p2->prev_entry;
p2->prev_entry->next_entry = p1;
p1->next_entry->next_entry->prev_entry = p2->next_entry;
}
p2->prev_entry = p1prevsaved;
p1->next_entry->next_entry = p2nextsaved;
}
static unsigned long long ql_getkey(struct ethtabent *entry, int ch)
{
unsigned long long result = 0;
switch (ch) {
case 'P':
result = entry->next_entry->un.figs.inpcount;
break;
case 'I':
result = entry->next_entry->un.figs.inippcount;
break;
case 'B':
result = entry->next_entry->un.figs.inbcount;
break;
case 'K':
result = entry->next_entry->un.figs.outpcount;
break;
case 'O':
result = entry->next_entry->un.figs.outippcount;
break;
case 'Y':
result = entry->next_entry->un.figs.outbcount;
break;
}
return result;
}
static struct ethtabent *ql_partition(struct ethtab *table,
struct ethtabent **low,
struct ethtabent **high, int ch)
{
struct ethtabent *pivot = *low;
struct ethtabent *left = *low;
struct ethtabent *right = *high;
struct ethtabent *ptmp;
unsigned long long pivot_value;
pivot_value = ql_getkey(pivot, ch);
while (left->index < right->index) {
while ((ql_getkey(left, ch) >= pivot_value)
&& (left->next_entry->next_entry != NULL))
left = left->next_entry->next_entry;
while (ql_getkey(right, ch) < pivot_value)
right = right->prev_entry->prev_entry;
if (left->index < right->index) {
swaphostents(table, left, right);
if (*low == left)
*low = right;
if (*high == right)
*high = left;
ptmp = left;
left = right;
right = ptmp;
}
}
swaphostents(table, pivot, right);
if (*low == pivot)
*low = right;
if (*high == right)
*high = pivot;
return pivot;
}
/*
* Quicksort routine for the LAN station monitor
*/
static void quicksort_lan_entries(struct ethtab *table, struct ethtabent *low,
struct ethtabent *high, int ch)
{
struct ethtabent *pivot;
if ((high == NULL) || (low == NULL))
return;
if (high->index > low->index) {
pivot = ql_partition(table, &low, &high, ch);
if (pivot->prev_entry != NULL)
quicksort_lan_entries(table, low,
pivot->prev_entry->prev_entry,
ch);
quicksort_lan_entries(table, pivot->next_entry->next_entry,
high, ch);
}
}
static void sort_hosttab(struct ethtab *list, unsigned int *idx, int command)
{
struct ethtabent *ptemp1;
int idxtmp;
if (!list->head)
return;
command = toupper(command);
if ((command != 'P') && (command != 'I') && (command != 'B')
&& (command != 'K') && (command != 'O') && (command != 'Y'))
return;
quicksort_lan_entries(list, list->head, list->tail->prev_entry,
command);
ptemp1 = list->firstvisible = list->head;
*idx = 1;
idxtmp = 0;
tx_colorwin(list->tabwin);
while ((ptemp1) && (idxtmp <= LINES - 4)) {
printethent(list, ptemp1, *idx);
idxtmp++;
if (idxtmp <= LINES - 4)
list->lastvisible = ptemp1;
ptemp1 = ptemp1->next_entry;
}
}
/*
* The LAN station monitor
*/
void hostmon(time_t facilitytime, char *ifptr)
{
int logging = options.logging;
struct ethtab table;
struct ethtabent *entry;
char scratch_saddr[ETH_ALEN];
char scratch_daddr[ETH_ALEN];
unsigned int idx = 1;
int is_ip;
int ch;
char *ifname = ifptr;
struct timeval tv;
struct timeval tv_rate;
time_t now = 0;
time_t statbegin = 0;
time_t startlog = 0;
struct timeval updtime;
struct eth_desc *list = NULL;
FILE *logfile = NULL;
int pkt_result;
WINDOW *sortwin;
PANEL *sortpanel;
int keymode = 0;
int fd;
if (ifptr && !dev_up(ifptr)) {
err_iface_down();
return;
}
LIST_HEAD(promisc);
if (options.promisc) {
promisc_init(&promisc, ifptr);
promisc_set_list(&promisc);
}
hostmonhelp();
initethtab(&table);
/* Ethernet description list */
struct eth_desc *elist = load_eth_desc(ARPHRD_ETHER);
/* FDDI description list */
struct eth_desc *flist = load_eth_desc(ARPHRD_FDDI);
if (logging) {
if (strcmp(current_logfile, "") == 0) {
strncpy(current_logfile,
gen_instance_logname(LANLOG, getpid()), 80);
if (!daemonized)
input_logfile(current_logfile, &logging);
}
}
if (logging) {
opentlog(&logfile, current_logfile);
if (logfile == NULL)
logging = 0;
}
if (logging) {
signal(SIGUSR1, rotate_lanlog);
rotate_flag = 0;
writelog(logging, logfile,
"******** LAN traffic monitor started ********");
}
leaveok(table.tabwin, TRUE);
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(fd == -1) {
write_error("Unable to obtain monitoring socket");
goto err;
}
if(ifptr && dev_bind_ifname(fd, ifptr) == -1) {
write_error("Unable to bind interface on the socket");
goto err_close;
}
exitloop = 0;
gettimeofday(&tv, NULL);
tv_rate = tv;
updtime = tv;
statbegin = startlog = tv.tv_sec;
PACKET_INIT(pkt);
do {
gettimeofday(&tv, NULL);
now = tv.tv_sec;
unsigned long msecs = timeval_diff_msec(&tv, &tv_rate);
if (msecs >= 1000) {
printelapsedtime(statbegin, now, LINES - 3, 15,
table.borderwin);
updateethrates(&table, msecs, idx);
tv_rate = tv;
}
if (logging) {
check_rotate_flag(&logfile);
if ((now - startlog) >= options.logspan) {
writeethlog(table.head, now - statbegin,
logfile);
startlog = now;
}
}
if (screen_update_needed(&tv, &updtime)) {
update_panels();
doupdate();
updtime = tv;
}
if ((facilitytime != 0)
&& (((now - statbegin) / 60) >= facilitytime))
exitloop = 1;
if (packet_get(fd, &pkt, &ch, table.tabwin) == -1) {
write_error("Packet receive failed");
exitloop = 1;
break;
}
if (ch != ERR) {
if (keymode == 0) {
switch (ch) {
case KEY_UP:
scrollethwin(&table, SCROLLDOWN, &idx);
break;
case KEY_DOWN:
scrollethwin(&table, SCROLLUP, &idx);
break;
case KEY_PPAGE:
case '-':
pageethwin(&table, SCROLLDOWN, &idx);
break;
case KEY_NPAGE:
case ' ':
pageethwin(&table, SCROLLUP, &idx);
break;
case 12:
case 'l':
case 'L':
tx_refresh_screen();
break;
case 's':
case 'S':
show_hostsort_keywin(&sortwin,
&sortpanel);
keymode = 1;
break;
case 'q':
case 'Q':
case 'x':
case 'X':
case 27:
case 24:
exitloop = 1;
}
} else if (keymode == 1) {
del_panel(sortpanel);
delwin(sortwin);
sort_hosttab(&table, &idx, ch);
keymode = 0;
}
}
if (pkt.pkt_len <= 0)
continue;
char ifnamebuf[IFNAMSIZ];
pkt_result =
packet_process(&pkt, NULL, NULL, NULL,
MATCH_OPPOSITE_USECONFIG,
0);
if (pkt_result != PACKET_OK)
continue;
if (!ifptr) {
/* we're capturing on "All interfaces", */
/* so get the name of the interface */
/* of this packet */
int r = dev_get_ifname(pkt.pkt_ifindex, ifnamebuf);
if (r != 0) {
write_error("Unable to get interface name");
break; /* can't get interface name, get out! */
}
ifname = ifnamebuf;
}
/* get HW addresses */
switch (pkt.pkt_hatype) {
case ARPHRD_ETHER: {
memcpy(scratch_saddr, pkt.ethhdr->h_source, ETH_ALEN);
memcpy(scratch_daddr, pkt.ethhdr->h_dest, ETH_ALEN);
list = elist;
break; }
case ARPHRD_FDDI: {
memcpy(scratch_saddr, pkt.fddihdr->saddr, FDDI_K_ALEN);
memcpy(scratch_daddr, pkt.fddihdr->daddr, FDDI_K_ALEN);
list = flist;
break; }
default:
/* unknown link protocol */
continue;
}
switch(pkt.pkt_protocol) {
case ETH_P_IP:
case ETH_P_IPV6:
is_ip = 1;
break;
default:
is_ip = 0;
break;
}
/* Check source address entry */
entry = in_ethtable(&table, pkt.pkt_hatype,
scratch_saddr);
if (!entry)
entry = addethentry(&table, pkt.pkt_hatype,
ifname, scratch_saddr, list);
if (entry != NULL) {
updateethent(entry, pkt.pkt_len, is_ip, 1);
if (!entry->prev_entry->un.desc.printed)
printethent(&table, entry->prev_entry,
idx);
printethent(&table, entry, idx);
}
/* Check destination address entry */
entry = in_ethtable(&table, pkt.pkt_hatype,
scratch_daddr);
if (!entry)
entry = addethentry(&table, pkt.pkt_hatype,
ifname, scratch_daddr, list);
if (entry != NULL) {
updateethent(entry, pkt.pkt_len, is_ip, 0);
if (!entry->prev_entry->un.desc.printed)
printethent(&table, entry->prev_entry,
idx);
printethent(&table, entry, idx);
}
} while (!exitloop);
err_close:
close(fd);
err:
if (options.promisc) {
promisc_restore_list(&promisc);
promisc_destroy(&promisc);
}
if (logging) {
signal(SIGUSR1, SIG_DFL);
writeethlog(table.head, time(NULL) - statbegin, logfile);
writelog(logging, logfile,
"******** LAN traffic monitor stopped ********");
fclose(logfile);
}
del_panel(table.tabpanel);
delwin(table.tabwin);
del_panel(table.borderpanel);
delwin(table.borderwin);
update_panels();
doupdate();
destroyethtab(&table);
free_eth_desc(elist);
free_eth_desc(flist);
strcpy(current_logfile, "");
}