Annotation of embedaddon/trafshow/show_stat.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     Copyright (c) 1998,2004 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: #include <sys/param.h>
                     15: #include <sys/types.h>
                     16: #include <sys/socket.h>
                     17: #include <netinet/in.h>
                     18: #include <arpa/inet.h>
                     19: #include <stdio.h>
                     20: #include <stdlib.h>
                     21: #include <string.h>
                     22: 
                     23: #include "show_stat.h"
                     24: #include "trafshow.h"
                     25: #include "screen.h"
                     26: #include "selector.h"
                     27: #include "netstat.h"
                     28: #include "getkey.h"
                     29: #include "addrtoname.h"
                     30: 
                     31: ShowStatMode show_stat_mode = Size;
                     32: static int find_backflow(NETSTAT **list, int items, NETSTAT *at);
                     33: static void sort_backflow(NETSTAT **list, int items);
                     34: 
                     35: static void
                     36: scale_size(addr, prot, data, rate)
                     37:        int *addr, *prot, *data, *rate;
                     38: {
                     39:        *addr   = line_factor * (double)SHOW_STAT_ADDR;
                     40:        *prot   = line_factor * (double)SHOW_STAT_PROT;
                     41:        *data   = line_factor * (double)SHOW_STAT_DATA;
                     42:        *rate   = line_factor * (double)SHOW_STAT_RATE;
                     43: }
                     44: 
                     45: static int
                     46: compare_pkt_len(p1, p2)
                     47:        register const NETSTAT **p1, **p2;
                     48: {
                     49:        if ((*p1)->pkt_len > (*p2)->pkt_len) return -1;
                     50:        if ((*p1)->pkt_len < (*p2)->pkt_len) return 1;
                     51:        return 0;
                     52: }
                     53: 
                     54: static int
                     55: compare_data_len(p1, p2)
                     56:        register const NETSTAT **p1, **p2;
                     57: {
                     58:        if ((*p1)->data_len > (*p2)->data_len) return -1;
                     59:        if ((*p1)->data_len < (*p2)->data_len) return 1;
                     60:        return 0;
                     61: }
                     62: 
                     63: static int
                     64: compare_pkt_cnt(p1, p2)
                     65:        register const NETSTAT **p1, **p2;
                     66: {
                     67:        if ((*p1)->pkt_cnt > (*p2)->pkt_cnt) return -1;
                     68:        if ((*p1)->pkt_cnt < (*p2)->pkt_cnt) return 1;
                     69:        return 0;
                     70: }
                     71: 
                     72: static int
                     73: find_backflow(list, items, at)
                     74:        NETSTAT **list;
                     75:        int items;
                     76:        NETSTAT *at;
                     77: {
                     78:        int i;
                     79: 
                     80:        /* sanity check */
                     81:        if (!list || items < 1 || !at)
                     82:                return -1;
                     83: 
                     84:        for (i = 0; i < items; i++) {
                     85:                if (netstat_bidir(at, list[i]))
                     86:                        return i;
                     87:        }
                     88:        return -1;
                     89: }
                     90: 
                     91: /* too bad implementation -- it take alot of CPU cycles like deadloop. XXX */
                     92: static void
                     93: sort_backflow(list, items)
                     94:        NETSTAT **list;
                     95:        int items;
                     96: {
                     97:        int i = 0, at;
                     98:        NETSTAT *ns;
                     99: 
                    100:        while (i < items-1) {
                    101:                ns = list[i++];
                    102:                if ((at = find_backflow(&list[i], items - i, ns)) < 0)
                    103:                        continue;
                    104:                if (at) {
                    105:                        ns = list[i + at];
                    106:                        memmove(&list[i + 1], &list[i], at * sizeof(NETSTAT *));
                    107:                        list[i] = ns;
                    108:                }
                    109:                i++;
                    110:        }
                    111: }
                    112: 
                    113: /*
                    114:  * Pretty print an Internet address (net address + port).
                    115:  */
                    116: static char *
                    117: ip_print(ver, proto, addr, dst, size)
                    118:        int ver;
                    119:        int proto;
                    120:        const struct ip_address *addr;
                    121:        char *dst;
                    122:        int size;
                    123: {
                    124:        const char *cp = 0;
                    125:        char buf[100];
                    126: 
                    127:        if (ver == 4 && addr->ip_addr.s_addr) {
                    128:                /*cp = intoa(addr->ip_addr.s_addr);*/
                    129:                cp = ipaddr_string(&addr->ip_addr);
                    130:        }
                    131: #ifdef INET6
                    132:        else if (ver == 6 && !IN6_IS_ADDR_UNSPECIFIED(&addr->ip6_addr)) {
                    133:                /*cp = inet_ntop(AF_INET6, &addr->ip6_addr, buf, sizeof(buf));*/
                    134:                cp = ip6addr_string(&addr->ip6_addr);
                    135:        }
                    136: #endif
                    137: 
                    138:        if (cp) {
                    139:                (void)strncpy(dst, cp, size);
                    140:                dst[size-1] = '\0';
                    141:        } else  snprintf(dst, size, "IPv%d", ver);
                    142: 
                    143:        if (addr->ip_port) {
                    144:                char pb[20];
                    145:                int len;
                    146:                switch (proto) {
                    147:                case IPPROTO_TCP:
                    148:                        if (nflag) {
                    149:                                sprintf(pb, "%d", ntohs(addr->ip_port));
                    150:                                cp = pb;
                    151:                        } else  cp = tcpport_string(ntohs(addr->ip_port));
                    152:                        break;
                    153:                case IPPROTO_UDP:
                    154:                        if (nflag) {
                    155:                                sprintf(pb, "%d", ntohs(addr->ip_port));
                    156:                                cp = pb;
                    157:                        } else  cp = udpport_string(ntohs(addr->ip_port));
                    158:                        break;
                    159:                case IPPROTO_ICMP:
                    160:                        if (nflag) {
                    161:                                sprintf(pb, "%04x", addr->ip_port - 1);
                    162:                                cp = pb;
                    163:                        } else  cp = icmp_string(addr->ip_port - 1);
                    164:                        break;
                    165: #ifdef INET6
                    166:                case IPPROTO_ICMPV6:
                    167:                        if (nflag) {
                    168:                                sprintf(pb, "%04x", addr->ip_port - 1);
                    169:                                cp = pb;
                    170:                        } else  cp = icmpv6_string(addr->ip_port - 1);
                    171:                        break;
                    172: #endif
                    173:                default: /* nonsense, but be strong */
                    174:                        sprintf(pb, "%d", ntohs(addr->ip_port));
                    175:                        cp = pb;
                    176:                }
                    177:                buf[0] = ',';
                    178:                (void)strncpy(&buf[1], cp, 10);
                    179:                buf[11] = '\0';
                    180:                len = strlen(buf);
                    181:                if (strlen(dst) + len < size)
                    182:                        (void)strcat(dst, buf);
                    183:                else    (void)strcpy(&dst[size - len - 1], buf);
                    184:        }
                    185:        return dst;
                    186: }
                    187: 
                    188: static char *
                    189: sap_print(addr, sap, dst, size)
                    190:        const u_char *addr;
                    191:        u_char sap;
                    192:        char *dst;
                    193:        int size;
                    194: {
                    195:        char buf[20];
                    196:        int len;
                    197: 
                    198:        (void)strncpy(dst, etheraddr_string(addr), size);
                    199:        dst[size-1] = '\0';
                    200: 
                    201:        buf[0] = '/';
                    202:        if (nflag)
                    203:                sprintf(&buf[1], "sap-%02x", sap & 0xff);
                    204:        else    (void)strncpy(&buf[1], llcsap_string(sap), 10);
                    205:        buf[11] = '\0';
                    206:        len = strlen(buf);
                    207:        if (strlen(dst) + len < size)
                    208:                (void)strcat(dst, buf);
                    209:        else    (void)strcpy(&dst[size - len - 1], buf);
                    210:        return dst;
                    211: }
                    212: 
                    213: void
                    214: hdr2str(nh, src_buf, src_len, dst_buf, dst_len, proto_buf, proto_len)
                    215:        const struct netstat_header *nh;
                    216:        char *src_buf, *dst_buf, *proto_buf;
                    217:        int src_len, dst_len, proto_len;
                    218: {
                    219:        const NETSTAT *ns;
                    220: 
                    221:        if (src_buf) *src_buf = '\0';
                    222:        if (dst_buf) *dst_buf = '\0';
                    223:        if (proto_buf) *proto_buf = '\0';
                    224: 
                    225:        /* sanity check */
                    226:        if (!nh) return;
                    227: 
                    228:        ns = (NETSTAT *)nh;
                    229: 
                    230:        if (ns->ip_ver) {
                    231:                if (src_buf && src_len > 1) {
                    232:                        ip_print(ns->ip_ver, ns->ip_proto, &ns->ip_src_addr,
                    233:                                 src_buf, src_len);
                    234:                }
                    235:                if (dst_buf && dst_len > 1) {
                    236:                        ip_print(ns->ip_ver, ns->ip_proto, &ns->ip_dst_addr,
                    237:                                 dst_buf, dst_len);
                    238:                }
                    239:                if (proto_buf && proto_len > 1) {
                    240:                        if (nflag)
                    241:                                snprintf(proto_buf, proto_len, "%d", (int)ns->ip_proto);
                    242:                        else    (void)strncpy(proto_buf, ipproto_string(ns->ip_proto),
                    243:                                              proto_len);
                    244:                        proto_buf[proto_len-1] = '\0';
                    245:                }
                    246:        } else if (ntohs(ns->eth_type) > 1500) { /* Ethernet II (DIX) */
                    247:                if (src_buf && src_len > 1) {
                    248:                        (void)strncpy(src_buf, etheraddr_string(ns->eth_src_addr),
                    249:                                      src_len);
                    250:                        src_buf[src_len-1] = '\0';
                    251:                }
                    252:                if (dst_buf && dst_len > 1) {
                    253:                        (void)strncpy(dst_buf, etheraddr_string(ns->eth_dst_addr),
                    254:                                      dst_len);
                    255:                        dst_buf[dst_len-1] = '\0';
                    256:                }
                    257:                if (proto_buf && proto_len > 1) {
                    258:                        if (nflag)
                    259:                                snprintf(proto_buf, proto_len, "%04x", ntohs(ns->eth_type));
                    260:                        else    (void)strncpy(proto_buf, ethertype_string(ns->eth_type),
                    261:                                              proto_len);
                    262:                        proto_buf[proto_len-1] = '\0';
                    263:                }
                    264:        } else if (ns->eth_ssap == ns->eth_dsap) {
                    265:                if (src_buf && src_len > 1) {
                    266:                        (void)strncpy(src_buf, etheraddr_string(ns->eth_src_addr),
                    267:                                      src_len);
                    268:                        src_buf[src_len-1] = '\0';
                    269:                }
                    270:                if (dst_buf && dst_len > 1) {
                    271:                        (void)strncpy(dst_buf, etheraddr_string(ns->eth_dst_addr),
                    272:                                      dst_len);
                    273:                        dst_buf[dst_len-1] = '\0';
                    274:                }
                    275:                if (proto_buf && proto_len > 1) {
                    276:                        if (nflag)
                    277:                                snprintf(proto_buf, proto_len, "sap-%02x",
                    278:                                         (int)(ns->eth_ssap & 0xff));
                    279:                        else    (void)strncpy(proto_buf, llcsap_string(ns->eth_ssap),
                    280:                                              proto_len);
                    281:                        proto_buf[proto_len-1] = '\0';
                    282:                }
                    283:        } else {
                    284:                if (src_buf && src_len > 1) {
                    285:                        sap_print(ns->eth_src_addr, ns->eth_ssap,
                    286:                                  src_buf, src_len);
                    287:                }
                    288:                if (dst_buf && dst_len > 1) {
                    289:                        sap_print(ns->eth_dst_addr, ns->eth_dsap,
                    290:                                  dst_buf, dst_len);
                    291:                }
                    292:                if (proto_buf && proto_len > 1) {
                    293:                        (void)strncpy(proto_buf, "802.3", proto_len);
                    294:                        proto_buf[proto_len-1] = '\0';
                    295:                }
                    296:        }
                    297: }
                    298: 
                    299: static int
                    300: show_stat_header(dst, size, ph)
                    301:        char *dst;
                    302:        int size;
                    303:        const PCAP_HANDLER *ph;
                    304: {
                    305:        int addr_sz, prot_sz, data_sz, rate_sz;
                    306:        char src_buf[100], dst_buf[100];
                    307:        const char *data_ptr, *rate_ptr;
                    308: 
                    309:        /* sanity check */
                    310:        if (!dst || size < 1 || !ph)
                    311:                return 0;
                    312: 
                    313:        scale_size(&addr_sz, &prot_sz, &data_sz, &rate_sz);
                    314: 
                    315:        (void)strcpy(src_buf, "Source");
                    316:        (void)strcpy(dst_buf, "Destination");
                    317:        if (ph->masklen >= 0) {
                    318:                sprintf(src_buf + strlen(src_buf), "/%d", ph->masklen);
                    319:                sprintf(dst_buf + strlen(dst_buf), "/%d", ph->masklen);
                    320:        }
                    321: 
                    322:        data_ptr = rate_ptr = "?";
                    323:        switch (show_stat_mode) {
                    324:        case Size:
                    325:                data_ptr = "Size";
                    326:                rate_ptr = "CPS";
                    327:                break;
                    328:        case Data:
                    329:                data_ptr = "Data";
                    330:                rate_ptr = "CPS";
                    331:                break;
                    332:        case Packets:
                    333:                data_ptr = "Packets";
                    334:                rate_ptr = "PPS";
                    335:                break;
                    336:        }
                    337:        snprintf(dst, size,
                    338:                 "%-*.*s %-*.*s %-*.*s %-*.*s %-*.*s",
                    339:                 addr_sz, addr_sz,      src_buf,
                    340:                 addr_sz, addr_sz,      dst_buf,
                    341:                 prot_sz, prot_sz,      "Protocol",
                    342:                 data_sz, data_sz,      data_ptr,
                    343:                 rate_sz, rate_sz,      rate_ptr);
                    344:        return 0;
                    345: }
                    346: 
                    347: static int
                    348: show_stat_line(dst, size, ns_list, idx)
                    349:        char *dst;
                    350:        int size;
                    351:        const NETSTAT **ns_list;
                    352:        int idx;
                    353: {
                    354:        int addr_sz, prot_sz, data_sz, rate_sz;
                    355:        const NETSTAT *ns;
                    356:        char src_buf[100], dst_buf[100], proto_buf[20], data_buf[20], rate_buf[20];
                    357: 
                    358:        /* sanity check */
                    359:        if (!dst || size < 1 || !ns_list)
                    360:                return 0;
                    361: 
                    362:        ns = ns_list[idx];
                    363: 
                    364:        scale_size(&addr_sz, &prot_sz, &data_sz, &rate_sz);
                    365: 
                    366:        hdr2str(&ns->ns_hdr,
                    367:                src_buf, MIN(sizeof(src_buf), addr_sz + 1),
                    368:                dst_buf, MIN(sizeof(dst_buf), addr_sz + 1),
                    369:                proto_buf, MIN(sizeof(proto_buf), prot_sz + 1));
                    370: 
                    371:        data_buf[0] = '\0';
                    372:        rate_buf[0] = '\0';
                    373:        switch (show_stat_mode) {
                    374:        case Size:
                    375:                if (ns->pkt_len >= 10000)
                    376:                        snprintf(data_buf, sizeof(data_buf), "%uK", ns->pkt_len / 1024);
                    377:                else    snprintf(data_buf, sizeof(data_buf), "%u", ns->pkt_len);
                    378: 
                    379:                if (ns->pkt_len_rate >= 10000)
                    380:                        snprintf(rate_buf, sizeof(rate_buf), "%uK", ns->pkt_len_rate / 1024);
                    381:                else if (ns->pkt_len_rate > 0)
                    382:                        snprintf(rate_buf, sizeof(rate_buf), "%u", ns->pkt_len_rate);
                    383:                break;
                    384:        case Data:
                    385:                if (ns->data_len >= 10000)
                    386:                        snprintf(data_buf, sizeof(data_buf), "%uK", ns->data_len / 1024);
                    387:                else    snprintf(data_buf, sizeof(data_buf), "%u", ns->data_len);
                    388: 
                    389:                if (ns->data_len_rate >= 10000)
                    390:                        snprintf(rate_buf, sizeof(rate_buf), "%uK", ns->data_len_rate / 1024);
                    391:                else if (ns->data_len_rate > 0)
                    392:                        snprintf(rate_buf, sizeof(rate_buf), "%u", ns->data_len_rate);
                    393:                break;
                    394:        case Packets:
                    395:                snprintf(data_buf, sizeof(data_buf), "%u", ns->pkt_cnt);
                    396: 
                    397:                if (ns->pkt_cnt_rate > 0)
                    398:                        snprintf(rate_buf, sizeof(rate_buf), "%u", ns->pkt_cnt_rate);
                    399:                break;
                    400:        }
                    401: 
                    402:        snprintf(dst, size,
                    403:                 "%-*.*s %-*.*s %-*.*s %-*.*s %-*.*s",
                    404:                 addr_sz, addr_sz,      src_buf,
                    405:                 addr_sz, addr_sz,      dst_buf,
                    406:                 prot_sz, prot_sz,      proto_buf,
                    407:                 data_sz, data_sz,      data_buf,
                    408:                 rate_sz, rate_sz,      rate_buf);
                    409: 
                    410:        return ns->attr;
                    411: }
                    412: 
                    413: static int
                    414: show_stat_footer(dst, size, ph)
                    415:        char *dst;
                    416:        int size;
                    417:        const PCAP_HANDLER *ph;
                    418: {
                    419:        const PCAP_HANDLER *top;
                    420:        int addr_sz, prot_sz, data_sz, rate_sz, depth;
                    421:        u_int64_t total = 0, rate = 0;
                    422:        char stat_buf[50], data_buf[20], rate_buf[20];
                    423: 
                    424:        /* sanity check */
                    425:        if (!dst || size < 1 || !ph)
                    426:                return 0;
                    427: 
                    428:        scale_size(&addr_sz, &prot_sz, &data_sz, &rate_sz);
                    429: 
                    430:        depth = 0;
                    431:        for (top = ph->top; top; top = top->top) depth++;
                    432:        if (depth) {
                    433:                snprintf(stat_buf, sizeof(stat_buf), "%d Flows (depth %d)",
                    434:                         netstat_count(ph), depth);
                    435:        } else {
                    436:                snprintf(stat_buf, sizeof(stat_buf), "%d Flows",
                    437:                         netstat_count(ph));
                    438:        }
                    439: 
                    440:        switch (show_stat_mode) {
                    441:        case Size:
                    442:                total = ph->pkt_len;
                    443:                rate = ph->pkt_len_rate;
                    444:                break;
                    445:        case Data:
                    446:                total = ph->data_len;
                    447:                rate = ph->data_len_rate;
                    448:                break;
                    449:        case Packets:
                    450:                total = ph->pkt_cnt;
                    451:                rate = ph->pkt_cnt_rate;
                    452:                break;
                    453:        }
                    454: 
                    455:        if (total >= 10000000)
                    456:                snprintf(data_buf, sizeof(data_buf), "%uM",
                    457:                         (unsigned int)(total / (1024 * 1024)));
                    458:        else if (total >= 10000)
                    459:                snprintf(data_buf, sizeof(data_buf), "%uK",
                    460:                         (unsigned int)(total / 1024));
                    461:        else    snprintf(data_buf, sizeof(data_buf), "%u",
                    462:                         (unsigned int)total);
                    463: 
                    464:        if (rate >= 10000000)
                    465:                snprintf(rate_buf, sizeof(rate_buf), "%uM",
                    466:                         (unsigned int)(rate / (1024 * 1024)));
                    467:        else if (rate >= 10000)
                    468:                snprintf(rate_buf, sizeof(rate_buf), "%uK",
                    469:                         (unsigned int)(rate / 1024));
                    470:        else    snprintf(rate_buf, sizeof(rate_buf), "%u",
                    471:                         (unsigned int)rate);
                    472: 
                    473:        snprintf(dst, size,
                    474:                 "%-*.*s %-*.*s %-*.*s %-*.*s %-*.*s",
                    475:                 addr_sz, addr_sz,      ph->name,
                    476:                 addr_sz, addr_sz,      stat_buf,
                    477:                 prot_sz, prot_sz,      "Total:",
                    478:                 data_sz, data_sz,      data_buf,
                    479:                 rate_sz, rate_sz,      rate_buf);
                    480:        return 0;
                    481: }
                    482: 
                    483: int
                    484: show_stat_input(ph, ch)
                    485:        PCAP_HANDLER *ph;
                    486:        int ch;
                    487: {
                    488:        switch (ch) {
                    489:        case '[':       /* rotate list mode left */
                    490:        case K_LEFT:
                    491:                if (show_stat_mode == Size)
                    492:                        show_stat_mode = Packets;
                    493:                else    show_stat_mode--;
                    494:                return 1;
                    495:        case ']':       /* rotate list mode right */
                    496:        case K_RIGHT:
                    497:                if (show_stat_mode == Packets)
                    498:                        show_stat_mode = Size;
                    499:                else    show_stat_mode++;
                    500:                return 1;
                    501:        case K_CTRL('R'): /* reset current netstat hash */
                    502:                if (ph) {
                    503:                        netstat_purge(ph, 0);
                    504:                        show_stat_list(ph);
                    505:                        return 1;
                    506:                }
                    507:                break;
                    508:        case K_TAB:     /* follow to backflow */
                    509:                if (ph) {
                    510:                        SELECTOR *sp = show_stat_selector(ph);
                    511:                        int idx = selector_get(sp);
                    512: 
                    513:                        if (idx >= 0) {
                    514:                                NETSTAT **ns_list = (NETSTAT **)sp->list;
                    515:                                const NETSTAT *ns = ns_list[idx];
                    516: 
                    517:                                for (idx = 0; idx < sp->items; idx++) {
                    518:                                        if (netstat_bidir(ns, ns_list[idx])) {
                    519:                                                selector_set(idx, sp);
                    520:                                                return 1;
                    521:                                        }
                    522:                                }
                    523:                        }
                    524:                }
                    525:                break;
                    526:        }
                    527:        return 0;
                    528: }
                    529: 
                    530: SELECTOR *
                    531: show_stat_selector(ph)
                    532:        PCAP_HANDLER *ph;
                    533: {
                    534:        if (!ph) return 0;
                    535:        if (!ph->selector && (ph->selector = selector_init()) != 0) {
                    536:                ph->selector->get_header = show_stat_header;
                    537:                ph->selector->get_line = show_stat_line;
                    538:                ph->selector->get_footer = show_stat_footer;
                    539:        }
                    540:        return ph->selector;
                    541: }
                    542: 
                    543: NETSTAT *
                    544: show_stat_get(ph, idx)
                    545:        PCAP_HANDLER *ph;
                    546:        int idx;
                    547: {
                    548:        SELECTOR *sp;
                    549:        NETSTAT **ns_list;
                    550: 
                    551:        /* sanity check */
                    552:        if (!ph || idx < 0 || (sp = show_stat_selector(ph)) == 0 || idx >= sp->items)
                    553:                return 0;
                    554: 
                    555:        ns_list = (NETSTAT **)sp->list;
                    556:        return ns_list[idx];
                    557: }
                    558: 
                    559: int
                    560: show_stat_search(ph, str)
                    561:        PCAP_HANDLER *ph;
                    562:        const char *str;
                    563: {
                    564:        SELECTOR *sp;
                    565:        NETSTAT **ns_list;
                    566:        const NETSTAT *ns;
                    567:        int idx;
                    568:        char src_buf[100], dst_buf[100], proto_buf[20];
                    569: 
                    570:        /* sanity check */
                    571:        if (!ph || !str || *str == '\0' || (sp = show_stat_selector(ph)) == 0)
                    572:                return -1;
                    573: 
                    574:        ns_list = (NETSTAT **)sp->list;
                    575:        for (idx = 0; idx < sp->items; idx++) {
                    576:                ns = ns_list[idx];
                    577:                hdr2str(&ns->ns_hdr,
                    578:                        src_buf, sizeof(src_buf),
                    579:                        dst_buf, sizeof(dst_buf),
                    580:                        proto_buf, sizeof(proto_buf));
                    581:                if (strstr(src_buf, str) ||
                    582:                    strstr(dst_buf, str) ||
                    583:                    strstr(proto_buf, str))
                    584:                        return idx;
                    585:        }
                    586:        return -1;
                    587: }
                    588: 
                    589: SELECTOR *
                    590: show_stat_list(ph)
                    591:        PCAP_HANDLER *ph;
                    592: {
                    593:        SELECTOR *sp;
                    594:        int cnt;
                    595: 
                    596:        /* sanity check */
                    597:        if (!ph || (sp = show_stat_selector(ph)) == 0)
                    598:                return 0;
                    599: 
                    600:        sp->header = ph;
                    601:        sp->footer = ph;
                    602: 
                    603:        if ((cnt = netstat_fetch((NETSTAT ***)&sp->list, ph)) < 0)
                    604:                return sp;
                    605: 
                    606:        sp->items = cnt;
                    607:        if (cnt < 2) /* no sorting required */
                    608:                return sp;
                    609: 
                    610:        /* sort it accroding to current mode */
                    611:        switch (show_stat_mode) {
                    612:        case Size:
                    613:                qsort(sp->list, sp->items, sizeof(NETSTAT *), compare_pkt_len);
                    614:                break;
                    615:        case Data:
                    616:                qsort(sp->list, sp->items, sizeof(NETSTAT *), compare_data_len);
                    617:                break;
                    618:        case Packets:
                    619:                qsort(sp->list, sp->items, sizeof(NETSTAT *), compare_pkt_cnt);
                    620:                break;
                    621:        }
                    622:        if (popbackflow)
                    623:                sort_backflow(sp->list, sp->items);
                    624: 
                    625:        return sp;
                    626: }
                    627: 

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