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