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

1.1       misho       1: /*
                      2:  *     Copyright (c) 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 <sys/time.h>
                     18: #include <netinet/in.h>
                     19: #include <netdb.h>
                     20: #include <stdio.h>
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23: #include <errno.h>
                     24: #include <pthread.h>
                     25: 
                     26: #include "netstat.h"
                     27: #include "hashtab.h"
                     28: #include "trafshow.h"
                     29: #include "events.h" /* just for tv_diff() */
                     30: #include "colormask.h"
                     31: #include "addrtoname.h"
                     32: 
                     33: int
                     34: netstat_count(ph)
                     35:        const PCAP_HANDLER *ph;
                     36: {
                     37:        /* sanity check */
                     38:        if (!ph || !ph->ns_hash)
                     39:                return 0;
                     40: 
                     41:        return hcount(ph->ns_hash);
                     42: }
                     43: 
                     44: static void
                     45: maskit(bp, len, bits)
                     46:        u_int8_t *bp;
                     47:        int len, bits;
                     48: {
                     49:        register u_int8_t mask;
                     50:        register int i, j;
                     51: 
                     52:        for (i = 0; i < len; i++) {
                     53:                mask = 0;
                     54:                for (j = 0; j < 8 && bits > 0; j++, bits--) {
                     55:                        mask >>= 1;
                     56:                        mask |= 0x80;
                     57:                }
                     58:                bp[i] &= mask;
                     59:        }
                     60: }
                     61: 
                     62: void
                     63: netstat_aggregate(nh, bits)
                     64:        struct netstat_header *nh;
                     65:        int bits;
                     66: {
                     67:        /* sanity check */
                     68:        if (!nh || bits < 0)
                     69:                return;
                     70: 
                     71:        memset(&nh->en_hdr.src, 0, sizeof(nh->en_hdr.src));
                     72:        memset(&nh->en_hdr.dst, 0, sizeof(nh->en_hdr.dst));
                     73: 
                     74:        if (nh->in_hdr.ver) {
                     75:                struct ip_address *src = &nh->in_hdr.src;
                     76:                struct ip_address *dst = &nh->in_hdr.dst;
                     77: 
                     78:                maskit((u_int8_t *)&src->ipaddr, sizeof(src->ipaddr), bits);
                     79:                maskit((u_int8_t *)&dst->ipaddr, sizeof(dst->ipaddr), bits);
                     80: 
                     81:                /* guess server port */
                     82:                if (src->ip_port && dst->ip_port) {
                     83:                        u_int16_t sport = ntohs(src->ip_port);
                     84:                        u_int16_t dport = ntohs(dst->ip_port);
                     85: 
                     86:                        if (isservport(sport))
                     87:                                dst->ip_port = 0;
                     88:                        else if (isservport(dport))
                     89:                                src->ip_port = 0;
                     90:                        else if (sport < IPPORT_RESERVED)
                     91:                                dst->ip_port = 0;
                     92:                        else if (dport < IPPORT_RESERVED)
                     93:                                src->ip_port = 0;
                     94:                        else if (sport >= IPPORT_DYNAMIC)
                     95:                                src->ip_port = 0;
                     96:                        else if (dport >= IPPORT_DYNAMIC)
                     97:                                dst->ip_port = 0;
                     98:                        else if (sport > dport)
                     99:                                src->ip_port = 0;
                    100:                        else    dst->ip_port = 0;
                    101:                }
                    102:        }
                    103: }
                    104: 
                    105: static int
                    106: htab_insert(ht, ns)
                    107:        struct htab *ht;
                    108:        const NETSTAT *ns;
                    109: {
                    110:        ub1 *key;
                    111:        ub4 keyl;
                    112:        int op;
                    113:        NETSTAT *dp;
                    114: 
                    115:        key = (ub1 *)&ns->ns_hdr;
                    116:        keyl = sizeof(ns->ns_hdr);
                    117:        if ((op = hadd(ht, key, keyl, 0)) < 0)
                    118:                return -1;
                    119: 
                    120:        if (op) { /* OK, new item inserted */
                    121:                if ((dp = (NETSTAT *)malloc(sizeof(NETSTAT))) == 0) {
                    122:                        hdel(ht);
                    123:                        return -1;
                    124:                }
                    125:                memcpy(dp, ns, sizeof(NETSTAT));
                    126:                dp->gain_pkt_cnt = ns->pkt_cnt;
                    127:                dp->gain_pkt_len = ns->pkt_len;
                    128:                dp->gain_data_len = ns->data_len;
                    129:                dp->attr = colormask(&dp->ns_hdr);
                    130: 
                    131:                hkey(ht) = (ub1 *)&dp->ns_hdr;
                    132:                hstuff(ht) = dp;
                    133:                return 1;
                    134:        }
                    135:        /* Failed because already in cache -- update it */
                    136: 
                    137:        if ((dp = (NETSTAT *)hstuff(ht)) == 0)
                    138:                return 0; /* should not happen */
                    139: 
                    140:        dp->pkt_cnt += ns->pkt_cnt;
                    141:        dp->pkt_len += ns->pkt_len;
                    142:        dp->data_len += ns->data_len;
                    143: 
                    144:        dp->gain_pkt_cnt += ns->pkt_cnt;
                    145:        dp->gain_pkt_len += ns->pkt_len;
                    146:        dp->gain_data_len += ns->data_len;
                    147: 
                    148:        if (ns->pkt_cnt_rate || ns->pkt_len_rate || ns->data_len_rate) {
                    149:                dp->mtime = ns->mtime;
                    150: 
                    151:                dp->pkt_cnt_rate = ns->pkt_cnt_rate;
                    152:                dp->pkt_len_rate = ns->pkt_len_rate;
                    153:                dp->data_len_rate = ns->data_len_rate;
                    154: 
                    155:        } else if ((op = tv_diff(&dp->mtime, &ns->mtime)) >= 1000) {
                    156:                dp->mtime = ns->mtime;
                    157: 
                    158:                dp->gain_pkt_cnt = dp->gain_pkt_cnt * 1000 / op;
                    159:                if (dp->gain_pkt_cnt) {
                    160:                        dp->pkt_cnt_rate = dp->gain_pkt_cnt;
                    161:                        dp->gain_pkt_cnt = 0;
                    162:                }
                    163:                dp->gain_pkt_len = dp->gain_pkt_len * 1000 / op;
                    164:                if (dp->gain_pkt_len) {
                    165:                        dp->pkt_len_rate = dp->gain_pkt_len;
                    166:                        dp->gain_pkt_len = 0;
                    167:                }
                    168:                dp->gain_data_len = dp->gain_data_len * 1000 / op;
                    169:                if (dp->gain_data_len) {
                    170:                        dp->data_len_rate = dp->gain_data_len;
                    171:                        dp->gain_data_len = 0;
                    172:                }
                    173:        }
                    174:        return 0;
                    175: }
                    176: 
                    177: int
                    178: netstat_insert(ph, ns)
                    179:        PCAP_HANDLER *ph;
                    180:        const NETSTAT *ns;
                    181: {
                    182:        int op;
                    183:        NETSTAT ns_buf;
                    184: 
                    185:        /* sanity check */
                    186:        if (!ph || !ns) {
                    187:                errno = EINVAL;
                    188:                return -1;
                    189:        }
                    190:        if (!ph->ns_hash && (ph->ns_hash = hcreate(65536)) == 0)
                    191:                return -1;
                    192: 
                    193:        if (ph->masklen >= 0) {
                    194:                memcpy(&ns_buf, ns, sizeof(NETSTAT));
                    195:                netstat_aggregate(&ns_buf.ns_hdr, ph->masklen);
                    196:                ns = &ns_buf;
                    197:        }
                    198:        if (ph->ns_mutex) pthread_mutex_lock(ph->ns_mutex);
                    199: 
                    200:        op = htab_insert(ph->ns_hash, ns);
                    201: 
                    202:        if (ph->ns_mutex) pthread_mutex_unlock(ph->ns_mutex);
                    203:        return op;
                    204: }
                    205: 
                    206: int
                    207: netstat_find(ph, ns)
                    208:        PCAP_HANDLER *ph;
                    209:        NETSTAT *ns; /* IN/OUT */
                    210: {
                    211:        struct htab *ht;
                    212:        ub1 *key;
                    213:        ub4 keyl;
                    214:        NETSTAT *found;
                    215:        int ok = 0;
                    216: 
                    217:        /* sanity check */
                    218:        if (!ph || !ns || netstat_count(ph) < 1)
                    219:                return 0;
                    220: 
                    221:        if (ph->ns_mutex) pthread_mutex_lock(ph->ns_mutex);
                    222:        ht = ph->ns_hash;
                    223: 
                    224:        key = (ub1 *)&ns->ns_hdr;
                    225:        keyl = sizeof(ns->ns_hdr);
                    226:        if (hfind(ht, key, keyl) && (found = hstuff(ht)) != 0) {
                    227:                ok = 1;
                    228:                *ns = *found;
                    229:        }
                    230: 
                    231:        if (ph->ns_mutex) pthread_mutex_unlock(ph->ns_mutex);
                    232:        return ok;
                    233: }
                    234: 
                    235: int
                    236: netstat_purge(ph, at)
                    237:        PCAP_HANDLER *ph;
                    238:        const struct timeval *at;
                    239: {
                    240:        struct htab *ht;
                    241:        int op, cnt = 0;
                    242:        NETSTAT *ns;
                    243: 
                    244:        /* sanity check */
                    245:        if (!ph) {
                    246:                errno = EINVAL;
                    247:                return -1;
                    248:        }
                    249:        if (netstat_count(ph) < 1)
                    250:                return 0;
                    251: 
                    252:        if (ph->ns_mutex) pthread_mutex_lock(ph->ns_mutex);
                    253:        ht = ph->ns_hash;
                    254: 
                    255:        op = hfirst(ht);
                    256:        while (op && hcount(ht) > 0) {
                    257:                ns = hstuff(ht);
                    258:                if (!ns) { /* should not happen */
                    259:                        op = hdel(ht);
                    260:                } else if (!at || timercmp(&ns->mtime, at, <)) {
                    261:                        free(ns);
                    262:                        op = hdel(ht);
                    263:                        cnt++;
                    264:                } else {
                    265:                        op = hnext(ht);
                    266:                }
                    267:        }
                    268:        if (ph->ns_mutex) pthread_mutex_unlock(ph->ns_mutex);
                    269:        return cnt;
                    270: }
                    271: 
                    272: void
                    273: netstat_free(ph)
                    274:        PCAP_HANDLER *ph;
                    275: {
                    276:        struct htab *ht;
                    277: 
                    278:        /* sanity check */
                    279:        if (!ph) return;
                    280: 
                    281:        netstat_purge(ph, 0);
                    282: 
                    283:        if (ph->ns_mutex) pthread_mutex_lock(ph->ns_mutex);
                    284:        ht = ph->ns_hash;
                    285:        ph->ns_hash = 0;
                    286:        if (ht) hdestroy(ht);
                    287:        if (ph->ns_mutex) pthread_mutex_unlock(ph->ns_mutex);
                    288: }
                    289: 
                    290: int
                    291: netstat_match(p1, p2)
                    292:        register const NETSTAT *p1, *p2;
                    293: {
                    294:        /* sanity check */
                    295:        if (!p1 || !p2) return 0;
                    296: 
                    297:        return !memcmp(&p1->ns_hdr, &p2->ns_hdr, sizeof(struct netstat_header));
                    298: }
                    299: 
                    300: int
                    301: netstat_bidir(p1, p2)
                    302:        register const NETSTAT *p1, *p2;
                    303: {
                    304:        /* sanity check */
                    305:        if (!p1 || !p2) return 0;
                    306: 
                    307:        if (p1->ip_ver) {
                    308:                if (p1->ip_ver == p2->ip_ver &&
                    309:                    p1->ip_proto == p2->ip_proto &&
                    310:                    !memcmp(&p1->ip_src_addr, &p2->ip_dst_addr,
                    311:                            sizeof(struct ip_address)) &&
                    312:                    !memcmp(&p2->ip_src_addr, &p1->ip_dst_addr,
                    313:                            sizeof(struct ip_address)))
                    314:                        return 1;
                    315:        } else if (!p2->ip_ver) {
                    316:                if (p1->eth_type == p2->eth_type &&
                    317:                    !memcmp(p1->eth_src_addr, p2->eth_dst_addr,
                    318:                            ETHER_ADDR_LEN) &&
                    319:                    !memcmp(p2->eth_src_addr, p1->eth_dst_addr,
                    320:                            ETHER_ADDR_LEN))
                    321:                        return 1;
                    322:        }
                    323:        return 0;
                    324: }
                    325: 
                    326: int
                    327: netstat_fetch(list, ph)
                    328:        NETSTAT **list[];
                    329:        PCAP_HANDLER *ph;
                    330: {
                    331:        struct htab *ht;
                    332:        int op, cnt, i;
                    333:        NETSTAT *ns, **array;
                    334: 
                    335:        /* sanity check */
                    336:        if (!list || !ph) {
                    337:                errno = EINVAL;
                    338:                return -1;
                    339:        }
                    340: 
                    341:        if ((cnt = netstat_count(ph)) < 1) {
                    342:                /* free previous */
                    343:                if (*list) free(*list);
                    344:                *list = 0;
                    345:                return 0;
                    346:        }
                    347:        if ((array = (NETSTAT **)malloc(cnt * sizeof(NETSTAT *))) == 0)
                    348:                return -1;
                    349: 
                    350:        if (ph->ns_mutex) pthread_mutex_lock(ph->ns_mutex);
                    351:        ht = ph->ns_hash;
                    352: 
                    353:        /* reset total statistics */
                    354:        ph->pkt_cnt = 0;
                    355:        ph->pkt_len = 0;
                    356:        ph->data_len = 0;
                    357: 
                    358:        ph->pkt_cnt_rate = 0;
                    359:        ph->pkt_len_rate = 0;
                    360:        ph->data_len_rate = 0;
                    361: 
                    362:        op = hfirst(ht);
                    363:        i = 0;
                    364:        while (op && i < cnt) {
                    365:                ns = hstuff(ht);
                    366:                if (ns) {
                    367:                        array[i++] = ns;
                    368: 
                    369:                        /* collect total statistics */
                    370:                        ph->pkt_cnt += ns->pkt_cnt;
                    371:                        ph->pkt_len += ns->pkt_len;
                    372:                        ph->data_len += ns->data_len;
                    373: 
                    374:                        ph->pkt_cnt_rate += ns->pkt_cnt_rate;
                    375:                        ph->pkt_len_rate += ns->pkt_len_rate;
                    376:                        ph->data_len_rate += ns->data_len_rate;
                    377:                }
                    378:                op = hnext(ht);
                    379:        }
                    380:        /* free previous */
                    381:        if (*list) free(*list);
                    382:        *list = array;
                    383: 
                    384:        if (ph->ns_mutex) pthread_mutex_unlock(ph->ns_mutex);
                    385:        return i;
                    386: }
                    387: 

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