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