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