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>