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