xref: /dragonfly/usr.bin/netstat/if.c (revision 19b217af)
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. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#)if.c	8.3 (Berkeley) 4/28/95
30  * $FreeBSD: src/usr.bin/netstat/if.c,v 1.32.2.9 2001/09/17 14:35:46 ru Exp $
31  */
32 
33 #define _KERNEL_STRUCTURES
34 #include <sys/param.h>
35 #include <sys/protosw.h>
36 #include <sys/socket.h>
37 #include <sys/sysctl.h>
38 #include <sys/time.h>
39 
40 #include <net/if.h>
41 #include <net/if_var.h>
42 #include <net/if_dl.h>
43 #include <net/if_types.h>
44 #include <net/ethernet.h>
45 #include <netinet/in.h>
46 #include <netinet/in_var.h>
47 #include <netproto/ipx/ipx.h>
48 #include <netproto/ipx/ipx_if.h>
49 #ifdef ISO
50 #include <netiso/iso.h>
51 #include <netiso/iso_var.h>
52 #endif
53 #include <arpa/inet.h>
54 
55 #include <signal.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <unistd.h>
60 
61 #include "netstat.h"
62 
63 #define	YES	1
64 #define	NO	0
65 
66 static void sidewaysintpr (u_int, u_long, int);
67 static void catchalarm (int);
68 
69 #ifdef INET6
70 static char ntop_buf[INET6_ADDRSTRLEN];		/* for inet_ntop() */
71 #endif
72 
73 
74 /*
75  * Display a formatted value, or a '-' in the same space.
76  */
77 static void
78 show_stat(const char *fmt, int width, u_long value, short showvalue)
79 {
80 	char newfmt[32];
81 
82 	/* Construct the format string */
83 	if (showvalue) {
84 		sprintf(newfmt, "%%%d%s", width, fmt);
85 		printf(newfmt, value);
86 	} else {
87 		sprintf(newfmt, "%%%ds", width);
88 		printf(newfmt, "-");
89 	}
90 }
91 
92 
93 
94 /*
95  * Print a description of the network interfaces.
96  */
97 void
98 intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *), u_long ncpusaddr)
99 {
100 	struct ifnet ifnet;
101 	struct ifdata_pcpu ifdata;
102 	struct ifaddr_container ifac;
103 	struct ifnethead ifnethead;
104 	union {
105 		struct ifaddr ifa;
106 		struct in_ifaddr in;
107 #ifdef INET6
108 		struct in6_ifaddr in6;
109 #endif
110 		struct ipx_ifaddr ipx;
111 #ifdef ISO
112 		struct iso_ifaddr iso;
113 #endif
114 	} ifaddr;
115 	u_long ifaddraddr;
116 	u_long ifaddrcont_addr;
117 	u_long ifaddrfound;
118 	u_long ifdataaddr;
119 	u_long opackets;
120 	u_long ipackets;
121 	u_long obytes;
122 	u_long ibytes;
123 	u_long oerrors;
124 	u_long ierrors;
125 	u_long collisions;
126 	short timer;
127 	int drops;
128 	struct sockaddr *sa = NULL;
129 	char name[IFNAMSIZ];
130 	short network_layer;
131 	short link_layer;
132 	int ncpus;
133 
134 	if (kread(ncpusaddr, (char *)&ncpus, sizeof(ncpus)))
135 		return;
136 
137 	if (ifnetaddr == 0) {
138 		printf("ifnet: symbol not defined\n");
139 		return;
140 	}
141 	if (interval1) {
142 		sidewaysintpr((unsigned)interval1, ifnetaddr, ncpus);
143 		return;
144 	}
145 	if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead))
146 		return;
147 	ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
148 	if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
149 		return;
150 
151 	if (!pfunc) {
152 		printf("%-7.7s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
153 		       "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
154 		if (bflag)
155 			printf(" %10.10s","Ibytes");
156 		printf(" %8.8s %5.5s", "Opkts", "Oerrs");
157 		if (bflag)
158 			printf(" %10.10s","Obytes");
159 		printf(" %5s", "Coll");
160 		if (tflag)
161 			printf(" %s", "Time");
162 		if (dflag)
163 			printf(" %s", "Drop");
164 		putchar('\n');
165 	}
166 	ifaddraddr = 0;
167 	ifaddrcont_addr = 0;
168 	while (ifnetaddr || ifaddraddr) {
169 		struct sockaddr_in *sin;
170 #ifdef INET6
171 		struct sockaddr_in6 *sin6;
172 #endif
173 		char *cp;
174 		int n, m, cpu;
175 
176 		network_layer = 0;
177 		link_layer = 0;
178 
179 		if (ifaddraddr == 0) {
180 			struct ifaddrhead head;
181 
182 			if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
183 				return;
184 			strlcpy(name, ifnet.if_xname, sizeof(name));
185 			ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link);
186 			if (interface != 0 && (strcmp(name, interface) != 0))
187 				continue;
188 			cp = strchr(name, '\0');
189 
190 			if (pfunc) {
191 				(*pfunc)(name);
192 				continue;
193 			}
194 
195 			if ((ifnet.if_flags&IFF_UP) == 0)
196 				*cp++ = '*';
197 			*cp = '\0';
198 
199 			if (kread((u_long)ifnet.if_addrheads,
200 				  (char *)&head, sizeof(head)))
201 				return;
202 
203 			ifaddrcont_addr =
204 				(u_long)TAILQ_FIRST(&head);
205 			if (ifaddrcont_addr == 0) {
206 				ifaddraddr = 0;
207 			} else {
208 				if (kread(ifaddrcont_addr, (char *)&ifac,
209 					  sizeof(ifac)))
210 					return;
211 				ifaddraddr = (u_long)ifac.ifa;
212 			}
213 		}
214 		ifaddrfound = ifaddraddr;
215 
216 		/*
217 		 * Get the interface stats.  These may get
218 		 * overriden below on a per-interface basis.
219 		 */
220 		ifdataaddr = (u_long)ifnet.if_data_pcpu;
221 		if (kread(ifdataaddr, (char *)&ifdata, sizeof(ifdata)))
222 			return;
223 		opackets = ifdata.ifd_opackets;
224 		ipackets = ifdata.ifd_ipackets;
225 		obytes = ifdata.ifd_obytes;
226 		ibytes = ifdata.ifd_ibytes;
227 		oerrors = ifdata.ifd_oerrors;
228 		ierrors = ifdata.ifd_ierrors;
229 		collisions = ifdata.ifd_collisions;
230 
231 		for (cpu = 1; cpu < ncpus; ++cpu) {
232 			if (kread(ifdataaddr + (cpu * sizeof(ifdata)),
233 			    (char *)&ifdata, sizeof(ifdata)))
234 				return;
235 			opackets += ifdata.ifd_opackets;
236 			ipackets += ifdata.ifd_ipackets;
237 			obytes += ifdata.ifd_obytes;
238 			ibytes += ifdata.ifd_ibytes;
239 			oerrors += ifdata.ifd_oerrors;
240 			ierrors += ifdata.ifd_ierrors;
241 			collisions += ifdata.ifd_collisions;
242 		}
243 
244 		timer = ifnet.if_timer;
245 		drops = 0;
246 
247 		if (ifaddraddr == 0) {
248 			printf("%-7.7s %-5lu ", name, ifnet.if_mtu);
249 			printf("%-13.13s ", "none");
250 			printf("%-15.15s ", "none");
251 		} else {
252 			if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
253 				ifaddraddr = 0;
254 				continue;
255 			}
256 
257 			ifaddr.ifa.if_ipackets = ifac.ifa_ipackets;
258 			ifaddr.ifa.if_ibytes = ifac.ifa_ibytes;
259 			ifaddr.ifa.if_opackets = ifac.ifa_opackets;
260 			ifaddr.ifa.if_obytes = ifac.ifa_obytes;
261 			for (cpu = 1; cpu < ncpus; ++cpu) {
262 				struct ifaddr_container nifac;
263 
264 				if (kread(ifaddrcont_addr +
265 				    (cpu * sizeof(nifac)),
266 				    (char *)&nifac, sizeof(nifac))) {
267 					ifaddraddr = 0;
268 					continue;
269 				}
270 				ifaddr.ifa.if_ipackets += nifac.ifa_ipackets;
271 				ifaddr.ifa.if_ibytes += nifac.ifa_ibytes;
272 				ifaddr.ifa.if_opackets += nifac.ifa_opackets;
273 				ifaddr.ifa.if_obytes += nifac.ifa_obytes;
274 			}
275 
276 #define CP(x) ((char *)(x))
277 			cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
278 				CP(&ifaddr);
279 			sa = (struct sockaddr *)cp;
280 			if (af != AF_UNSPEC && sa->sa_family != af) {
281 				ifaddrcont_addr =
282 					(u_long)TAILQ_NEXT(&ifac, ifa_link);
283 				if (ifaddrcont_addr == 0) {
284 					ifaddraddr = 0;
285 				} else {
286 					if (kread(ifaddrcont_addr,
287 					    (char *)&ifac, sizeof(ifac))) {
288 						ifaddraddr = 0;
289 						continue;
290 					}
291 					ifaddraddr = (u_long)ifac.ifa;
292 				}
293 				continue;
294 			}
295 			printf("%-7.7s %-5lu ", name, ifnet.if_mtu);
296 			switch (sa->sa_family) {
297 			case AF_UNSPEC:
298 				printf("%-13.13s ", "none");
299 				printf("%-15.15s ", "none");
300 				break;
301 			case AF_INET:
302 				sin = (struct sockaddr_in *)sa;
303 #ifdef notdef
304 				/* can't use inet_makeaddr because kernel
305 				 * keeps nets unshifted.
306 				 */
307 				in = inet_makeaddr(ifaddr.in.ia_subnet,
308 					INADDR_ANY);
309 				printf("%-13.13s ", netname(in.s_addr,
310 				    ifaddr.in.ia_subnetmask));
311 #else
312 				printf("%-13.13s ",
313 				    netname(htonl(ifaddr.in.ia_subnet),
314 				    ifaddr.in.ia_subnetmask));
315 #endif
316 				printf("%-15.15s ",
317 				    routename(sin->sin_addr.s_addr));
318 
319 				network_layer = 1;
320 				break;
321 #ifdef INET6
322 			case AF_INET6:
323 				sin6 = (struct sockaddr_in6 *)sa;
324 				printf("%-11.11s ",
325 				       netname6(&ifaddr.in6.ia_addr,
326 						&ifaddr.in6.ia_prefixmask.sin6_addr));
327 				printf("%-17.17s ",
328 				    inet_ntop(AF_INET6,
329 					&sin6->sin6_addr,
330 					ntop_buf, sizeof(ntop_buf)));
331 
332 				network_layer = 1;
333 				break;
334 #endif /*INET6*/
335 			case AF_IPX:
336 				{
337 				struct sockaddr_ipx *sipx =
338 					(struct sockaddr_ipx *)sa;
339 				u_long net;
340 				char netnum[10];
341 
342 				*(union ipx_net *) &net = sipx->sipx_addr.x_net;
343 				sprintf(netnum, "%lx", (u_long)ntohl(net));
344 				printf("ipx:%-8s  ", netnum);
345 /*				printf("ipx:%-8s ", netname(net, 0L)); */
346 				printf("%-15s ",
347 				    ipx_phost((struct sockaddr *)sipx));
348 				}
349 				break;
350 
351 			case AF_LINK:
352 				{
353 				struct sockaddr_dl *sdl =
354 					(struct sockaddr_dl *)sa;
355 				char linknum[10];
356 				cp = (char *)LLADDR(sdl);
357 				n = sdl->sdl_alen;
358 				sprintf(linknum, "<Link#%d>", sdl->sdl_index);
359 				m = printf("%-11.11s ", linknum);
360 				}
361 				goto hexprint;
362 			default:
363 				m = printf("(%d)", sa->sa_family);
364 				for (cp = sa->sa_len + (char *)sa;
365 					--cp > sa->sa_data && (*cp == 0);) {}
366 				n = cp - sa->sa_data + 1;
367 				cp = sa->sa_data;
368 			hexprint:
369 				while (--n >= 0)
370 					m += printf("%02x%c", *cp++ & 0xff,
371 						    n > 0 ? ':' : ' ');
372 				m = 30 - m;
373 				while (m-- > 0)
374 					putchar(' ');
375 
376 				link_layer = 1;
377 				break;
378 			}
379 
380 			/*
381 			 * Fixup the statistics for interfaces that
382 			 * update stats for their network addresses
383 			 */
384 			if (network_layer) {
385 				opackets = ifaddr.ifa.if_opackets;
386 				ipackets = ifaddr.ifa.if_ipackets;
387 				obytes = ifaddr.ifa.if_obytes;
388 				ibytes = ifaddr.ifa.if_ibytes;
389 			}
390 
391 			ifaddrcont_addr =
392 				(u_long)TAILQ_NEXT(&ifac, ifa_link);
393 			if (ifaddrcont_addr == 0) {
394 				ifaddraddr = 0;
395 			} else {
396 				if (kread(ifaddrcont_addr,
397 				    (char *)&ifac, sizeof(ifac))) {
398 					ifaddraddr = 0;
399 				} else {
400 					ifaddraddr = (u_long)ifac.ifa;
401 				}
402 			}
403 		}
404 
405 		show_stat("lu", 8, ipackets, link_layer|network_layer);
406 		printf(" ");
407 		show_stat("lu", 5, ierrors, link_layer);
408 		printf(" ");
409 		if (bflag) {
410 			show_stat("lu", 10, ibytes, link_layer|network_layer);
411 			printf(" ");
412 		}
413 		show_stat("lu", 8, opackets, link_layer|network_layer);
414 		printf(" ");
415 		show_stat("lu", 5, oerrors, link_layer);
416 		printf(" ");
417 		if (bflag) {
418 			show_stat("lu", 10, obytes, link_layer|network_layer);
419 			printf(" ");
420 		}
421 		show_stat("lu", 5, collisions, link_layer);
422 		if (tflag) {
423 			printf(" ");
424 			show_stat("d", 3, timer, link_layer);
425 		}
426 		if (dflag) {
427 			printf(" ");
428 			show_stat("d", 3, drops, link_layer);
429 		}
430 		putchar('\n');
431 		if (aflag && ifaddrfound) {
432 			/*
433 			 * Print family's multicast addresses
434 			 */
435 			struct ifmultiaddr *multiaddr;
436 			struct ifmultiaddr ifma;
437 			union {
438 				struct sockaddr sa;
439 				struct sockaddr_in in;
440 #ifdef INET6
441 				struct sockaddr_in6 in6;
442 #endif /* INET6 */
443 				struct sockaddr_dl dl;
444 			} msa;
445 			const char *fmt;
446 
447 			TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
448 				if (kread((u_long)multiaddr, (char *)&ifma,
449 					  sizeof ifma))
450 					break;
451 				multiaddr = &ifma;
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 = NULL;
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[IFNAMSIZ];	/* 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 interval1 seconds, showing statistics
509  * collected over that interval.  Assumes that interval1 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 interval1, u_long off, int ncpus)
515 {
516 	struct ifnet ifnet;
517 	u_long firstifnet;
518 	struct ifnethead ifnethead;
519 	struct ifdata_pcpu ifdata;
520 	struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
521 	int line, cpu;
522 	int oldmask, first;
523 	u_long interesting_off;
524 	u_long ifdata_addr;
525 
526 	if (kread(off, (char *)&ifnethead, sizeof ifnethead))
527 		return;
528 	firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
529 
530 	if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
531 		printf("malloc failed\n");
532 		exit(1);
533 	}
534 	memset(iftot, 0, sizeof(struct iftot));
535 
536 	interesting = NULL;
537 	interesting_off = 0;
538 	for (off = firstifnet, ip = iftot; off;) {
539 		char name[IFNAMSIZ];
540 
541 		if (kread(off, (char *)&ifnet, sizeof ifnet))
542 			break;
543 		strlcpy(name, ifnet.if_xname, sizeof(name));
544 		if (interface && strcmp(name, interface) == 0) {
545 			interesting = ip;
546 			interesting_off = off;
547 		}
548 		snprintf(ip->ift_name, 16, "(%s)", name);
549 		if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
550 			printf("malloc failed\n");
551 			exit(1);
552 		}
553 		memset(ipn, 0, sizeof(struct iftot));
554 		SLIST_NEXT(ip, chain) = ipn;
555 		ip = ipn;
556 		off = (u_long)TAILQ_NEXT(&ifnet, if_link);
557 	}
558 	if ((total = malloc(sizeof(struct iftot))) == NULL) {
559 		printf("malloc failed\n");
560 		exit(1);
561 	}
562 	memset(total, 0, sizeof(struct iftot));
563 	if ((sum = malloc(sizeof(struct iftot))) == NULL) {
564 		printf("malloc failed\n");
565 		exit(1);
566 	}
567 	memset(sum, 0, sizeof(struct iftot));
568 
569 
570 	(void)signal(SIGALRM, catchalarm);
571 	signalled = NO;
572 	(void)alarm(interval1);
573 	first = 1;
574 banner:
575 	printf("%17s %14s %16s", "input",
576 	    interesting ? interesting->ift_name : "(Total)", "output");
577 	putchar('\n');
578 	printf("%10s %5s %10s %10s %5s %10s %5s",
579 	    "packets", "errs", "bytes", "packets", "errs", "bytes", "colls");
580 	if (dflag)
581 		printf(" %5.5s", "drops");
582 	putchar('\n');
583 	fflush(stdout);
584 	line = 0;
585 loop:
586 	if (interesting != NULL) {
587 		ip = interesting;
588 		if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) {
589 			printf("???\n");
590 			exit(1);
591 		}
592 
593 		ifdata_addr = (u_long)ifnet.if_data_pcpu;
594 		if (kread(ifdata_addr, (char *)&ifdata, sizeof(ifdata))) {
595 			printf("ifdata 1\n");
596 			exit(1);
597 		}
598 		ifnet.if_ipackets = ifdata.ifd_ipackets;
599 		ifnet.if_ierrors = ifdata.ifd_ierrors;
600 		ifnet.if_ibytes = ifdata.ifd_ibytes;
601 		ifnet.if_opackets = ifdata.ifd_opackets;
602 		ifnet.if_oerrors = ifdata.ifd_oerrors;
603 		ifnet.if_obytes = ifdata.ifd_obytes;
604 		ifnet.if_collisions = ifdata.ifd_collisions;
605 
606 		for (cpu = 1; cpu < ncpus; ++cpu) {
607 			if (kread(ifdata_addr + (cpu * sizeof(ifdata)),
608 			    (char *)&ifdata, sizeof(ifdata))) {
609 				printf("ifdata 2\n");
610 				exit(1);
611 			}
612 			ifnet.if_ipackets += ifdata.ifd_ipackets;
613 			ifnet.if_ierrors += ifdata.ifd_ierrors;
614 			ifnet.if_ibytes += ifdata.ifd_ibytes;
615 			ifnet.if_opackets += ifdata.ifd_opackets;
616 			ifnet.if_oerrors += ifdata.ifd_oerrors;
617 			ifnet.if_obytes += ifdata.ifd_obytes;
618 			ifnet.if_collisions += ifdata.ifd_collisions;
619 		}
620 
621 		if (!first) {
622 			printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu",
623 				ifnet.if_ipackets - ip->ift_ip,
624 				ifnet.if_ierrors - ip->ift_ie,
625 				ifnet.if_ibytes - ip->ift_ib,
626 				ifnet.if_opackets - ip->ift_op,
627 				ifnet.if_oerrors - ip->ift_oe,
628 				ifnet.if_obytes - ip->ift_ob,
629 				ifnet.if_collisions - ip->ift_co);
630 			if (dflag)
631 				printf(" %5u", 0 - ip->ift_dr);
632 		}
633 		ip->ift_ip = ifnet.if_ipackets;
634 		ip->ift_ie = ifnet.if_ierrors;
635 		ip->ift_ib = ifnet.if_ibytes;
636 		ip->ift_op = ifnet.if_opackets;
637 		ip->ift_oe = ifnet.if_oerrors;
638 		ip->ift_ob = ifnet.if_obytes;
639 		ip->ift_co = ifnet.if_collisions;
640 		ip->ift_dr = 0;
641 	} else {
642 		sum->ift_ip = 0;
643 		sum->ift_ie = 0;
644 		sum->ift_ib = 0;
645 		sum->ift_op = 0;
646 		sum->ift_oe = 0;
647 		sum->ift_ob = 0;
648 		sum->ift_co = 0;
649 		sum->ift_dr = 0;
650 		for (off = firstifnet, ip = iftot;
651 		     off && SLIST_NEXT(ip, chain) != NULL;
652 		     ip = SLIST_NEXT(ip, chain)) {
653 			if (kread(off, (char *)&ifnet, sizeof ifnet)) {
654 				off = 0;
655 				continue;
656 			}
657 
658 			ifdata_addr = (u_long)ifnet.if_data_pcpu;
659 			if (kread(ifdata_addr, (char *)&ifdata,
660 			    sizeof(ifdata))) {
661 				printf("ifdata 3\n");
662 				exit(1);
663 			}
664 			ifnet.if_ipackets = ifdata.ifd_ipackets;
665 			ifnet.if_ierrors = ifdata.ifd_ierrors;
666 			ifnet.if_ibytes = ifdata.ifd_ibytes;
667 			ifnet.if_opackets = ifdata.ifd_opackets;
668 			ifnet.if_oerrors = ifdata.ifd_oerrors;
669 			ifnet.if_obytes = ifdata.ifd_obytes;
670 			ifnet.if_collisions = ifdata.ifd_collisions;
671 
672 			for (cpu = 1; cpu < ncpus; ++cpu) {
673 				if (kread(ifdata_addr + (cpu * sizeof(ifdata)),
674 				    (char *)&ifdata, sizeof(ifdata))) {
675 					printf("ifdata 2\n");
676 					exit(1);
677 				}
678 				ifnet.if_ipackets += ifdata.ifd_ipackets;
679 				ifnet.if_ierrors += ifdata.ifd_ierrors;
680 				ifnet.if_ibytes += ifdata.ifd_ibytes;
681 				ifnet.if_opackets += ifdata.ifd_opackets;
682 				ifnet.if_oerrors += ifdata.ifd_oerrors;
683 				ifnet.if_obytes += ifdata.ifd_obytes;
684 				ifnet.if_collisions += ifdata.ifd_collisions;
685 			}
686 
687 			/*
688 			 * Don't double-count interfaces that are associated
689 			 * with bridges, they will be rolled up by the
690 			 * bridge.  Errors and collisions are not rolled up.
691 			 */
692 			if (ifnet.if_bridge) {
693 				sum->ift_ie += ifnet.if_ierrors;
694 				sum->ift_oe += ifnet.if_oerrors;
695 				sum->ift_co += ifnet.if_collisions;
696 			} else {
697 				sum->ift_ip += ifnet.if_ipackets;
698 				sum->ift_ie += ifnet.if_ierrors;
699 				sum->ift_ib += ifnet.if_ibytes;
700 				sum->ift_op += ifnet.if_opackets;
701 				sum->ift_oe += ifnet.if_oerrors;
702 				sum->ift_ob += ifnet.if_obytes;
703 				sum->ift_co += ifnet.if_collisions;
704 				sum->ift_dr += 0;
705 			}
706 			off = (u_long)TAILQ_NEXT(&ifnet, if_link);
707 		}
708 		if (!first) {
709 			printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu",
710 				sum->ift_ip - total->ift_ip,
711 				sum->ift_ie - total->ift_ie,
712 				sum->ift_ib - total->ift_ib,
713 				sum->ift_op - total->ift_op,
714 				sum->ift_oe - total->ift_oe,
715 				sum->ift_ob - total->ift_ob,
716 				sum->ift_co - total->ift_co);
717 			if (dflag)
718 				printf(" %5u", sum->ift_dr - total->ift_dr);
719 		}
720 		*total = *sum;
721 	}
722 	if (!first)
723 		putchar('\n');
724 	fflush(stdout);
725 	oldmask = sigblock(sigmask(SIGALRM));
726 	if (! signalled) {
727 		sigpause(0);
728 	}
729 	sigsetmask(oldmask);
730 	signalled = NO;
731 	(void)alarm(interval1);
732 	line++;
733 	first = 0;
734 	if (line == 21)
735 		goto banner;
736 	else
737 		goto loop;
738 	/*NOTREACHED*/
739 }
740 
741 /*
742  * Called if an interval expires before sidewaysintpr has completed a loop.
743  * Sets a flag to not wait for the alarm.
744  */
745 static void
746 catchalarm(int signo __unused)
747 {
748 	signalled = YES;
749 }
750