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