Annotation of embedaddon/trafshow/trafshow.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>