-h (human-readable counters) for netstat
[dragonfly.git] / usr.bin / netstat / if.c
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 }