1 /*
2  *	Copyleft (c) 2001 Grumbler <g@grumbler.org>
3  *
4  *	Copyright (c) 1999 RISS-Telecom Networking Center
5  *
6  *	Copyright (c) 1993 The CAD lab of the
7  *	Novosibirsk Institute of Broadcasting and Telecommunication
8  *
9  *	BPFT $Id: traflog.c,v 1.12 2003/10/27 13:28:17 bartosh Exp $
10  *
11  *
12  * Redistribution and use in source forms, with and without modification,
13  * are permitted provided that this entire comment appears intact.
14  * Redistribution in binary form may occur without any restrictions.
15  *
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
17  */
18 
19 /*	traflog.c - tcp/udp data traffic log manager	*/
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <time.h>
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/time.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <netdb.h>
35 #include <pcap.h>
36 
37 #include "interface.h"
38 #include "addrtoname.h"
39 #include "traffic.h"
40 #include "traflog.h"
41 
42 static unsigned no = 0;
43 static int n_call = 0;
44 static int n_pat = 0;
45 
46 static struct t_entry *sum = NULL;
47 
48 static struct pat_mask {
49 	struct  in_addr in_ip, out_ip;
50 	struct  in_addr in_mask, out_mask;
51 	u_char  ip_protocol;
52 	u_short p_port;
53 } *pat = NULL;
54 
55 /* struct t_header defined in the traffic.h */
56 static struct t_header s;
57 
58 u_long
addrmask(addr)59 addrmask(addr)
60 	u_long addr;
61 {
62 	register u_long m = INADDR_NONE;
63 
64 	if (addr)
65 		while (!(addr & IN_CLASSA_NET))
66 			addr <<= IN_CLASSC_NSHIFT, m >>= IN_CLASSC_NSHIFT;
67 	else
68 		m = INADDR_ANY;
69 
70 	return m;
71 }
72 
73 char *
hostnetstr(in,mask)74 hostnetstr(in, mask)
75 	struct in_addr in;
76 	u_long mask;
77 {
78 	char *cp = NULL;
79 	static char line[MAXHOSTNAMELEN + 1];
80 	register u_long i;
81 
82 	i = ntohl(in.s_addr);
83 	NTOHL(mask);
84 	i &= mask;
85 	if (!i) {
86 		strcpy(line, "all");
87 		return line;
88 	}
89 	if (!(htonl(i) ^ in.s_addr) && addrmask(in.s_addr) == INADDR_NONE) {
90 		strncpy(line, ipaddr_string(&in), sizeof(line));
91 		line[sizeof(line)]=0;
92 		return line;
93 	}
94 	if (!nflag) {
95 		register u_long net = i;
96 		struct netent *np = NULL;
97 
98 		while ((mask & 1) == 0)
99 			mask >>= 1, net >>= 1;
100 		if ((np = getnetbyaddr(net, AF_INET)) != NULL)
101 			cp = np->n_name;
102 	}
103 #define	C(x)	(unsigned)((x) & 0xff)
104 	if (cp) {
105 		strncpy(line, cp, sizeof(line) - 1);
106 		line[sizeof(line)]=0;
107 	}
108 	else if ((i & 0xffffff) == 0)
109 		sprintf(line, "%u", C(i >> 24));
110 	else if ((i & 0xffff) == 0)
111 		sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16));
112 	else if ((i & 0xff) == 0)
113 		sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
114 	else
115 		sprintf(line, "%u.%u.%u.%u", C(i >> 24),
116 			C(i >> 16), C(i >> 8), C(i));
117 	return line;
118 }
119 
120 int
pat_print()121 pat_print()
122 {
123 	register int i;
124 	char port[16], proto[16];
125 	struct servent *svc;
126 
127 	printf("%-24s %-24s %-10s %s\n", "From", "To", "Port", "Protocol");
128 	for (i = 0; i < n_pat; i++) {
129 		printf("%-24.24s ", hostnetstr(pat[i].in_ip,
130 					       pat[i].in_mask.s_addr));
131 		printf("%-24.24s ", hostnetstr(pat[i].out_ip,
132 					       pat[i].out_mask.s_addr));
133 		port[0] = proto[0] = 0;
134 		if (pat[i].p_port) {
135 			register int p = htons(pat[i].p_port);
136 			if (pat[i].ip_protocol != IPPROTO_UDP)
137 				if ((svc = getservbyport(p, "tcp")) != NULL) {
138 					strncpy(port, svc->s_name, sizeof(port));
139 					port[sizeof(port)]=0;
140 					strcpy(proto, "tcp ");
141 				}
142 			if (pat[i].ip_protocol != IPPROTO_TCP)
143 				if ((svc = getservbyport(p, "udp")) != NULL) {
144 					if (!port[0]) {
145 						strncpy(port, svc->s_name, sizeof(port));
146 						port[sizeof(port)]=0;
147 					}
148 					strcpy(proto, "udp");
149 				}
150 			if (port[0] && !nflag)
151 				printf("%-10.10s ", port);
152 			else
153 				printf("%-10d ", pat[i].p_port);
154 		} else {
155 			printf("%-10.10s ", "all");
156 			if (pat[i].ip_protocol == IPPROTO_TCP)
157 				strcpy(proto, "tcp");
158 			if (pat[i].ip_protocol == IPPROTO_UDP)
159 				strcpy(proto, "udp");
160 		}
161 		printf("%s\n", proto[0] ? proto : "tcp udp");
162 	}
163 	return 0;
164 }
165 
166 u_long
strhostnet(cmdarg,mask)167 strhostnet(cmdarg, mask)
168 	char *cmdarg;
169 	u_long *mask;
170 {
171 	struct in_addr in;
172 	struct netent *np;
173 	struct hostent *hp;
174 
175 	if ((in.s_addr = inet_network(cmdarg)) != INADDR_NONE) {
176 		net_mask(&in.s_addr);
177 		HTONL(in.s_addr);
178 		*mask = addrmask(in.s_addr);
179 		return in.s_addr;
180 	}
181 	if (!strcasecmp(cmdarg, "all")) {
182 		*mask = INADDR_ANY;
183 		return INADDR_ANY;
184 	}
185 	if ((np = getnetbyname(cmdarg)) != NULL) {
186 		in.s_addr = np->n_net;
187 		*mask = htonl(net_mask(&in.s_addr));
188 		return htonl(in.s_addr);
189 	}
190 	if ((hp = gethostbyname(cmdarg)) != NULL) {
191 		in.s_addr = *(u_long *)*hp->h_addr_list;
192 		*mask = addrmask(in.s_addr);
193 		return in.s_addr;
194 	}
195 	error("unknown host or network '%s'", cmdarg);
196 }
197 
198 int
iscmd(token)199 iscmd(token)
200 	register char *token;
201 {
202 	if (!strcasecmp(token, "from"))
203 		return FROM;
204 	if (!strcasecmp(token, "to"))
205 		return TO;
206 	if (!strcasecmp(token, "port"))
207 		return PORT;
208 	if (!strcasecmp(token, "proto"))
209 		return PROTO;
210 	if (!strcasecmp(token, "mask"))
211 		return MASK;
212 	return NOCMD;
213 }
214 
215 void
alloc_pat()216 alloc_pat()
217 {
218 	if ((pat = realloc(pat, ++n_pat * sizeof(struct pat_mask))) == NULL)
219 		error("can't reallocate memory");
220 	if (n_pat > 1)
221 		bcopy(pat + n_pat-2, pat + n_pat-1, sizeof(struct pat_mask));
222 	else
223 		bzero(pat, sizeof(struct pat_mask));
224 }
225 
226 /* Decode command line parameters */
227 void
pattern(cmdbuf)228 pattern(cmdbuf)
229 	char *cmdbuf;
230 {
231 	register int cmd, cmdp = MASK;
232 	register char *cmdarg;
233 	char *token;
234 	struct servent *svc;
235 
236 	if (cmdbuf)
237 	while ((token = strtok(cmdbuf, " \t\r\n")) != NULL) {
238 		if (*token == '#' || *token == ';')
239 			continue;
240 		if ((cmd = iscmd(token)) == NOCMD)
241 			error("unknown keyword '%s'", token);
242 		if (!(cmdarg = strtok(NULL, " \t\r\n")))
243 			error("keyword '%s': missing argument", token);
244 		if (cmd <= cmdp)
245 			alloc_pat();
246 		switch (cmd) {
247 		case FROM:
248 			pat[n_pat-1].in_ip.s_addr = strhostnet(cmdarg,
249 						&pat[n_pat-1].in_mask.s_addr);
250 			break;
251 		case TO:
252 			pat[n_pat-1].out_ip.s_addr = strhostnet(cmdarg,
253 						&pat[n_pat-1].out_mask.s_addr);
254 			break;
255 		case MASK:
256 			switch(cmdp) {
257 			case FROM:
258 				pat[n_pat-1].in_mask.s_addr = inet_addr(cmdarg);
259 				break;
260 			case TO:
261 				pat[n_pat-1].out_mask.s_addr = inet_addr(cmdarg);
262 				break;
263 			default:
264 				error("inconsistent usage '%s %s'", token, cmdarg);
265 			}
266 			cmd = cmdp;
267 			break;
268 		case PORT:
269 			if (!(pat[n_pat-1].p_port = (u_short)atoi(cmdarg))) {
270 				if (!strcasecmp(cmdarg, "all")) {
271 					pat[n_pat-1].p_port = 0;
272 					break;
273 				}
274 				if ((svc = getservbyname(cmdarg, "tcp")) != NULL)
275 					pat[n_pat-1].p_port = ntohs(svc->s_port);
276 				if ((svc = getservbyname(cmdarg, "udp")) != NULL)
277 					pat[n_pat-1].p_port = ntohs(svc->s_port);
278 				if (!pat[n_pat-1].p_port)
279 					error("unknown port '%s'", cmdarg);
280 			}
281 			break;
282 		case PROTO:
283 			if (!strcasecmp(cmdarg, "udp")) {
284 				pat[n_pat-1].ip_protocol = IPPROTO_UDP;
285 				break;
286 			}
287 			if (!strcasecmp(cmdarg, "tcp")) {
288 				pat[n_pat-1].ip_protocol = IPPROTO_TCP;
289 				break;
290 			}
291 			error("unknown protocol '%s'", cmdarg);
292 		default:
293 			error("unknown keyword '%s'", token);
294 		}
295 		cmdp = cmd;
296 		cmdbuf = NULL;
297 	}
298 	if (!n_pat)
299 		alloc_pat();
300 }
301 
302 
303 /* Get header from trafd.log */
304 int
getheader(fd,header)305 getheader(fd, header)
306 	register FILE *fd;
307 	register struct t_header *header;
308 {
309 	if (fread((struct t_header *)header, sizeof(struct t_header), 1, fd) != 1) {
310 		if (!feof(fd))
311 			warning("fread: can't read header (error: %s", strerror(errno) );
312 		return 0;
313 	}
314 	if (header->t_size > MAX_TO_SAVE) {
315 		warning("table too big to fit into memory");
316 		return 0;
317 	}
318 	return 1;
319 }
320 
321 /*
322  * Output contents list of daemon logfile.
323  */
324 int
contents(fd,h)325 contents(fd, h)
326 	register FILE *fd;
327 	register struct t_header *h;
328 {
329 	register int i;
330 	register u_int64_t bytes = 0, psize = 0;
331 	struct t_entry t;
332 
333 	if (!n_call && !rflag)
334 		printf("\
335  #        Started            Dumped            Data         All     Recs\n");
336 
337 	for (i = 0; i < h->t_size; i++) {
338 		if (fread((struct t_entry *)&t, sizeof(struct t_entry), 1, fd) != 1) {
339 			warning("fread: can't read entry");
340 			return 0;
341 		}
342 		bytes += t.n_bytes, psize += t.n_psize;
343 	}
344 	if (!rflag) {
345 		printf("%03d   %.15s", no, ctime((time_t *)&h->start) + 4);
346 		printf("%18.15s   %10qu   %10qu   %4d\n", ctime((time_t *)&h->stop)+4,
347 		       bytes, psize, h->t_size);
348 	}
349 	return 1;
350 }
351 
352 
353 /* Compare trafd.log records with pattern */
354 int
patmatch(e)355 patmatch(e)
356 	register struct t_entry *e;
357 {
358 	register int i = 0;
359 
360 	if (e->in_ip.s_addr == 0)
361 		return 0;
362 	for (i = 0; i < n_pat; i++) {
363 		if ((e->in_ip.s_addr & pat[i].in_mask.s_addr) ^
364 		      pat[i].in_ip.s_addr)
365 			continue;
366 		if ((e->out_ip.s_addr & pat[i].out_mask.s_addr) ^
367 		    pat[i].out_ip.s_addr)
368 			continue;
369 		if (pat[i].ip_protocol && e->ip_protocol != pat[i].ip_protocol)
370 			continue;
371 #if LAYOUT==OLD
372 		if ( !pat[i].p_port || e->p_port == pat[i].p_port )
373 #else
374 		if ( !pat[i].p_port || e->p_port == pat[i].p_port
375 			|| e->o_port == pat[i].p_port )
376 #endif
377 			break;
378 	}
379 	return (n_pat - i);
380 }
381 
382 /* Read one record from trafd.log, test it to pattern & add values to summary */
383 int
ioblock(fd,h)384 ioblock(fd, h)
385 	FILE *fd;
386 	register struct t_header *h;
387 {
388 	register int i, j;
389 	register struct t_entry *block;
390 
391 	if (!sflag || !n_call) {
392 		bzero((struct t_header *)&s, sizeof(struct t_header));
393 		if (sum != NULL)
394 			free(sum);
395 		sum = NULL;
396 	}
397 	block = (struct t_entry *) alloca(h->t_size * sizeof(struct t_entry));
398 	if (block == NULL) {
399 		warning("traflog.c:ioblock(): alloca: can't allocate memory");
400 		return 0;
401 	}
402 	if (fread((struct t_entry *)block, sizeof(struct t_entry), h->t_size,
403 		  fd) != h->t_size) {
404 		warning("traflog.c:ioblock(): fread: can't read table");
405 		return 0;
406 	}
407 	for (i = 0; i < h->t_size; i++) {
408 		if (!patmatch(block + i))
409 			continue;
410 		for (j = 0; j < s.t_size; j++) {
411 			if (block[i].in_ip.s_addr == sum[j].in_ip.s_addr &&
412 			    block[i].out_ip.s_addr == sum[j].out_ip.s_addr &&
413 			    block[i].ip_protocol == sum[j].ip_protocol &&
414 #if LAYOUT==OLD
415 			    block[i].who_srv == sum[j].who_srv &&
416 #else
417 			    block[i].o_port == sum[j].o_port &&
418 #endif
419 			    block[i].p_port == sum[j].p_port) {
420 				sum[j].n_bytes += block[i].n_bytes;
421 				sum[j].n_psize += block[i].n_psize;
422 				break;
423 			}
424 		}
425 		if (j < s.t_size)
426 			continue;
427 		sum = (struct t_entry *) realloc(sum, ++s.t_size *
428 						sizeof(struct t_entry));
429 		if (sum == NULL) {
430 			warning("traflog.c:ioblock(): realloc: can't reallocate memory");
431 			return 0;
432 		}
433 		bcopy(block + i, sum + j, sizeof(struct t_entry));
434 	}
435 	if (!s.start.tv_sec)
436 		s.start = h->start;
437 	s.stop = h->stop;
438 	return 1;
439 }
440 
range(h)441 static int range(h)
442 	register struct t_header *h;
443 {
444 	register int true = 0;
445 
446 	if (tbflag) {
447 		if (tb.tv_sec <= h->start.tv_sec)
448 			++true;
449 	} else {
450 		if (begin <= no)
451 			++true;
452 	}
453 	if (teflag) {
454 		if (te.tv_sec >= h->stop.tv_sec)
455 			++true;
456 	} else {
457 		if (endin >= no)
458 			++true;
459 	}
460 	return true;
461 }
462 
traf_write(fd)463 void traf_write(fd)
464 	FILE *fd;
465 {
466 	if (fwrite((struct t_header *)&s, sizeof(struct t_header), 1, fd) != 1)
467 		error("write header error");
468 	if (fwrite((struct t_entry *)sum, sizeof(struct t_entry), s.t_size, fd) != s.t_size)
469 		error("write table error");
470 }
471 
472 
473 int
sortbyfrom(left,right)474 sortbyfrom(left, right)
475 	register struct t_entry *left;
476 	register struct t_entry *right;
477 {
478 	if (htonl(left->in_ip.s_addr) < htonl(right->in_ip.s_addr))
479 		return LESS;
480 	if (htonl(left->in_ip.s_addr) > htonl(right->in_ip.s_addr))
481 		return GREATER;
482 	return EQUAL;
483 }
484 
485 int
sortbyto(left,right)486 sortbyto(left, right)
487 	register struct t_entry *left;
488 	register struct t_entry *right;
489 {
490 	if (htonl(left->out_ip.s_addr) < htonl(right->out_ip.s_addr))
491 		return LESS;
492 	if (htonl(left->out_ip.s_addr) > htonl(right->out_ip.s_addr))
493 		return GREATER;
494 	return EQUAL;
495 }
496 
497 int
sortbypport(left,right)498 sortbypport(left, right)
499 	register struct t_entry *left;
500 	register struct t_entry *right;
501 {
502 	if (htons(left->p_port) < htons(right->p_port))
503 		return LESS;
504 	if (htons(left->p_port) > htons(right->p_port))
505 		return GREATER;
506 	return EQUAL;
507 }
508 
509 #if LAYOUT!=OLD
510 int
sortbyoport(left,right)511 sortbyoport(left, right)
512         register struct t_entry *left;
513         register struct t_entry *right;
514 {
515         if (htons(left->o_port) < htons(right->o_port))
516                 return LESS;
517         if (htons(left->o_port) > htons(right->o_port))
518                 return GREATER;
519         return EQUAL;
520 }
521 #endif
522 
523 int
sortbysize(left,right)524 sortbysize(left, right)
525 	register struct t_entry *left;
526 	register struct t_entry *right;
527 {
528 	if (left->n_psize < right->n_psize)
529 		return GREATER;
530 	if (left->n_psize > right->n_psize)
531 		return LESS;
532 	return EQUAL;
533 }
534 
535 
traf_print()536 void traf_print()
537 {
538 	register int i, j;
539 	u_int64_t abytes = 0, dbytes = 0;
540 	struct protoent *protoent_p; /* for getprotobynumber() */
541 
542 	char buf[MAXHOSTNAMELEN + 1];
543 #if LAYOUT==OLD
544 	char *port, *user, *proto;
545 #else
546 	char *s_port, *d_port, *proto;
547 #endif
548 	for (i = 0; i < s.t_size; i++)
549 		abytes += sum[i].n_psize, dbytes += sum[i].n_bytes;
550 	if (rflag) {
551 		printf("%qu\n", abytes);
552 		return;
553 	}
554 	qsort(sum, s.t_size, sizeof(struct t_entry), sortbysize);
555 	switch ( order ){
556 	case ORDER_TO:
557 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbyto);
558 		break;
559 	case ORDER_FROM:
560 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbyfrom);
561 		break;
562 	case ORDER_SIZE:
563 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbysize);
564 		break;
565 	case ORDER_DPORT:
566 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbypport);
567 		break;
568 #if LAYOUT!=OLD
569 	case ORDER_SPORT:
570 		qsort(sum, s.t_size, sizeof(struct t_entry), sortbyoport);
571 		break;
572 #endif
573 	}
574 	if (!fvnum) {
575 		gethostname(buf, sizeof(buf));
576 		printf("\n (%s) %s at", device_name, buf);
577 		printf(" %.15s -", ctime((time_t *)&s.start) + 4);
578 		printf(" %.15s\n", ctime((time_t *)&s.stop) + 4);
579 		printf(" Summary: %qu data bytes, %qu all bytes, %u records\n",
580 		       dbytes, abytes, s.t_size);
581 		printf("\
582      From           Port         To            Port  Proto     Data       All\n");
583 	}
584 	setprotoent(1);
585 	for (i = 0; i < s.t_size; i++) {
586 #if LAYOUT==OLD
587 		port = "undef";
588 #else
589 		s_port = "";
590 		d_port = "";
591 #endif
592 		switch(sum[i].ip_protocol) {
593 			case IPPROTO_TCP:
594 #if LAYOUT==OLD
595 				if (sum[i].p_port)
596 					port = tcpport_string(sum[i].p_port);
597 #else
598 				if (sum[i].p_port || sum[i].o_port)
599 				{	s_port = tcpport_string(sum[i].o_port);
600 					d_port = tcpport_string(sum[i].p_port);
601 				}
602 #endif
603 /*				proto = "tcp";	*/
604 				break;
605 			case IPPROTO_UDP:
606 #if LAYOUT==OLD
607 				if (sum[i].p_port)
608 					port = udpport_string(sum[i].p_port);
609 #else
610 				if (sum[i].p_port || sum[i].o_port)
611 				{	s_port = udpport_string(sum[i].o_port);
612 					d_port = udpport_string(sum[i].p_port);
613 				}
614 #endif
615 /*				proto = "udp";	*/
616 				break;
617 /*
618 			case IPPROTO_ICMP:
619 				proto = "icmp";
620 				break;
621 			case IPPROTO_EGP:
622 				proto = "egp";
623 				break;
624 			case IPPROTO_OSPF:
625 				proto = "ospf";
626 				break;
627 			case IPPROTO_IGMP:
628 				proto = "igmp";
629 				break;
630 			default:
631 				proto = "unkn";
632 */
633 		}
634 		/* This run slowly, hoverer support all protocols, listed
635 		 * in /etc/protocols */
636 		if( (protoent_p = getprotobynumber(sum[i].ip_protocol)) != NULL ){
637 			proto = protoent_p->p_name;
638 		}else{
639 			proto = "unkn";
640 		}
641 
642 #if LAYOUT==OLD
643 		if (sum[i].p_port)	user = "client";
644 		else			user = "none";
645 #endif
646 		if (fvnum) {
647 			for (j = 0; j < fvnum; j++)
648 				switch (fv[j].cmd) {
649 				case FROM:
650 					printf(fv[j].format, ipaddr_string(&sum[i].in_ip));
651 					break;
652 				case TO:
653 					printf(fv[j].format, ipaddr_string(&sum[i].out_ip));
654 					break;
655 #if LAYOUT==OLD
656 				case SPORT:
657 					printf(fv[j].format,
658 					       (sum[i].who_srv & 1) ? port : user);
659 					break;
660 				case DPORT:
661 					printf(fv[j].format,
662 					       (sum[i].who_srv & 2) ? port : user);
663 					break;
664 #else
665 				case SPORT:
666 					printf(fv[j].format,
667 					       s_port);
668 					break;
669 				case DPORT:
670 					printf(fv[j].format,
671 					       d_port);
672 					break;
673 #endif
674 				case PROTO:
675 					printf(fv[j].format, proto);
676 					break;
677 				case BYTES:
678 					printf(fv[j].format, sum[i].n_bytes);
679 					break;
680 				case PSIZE:
681 					printf(fv[j].format, sum[i].n_psize);
682 					break;
683 				case FTIME:
684 					strftime(buf, sizeof(buf), fv[j].format,
685 						 localtime((time_t *)&s.start));
686 					printf("%s", buf);
687 					break;
688 				case LTIME:
689 					strftime(buf, sizeof(buf), fv[j].format,
690 						 localtime((time_t *)&s.stop));
691 					printf("%s", buf);
692 					break;
693 				}
694 		} else {
695 #if LAYOUT==OLD
696 			printf("%-18.18s %-6.6s  ", ipaddr_string(&sum[i].in_ip),
697 			       (sum[i].who_srv & 1) ? port : user);
698 			printf("%-18.18s %-6.6s  ", ipaddr_string(&sum[i].out_ip),
699 			       (sum[i].who_srv & 2) ? port : user);
700 			printf("%-4.4s %9lu %10lu\n", proto, sum[i].n_bytes,
701 			       sum[i].n_psize);
702 #else
703 			printf("%-18.18s %-6.6s  ", ipaddr_string(&sum[i].in_ip),
704 			       s_port);
705 			printf("%-18.18s %-6.6s  ", ipaddr_string(&sum[i].out_ip),
706 			       d_port);
707 			printf("%-4.4s %9lu %10lu\n", proto, sum[i].n_bytes,
708 			       sum[i].n_psize);
709 #endif
710 		}
711 	}
712 	endprotoent();
713 }
714 
715 /* Read trafd.log cycle */
716 void
log_loop(fd,fdw)717 log_loop(fd, fdw)
718 	register FILE *fd;
719 	FILE *fdw;
720 {
721 	struct t_header h;
722 	int retval;
723 
724 	while (getheader(fd, &h)) {
725 		no++;
726 		if (range(&h) == 2) {
727 			if (lflag) retval = contents(fd, &h);
728 			else retval = ioblock(fd, &h);
729 			if (retval) n_call++;
730 			else {
731 				warning( "Error reading data file\n" );
732 				break;
733 			}
734 			if (aflag && !sflag) {
735 				if (fdw) traf_write(fdw);
736 				else traf_print();
737 			}
738 		} else
739 			fseek(fd, h.t_size * sizeof(struct t_entry), SEEK_CUR);
740 	}
741 	if (aflag && !sflag)
742 		return;
743 	if (lflag) {
744 		if (rflag)
745 			printf("%d\n", n_call);
746 		return;
747 	}
748 	if (fdw) traf_write(fdw);
749 	else traf_print();
750 
751 	return;
752 }
753