1 /*
2  * Copyright (c) 2001 Stas Degteff <g@grumbler.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that: (1) source code distributions
6  * retain the above copyright notice and this paragraph in its entirety, (2)
7  * distributions including binary code include the above copyright notice and
8  * this paragraph in its entirety in the documentation or other materials
9  * provided with the distribution.
10  *
11  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14  *
15  *
16  * BPFT - bpfilter trafic collector
17  *
18  * $Id: output.c,v 1.2 2002/10/18 03:28:27 stas_degteff Exp $
19  * Common functions for trafstat & traflog utilities.
20  *
21  */
22 
23 #include <unistd.h>
24 #include <netinet/in.h>
25 #include <sys/param.h>
26 #include "output.h"
27 #include "traffic.h"
28 
29 int
sortbyfrom(left,right)30 sortbyfrom(left, right)
31 	register struct t_entry *left;
32 	register struct t_entry *right;
33 {
34 	if (htonl(left->in_ip.s_addr) < htonl(right->in_ip.s_addr))
35 		return LESS;
36 	if (htonl(left->in_ip.s_addr) > htonl(right->in_ip.s_addr))
37 		return GREATER;
38 	return EQUAL;
39 }
40 
41 int
sortbyto(left,right)42 sortbyto(left, right)
43 	register struct t_entry *left;
44 	register struct t_entry *right;
45 {
46 	if (htonl(left->out_ip.s_addr) < htonl(right->out_ip.s_addr))
47 		return LESS;
48 	if (htonl(left->out_ip.s_addr) > htonl(right->out_ip.s_addr))
49 		return GREATER;
50 	return EQUAL;
51 }
52 
53 int
sortbypport(left,right)54 sortbypport(left, right)
55 	register struct t_entry *left;
56 	register struct t_entry *right;
57 {
58 	if (htons(left->p_port) < htons(right->p_port))
59 		return LESS;
60 	if (htons(left->p_port) > htons(right->p_port))
61 		return GREATER;
62 	return EQUAL;
63 }
64 
65 #if LAYOUT!=OLD
66 int
sortbyoport(left,right)67 sortbyoport(left, right)
68         register struct t_entry *left;
69         register struct t_entry *right;
70 {
71         if (htons(left->o_port) < htons(right->o_port))
72                 return LESS;
73         if (htons(left->o_port) > htons(right->o_port))
74                 return GREATER;
75         return EQUAL;
76 }
77 #endif
78 
79 int
sortbysize(left,right)80 sortbysize(left, right)
81 	register struct t_entry *left;
82 	register struct t_entry *right;
83 {
84 	if (left->n_psize < right->n_psize)
85 		return GREATER;
86 	if (left->n_psize > right->n_psize)
87 		return LESS;
88 	return EQUAL;
89 }
90 
91 
traf_print()92 traf_print()
93 {
94 	register int i, j;
95 	u_int64_t abytes = 0, dbytes = 0;
96 	char buf[MAXHOSTNAMELEN + 1];
97 #if LAYOUT==OLD
98 	char *port, *user, *proto;
99 #else
100 	char *s_port, *d_port, *proto;
101 #endif
102 	for (i = 0; i < s.t_size; i++)
103 		abytes += sum[i].n_psize, dbytes += sum[i].n_bytes;
104 	if (rflag) {
105 		printf("%qu\n", abytes);
106 		return;
107 	}
108 	qsort(sum, s.t_size, sizeof(struct t_entry), sortbysize);
109 	switch ( order ){
110 	case ORDER_TO:
111 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbyto);
112 		break;
113 	case ORDER_FROM:
114 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbyfrom);
115 		break;
116 	case ORDER_SIZE:
117 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbysize);
118 		break;
119 	case ORDER_DPORT:
120 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbypport);
121 		break;
122 #if LAYOUT!=OLD
123 	case ORDER_SPORT:
124 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbyoport);
125 		break;
126 #endif
127 	}
128 	if (!fvnum) {
129 		gethostname(buf, MAXHOSTNAMELEN);
130 		printf("\n (%s) %s at", device_name, buf);
131 		printf(" %.15s -", ctime((time_t *)&s.start) + 4);
132 		printf(" %.15s\n", ctime((time_t *)&s.stop) + 4);
133 		printf(" Summary: %qu data bytes, %qu all bytes, %u records\n",
134 		       dbytes, abytes, s.t_size);
135 		printf("\
136      From           Port         To            Port  Proto     Data       All\n");
137 	}
138 	for (i = 0; i < s.t_size; i++) {
139 #if LAYOUT==OLD
140 		port = "undef";
141 #else
142 		s_port = "";
143 		d_port = "";
144 #endif
145 		switch(sum[i].ip_protocol) {
146 			case IPPROTO_TCP:
147 				if (sum[i].p_port || sum[i].o_port)
148 #if LAYOUT==OLD
149 					port = tcpport_string(sum[i].p_port);
150 #else
151 					s_port = tcpport_string(sum[i].o_port);
152 					d_port = tcpport_string(sum[i].p_port);
153 #endif
154 				proto = "tcp";
155 				break;
156 			case IPPROTO_UDP:
157 				if (sum[i].p_port || sum[i].o_port)
158 #if LAYOUT==OLD
159 					port = udpport_string(sum[i].p_port);
160 #else
161 					s_port = udpport_string(sum[i].o_port);
162 					d_port = udpport_string(sum[i].p_port);
163 #endif
164 				proto = "udp";
165 				break;
166 			case IPPROTO_ICMP:
167 				proto = "icmp";
168 				break;
169 			case IPPROTO_EGP:
170 				proto = "egp";
171 				break;
172 			case IPPROTO_OSPF:
173 				proto = "ospf";
174 				break;
175 			case IPPROTO_IGMP:
176 				proto = "igmp";
177 				break;
178 			default:
179 				proto = "unkn";
180 		}
181 #if LAYOUT==OLD
182 		if (sum[i].p_port)	user = "client";
183 		else			user = "none";
184 #endif
185 		if (!fvnum) {
186 #if LAYOUT==OLD
187 			printf("%-18.18s %-6.6s  ", ipaddr_string(&sum[i].in_ip),
188 			       (sum[i].who_srv & 1) ? port : user);
189 			printf("%-18.18s %-6.6s  ", ipaddr_string(&sum[i].out_ip),
190 			       (sum[i].who_srv & 2) ? port : user);
191 			printf("%-4.4s %9ld %10ld\n", proto, sum[i].n_bytes,
192 			       sum[i].n_psize);
193 #else
194 			printf("%-18.18s %-6.6s  ", ipaddr_string(&sum[i].in_ip),
195 			       s_port);
196 			printf("%-18.18s %-6.6s  ", ipaddr_string(&sum[i].out_ip),
197 			       d_port);
198 			printf("%-4.4s %9ld %10ld\n", proto, sum[i].n_bytes,
199 			       sum[i].n_psize);
200 #endif
201 		} else
202 			for (j = 0; j < fvnum; j++)
203 				switch (fv[j].cmd) {
204 				case FROM:
205 					printf(fv[j].format, ipaddr_string(&sum[i].in_ip));
206 					break;
207 				case TO:
208 					printf(fv[j].format, ipaddr_string(&sum[i].out_ip));
209 					break;
210 #if LAYOUT==OLD
211 				case SPORT:
212 					printf(fv[j].format,
213 					       (sum[i].who_srv & 1) ? port : user);
214 					break;
215 				case DPORT:
216 					printf(fv[j].format,
217 					       (sum[i].who_srv & 2) ? port : user);
218 					break;
219 #else
220 				case SPORT:
221 					printf(fv[j].format,
222 					       s_port);
223 					break;
224 				case DPORT:
225 					printf(fv[j].format,
226 					       d_port);
227 					break;
228 #endif
229 				case PROTO:
230 					printf(fv[j].format, proto);
231 					break;
232 				case BYTES:
233 					printf(fv[j].format, sum[i].n_bytes);
234 					break;
235 				case PSIZE:
236 					printf(fv[j].format, sum[i].n_psize);
237 					break;
238 				case FTIME:
239 					strftime(buf, sizeof(buf), fv[j].format,
240 						 localtime((time_t *)&s.start));
241 					printf("%s", buf);
242 					break;
243 				case LTIME:
244 					strftime(buf, sizeof(buf), fv[j].format,
245 						 localtime((time_t *)&s.stop));
246 					printf("%s", buf);
247 					break;
248 				}
249 	}
250 }
251 
252 
253 /*
254  * Put traffic table to fd in binary form.
255  */
256 void
traf_put(fd)257 traf_put(fd)
258 	register int fd;
259 {
260 	register int i;
261 	int c = 0;
262 
263 	c += write(fd, (int *)&n_entry, sizeof(n_entry));
264 	c += write(fd, (struct timeval *)&start_time, sizeof(start_time));
265 	c += write(fd, (struct timeval *)&drop_time, sizeof(drop_time));
266 	for (i = 0; i < n_entry; i++) {
267 		c += write(fd, (struct t_entry *)&entries[i],
268 			   sizeof(struct t_entry));
269 	}
270 	(void)write(fd, (int *)&c, sizeof(c));
271 	return;
272 }
273 
traf_write(fd)274 traf_write(fd)
275 	FILE *fd;
276 {
277 	if (fwrite((struct t_header *)&s, sizeof(struct t_header), 1, fd) != 1)
278 		error("write header error");
279 	if (fwrite((struct t_entry *)sum, sizeof(struct t_entry), s.t_size, fd) != s.t_size)
280 		error("write table error");
281 	return;
282 }
283