Annotation of embedaddon/trafshow/netstat.c, revision 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>