Annotation of embedaddon/trafshow/trafshow.c, revision 1.1.1.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>
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>