xref: /dragonfly/usr.bin/netstat/if.c (revision d4ef6694)
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 #ifdef ISO
48 #include <netiso/iso.h>
49 #include <netiso/iso_var.h>
50 #endif
51 #include <arpa/inet.h>
52 
53 #include <signal.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58 
59 #include "netstat.h"
60 
61 #define	YES	1
62 #define	NO	0
63 
64 static void sidewaysintpr (u_int, u_long, int);
65 static void catchalarm (int);
66 
67 #ifdef INET6
68 static char ntop_buf[INET6_ADDRSTRLEN];		/* for inet_ntop() */
69 #endif
70 
71 
72 /*
73  * Display a formatted value, or a '-' in the same space.
74  */
75 static void
76 show_stat(const char *fmt, int width, u_long value, short showvalue)
77 {
78 	char newfmt[32];
79 
80 	/* Construct the format string */
81 	if (showvalue) {
82 		sprintf(newfmt, "%%%d%s", width, fmt);
83 		printf(newfmt, value);
84 	} else {
85 		sprintf(newfmt, "%%%ds", width);
86 		printf(newfmt, "-");
87 	}
88 }
89 
90 
91 
92 /*
93  * Print a description of the network interfaces.
94  */
95 void
96 intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *), u_long ncpusaddr)
97 {
98 	struct ifnet ifnet;
99 	struct ifdata_pcpu ifdata;
100 	struct ifaddr_container ifac;
101 	struct ifnethead ifnethead;
102 	union {
103 		struct ifaddr ifa;
104 		struct in_ifaddr in;
105 #ifdef INET6
106 		struct in6_ifaddr in6;
107 #endif
108 #ifdef ISO
109 		struct iso_ifaddr iso;
110 #endif
111 	} ifaddr;
112 	u_long ifaddraddr;
113 	u_long ifaddrcont_addr;
114 	u_long ifaddrfound;
115 	u_long ifdataaddr;
116 	u_long opackets;
117 	u_long ipackets;
118 	u_long obytes;
119 	u_long ibytes;
120 	u_long oerrors;
121 	u_long ierrors;
122 	u_long collisions;
123 	short timer;
124 	int drops;
125 	struct sockaddr *sa = NULL;
126 	char name[IFNAMSIZ];
127 	short network_layer;
128 	short link_layer;
129 	int ncpus;
130 
131 	if (kread(ncpusaddr, (char *)&ncpus, sizeof(ncpus)))
132 		return;
133 
134 	if (ifnetaddr == 0) {
135 		printf("ifnet: symbol not defined\n");
136 		return;
137 	}
138 	if (interval1) {
139 		sidewaysintpr((unsigned)interval1, ifnetaddr, ncpus);
140 		return;
141 	}
142 	if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead))
143 		return;
144 	ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
145 	if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
146 		return;
147 
148 	if (!pfunc) {
149 		printf("%-7.7s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
150 		       "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
151 		if (bflag)
152 			printf(" %10.10s","Ibytes");
153 		printf(" %8.8s %5.5s", "Opkts", "Oerrs");
154 		if (bflag)
155 			printf(" %10.10s","Obytes");
156 		printf(" %5s", "Coll");
157 		if (tflag)
158 			printf(" %s", "Time");
159 		if (dflag)
160 			printf(" %s", "Drop");
161 		putchar('\n');
162 	}
163 	ifaddraddr = 0;
164 	ifaddrcont_addr = 0;
165 	while (ifnetaddr || ifaddraddr) {
166 		struct sockaddr_in *sin;
167 #ifdef INET6
168 		struct sockaddr_in6 *sin6;
169 #endif
170 		char *cp;
171 		int n, m, cpu;
172 
173 		network_layer = 0;
174 		link_layer = 0;
175 
176 		if (ifaddraddr == 0) {
177 			struct ifaddrhead head;
178 
179 			if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
180 				return;
181 			strlcpy(name, ifnet.if_xname, sizeof(name));
182 			ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link);
183 			if (interface != 0 && (strcmp(name, interface) != 0))
184 				continue;
185 			cp = strchr(name, '\0');
186 
187 			if (pfunc) {
188 				(*pfunc)(name);
189 				continue;
190 			}
191 
192 			if ((ifnet.if_flags&IFF_UP) == 0)
193 				*cp++ = '*';
194 			*cp = '\0';
195 
196 			if (kread((u_long)ifnet.if_addrheads,
197 				  (char *)&head, sizeof(head)))
198 				return;
199 
200 			ifaddrcont_addr =
201 				(u_long)TAILQ_FIRST(&head);
202 			if (ifaddrcont_addr == 0) {
203 				ifaddraddr = 0;
204 			} else {
205 				if (kread(ifaddrcont_addr, (char *)&ifac,
206 					  sizeof(ifac)))
207 					return;
208 				ifaddraddr = (u_long)ifac.ifa;
209 			}
210 		}
211 		ifaddrfound = ifaddraddr;
212 
213 		/*
214 		 * Get the interface stats.  These may get
215 		 * overriden below on a per-interface basis.
216 		 */
217 		ifdataaddr = (u_long)ifnet.if_data_pcpu;
218 		if (kread(ifdataaddr, (char *)&ifdata, sizeof(ifdata)))
219 			return;
220 		opackets = ifdata.ifd_opackets;
221 		ipackets = ifdata.ifd_ipackets;
222 		obytes = ifdata.ifd_obytes;
223 		ibytes = ifdata.ifd_ibytes;
224 		oerrors = ifdata.ifd_oerrors;
225 		ierrors = ifdata.ifd_ierrors;
226 		collisions = ifdata.ifd_collisions;
227 
228 		for (cpu = 1; cpu < ncpus; ++cpu) {
229 			if (kread(ifdataaddr + (cpu * sizeof(ifdata)),
230 			    (char *)&ifdata, sizeof(ifdata)))
231 				return;
232 			opackets += ifdata.ifd_opackets;
233 			ipackets += ifdata.ifd_ipackets;
234 			obytes += ifdata.ifd_obytes;
235 			ibytes += ifdata.ifd_ibytes;
236 			oerrors += ifdata.ifd_oerrors;
237 			ierrors += ifdata.ifd_ierrors;
238 			collisions += ifdata.ifd_collisions;
239 		}
240 
241 		timer = ifnet.if_timer;
242 		drops = 0;
243 
244 		if (ifaddraddr == 0) {
245 			printf("%-7.7s %-5lu ", name, ifnet.if_mtu);
246 			printf("%-13.13s ", "none");
247 			printf("%-15.15s ", "none");
248 		} else {
249 			if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
250 				ifaddraddr = 0;
251 				continue;
252 			}
253 
254 			ifaddr.ifa.if_ipackets = ifac.ifa_ipackets;
255 			ifaddr.ifa.if_ibytes = ifac.ifa_ibytes;
256 			ifaddr.ifa.if_opackets = ifac.ifa_opackets;
257 			ifaddr.ifa.if_obytes = ifac.ifa_obytes;
258 			for (cpu = 1; cpu < ncpus; ++cpu) {
259 				struct ifaddr_container nifac;
260 
261 				if (kread(ifaddrcont_addr +
262 				    (cpu * sizeof(nifac)),
263 				    (char *)&nifac, sizeof(nifac))) {
264 					ifaddraddr = 0;
265 					continue;
266 				}
267 				ifaddr.ifa.if_ipackets += nifac.ifa_ipackets;
268 				ifaddr.ifa.if_ibytes += nifac.ifa_ibytes;
269 				ifaddr.ifa.if_opackets += nifac.ifa_opackets;
270 				ifaddr.ifa.if_obytes += nifac.ifa_obytes;
271 			}
272 
273 #define CP(x) ((char *)(x))
274 			cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
275 				CP(&ifaddr);
276 			sa = (struct sockaddr *)cp;
277 			if (af != AF_UNSPEC && sa->sa_family != af) {
278 				ifaddrcont_addr =
279 					(u_long)TAILQ_NEXT(&ifac, ifa_link);
280 				if (ifaddrcont_addr == 0) {
281 					ifaddraddr = 0;
282 				} else {
283 					if (kread(ifaddrcont_addr,
284 					    (char *)&ifac, sizeof(ifac))) {
285 						ifaddraddr = 0;
286 						continue;
287 					}
288 					ifaddraddr = (u_long)ifac.ifa;
289 				}
290 				continue;
291 			}
292 			printf("%-7.7s %-5lu ", name, ifnet.if_mtu);
293 			switch (sa->sa_family) {
294 			case AF_UNSPEC:
295 				printf("%-13.13s ", "none");
296 				printf("%-15.15s ", "none");
297 				break;
298 			case AF_INET:
299 				sin = (struct sockaddr_in *)sa;
300 #ifdef notdef
301 				/* can't use inet_makeaddr because kernel
302 				 * keeps nets unshifted.
303 				 */
304 				in = inet_makeaddr(ifaddr.in.ia_subnet,
305 					INADDR_ANY);
306 				printf("%-13.13s ", netname(in.s_addr,
307 				    ifaddr.in.ia_subnetmask));
308 #else
309 				printf("%-13.13s ",
310 				    netname(htonl(ifaddr.in.ia_subnet),
311 				    ifaddr.in.ia_subnetmask));
312 #endif
313 				printf("%-15.15s ",
314 				    routename(sin->sin_addr.s_addr));
315 
316 				network_layer = 1;
317 				break;
318 #ifdef INET6
319 			case AF_INET6:
320 				sin6 = (struct sockaddr_in6 *)sa;
321 				printf("%-11.11s ",
322 				       netname6(&ifaddr.in6.ia_addr,
323 						&ifaddr.in6.ia_prefixmask.sin6_addr));
324 				printf("%-17.17s ",
325 				    inet_ntop(AF_INET6,
326 					&sin6->sin6_addr,
327 					ntop_buf, sizeof(ntop_buf)));
328 
329 				network_layer = 1;
330 				break;
331 #endif /*INET6*/
332 			case AF_LINK:
333 				{
334 				struct sockaddr_dl *sdl =
335 					(struct sockaddr_dl *)sa;
336 				char linknum[10];
337 				cp = (char *)LLADDR(sdl);
338 				n = sdl->sdl_alen;
339 				sprintf(linknum, "<Link#%d>", sdl->sdl_index);
340 				m = printf("%-11.11s ", linknum);
341 				}
342 				goto hexprint;
343 			default:
344 				m = printf("(%d)", sa->sa_family);
345 				for (cp = sa->sa_len + (char *)sa;
346 					--cp > sa->sa_data && (*cp == 0);) {}
347 				n = cp - sa->sa_data + 1;
348 				cp = sa->sa_data;
349 			hexprint:
350 				while (--n >= 0)
351 					m += printf("%02x%c", *cp++ & 0xff,
352 						    n > 0 ? ':' : ' ');
353 				m = 30 - m;
354 				while (m-- > 0)
355 					putchar(' ');
356 
357 				link_layer = 1;
358 				break;
359 			}
360 
361 			/*
362 			 * Fixup the statistics for interfaces that
363 			 * update stats for their network addresses
364 			 */
365 			if (network_layer) {
366 				opackets = ifaddr.ifa.if_opackets;
367 				ipackets = ifaddr.ifa.if_ipackets;
368 				obytes = ifaddr.ifa.if_obytes;
369 				ibytes = ifaddr.ifa.if_ibytes;
370 			}
371 
372 			ifaddrcont_addr =
373 				(u_long)TAILQ_NEXT(&ifac, ifa_link);
374 			if (ifaddrcont_addr == 0) {
375 				ifaddraddr = 0;
376 			} else {
377 				if (kread(ifaddrcont_addr,
378 				    (char *)&ifac, sizeof(ifac))) {
379 					ifaddraddr = 0;
380 				} else {
381 					ifaddraddr = (u_long)ifac.ifa;
382 				}
383 			}
384 		}
385 
386 		show_stat("lu", 8, ipackets, link_layer|network_layer);
387 		printf(" ");
388 		show_stat("lu", 5, ierrors, link_layer);
389 		printf(" ");
390 		if (bflag) {
391 			show_stat("lu", 10, ibytes, link_layer|network_layer);
392 			printf(" ");
393 		}
394 		show_stat("lu", 8, opackets, link_layer|network_layer);
395 		printf(" ");
396 		show_stat("lu", 5, oerrors, link_layer);
397 		printf(" ");
398 		if (bflag) {
399 			show_stat("lu", 10, obytes, link_layer|network_layer);
400 			printf(" ");
401 		}
402 		show_stat("lu", 5, collisions, link_layer);
403 		if (tflag) {
404 			printf(" ");
405 			show_stat("d", 3, timer, link_layer);
406 		}
407 		if (dflag) {
408 			printf(" ");
409 			show_stat("d", 3, drops, link_layer);
410 		}
411 		putchar('\n');
412 		if (aflag && ifaddrfound) {
413 			/*
414 			 * Print family's multicast addresses
415 			 */
416 			struct ifmultiaddr *multiaddr;
417 			struct ifmultiaddr ifma;
418 			union {
419 				struct sockaddr sa;
420 				struct sockaddr_in in;
421 #ifdef INET6
422 				struct sockaddr_in6 in6;
423 #endif /* INET6 */
424 				struct sockaddr_dl dl;
425 			} msa;
426 			const char *fmt;
427 
428 			TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
429 				if (kread((u_long)multiaddr, (char *)&ifma,
430 					  sizeof ifma))
431 					break;
432 				multiaddr = &ifma;
433 				if (kread((u_long)ifma.ifma_addr, (char *)&msa,
434 					  sizeof msa))
435 					break;
436 				if (msa.sa.sa_family != sa->sa_family)
437 					continue;
438 
439 				fmt = NULL;
440 				switch (msa.sa.sa_family) {
441 				case AF_INET:
442 					fmt = routename(msa.in.sin_addr.s_addr);
443 					break;
444 #ifdef INET6
445 				case AF_INET6:
446 					printf("%23s %-19.19s(refs: %d)\n", "",
447 					       inet_ntop(AF_INET6,
448 							 &msa.in6.sin6_addr,
449 							 ntop_buf,
450 							 sizeof(ntop_buf)),
451 					       ifma.ifma_refcount);
452 					break;
453 #endif /* INET6 */
454 				case AF_LINK:
455 					switch (msa.dl.sdl_type) {
456 					case IFT_ETHER:
457 					case IFT_FDDI:
458 						fmt = ether_ntoa(
459 							(struct ether_addr *)
460 							LLADDR(&msa.dl));
461 						break;
462 					}
463 					break;
464 				}
465 				if (fmt)
466 					printf("%23s %s\n", "", fmt);
467 			}
468 		}
469 	}
470 }
471 
472 struct	iftot {
473 	SLIST_ENTRY(iftot) chain;
474 	char	ift_name[IFNAMSIZ];	/* interface name */
475 	u_long	ift_ip;			/* input packets */
476 	u_long	ift_ie;			/* input errors */
477 	u_long	ift_op;			/* output packets */
478 	u_long	ift_oe;			/* output errors */
479 	u_long	ift_co;			/* collisions */
480 	u_int	ift_dr;			/* drops */
481 	u_long	ift_ib;			/* input bytes */
482 	u_long	ift_ob;			/* output bytes */
483 };
484 
485 u_char	signalled;			/* set if alarm goes off "early" */
486 
487 /*
488  * Print a running summary of interface statistics.
489  * Repeat display every interval1 seconds, showing statistics
490  * collected over that interval.  Assumes that interval1 is non-zero.
491  * First line printed at top of screen is always cumulative.
492  * XXX - should be rewritten to use ifmib(4).
493  */
494 static void
495 sidewaysintpr(unsigned interval1, u_long off, int ncpus)
496 {
497 	struct ifnet ifnet;
498 	u_long firstifnet;
499 	struct ifnethead ifnethead;
500 	struct ifdata_pcpu ifdata;
501 	struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
502 	int line, cpu;
503 	int oldmask, first;
504 	u_long interesting_off;
505 	u_long ifdata_addr;
506 
507 	if (kread(off, (char *)&ifnethead, sizeof ifnethead))
508 		return;
509 	firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
510 
511 	if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
512 		printf("malloc failed\n");
513 		exit(1);
514 	}
515 	memset(iftot, 0, sizeof(struct iftot));
516 
517 	interesting = NULL;
518 	interesting_off = 0;
519 	for (off = firstifnet, ip = iftot; off;) {
520 		char name[IFNAMSIZ];
521 
522 		if (kread(off, (char *)&ifnet, sizeof ifnet))
523 			break;
524 		strlcpy(name, ifnet.if_xname, sizeof(name));
525 		if (interface && strcmp(name, interface) == 0) {
526 			interesting = ip;
527 			interesting_off = off;
528 		}
529 		snprintf(ip->ift_name, 16, "(%s)", name);
530 		if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
531 			printf("malloc failed\n");
532 			exit(1);
533 		}
534 		memset(ipn, 0, sizeof(struct iftot));
535 		SLIST_NEXT(ip, chain) = ipn;
536 		ip = ipn;
537 		off = (u_long)TAILQ_NEXT(&ifnet, if_link);
538 	}
539 	if ((total = malloc(sizeof(struct iftot))) == NULL) {
540 		printf("malloc failed\n");
541 		exit(1);
542 	}
543 	memset(total, 0, sizeof(struct iftot));
544 	if ((sum = malloc(sizeof(struct iftot))) == NULL) {
545 		printf("malloc failed\n");
546 		exit(1);
547 	}
548 	memset(sum, 0, sizeof(struct iftot));
549 
550 
551 	(void)signal(SIGALRM, catchalarm);
552 	signalled = NO;
553 	(void)alarm(interval1);
554 	first = 1;
555 banner:
556 	printf("%17s %14s %16s", "input",
557 	    interesting ? interesting->ift_name : "(Total)", "output");
558 	putchar('\n');
559 	printf("%10s %5s %10s %10s %5s %10s %5s",
560 	    "packets", "errs", "bytes", "packets", "errs", "bytes", "colls");
561 	if (dflag)
562 		printf(" %5.5s", "drops");
563 	putchar('\n');
564 	fflush(stdout);
565 	line = 0;
566 loop:
567 	if (interesting != NULL) {
568 		ip = interesting;
569 		if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) {
570 			printf("???\n");
571 			exit(1);
572 		}
573 
574 		ifdata_addr = (u_long)ifnet.if_data_pcpu;
575 		if (kread(ifdata_addr, (char *)&ifdata, sizeof(ifdata))) {
576 			printf("ifdata 1\n");
577 			exit(1);
578 		}
579 		ifnet.if_ipackets = ifdata.ifd_ipackets;
580 		ifnet.if_ierrors = ifdata.ifd_ierrors;
581 		ifnet.if_ibytes = ifdata.ifd_ibytes;
582 		ifnet.if_opackets = ifdata.ifd_opackets;
583 		ifnet.if_oerrors = ifdata.ifd_oerrors;
584 		ifnet.if_obytes = ifdata.ifd_obytes;
585 		ifnet.if_collisions = ifdata.ifd_collisions;
586 
587 		for (cpu = 1; cpu < ncpus; ++cpu) {
588 			if (kread(ifdata_addr + (cpu * sizeof(ifdata)),
589 			    (char *)&ifdata, sizeof(ifdata))) {
590 				printf("ifdata 2\n");
591 				exit(1);
592 			}
593 			ifnet.if_ipackets += ifdata.ifd_ipackets;
594 			ifnet.if_ierrors += ifdata.ifd_ierrors;
595 			ifnet.if_ibytes += ifdata.ifd_ibytes;
596 			ifnet.if_opackets += ifdata.ifd_opackets;
597 			ifnet.if_oerrors += ifdata.ifd_oerrors;
598 			ifnet.if_obytes += ifdata.ifd_obytes;
599 			ifnet.if_collisions += ifdata.ifd_collisions;
600 		}
601 
602 		if (!first) {
603 			printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu",
604 				ifnet.if_ipackets - ip->ift_ip,
605 				ifnet.if_ierrors - ip->ift_ie,
606 				ifnet.if_ibytes - ip->ift_ib,
607 				ifnet.if_opackets - ip->ift_op,
608 				ifnet.if_oerrors - ip->ift_oe,
609 				ifnet.if_obytes - ip->ift_ob,
610 				ifnet.if_collisions - ip->ift_co);
611 			if (dflag)
612 				printf(" %5u", 0 - ip->ift_dr);
613 		}
614 		ip->ift_ip = ifnet.if_ipackets;
615 		ip->ift_ie = ifnet.if_ierrors;
616 		ip->ift_ib = ifnet.if_ibytes;
617 		ip->ift_op = ifnet.if_opackets;
618 		ip->ift_oe = ifnet.if_oerrors;
619 		ip->ift_ob = ifnet.if_obytes;
620 		ip->ift_co = ifnet.if_collisions;
621 		ip->ift_dr = 0;
622 	} else {
623 		sum->ift_ip = 0;
624 		sum->ift_ie = 0;
625 		sum->ift_ib = 0;
626 		sum->ift_op = 0;
627 		sum->ift_oe = 0;
628 		sum->ift_ob = 0;
629 		sum->ift_co = 0;
630 		sum->ift_dr = 0;
631 		for (off = firstifnet, ip = iftot;
632 		     off && SLIST_NEXT(ip, chain) != NULL;
633 		     ip = SLIST_NEXT(ip, chain)) {
634 			if (kread(off, (char *)&ifnet, sizeof ifnet)) {
635 				off = 0;
636 				continue;
637 			}
638 
639 			ifdata_addr = (u_long)ifnet.if_data_pcpu;
640 			if (kread(ifdata_addr, (char *)&ifdata,
641 			    sizeof(ifdata))) {
642 				printf("ifdata 3\n");
643 				exit(1);
644 			}
645 			ifnet.if_ipackets = ifdata.ifd_ipackets;
646 			ifnet.if_ierrors = ifdata.ifd_ierrors;
647 			ifnet.if_ibytes = ifdata.ifd_ibytes;
648 			ifnet.if_opackets = ifdata.ifd_opackets;
649 			ifnet.if_oerrors = ifdata.ifd_oerrors;
650 			ifnet.if_obytes = ifdata.ifd_obytes;
651 			ifnet.if_collisions = ifdata.ifd_collisions;
652 
653 			for (cpu = 1; cpu < ncpus; ++cpu) {
654 				if (kread(ifdata_addr + (cpu * sizeof(ifdata)),
655 				    (char *)&ifdata, sizeof(ifdata))) {
656 					printf("ifdata 2\n");
657 					exit(1);
658 				}
659 				ifnet.if_ipackets += ifdata.ifd_ipackets;
660 				ifnet.if_ierrors += ifdata.ifd_ierrors;
661 				ifnet.if_ibytes += ifdata.ifd_ibytes;
662 				ifnet.if_opackets += ifdata.ifd_opackets;
663 				ifnet.if_oerrors += ifdata.ifd_oerrors;
664 				ifnet.if_obytes += ifdata.ifd_obytes;
665 				ifnet.if_collisions += ifdata.ifd_collisions;
666 			}
667 
668 			/*
669 			 * Don't double-count interfaces that are associated
670 			 * with bridges, they will be rolled up by the
671 			 * bridge.  Errors and collisions are not rolled up.
672 			 */
673 			if (ifnet.if_bridge) {
674 				sum->ift_ie += ifnet.if_ierrors;
675 				sum->ift_oe += ifnet.if_oerrors;
676 				sum->ift_co += ifnet.if_collisions;
677 			} else {
678 				sum->ift_ip += ifnet.if_ipackets;
679 				sum->ift_ie += ifnet.if_ierrors;
680 				sum->ift_ib += ifnet.if_ibytes;
681 				sum->ift_op += ifnet.if_opackets;
682 				sum->ift_oe += ifnet.if_oerrors;
683 				sum->ift_ob += ifnet.if_obytes;
684 				sum->ift_co += ifnet.if_collisions;
685 				sum->ift_dr += 0;
686 			}
687 			off = (u_long)TAILQ_NEXT(&ifnet, if_link);
688 		}
689 		if (!first) {
690 			printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu",
691 				sum->ift_ip - total->ift_ip,
692 				sum->ift_ie - total->ift_ie,
693 				sum->ift_ib - total->ift_ib,
694 				sum->ift_op - total->ift_op,
695 				sum->ift_oe - total->ift_oe,
696 				sum->ift_ob - total->ift_ob,
697 				sum->ift_co - total->ift_co);
698 			if (dflag)
699 				printf(" %5u", sum->ift_dr - total->ift_dr);
700 		}
701 		*total = *sum;
702 	}
703 	if (!first)
704 		putchar('\n');
705 	fflush(stdout);
706 	oldmask = sigblock(sigmask(SIGALRM));
707 	if (! signalled) {
708 		sigpause(0);
709 	}
710 	sigsetmask(oldmask);
711 	signalled = NO;
712 	(void)alarm(interval1);
713 	line++;
714 	first = 0;
715 	if (line == 21)
716 		goto banner;
717 	else
718 		goto loop;
719 	/*NOTREACHED*/
720 }
721 
722 /*
723  * Called if an interval expires before sidewaysintpr has completed a loop.
724  * Sets a flag to not wait for the alarm.
725  */
726 static void
727 catchalarm(int signo __unused)
728 {
729 	signalled = YES;
730 }
731