File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / trafshow / trafshow.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:55:18 2012 UTC (12 years, 3 months ago) by misho
Branches: trafshow, MAIN
CVS tags: v5_2_3p0, v5_2_3, HEAD
trafshow

    1: /*
    2:  *	Copyright (c) 1993-2006 Rinet Corp., Novosibirsk, Russia
    3:  *
    4:  * Redistribution and use in source forms, with and without modification,
    5:  * are permitted provided that this entire comment appears intact.
    6:  *
    7:  * THIS SOURCE CODE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
    8:  */
    9: 
   10: #ifdef	HAVE_CONFIG_H
   11: #include <config.h>
   12: #endif
   13: 
   14: #ifdef	HAVE_SLCURSES
   15: #include <slcurses.h>
   16: #elif	HAVE_NCURSES
   17: #include <ncurses.h>
   18: #else
   19: #include <curses.h>
   20: #endif
   21: #include <sys/types.h>
   22: #include <sys/socket.h>
   23: #ifdef	HAVE_PCAP_GET_SELECTABLE_FD
   24: #include <sys/select.h>
   25: #endif
   26: #include <stdio.h>
   27: #include <stdlib.h>
   28: #include <signal.h>
   29: #include <string.h>
   30: #include <unistd.h>
   31: #include <time.h>
   32: #include <pcap.h>
   33: #include <pthread.h>
   34: #include <errno.h>
   35: #ifdef	linux
   36: #include <sys/ioctl.h>
   37: #include <linux/if.h>
   38: #endif
   39: 
   40: #include "trafshow.h"
   41: #include "parse_dl.h"
   42: #include "screen.h"
   43: #include "show_if.h"
   44: #include "show_stat.h"
   45: #include "show_dump.h"
   46: #include "getkey.h"
   47: #include "selector.h"
   48: #include "addrtoname.h"
   49: #include "netstat.h"
   50: #include "util.h"
   51: #include "events.h"
   52: #include "session.h"
   53: #include "cisco_netflow.h"
   54: #include "help_page.h"
   55: 
   56: char copyright[] = "Copyright (c) 1993-2006 Rinet Corp., Novosibirsk, Russia";
   57: 
   58: static void vers();
   59: static void usage();
   60: static pcap_if_t *pcap_matchdev(pcap_if_t *dp, const char *name);
   61: static int pcap_init(PCAP_HANDLER **ph_list, pcap_if_t *dp);
   62: static void *pcap_feed(void *arg); /* PCAP_HANDLER *ph */
   63: #ifdef	HAVE_PCAP_GET_SELECTABLE_FD
   64: static void *pcap_feed2(void *arg); /* PCAP_HANDLER *ph */
   65: #endif
   66: static void parse_feed(u_char *a, const struct pcap_pkthdr *h, const u_char *p);
   67: static void *traf_show(void *arg); /* PCAP_HANDLER *ph_list */
   68: static void *catch_signals(void *arg); /* sigset_t *set */
   69: static void cleanup(void);
   70: 
   71: static int resize_pending = 0;
   72: 
   73: const char *progname;
   74: const char *hostname;
   75: const char *color_conf = 0;
   76: char *expression = 0;
   77: char *search = 0;
   78: int aggregate = -1;
   79: int popbackflow = 0;
   80: int refresh_time = REFRESH_TIME;
   81: int purge_time = PURGE_TIME;
   82: ShowMode show_mode = Interfaces;
   83: 
   84: int promisc = 1;	/* promiscuous mode */
   85: int Oflag = 1;		/* optimize filter code */
   86: int nflag = 0;		/* use numeric value of service ports and protocols */
   87: 
   88: int
   89: main(argc, argv)
   90: 	int argc;
   91: 	char **argv;
   92: {
   93: 	char buf[256], *dev_name = 0, *filter = 0;
   94: 	pcap_if_t *dev_list = 0;
   95: 	PCAP_HANDLER *ph_list = 0;
   96: 	int op, udp_port = CNF_PORT;
   97: 	sigset_t sigset;
   98: 	pthread_t show_thr, sig_thr, pcap_thr;
   99: 	extern char *optarg;
  100: 	extern int optind, opterr;
  101: 
  102: 	progname = strdup(strip_path(argv[0]));
  103: 
  104: 	if (gethostname(buf, sizeof(buf)) < 0)
  105: 		(void)strcpy(buf, "localhost");
  106: 	hostname = strdup(buf);
  107: 
  108: 	/* get list of all pcap devices */
  109: 	if (pcap_findalldevs(&dev_list, buf) < 0) {
  110: 		fprintf(stderr, "pcap_findalldevs: %s\n", buf);
  111: 		exit(1);
  112: 	}
  113: 
  114: 	opterr = 0;
  115: 	while ((op = getopt(argc, argv, "a:bc:i:ns:u:pF:R:P:vh?")) != EOF) {
  116: 		switch (op) {
  117: 		case 'a':
  118: 			aggregate = atoi(optarg);
  119: 			if (aggregate < 0 || aggregate > ADDRBITLEN)
  120: 				usage();
  121: 			break;
  122: 		case 'b':
  123: 			popbackflow = 1;
  124: 			break;
  125: 		case 'c':
  126: 			color_conf = optarg;
  127: 			break;
  128: 		case 'i':
  129: 			dev_name = optarg;
  130: 			break;
  131: 		case 'n':
  132: 			nflag = 1;
  133: 			break;
  134: 		case 's':
  135: 			search = strdup(optarg);
  136: 			break;
  137: 		case 'u':
  138: 			udp_port = atoi(optarg);
  139: 			break;
  140: 		case 'p':
  141: 			promisc = 0;
  142: 			break;
  143: 		case 'F':
  144: 			filter = optarg;
  145: 			break;
  146: 		case 'R':
  147: 			if ((refresh_time = atoi(optarg)) < 1)
  148: 				usage();
  149: 			break;
  150: 		case 'P':
  151: 			if ((purge_time = atoi(optarg)) < 1)
  152: 				usage();
  153: 			break;
  154: 		case 'v':
  155: 			vers();
  156: 		case 'h':
  157: 		case '?':
  158: 		default:
  159: 			usage();
  160: 		}
  161: 	}
  162: 
  163: 	/* check for command line options */
  164: 	if (dev_name && (dev_list = pcap_matchdev(dev_list, dev_name)) == 0) {
  165: 		fprintf(stderr, "Interface %s not found\n", dev_name);
  166: 		exit(1);
  167: 	}
  168: 	if (refresh_time >= purge_time) {
  169: 		fprintf(stderr, "Refresh Time (%d sec) must be less than Purge Time (%d sec)\n",
  170: 			refresh_time, purge_time);
  171: 		exit(1);
  172: 	}
  173: 
  174: 	/* initialize list of pcap handlers */
  175: 	if ((op = pcap_init(&ph_list, dev_list)) < 1) {
  176: 		fprintf(stderr, "No packet capture device available (no permission?)\n");
  177: 		exit(1);
  178: 	}
  179: 
  180: 	/* listen for cisco netflow */
  181: 	if (udp_port > 1 && (cisco_netflow_init(&ph_list, udp_port) < 0)) {
  182: 		fprintf(stderr, "Can't start cisco-netflow collector at UDP port %d\n",
  183: 			udp_port);
  184: 		exit(1);
  185: 	}
  186: 
  187: 	/* if only one interface -- make it selected */
  188: 	if (ph_list && op == 1) {
  189: 		ph_list->selected = 1;
  190: 		show_mode = NetStat;
  191: 	}
  192: 
  193: 	/* get back to user process */
  194: 	setuid(getuid());
  195: 
  196: 	/* set the filter expression if any */
  197: 	if (ph_list && (argv[optind] || filter)) {
  198: 		if (filter)
  199: 			expression = load_file(filter);
  200: 		else	expression = copy_argv(&argv[optind]);
  201: 		if (!expression) exit(1);
  202: 
  203: 		if ((filter = pcap_setexpr(ph_list, expression)) != 0) {
  204: 			fprintf(stderr, "%s\n", filter);
  205: 			exit(1);
  206: 		}
  207: 	}
  208: 
  209: 	/* intialize addrtoname stuff */
  210: 	init_addrtoname();
  211: 
  212: 	/* initialize curses */
  213: 	if (screen_open(0) < 0)
  214: 		exit(1);
  215: 
  216: 	/* register cleanup function at exit */
  217: 	atexit(cleanup);
  218: 
  219: 	show_thr = pthread_self();
  220: 
  221: 	/* spawn thread to catch some usefull signals */
  222: 	sigemptyset(&sigset);
  223: 	sigaddset(&sigset, SIGWINCH);
  224: 	sigprocmask(SIG_BLOCK, &sigset, 0);
  225: 	if (pthread_create(&sig_thr, 0, catch_signals, &sigset)) {
  226: 		perror("pthread_create(catch_signals)");
  227: 		exit(1);
  228: 	}
  229: 
  230: 	/* spawn thread for the live packet capture */
  231: 	if (ph_list) {
  232: #ifdef	HAVE_PCAP_GET_SELECTABLE_FD
  233: 		PCAP_HANDLER *ph;
  234: 		for (ph = ph_list; ph; ph = ph->next) {
  235: 			if (pcap_get_selectable_fd(ph->pcap) < 0)
  236: 				break;
  237: 		}
  238: 		if (!ph) {
  239: 			if (pthread_create(&pcap_thr, 0, pcap_feed2, ph_list)) {
  240: 				perror("pthread_create(pcap_feed2)");
  241: 				exit(1);
  242: 			}
  243: 		} else
  244: #endif
  245: 		if (pthread_create(&pcap_thr, 0, pcap_feed, ph_list)) {
  246: 			perror("pthread_create(pcap_feed)");
  247: 			exit(1);
  248: 		}
  249: 	}
  250: 
  251: 	/* start main loop */
  252: 	(void)traf_show(ph_list);
  253: 
  254: 	exit(0);
  255: }
  256: 
  257: static void
  258: cleanup()
  259: {
  260: 	if (dump_file) (void)unlink(dump_file);
  261: 	screen_close();
  262: 	_exit(0);
  263: }
  264: 
  265: static void *
  266: catch_signals(arg)
  267: 	void *arg;
  268: {
  269: 	sigset_t sigset;
  270: 	int sig;
  271: 
  272: 	for (;;) {
  273: 		sigset = *(sigset_t *)arg;
  274: 		if (sigwait(&sigset, &sig))
  275: 			break; /* should not happen */
  276: 
  277: 		if (sig == SIGWINCH)
  278: 			resize_pending++;
  279: 	}
  280: 	return 0;
  281: }
  282: 
  283: static pcap_if_t *
  284: pcap_matchdev(dp, name)
  285: 	pcap_if_t *dp;
  286: 	const char *name;
  287: {
  288: 	for (; dp; dp = dp->next) {
  289: 		if (!strcasecmp(dp->name, "any"))
  290: 			continue; /* discard linux's any device silently */
  291: 
  292: 		if (!strcasecmp(dp->name, name)) {
  293: 			dp->next = 0;
  294: 			return dp;
  295: 		}
  296: 	}
  297: 	return 0;
  298: }
  299: 
  300: static int
  301: pcap_init(ph_list, dp)
  302: 	PCAP_HANDLER **ph_list;
  303: 	pcap_if_t *dp;
  304: {
  305: 	int cnt = 0, err = 0, type;
  306: 	pcap_t *pd;
  307: 	const pcap_addr_t *ap;
  308: 	PCAP_HANDLER *ph, *ph_prev = 0;
  309: 	char *cp, buf[256];
  310: 
  311: 	if (!ph_list) return -1;
  312: 
  313: 	for (; dp; dp = dp->next) {
  314: 		if (!strcasecmp(dp->name, "any"))
  315: 			continue; /* discard linux's any device silently */
  316: 
  317: 		buf[0] = '\0';
  318: 		if ((pd = pcap_open_live(dp->name, SNAPLEN, promisc, 1, buf)) == 0) {
  319: 			fprintf(stderr, "%s: %s\n", dp->name, buf);
  320: 			err++;
  321: 			continue;
  322: 		}
  323: 		type = pcap_datalink(pd);
  324: 		if (!is_parse_dl(type)) {
  325: 			fprintf(stderr, "%s: datalink type %d is not supported\n",
  326: 				dp->name, type);
  327: 			pcap_close(pd);
  328: 			err++;
  329: 			continue;
  330: 		}
  331: 		if (buf[0] != '\0') {
  332: 			fprintf(stderr, "%s: %s\n", dp->name, buf);
  333: 			err++;
  334: 		}
  335: 		if (pcap_setnonblock(pd, 1, buf) < 0) {
  336: 			fprintf(stderr, "%s: %s\n", dp->name, buf);
  337: 			pcap_close(pd);
  338: 			err++;
  339: 			continue;
  340: 		}
  341: 		if ((ph = (PCAP_HANDLER *)malloc(sizeof(PCAP_HANDLER))) == 0) {
  342: 			perror("malloc");
  343: 			exit(1);
  344: 		}
  345: 		memset(ph, 0, sizeof(PCAP_HANDLER));
  346: 
  347: 		ph->masklen = aggregate;
  348: 		ph->name = strdup(dp->name);
  349: 		if (dp->description && *dp->description)
  350: 			ph->descr = strdup(dp->description);
  351: 		else if (dp->flags & PCAP_IF_LOOPBACK)
  352: 			ph->descr = strdup("Loopback");
  353: 		else	ph->descr = strdup(parse_dl_name(type));
  354: 		ph->pcap = pd;
  355: 		ph->addr = dp->addresses; /* XXX must be deep copy? */
  356: 
  357: 		/* make string of network address list */
  358: 		buf[0] = '\0';
  359: 		cp = buf;
  360: #ifdef  linux
  361: 		if (type == DLT_EN10MB && (dp->flags & PCAP_IF_LOOPBACK) == 0) {
  362: 			int sfd = socket(AF_INET, SOCK_DGRAM, 0);
  363: 			if (sfd != -1) {
  364: 				struct ifreq ifr;
  365: 				memset(&ifr, 0, sizeof(struct ifreq));
  366: 				memcpy(ifr.ifr_name, dp->name,
  367: 				       MIN(strlen(dp->name), sizeof(ifr.ifr_name)-1));
  368: 				if (ioctl(sfd, SIOCGIFHWADDR, &ifr) != -1) {
  369: 					(void)strcpy(cp, linkaddr_string((u_char *)ifr.ifr_hwaddr.sa_data,
  370: 									 ETHER_ADDR_LEN));
  371: 					cp += strlen(cp);
  372: 				}
  373: 				close(sfd);
  374: 			}
  375: 		}
  376: #endif
  377: 		for (ap = dp->addresses; ap && cp < (buf + sizeof(buf)-1);
  378: 		     ap = ap->next) {
  379: 			if (buf[0]) {
  380: 				*cp++ = ' ';
  381: 				*cp = '\0';
  382: 			}
  383: 			if (satoa(ap->addr, cp, (buf + sizeof(buf)) - cp))
  384: 				cp += strlen(cp);
  385: 		}
  386: 		*cp = '\0';
  387: 		ph->addrstr = strdup(buf);
  388: 
  389: 		if ((ph->ns_mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t))) == 0) {
  390: 			perror("malloc");
  391: 			exit(1);
  392: 		}
  393: 		pthread_mutex_init(ph->ns_mutex, 0);
  394: 
  395: 		ph->prev = ph_prev;
  396: 		if (ph_prev)
  397: 			ph_prev->next = ph;
  398: 		else	*ph_list = ph;
  399: 		ph_prev = ph;
  400: 
  401: 		cnt++;
  402: 	}
  403: 	if (cnt && err) {
  404: 		fflush(stderr);
  405: 		sleep(1);
  406: 	}
  407: 	return cnt;
  408: }
  409: 
  410: PCAP_HANDLER *
  411: pcaph_create(top, nh)
  412: 	PCAP_HANDLER *top;
  413: 	const struct netstat_header *nh;
  414: {
  415: 	PCAP_HANDLER *ph;
  416: 
  417: 	/* sanity check */
  418: 	if (!top || top->masklen < 0 || !nh)
  419: 		return 0;
  420: 
  421: 	if ((ph = (PCAP_HANDLER *)malloc(sizeof(PCAP_HANDLER))) == 0)
  422: 		return 0;
  423: 	memset(ph, 0, sizeof(PCAP_HANDLER));
  424: 
  425: 	ph->masklen = -1;
  426: 	ph->maskhdr = (struct netstat_header *)malloc(sizeof(struct netstat_header));
  427: 	if (!ph->maskhdr) return 0;
  428: 	memcpy(ph->maskhdr, nh, sizeof(struct netstat_header));
  429: 	netstat_aggregate(ph->maskhdr, top->masklen);
  430: 
  431: 	if ((ph->ns_mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t))) == 0) {
  432: 		free(ph->maskhdr);
  433: 		return 0;
  434: 	}
  435: 	pthread_mutex_init(ph->ns_mutex, 0);
  436: 
  437: 	ph->name = top->name;
  438: 	ph->descr = top->descr;
  439: 	ph->pcap = top->pcap;
  440: 	ph->selected = 1;
  441: 
  442: 	ph->top = top;
  443: 	top->deep = ph;
  444: 	return ph;
  445: }
  446: 
  447: void
  448: pcaph_close(ph)
  449: 	PCAP_HANDLER *ph;
  450: {
  451: 	/* sanity check */
  452: 	if (!ph || !ph->top) return;
  453: 
  454: 	ph->top->deep = 0;
  455: 	if (ph->deep) pcaph_close(ph->deep); /* recursion */
  456: 
  457: 	netstat_free(ph);
  458: 	if (ph->ns_mutex) {
  459: 		pthread_mutex_destroy(ph->ns_mutex);
  460: 		free(ph->ns_mutex);
  461: 		ph->ns_mutex = 0;
  462: 	}
  463: 	remove_event(0, ph);
  464: 	if (ph->maskhdr) free(ph->maskhdr);
  465: 	if (ph->selector) {
  466: 		if (ph->selector->list)
  467: 			free(ph->selector->list);
  468: 		free(ph->selector);
  469: 	}
  470: 	free(ph);
  471: }
  472: 
  473: char *
  474: pcap_setexpr(ph, expr)
  475: 	PCAP_HANDLER *ph;
  476: 	const char *expr;
  477: {
  478: 	int op;
  479: 	struct bpf_program filter;
  480: 	bpf_u_int32 net;
  481: 	bpf_u_int32 mask;
  482: 	char name[100], buf[256];
  483: 
  484: 	if (!expr) return 0;
  485: 
  486: 	for (; ph; ph = ph->next) {
  487: 		if (!ph->pcap) /* skip non-pcap devices */
  488: 			continue;
  489: 
  490: 		if (pcap_lookupnet(strcpy(name, ph->name), &net, &mask, buf) < 0) {
  491: 			/* ignore error */
  492: 			net = 0;
  493: 			mask = 0;
  494: 		}
  495: 
  496: 		(void)strncpy(buf, expr, sizeof(buf));
  497: 		buf[sizeof(buf)-1] = '\0';
  498: 		if (pcap_compile(ph->pcap, &filter, buf, Oflag, mask) < 0)
  499: 			return pcap_geterr(ph->pcap);
  500: 
  501: 		op = pcap_setfilter(ph->pcap, &filter);
  502: 		pcap_freecode(&filter);
  503: 		if (op < 0) return pcap_geterr(ph->pcap);
  504: 	}
  505: 	return 0;
  506: }
  507: 
  508: static void *
  509: pcap_feed(arg)
  510: 	void *arg;
  511: {
  512: 	PCAP_HANDLER *ph, *ph_list = (PCAP_HANDLER *)arg;
  513: 	int npkt = -1, ndev, op;
  514: 
  515: 	do {
  516: 		if (!npkt) usleep(1000); /* 1ms idle to prevent deadloop */
  517: 		npkt = 0;
  518: 		ndev = 0;
  519: 		for (ph = ph_list; ph; ph = ph->next) {
  520: 			if (!ph->pcap) /* skip non-pcap devices */
  521: 				continue;
  522: 			op = pcap_dispatch(ph->pcap, -1, parse_feed, (u_char *)ph);
  523: 
  524: 			if (op > 0) {
  525: 				npkt += op;
  526: 			} else if (op == -2 || (op == -1 && errno != EAGAIN)) {
  527: 				pcap_close(ph->pcap);
  528: 				ph->pcap = 0;
  529: 				continue;
  530: 			}
  531: 			ndev++;
  532: 		}
  533: 	} while (ndev);
  534: 
  535: 	return 0;
  536: }
  537: 
  538: #ifdef	HAVE_PCAP_GET_SELECTABLE_FD
  539: static void *
  540: pcap_feed2(arg)
  541: 	void *arg;
  542: {
  543: 	PCAP_HANDLER *ph, *ph_list = (PCAP_HANDLER *)arg;
  544: 	int npkt = -1, ndev, op;
  545: 	fd_set readfds;
  546: 
  547: 	for (;;) {
  548: #ifdef	notdef
  549: 		if (!npkt) usleep(1000); /* 1ms idle to prevent deadloop */
  550: #endif
  551: 		npkt = 0;
  552: 		ndev = 0;
  553: 		FD_ZERO(&readfds);
  554: 		for (ph = ph_list; ph; ph = ph->next) {
  555: 			if (!ph->pcap) /* skip non-pcap devices */
  556: 				continue;
  557: 			op = pcap_get_selectable_fd(ph->pcap);
  558: 			if (op < 0) /* should not happen */
  559: 				continue;
  560: 			if (op + 1 > ndev)
  561: 				ndev = op + 1;
  562: 			FD_SET(op, &readfds);
  563: 		}
  564: 		if (ndev < 1) /* no one device fd for selecting? */
  565: 			break;
  566: 
  567: 		if ((op = select(ndev, &readfds, 0, 0, 0)) < 0) {
  568: 			if (errno == EINTR || errno == EAGAIN)
  569: 				continue;
  570: 			/* select error? */
  571: 			break;
  572: 		}
  573: 		if (!op) /* select timed out, try again */
  574: 			continue;
  575: 		for (ph = ph_list; ph; ph = ph->next) {
  576: 			if (!ph->pcap) /* skip non-pcap devices */
  577: 				continue;
  578: #ifdef	notdef
  579: 			if (!FD_ISSET(pcap_get_selectable_fd(ph->pcap), &readfds))
  580: 				continue; /* skip silent devices */
  581: #endif
  582: 			op = pcap_dispatch(ph->pcap, -1, parse_feed, (u_char *)ph);
  583: 			if (op > 0) {
  584: 				npkt += op;
  585: 			} else if (op == -2 || (op == -1 && errno != EAGAIN)) {
  586: 				pcap_close(ph->pcap);
  587: 				ph->pcap = 0;
  588: 			}
  589: 		}
  590: 	}
  591: 	return 0;
  592: }
  593: #endif
  594: 
  595: static void
  596: parse_feed(a, h, p)
  597: 	u_char *a;
  598: 	const struct pcap_pkthdr *h;
  599: 	const u_char *p;
  600: {
  601: 	PCAP_HANDLER *ph = (PCAP_HANDLER *)a;
  602: 	NETSTAT ns;
  603: 
  604: 	/* sanity check */
  605: 	if (!ph || !ph->pcap) return;
  606: 
  607: 	/*ph->pcap_time = h->ts;*/
  608: 	memset(&ns, 0, sizeof(NETSTAT));
  609: 
  610: 	if (parse_dl(&ns, pcap_datalink(ph->pcap), h->caplen, h->len, p) < 0)
  611: 		return;
  612: 
  613: 	ns.mtime = h->ts;
  614: 	pcap_save(ph, &ns);
  615: }
  616: 
  617: void
  618: pcap_save(ph, ns)
  619: 	PCAP_HANDLER *ph;
  620: 	const NETSTAT *ns;
  621: {
  622: 	int num;
  623: 	struct netstat_header nh;
  624: 
  625: 	/* sanity check */
  626: 	if (!ph || !ns) return;
  627: 
  628: 	if (netstat_insert(ph, ns) && aggregate < 0) {
  629: 		num = netstat_count(ph);
  630: 		if (num > 5000) {
  631: 			if (ph->masklen)
  632: 				ph->masklen = 0;
  633: 		} else if (num > 1000) {
  634: 			if (ph->masklen < 0 || ph->masklen > 16)
  635: 				ph->masklen = 16;
  636: 		} else if (num > 250) {
  637: 			if (ph->masklen < 0 || ph->masklen > 24)
  638: 				ph->masklen = 24;
  639: 		}
  640: 	}
  641: 	while (ph->deep) {
  642: 		num = ph->masklen;
  643: 		ph = ph->deep;
  644: 		if (!ph->maskhdr) /* should not happen */
  645: 			continue;
  646: 		memcpy(&nh, &ns->ns_hdr, sizeof(struct netstat_header));
  647: 		netstat_aggregate(&nh, num);
  648: 		if (!memcmp(&nh, ph->maskhdr, sizeof(struct netstat_header)))
  649: 			netstat_insert(ph, ns);
  650: 	}
  651: }
  652: 
  653: void
  654: pcap_show(arg)
  655: 	void *arg;
  656: {
  657: 	PCAP_HANDLER *ph = (PCAP_HANDLER *)arg;
  658: 	SELECTOR *sp;
  659: 	int idx;
  660: 	struct timeval now;
  661: 
  662: 	gettimeofday(&now, 0);
  663: 
  664: 	switch (show_mode) {
  665: 	case Interfaces:
  666: 		sp = show_if_list(ph);
  667: 		if (search && (idx = show_if_search(ph, search)) != -1)
  668: 			selector_set(idx, sp);
  669: 		selector_redraw(sp);
  670: 		break;
  671: 	case NetStat:
  672: 		ph = pcap_get_selected(ph);
  673: 		sp = show_stat_list(ph);
  674: 		if (search && (idx = show_stat_search(ph, search)) != -1)
  675: 			selector_set(idx, sp);
  676: 		selector_redraw(sp);
  677: 		break;
  678: 	case FlowDump:
  679: 		show_dump_print(pcap_get_selected(ph));
  680: 		break;
  681: 	case HelpPage:
  682: #ifdef	notdef
  683: 		/* overlapping is not good idea -- too flicker */
  684: 		show_mode = help_page_mode();
  685: 		if (show_mode != HelpPage) { /* just for sanity */
  686: 			pcap_show(arg);
  687: 			show_mode = HelpPage;
  688: 		}
  689: #endif
  690: 		selector_redraw(help_page_selector());
  691: 		break;
  692: 	}
  693: 
  694: 	/* schedule next time */
  695: 	now.tv_sec += refresh_time;
  696: 	add_event(&now, pcap_show, arg);
  697: }
  698: 
  699: void
  700: pcap_purge(arg)
  701: 	void *arg;
  702: {
  703: 	PCAP_HANDLER *ph = (PCAP_HANDLER *)arg, *p;
  704: 	struct timeval now;
  705: 
  706: 	gettimeofday(&now, 0);
  707: 	now.tv_sec -= purge_time;
  708: 
  709: 	for (; ph; ph = ph->next) {
  710: 		for (p = ph; p; p = p->deep)
  711: 			netstat_purge(p, &now);
  712: 	}
  713: 	/* schedule next time */
  714: 	now.tv_sec += purge_time * 2;
  715: 	add_event(&now, pcap_purge, arg);
  716: 
  717: 	pcap_show(arg);
  718: }
  719: 
  720: void
  721: pcap_clear(arg)
  722: 	void *arg;
  723: {
  724: 	PCAP_HANDLER *ph = (PCAP_HANDLER *)arg, *p;
  725: 
  726: 	for (; ph; ph = ph->next) {
  727: 		for (p = ph; p; p = p->deep)
  728: 			netstat_purge(p, 0);
  729: 	}
  730: 	pcap_show(arg);
  731: }
  732: 
  733: PCAP_HANDLER *
  734: pcap_get_selected(ph)
  735: 	PCAP_HANDLER *ph;
  736: {
  737: 	for (; ph; ph = ph->next) {
  738: 		if (ph->selected) {
  739: 			while (ph->deep) ph = ph->deep;
  740: 			return ph;
  741: 		}
  742: 	}
  743: 	return 0;
  744: }
  745: 
  746: PCAP_HANDLER *
  747: pcap_set_selected(ph, idx)
  748: 	PCAP_HANDLER *ph;
  749: 	int idx;
  750: {
  751: 	PCAP_HANDLER *sel = 0;
  752: 	int i = 0;
  753: 
  754: 	for (; ph; ph = ph->next) {
  755: 		if (i++ == idx) {
  756: 			sel = ph;
  757: 			ph->selected = 1;
  758: 		} else	ph->selected = 0;
  759: 	}
  760: 	return sel;
  761: }
  762: 
  763: static void *
  764: traf_show(arg)
  765: 	void *arg;
  766: {
  767: 	PCAP_HANDLER *ph_list = (PCAP_HANDLER *)arg;
  768: 	int op, nfds;
  769: 	fd_set readfds, writefds;
  770: 	struct timeval timeout;
  771: 
  772: 	/* start show */
  773: 	pcap_purge(ph_list);
  774: 
  775: 	/* init keyboard functions */
  776: 	getkey_init(ph_list);
  777: 
  778: 	for (;;) {
  779: 		if (resize_pending) {
  780: 			if (screen_open(resize_pending) < 0)
  781: 				return 0;
  782: 			add_event(0, pcap_show, ph_list);
  783: 			resize_pending = 0;
  784: 		}
  785: 		nfds = 0;
  786: 		FD_ZERO(&readfds);
  787: 		FD_ZERO(&writefds);
  788: 		op = select_event(&timeout);
  789: 		if (!session_select(&nfds, &readfds, &writefds, &timeout, &op)) {
  790: 			/* no one active session?? should not happen */
  791: 			return 0;
  792: 		}
  793: 		op = select(nfds, &readfds, &writefds, 0, op ? 0 : &timeout);
  794: 		if (op < 1) { /* select interrupted by signals or timed out */
  795: 			if (op < 0) {
  796: 				if (errno == EINTR || errno == EAGAIN)
  797: 					continue;
  798: 				screen_status("select: %s", strerror(errno));
  799: 				return 0;
  800: 			} else	session_timeout();
  801: 		} else	session_operate(&readfds, &writefds);
  802: 	}
  803: 
  804: 	/* NOT REACHED */
  805: 	return 0;
  806: }
  807: 
  808: static void
  809: vers()
  810: {
  811: 	extern char pcap_version[];
  812: 
  813: 	int hc = 0;
  814: #ifdef  HAVE_HAS_COLORS
  815: 	initscr();
  816: 	hc = has_colors();
  817: 	endwin();
  818: #endif	/* HAVE_HAS_COLORS */
  819: 
  820: 	fprintf(stderr, "\n%s Version %s\ncompiled for %s with\n %s\n",
  821: 		progname, version, target, compiled);
  822: 
  823: 	fprintf(stderr, "\tlibpcap version %s\n", pcap_version);
  824: 
  825: #ifdef	HAVE_SLCURSES
  826: 	fprintf(stderr, "\tslcurses version %d\n", SLang_Version);
  827: #elif	HAVE_NCURSES
  828: #ifdef	NCURSES_VERSION
  829: 	fprintf(stderr, "\tncurses version %s\n", NCURSES_VERSION);
  830: #else
  831: 	fprintf(stderr, "\tncurses version unknown\n");
  832: #endif	/* NCURSES_VERSION */
  833: #elif	HAVE_CURSES
  834: 	fprintf(stderr, "\tunknown curses library\n");
  835: #endif	/* HAVE_SLCURSES */
  836: 
  837: #ifdef	HAVE_HAS_COLORS
  838: 	fprintf(stderr, "\tcolors support\n");
  839: 	if (hc) fprintf(stderr, "\tyour current terminal has color capability\n");
  840: #ifndef	HAVE_SLCURSES
  841: 	else fprintf(stderr, "\tyour current terminal has no color capability\n");
  842: #endif
  843: #else
  844: 	fprintf(stderr, "\tno colors support\n");
  845: #endif	/* HAVE_HAS_COLORS */
  846: 
  847: 	fprintf(stderr, "\n%s\n", copyright);
  848: 	fprintf(stderr,"For bug report please email to trafshow@risp.ru (include this page)\n\n");
  849: 
  850: 	exit(1);
  851: }
  852: 
  853: static void
  854: usage()
  855: {
  856: 	fprintf(stderr,
  857: "Usage:\n\
  858:  %s [-vpnb] [-a len] [-c conf] [-i ifname] [-s str] [-u port] [-R refresh] [-P purge] [-F file | expr]\n\
  859: Where:\n\
  860:  -v         Print version number, compile-time definitions, and exit\n\
  861:  -p         Don't put the interface(s) into promiscuous mode\n\
  862:  -n         Don't convert numeric values to names\n\
  863:  -b         To place a backflow near to the main stream\n\
  864:  -a len     To aggregate IP addresses using the prefix length\n\
  865:  -c conf    Color config file instead of default /etc/trafshow\n\
  866:  -i ifname  Network interface name; all by default\n\
  867:  -s str     To search & follow for string in the list show\n\
  868:  -u port    UDP port number to listen for Cisco Netflow; default %d\n\
  869:  -R refresh Set the refresh-period of data show to seconds; default %d sec\n\
  870:  -P purge   Set the expired data purge-period to seconds; default %d sec\n\
  871:  -F file    Use file as input for the filter expression\n\
  872:  expr       Filter expression; see tcpdump(1) for syntax\n\
  873: 		\n", progname, CNF_PORT, REFRESH_TIME, PURGE_TIME);
  874: 
  875: 	exit(1);
  876: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>