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>