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