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>