xref: /dragonfly/usr.bin/netstat/if.c (revision 851dc90d)
1 /*
2  * Copyright (c) 1983, 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)if.c	8.3 (Berkeley) 4/28/95
34  * $FreeBSD: src/usr.bin/netstat/if.c,v 1.32.2.9 2001/09/17 14:35:46 ru Exp $
35  * $DragonFly: src/usr.bin/netstat/if.c,v 1.3 2003/08/08 04:18:43 dillon Exp $
36  */
37 
38 #include <sys/types.h>
39 #include <sys/protosw.h>
40 #include <sys/socket.h>
41 #include <sys/sysctl.h>
42 #include <sys/time.h>
43 
44 #include <net/if.h>
45 #include <net/if_var.h>
46 #include <net/if_dl.h>
47 #include <net/if_types.h>
48 #include <net/bridge/bridge.h>
49 #include <net/ethernet.h>
50 #include <netinet/in.h>
51 #include <netinet/in_var.h>
52 #include <netproto/ipx/ipx.h>
53 #include <netproto/ipx/ipx_if.h>
54 #ifdef NS
55 #include <netproto/ns/ns.h>
56 #include <netproto/ns/ns_if.h>
57 #endif
58 #ifdef ISO
59 #include <netiso/iso.h>
60 #include <netiso/iso_var.h>
61 #endif
62 #include <arpa/inet.h>
63 
64 #include <signal.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <unistd.h>
69 
70 #include "netstat.h"
71 
72 #define	YES	1
73 #define	NO	0
74 
75 static void sidewaysintpr (u_int, u_long);
76 static void catchalarm (int);
77 
78 #ifdef INET6
79 char *netname6 (struct sockaddr_in6 *, struct in6_addr *);
80 static char ntop_buf[INET6_ADDRSTRLEN];		/* for inet_ntop() */
81 static int bdg_done;
82 #endif
83 
84 /* print bridge statistics */
85 void
86 bdg_stats(u_long dummy __unused, char *name, int af __unused)
87 {
88     int i;
89     size_t slen ;
90     struct bdg_stats s ;
91     int mib[4] ;
92 
93     slen = sizeof(s);
94 
95     mib[0] = CTL_NET ;
96     mib[1] = PF_LINK ;
97     mib[2] = IFT_ETHER ;
98     mib[3] = PF_BDG ;
99     if (sysctl(mib,4, &s,&slen,NULL,0)==-1)
100 	return ; /* no bridging */
101 #ifdef INET6
102     if (bdg_done != 0)
103 	return;
104     else
105 	bdg_done = 1;
106 #endif
107     printf("-- Bridging statistics (%s) --\n", name) ;
108     printf(
109 "Name          In      Out  Forward     Drop    Bcast    Mcast    Local  Unknown\n");
110     for (i = 0 ; i < 16 ; i++) {
111 	if (s.s[i].name[0])
112 	printf("%-6s %9ld%9ld%9ld%9ld%9ld%9ld%9ld%9ld\n",
113 	  s.s[i].name,
114 	  s.s[i].p_in[(int)BDG_IN],
115 	  s.s[i].p_in[(int)BDG_OUT],
116 	  s.s[i].p_in[(int)BDG_FORWARD],
117 	  s.s[i].p_in[(int)BDG_DROP],
118 	  s.s[i].p_in[(int)BDG_BCAST],
119 	  s.s[i].p_in[(int)BDG_MCAST],
120 	  s.s[i].p_in[(int)BDG_LOCAL],
121 	  s.s[i].p_in[(int)BDG_UNKNOWN] );
122     }
123 }
124 
125 
126 
127 
128 /*
129  * Display a formatted value, or a '-' in the same space.
130  */
131 static void
132 show_stat(const char *fmt, int width, u_long value, short showvalue)
133 {
134 	char newfmt[32];
135 
136 	/* Construct the format string */
137 	if (showvalue) {
138 		sprintf(newfmt, "%%%d%s", width, fmt);
139 		printf(newfmt, value);
140 	} else {
141 		sprintf(newfmt, "%%%ds", width);
142 		printf(newfmt, "-");
143 	}
144 }
145 
146 
147 
148 /*
149  * Print a description of the network interfaces.
150  */
151 void
152 intpr(int interval, u_long ifnetaddr, void (*pfunc)(char *))
153 {
154 	struct ifnet ifnet;
155 	struct ifnethead ifnethead;
156 	union {
157 		struct ifaddr ifa;
158 		struct in_ifaddr in;
159 #ifdef INET6
160 		struct in6_ifaddr in6;
161 #endif
162 		struct ipx_ifaddr ipx;
163 #ifdef NS
164 		struct ns_ifaddr ns;
165 #endif
166 #ifdef ISO
167 		struct iso_ifaddr iso;
168 #endif
169 	} ifaddr;
170 	u_long ifaddraddr;
171 	u_long ifaddrfound;
172 	u_long ifnetfound;
173 	u_long opackets;
174 	u_long ipackets;
175 	u_long obytes;
176 	u_long ibytes;
177 	u_long oerrors;
178 	u_long ierrors;
179 	u_long collisions;
180 	short timer;
181 	int drops;
182 	struct sockaddr *sa = NULL;
183 	char name[32], tname[16];
184 	short network_layer;
185 	short link_layer;
186 
187 	if (ifnetaddr == 0) {
188 		printf("ifnet: symbol not defined\n");
189 		return;
190 	}
191 	if (interval) {
192 		sidewaysintpr((unsigned)interval, ifnetaddr);
193 		return;
194 	}
195 	if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead))
196 		return;
197 	ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
198 	if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
199 		return;
200 
201 	if (!pfunc) {
202 		printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
203 		       "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
204 		if (bflag)
205 			printf(" %10.10s","Ibytes");
206 		printf(" %8.8s %5.5s", "Opkts", "Oerrs");
207 		if (bflag)
208 			printf(" %10.10s","Obytes");
209 		printf(" %5s", "Coll");
210 		if (tflag)
211 			printf(" %s", "Time");
212 		if (dflag)
213 			printf(" %s", "Drop");
214 		putchar('\n');
215 	}
216 	ifaddraddr = 0;
217 	while (ifnetaddr || ifaddraddr) {
218 		struct sockaddr_in *sin;
219 #ifdef INET6
220 		struct sockaddr_in6 *sin6;
221 #endif
222 		register char *cp;
223 		int n, m;
224 
225 		network_layer = 0;
226 		link_layer = 0;
227 
228 		if (ifaddraddr == 0) {
229 			ifnetfound = ifnetaddr;
230 			if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) ||
231 			    kread((u_long)ifnet.if_name, tname, 16))
232 				return;
233 			tname[15] = '\0';
234 			ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link);
235 			snprintf(name, 32, "%s%d", tname, ifnet.if_unit);
236 			if (interface != 0 && (strcmp(name, interface) != 0))
237 				continue;
238 			cp = index(name, '\0');
239 
240 			if (pfunc) {
241 				(*pfunc)(name);
242 				continue;
243 			}
244 
245 			if ((ifnet.if_flags&IFF_UP) == 0)
246 				*cp++ = '*';
247 			*cp = '\0';
248 			ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead);
249 		}
250 		ifaddrfound = ifaddraddr;
251 
252 		/*
253 		 * Get the interface stats.  These may get
254 		 * overriden below on a per-interface basis.
255 		 */
256 		opackets = ifnet.if_opackets;
257 		ipackets = ifnet.if_ipackets;
258 		obytes = ifnet.if_obytes;
259 		ibytes = ifnet.if_ibytes;
260 		oerrors = ifnet.if_oerrors;
261 		ierrors = ifnet.if_ierrors;
262 		collisions = ifnet.if_collisions;
263 		timer = ifnet.if_timer;
264 		drops = ifnet.if_snd.ifq_drops;
265 
266 		if (ifaddraddr == 0) {
267 			printf("%-5.5s %-5lu ", name, ifnet.if_mtu);
268 			printf("%-13.13s ", "none");
269 			printf("%-15.15s ", "none");
270 		} else {
271 			if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
272 				ifaddraddr = 0;
273 				continue;
274 			}
275 #define CP(x) ((char *)(x))
276 			cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
277 				CP(&ifaddr);
278 			sa = (struct sockaddr *)cp;
279 			if (af != AF_UNSPEC && sa->sa_family != af) {
280 				ifaddraddr =
281 				    (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
282 				continue;
283 			}
284 			printf("%-5.5s %-5lu ", name, ifnet.if_mtu);
285 			switch (sa->sa_family) {
286 			case AF_UNSPEC:
287 				printf("%-13.13s ", "none");
288 				printf("%-15.15s ", "none");
289 				break;
290 			case AF_INET:
291 				sin = (struct sockaddr_in *)sa;
292 #ifdef notdef
293 				/* can't use inet_makeaddr because kernel
294 				 * keeps nets unshifted.
295 				 */
296 				in = inet_makeaddr(ifaddr.in.ia_subnet,
297 					INADDR_ANY);
298 				printf("%-13.13s ", netname(in.s_addr,
299 				    ifaddr.in.ia_subnetmask));
300 #else
301 				printf("%-13.13s ",
302 				    netname(htonl(ifaddr.in.ia_subnet),
303 				    ifaddr.in.ia_subnetmask));
304 #endif
305 				printf("%-15.15s ",
306 				    routename(sin->sin_addr.s_addr));
307 
308 				network_layer = 1;
309 				break;
310 #ifdef INET6
311 			case AF_INET6:
312 				sin6 = (struct sockaddr_in6 *)sa;
313 				printf("%-11.11s ",
314 				       netname6(&ifaddr.in6.ia_addr,
315 						&ifaddr.in6.ia_prefixmask.sin6_addr));
316 				printf("%-17.17s ",
317 				    (char *)inet_ntop(AF_INET6,
318 					&sin6->sin6_addr,
319 					ntop_buf, sizeof(ntop_buf)));
320 
321 				network_layer = 1;
322 				break;
323 #endif /*INET6*/
324 			case AF_IPX:
325 				{
326 				struct sockaddr_ipx *sipx =
327 					(struct sockaddr_ipx *)sa;
328 				u_long net;
329 				char netnum[10];
330 
331 				*(union ipx_net *) &net = sipx->sipx_addr.x_net;
332 				sprintf(netnum, "%lx", (u_long)ntohl(net));
333 				printf("ipx:%-8s  ", netnum);
334 /*				printf("ipx:%-8s ", netname(net, 0L)); */
335 				printf("%-15s ",
336 				    ipx_phost((struct sockaddr *)sipx));
337 				}
338 				break;
339 
340 			case AF_APPLETALK:
341 				printf("atalk:%-12.12s ",atalk_print(sa,0x10) );
342 				printf("%-9.9s  ",atalk_print(sa,0x0b) );
343 				break;
344 #ifdef NS
345 			case AF_NS:
346 				{
347 				struct sockaddr_ns *sns =
348 					(struct sockaddr_ns *)sa;
349 				u_long net;
350 				char netnum[10];
351 
352 				*(union ns_net *) &net = sns->sns_addr.x_net;
353 				sprintf(netnum, "%lxH", ntohl(net));
354 				upHex(netnum);
355 				printf("ns:%-8s ", netnum);
356 				printf("%-15s ",
357 				    ns_phost((struct sockaddr *)sns));
358 				}
359 				break;
360 #endif
361 			case AF_LINK:
362 				{
363 				struct sockaddr_dl *sdl =
364 					(struct sockaddr_dl *)sa;
365 				char linknum[10];
366 				cp = (char *)LLADDR(sdl);
367 				n = sdl->sdl_alen;
368 				sprintf(linknum, "<Link#%d>", sdl->sdl_index);
369 				m = printf("%-11.11s ", linknum);
370 				}
371 				goto hexprint;
372 			default:
373 				m = printf("(%d)", sa->sa_family);
374 				for (cp = sa->sa_len + (char *)sa;
375 					--cp > sa->sa_data && (*cp == 0);) {}
376 				n = cp - sa->sa_data + 1;
377 				cp = sa->sa_data;
378 			hexprint:
379 				while (--n >= 0)
380 					m += printf("%02x%c", *cp++ & 0xff,
381 						    n > 0 ? ':' : ' ');
382 				m = 30 - m;
383 				while (m-- > 0)
384 					putchar(' ');
385 
386 				link_layer = 1;
387 				break;
388 			}
389 
390 			/*
391 			 * Fixup the statistics for interfaces that
392 			 * update stats for their network addresses
393 			 */
394 			if (network_layer) {
395 				opackets = ifaddr.in.ia_ifa.if_opackets;
396 				ipackets = ifaddr.in.ia_ifa.if_ipackets;
397 				obytes = ifaddr.in.ia_ifa.if_obytes;
398 				ibytes = ifaddr.in.ia_ifa.if_ibytes;
399 			}
400 
401 			ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
402 		}
403 
404 		show_stat("lu", 8, ipackets, link_layer|network_layer);
405 		printf(" ");
406 		show_stat("lu", 5, ierrors, link_layer);
407 		printf(" ");
408 		if (bflag) {
409 			show_stat("lu", 10, ibytes, link_layer|network_layer);
410 			printf(" ");
411 		}
412 		show_stat("lu", 8, opackets, link_layer|network_layer);
413 		printf(" ");
414 		show_stat("lu", 5, oerrors, link_layer);
415 		printf(" ");
416 		if (bflag) {
417 			show_stat("lu", 10, obytes, link_layer|network_layer);
418 			printf(" ");
419 		}
420 		show_stat("lu", 5, collisions, link_layer);
421 		if (tflag) {
422 			printf(" ");
423 			show_stat("d", 3, timer, link_layer);
424 		}
425 		if (dflag) {
426 			printf(" ");
427 			show_stat("d", 3, drops, link_layer);
428 		}
429 		putchar('\n');
430 		if (aflag && ifaddrfound) {
431 			/*
432 			 * Print family's multicast addresses
433 			 */
434 			u_long multiaddr;
435 			struct ifmultiaddr ifma;
436 			union {
437 				struct sockaddr sa;
438 				struct sockaddr_in in;
439 #ifdef INET6
440 				struct sockaddr_in6 in6;
441 #endif /* INET6 */
442 				struct sockaddr_dl dl;
443 			} msa;
444 			const char *fmt;
445 
446 			for(multiaddr = (u_long)ifnet.if_multiaddrs.lh_first;
447 			    multiaddr;
448 			    multiaddr = (u_long)ifma.ifma_link.le_next) {
449 				if (kread(multiaddr, (char *)&ifma,
450 					  sizeof ifma))
451 					break;
452 				if (kread((u_long)ifma.ifma_addr, (char *)&msa,
453 					  sizeof msa))
454 					break;
455 				if (msa.sa.sa_family != sa->sa_family)
456 					continue;
457 
458 				fmt = 0;
459 				switch (msa.sa.sa_family) {
460 				case AF_INET:
461 					fmt = routename(msa.in.sin_addr.s_addr);
462 					break;
463 #ifdef INET6
464 				case AF_INET6:
465 					printf("%23s %-19.19s(refs: %d)\n", "",
466 					       inet_ntop(AF_INET6,
467 							 &msa.in6.sin6_addr,
468 							 ntop_buf,
469 							 sizeof(ntop_buf)),
470 					       ifma.ifma_refcount);
471 					break;
472 #endif /* INET6 */
473 				case AF_LINK:
474 					switch (msa.dl.sdl_type) {
475 					case IFT_ETHER:
476 					case IFT_FDDI:
477 						fmt = ether_ntoa(
478 							(struct ether_addr *)
479 							LLADDR(&msa.dl));
480 						break;
481 					}
482 					break;
483 				}
484 				if (fmt)
485 					printf("%23s %s\n", "", fmt);
486 			}
487 		}
488 	}
489 }
490 
491 struct	iftot {
492 	SLIST_ENTRY(iftot) chain;
493 	char	ift_name[16];		/* interface name */
494 	u_long	ift_ip;			/* input packets */
495 	u_long	ift_ie;			/* input errors */
496 	u_long	ift_op;			/* output packets */
497 	u_long	ift_oe;			/* output errors */
498 	u_long	ift_co;			/* collisions */
499 	u_int	ift_dr;			/* drops */
500 	u_long	ift_ib;			/* input bytes */
501 	u_long	ift_ob;			/* output bytes */
502 };
503 
504 u_char	signalled;			/* set if alarm goes off "early" */
505 
506 /*
507  * Print a running summary of interface statistics.
508  * Repeat display every interval seconds, showing statistics
509  * collected over that interval.  Assumes that interval is non-zero.
510  * First line printed at top of screen is always cumulative.
511  * XXX - should be rewritten to use ifmib(4).
512  */
513 static void
514 sidewaysintpr(unsigned interval, u_long off)
515 {
516 	struct ifnet ifnet;
517 	u_long firstifnet;
518 	struct ifnethead ifnethead;
519 	struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
520 	register int line;
521 	int oldmask, first;
522 	u_long interesting_off;
523 
524 	if (kread(off, (char *)&ifnethead, sizeof ifnethead))
525 		return;
526 	firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
527 
528 	if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
529 		printf("malloc failed\n");
530 		exit(1);
531 	}
532 	memset(iftot, 0, sizeof(struct iftot));
533 
534 	interesting = NULL;
535 	interesting_off = 0;
536 	for (off = firstifnet, ip = iftot; off;) {
537 		char name[16], tname[16];
538 
539 		if (kread(off, (char *)&ifnet, sizeof ifnet))
540 			break;
541 		if (kread((u_long)ifnet.if_name, tname, 16))
542 			break;
543 		tname[15] = '\0';
544 		snprintf(name, 16, "%s%d", tname, ifnet.if_unit);
545 		if (interface && strcmp(name, interface) == 0) {
546 			interesting = ip;
547 			interesting_off = off;
548 		}
549 		snprintf(ip->ift_name, 16, "(%s)", name);;
550 		if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
551 			printf("malloc failed\n");
552 			exit(1);
553 		}
554 		memset(ipn, 0, sizeof(struct iftot));
555 		SLIST_NEXT(ip, chain) = ipn;
556 		ip = ipn;
557 		off = (u_long)TAILQ_NEXT(&ifnet, if_link);
558 	}
559 	if ((total = malloc(sizeof(struct iftot))) == NULL) {
560 		printf("malloc failed\n");
561 		exit(1);
562 	}
563 	memset(total, 0, sizeof(struct iftot));
564 	if ((sum = malloc(sizeof(struct iftot))) == NULL) {
565 		printf("malloc failed\n");
566 		exit(1);
567 	}
568 	memset(sum, 0, sizeof(struct iftot));
569 
570 
571 	(void)signal(SIGALRM, catchalarm);
572 	signalled = NO;
573 	(void)alarm(interval);
574 	first = 1;
575 banner:
576 	printf("%17s %14s %16s", "input",
577 	    interesting ? interesting->ift_name : "(Total)", "output");
578 	putchar('\n');
579 	printf("%10s %5s %10s %10s %5s %10s %5s",
580 	    "packets", "errs", "bytes", "packets", "errs", "bytes", "colls");
581 	if (dflag)
582 		printf(" %5.5s", "drops");
583 	putchar('\n');
584 	fflush(stdout);
585 	line = 0;
586 loop:
587 	if (interesting != NULL) {
588 		ip = interesting;
589 		if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) {
590 			printf("???\n");
591 			exit(1);
592 		};
593 		if (!first) {
594 			printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu",
595 				ifnet.if_ipackets - ip->ift_ip,
596 				ifnet.if_ierrors - ip->ift_ie,
597 				ifnet.if_ibytes - ip->ift_ib,
598 				ifnet.if_opackets - ip->ift_op,
599 				ifnet.if_oerrors - ip->ift_oe,
600 				ifnet.if_obytes - ip->ift_ob,
601 				ifnet.if_collisions - ip->ift_co);
602 			if (dflag)
603 				printf(" %5u", ifnet.if_snd.ifq_drops - ip->ift_dr);
604 		}
605 		ip->ift_ip = ifnet.if_ipackets;
606 		ip->ift_ie = ifnet.if_ierrors;
607 		ip->ift_ib = ifnet.if_ibytes;
608 		ip->ift_op = ifnet.if_opackets;
609 		ip->ift_oe = ifnet.if_oerrors;
610 		ip->ift_ob = ifnet.if_obytes;
611 		ip->ift_co = ifnet.if_collisions;
612 		ip->ift_dr = ifnet.if_snd.ifq_drops;
613 	} else {
614 		sum->ift_ip = 0;
615 		sum->ift_ie = 0;
616 		sum->ift_ib = 0;
617 		sum->ift_op = 0;
618 		sum->ift_oe = 0;
619 		sum->ift_ob = 0;
620 		sum->ift_co = 0;
621 		sum->ift_dr = 0;
622 		for (off = firstifnet, ip = iftot;
623 		     off && SLIST_NEXT(ip, chain) != NULL;
624 		     ip = SLIST_NEXT(ip, chain)) {
625 			if (kread(off, (char *)&ifnet, sizeof ifnet)) {
626 				off = 0;
627 				continue;
628 			}
629 			sum->ift_ip += ifnet.if_ipackets;
630 			sum->ift_ie += ifnet.if_ierrors;
631 			sum->ift_ib += ifnet.if_ibytes;
632 			sum->ift_op += ifnet.if_opackets;
633 			sum->ift_oe += ifnet.if_oerrors;
634 			sum->ift_ob += ifnet.if_obytes;
635 			sum->ift_co += ifnet.if_collisions;
636 			sum->ift_dr += ifnet.if_snd.ifq_drops;
637 			off = (u_long)TAILQ_NEXT(&ifnet, if_link);
638 		}
639 		if (!first) {
640 			printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu",
641 				sum->ift_ip - total->ift_ip,
642 				sum->ift_ie - total->ift_ie,
643 				sum->ift_ib - total->ift_ib,
644 				sum->ift_op - total->ift_op,
645 				sum->ift_oe - total->ift_oe,
646 				sum->ift_ob - total->ift_ob,
647 				sum->ift_co - total->ift_co);
648 			if (dflag)
649 				printf(" %5u", sum->ift_dr - total->ift_dr);
650 		}
651 		*total = *sum;
652 	}
653 	if (!first)
654 		putchar('\n');
655 	fflush(stdout);
656 	oldmask = sigblock(sigmask(SIGALRM));
657 	if (! signalled) {
658 		sigpause(0);
659 	}
660 	sigsetmask(oldmask);
661 	signalled = NO;
662 	(void)alarm(interval);
663 	line++;
664 	first = 0;
665 	if (line == 21)
666 		goto banner;
667 	else
668 		goto loop;
669 	/*NOTREACHED*/
670 }
671 
672 /*
673  * Called if an interval expires before sidewaysintpr has completed a loop.
674  * Sets a flag to not wait for the alarm.
675  */
676 static void
677 catchalarm(int signo __unused)
678 {
679 	signalled = YES;
680 }
681