File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / trafshow / netstat.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:55:18 2012 UTC (12 years, 4 months ago) by misho
Branches: trafshow, MAIN
CVS tags: v5_2_3p0, v5_2_3, HEAD
trafshow

    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>