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         u_long oqdrops;
128         short timer;
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                 oqdrops = ifdata.ifd_oqdrops;
232
233                 for (cpu = 1; cpu < ncpus; ++cpu) {
234                         if (kread(ifdataaddr + (cpu * sizeof(ifdata)),
235                             (char *)&ifdata, sizeof(ifdata)))
236                                 return;
237                         opackets += ifdata.ifd_opackets;
238                         ipackets += ifdata.ifd_ipackets;
239                         obytes += ifdata.ifd_obytes;
240                         ibytes += ifdata.ifd_ibytes;
241                         oerrors += ifdata.ifd_oerrors;
242                         ierrors += ifdata.ifd_ierrors;
243                         collisions += ifdata.ifd_collisions;
244                         oqdrops += ifdata.ifd_oqdrops;
245                 }
246
247                 timer = ifnet.if_timer;
248
249                 if (ifaddraddr == 0) {
250                         printf("%-7.7s %-5lu ", name, ifnet.if_mtu);
251                         printf("%-13.13s ", "none");
252                         printf("%-15.15s ", "none");
253                 } else {
254                         if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
255                                 ifaddraddr = 0;
256                                 continue;
257                         }
258
259                         ifaddr.ifa.if_ipackets = ifac.ifa_ipackets;
260                         ifaddr.ifa.if_ibytes = ifac.ifa_ibytes;
261                         ifaddr.ifa.if_opackets = ifac.ifa_opackets;
262                         ifaddr.ifa.if_obytes = ifac.ifa_obytes;
263                         for (cpu = 1; cpu < ncpus; ++cpu) {
264                                 struct ifaddr_container nifac;
265
266                                 if (kread(ifaddrcont_addr +
267                                     (cpu * sizeof(nifac)),
268                                     (char *)&nifac, sizeof(nifac))) {
269                                         ifaddraddr = 0;
270                                         continue;
271                                 }
272                                 ifaddr.ifa.if_ipackets += nifac.ifa_ipackets;
273                                 ifaddr.ifa.if_ibytes += nifac.ifa_ibytes;
274                                 ifaddr.ifa.if_opackets += nifac.ifa_opackets;
275                                 ifaddr.ifa.if_obytes += nifac.ifa_obytes;
276                         }
277
278 #define CP(x) ((char *)(x))
279                         cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
280                                 CP(&ifaddr);
281                         sa = (struct sockaddr *)cp;
282                         if (af != AF_UNSPEC && sa->sa_family != af) {
283                                 ifaddrcont_addr =
284                                         (u_long)TAILQ_NEXT(&ifac, ifa_link);
285                                 if (ifaddrcont_addr == 0) {
286                                         ifaddraddr = 0;
287                                 } else {
288                                         if (kread(ifaddrcont_addr,
289                                             (char *)&ifac, sizeof(ifac))) {
290                                                 ifaddraddr = 0;
291                                                 continue;
292                                         }
293                                         ifaddraddr = (u_long)ifac.ifa;
294                                 }
295                                 continue;
296                         }
297                         printf("%-7.7s %-5lu ", name, ifnet.if_mtu);
298                         switch (sa->sa_family) {
299                         case AF_UNSPEC:
300                                 printf("%-13.13s ", "none");
301                                 printf("%-15.15s ", "none");
302                                 break;
303                         case AF_INET:
304                                 sin = (struct sockaddr_in *)sa;
305 #ifdef notdef
306                                 /* can't use inet_makeaddr because kernel
307                                  * keeps nets unshifted.
308                                  */
309                                 in = inet_makeaddr(ifaddr.in.ia_subnet,
310                                         INADDR_ANY);
311                                 printf("%-13.13s ", netname(in.s_addr,
312                                     ifaddr.in.ia_subnetmask));
313 #else
314                                 printf("%-13.13s ",
315                                     netname(htonl(ifaddr.in.ia_subnet),
316                                     ifaddr.in.ia_subnetmask));
317 #endif
318                                 printf("%-15.15s ",
319                                     routename(sin->sin_addr.s_addr));
320
321                                 network_layer = 1;
322                                 break;
323 #ifdef INET6
324                         case AF_INET6:
325                                 sin6 = (struct sockaddr_in6 *)sa;
326                                 printf("%-11.11s ",
327                                        netname6(&ifaddr.in6.ia_addr,
328                                                 &ifaddr.in6.ia_prefixmask.sin6_addr));
329                                 printf("%-17.17s ",
330                                     inet_ntop(AF_INET6,
331                                         &sin6->sin6_addr,
332                                         ntop_buf, sizeof(ntop_buf)));
333
334                                 network_layer = 1;
335                                 break;
336 #endif /*INET6*/
337                         case AF_LINK:
338                                 {
339                                 struct sockaddr_dl *sdl =
340                                         (struct sockaddr_dl *)sa;
341                                 char linknum[10];
342                                 cp = (char *)LLADDR(sdl);
343                                 n = sdl->sdl_alen;
344                                 sprintf(linknum, "<Link#%d>", sdl->sdl_index);
345                                 m = printf("%-11.11s ", linknum);
346                                 }
347                                 goto hexprint;
348                         default:
349                                 m = printf("(%d)", sa->sa_family);
350                                 for (cp = sa->sa_len + (char *)sa;
351                                         --cp > sa->sa_data && (*cp == 0);) {}
352                                 n = cp - sa->sa_data + 1;
353                                 cp = sa->sa_data;
354                         hexprint:
355                                 while (--n >= 0)
356                                         m += printf("%02x%c", *cp++ & 0xff,
357                                                     n > 0 ? ':' : ' ');
358                                 m = 30 - m;
359                                 while (m-- > 0)
360                                         putchar(' ');
361
362                                 link_layer = 1;
363                                 break;
364                         }
365
366                         /*
367                          * Fixup the statistics for interfaces that
368                          * update stats for their network addresses
369                          */
370                         if (network_layer) {
371                                 opackets = ifaddr.ifa.if_opackets;
372                                 ipackets = ifaddr.ifa.if_ipackets;
373                                 obytes = ifaddr.ifa.if_obytes;
374                                 ibytes = ifaddr.ifa.if_ibytes;
375                         }
376
377                         ifaddrcont_addr =
378                                 (u_long)TAILQ_NEXT(&ifac, ifa_link);
379                         if (ifaddrcont_addr == 0) {
380                                 ifaddraddr = 0;
381                         } else {
382                                 if (kread(ifaddrcont_addr,
383                                     (char *)&ifac, sizeof(ifac))) {
384                                         ifaddraddr = 0;
385                                 } else {
386                                         ifaddraddr = (u_long)ifac.ifa;
387                                 }
388                         }
389                 }
390
391                 show_stat("lu", 8, ipackets, link_layer|network_layer);
392                 printf(" ");
393                 show_stat("lu", 5, ierrors, link_layer);
394                 printf(" ");
395                 if (bflag) {
396                         show_stat("lu", 10, ibytes, link_layer|network_layer);
397                         printf(" ");
398                 }
399                 show_stat("lu", 8, opackets, link_layer|network_layer);
400                 printf(" ");
401                 show_stat("lu", 5, oerrors, link_layer);
402                 printf(" ");
403                 if (bflag) {
404                         show_stat("lu", 10, obytes, link_layer|network_layer);
405                         printf(" ");
406                 }
407                 show_stat("lu", 5, collisions, link_layer);
408                 if (tflag) {
409                         printf(" ");
410                         show_stat("d", 3, timer, link_layer);
411                 }
412                 if (dflag) {
413                         printf(" ");
414                         show_stat("lu", 5, oqdrops, link_layer);
415                 }
416                 putchar('\n');
417                 if (aflag && ifaddrfound) {
418                         /*
419                          * Print family's multicast addresses
420                          */
421                         struct ifmultiaddr *multiaddr;
422                         struct ifmultiaddr ifma;
423                         union {
424                                 struct sockaddr sa;
425                                 struct sockaddr_in in;
426 #ifdef INET6
427                                 struct sockaddr_in6 in6;
428 #endif /* INET6 */
429                                 struct sockaddr_dl dl;
430                         } msa;
431                         const char *fmt;
432
433                         TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
434                                 if (kread((u_long)multiaddr, (char *)&ifma,
435                                           sizeof ifma))
436                                         break;
437                                 multiaddr = &ifma;
438                                 if (kread((u_long)ifma.ifma_addr, (char *)&msa,
439                                           sizeof msa))
440                                         break;
441                                 if (msa.sa.sa_family != sa->sa_family)
442                                         continue;
443                                 
444                                 fmt = NULL;
445                                 switch (msa.sa.sa_family) {
446                                 case AF_INET:
447                                         fmt = routename(msa.in.sin_addr.s_addr);
448                                         break;
449 #ifdef INET6
450                                 case AF_INET6:
451                                         printf("%23s %-19.19s(refs: %d)\n", "",
452                                                inet_ntop(AF_INET6,
453                                                          &msa.in6.sin6_addr,
454                                                          ntop_buf,
455                                                          sizeof(ntop_buf)),
456                                                ifma.ifma_refcount);
457                                         break;
458 #endif /* INET6 */
459                                 case AF_LINK:
460                                         switch (msa.dl.sdl_type) {
461                                         case IFT_ETHER:
462                                         case IFT_FDDI:
463                                                 fmt = ether_ntoa(
464                                                         (struct ether_addr *)
465                                                         LLADDR(&msa.dl));
466                                                 break;
467                                         }
468                                         break;
469                                 }
470                                 if (fmt)
471                                         printf("%23s %s\n", "", fmt);
472                         }
473                 }
474         }
475 }
476
477 struct  iftot {
478         SLIST_ENTRY(iftot) chain;
479         char    ift_name[IFNAMSIZ];     /* interface name */
480         u_long  ift_ip;                 /* input packets */
481         u_long  ift_ie;                 /* input errors */
482         u_long  ift_op;                 /* output packets */
483         u_long  ift_oe;                 /* output errors */
484         u_long  ift_co;                 /* collisions */
485         u_long  ift_dr;                 /* drops */
486         u_long  ift_ib;                 /* input bytes */
487         u_long  ift_ob;                 /* output bytes */
488 };
489
490 u_char  signalled;                      /* set if alarm goes off "early" */
491
492 /*
493  * Print a running summary of interface statistics.
494  * Repeat display every interval1 seconds, showing statistics
495  * collected over that interval.  Assumes that interval1 is non-zero.
496  * First line printed at top of screen is always cumulative.
497  * XXX - should be rewritten to use ifmib(4).
498  */
499 static void
500 sidewaysintpr(unsigned interval1, u_long off, int ncpus)
501 {
502         struct ifnet ifnet;
503         u_long firstifnet;
504         struct ifnethead ifnethead;
505         struct ifdata_pcpu ifdata;
506         struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
507         int line, cpu;
508         int oldmask, first;
509         u_long interesting_off;
510         u_long ifdata_addr;
511
512         if (kread(off, (char *)&ifnethead, sizeof ifnethead))
513                 return;
514         firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
515
516         if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
517                 printf("malloc failed\n");
518                 exit(1);
519         }
520         memset(iftot, 0, sizeof(struct iftot));
521
522         interesting = NULL;
523         interesting_off = 0;
524         for (off = firstifnet, ip = iftot; off;) {
525                 char name[IFNAMSIZ];
526
527                 if (kread(off, (char *)&ifnet, sizeof ifnet))
528                         break;
529                 strlcpy(name, ifnet.if_xname, sizeof(name));
530                 if (interface && strcmp(name, interface) == 0) {
531                         interesting = ip;
532                         interesting_off = off;
533                 }
534                 snprintf(ip->ift_name, 16, "(%s)", name);
535                 if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
536                         printf("malloc failed\n");
537                         exit(1);
538                 }
539                 memset(ipn, 0, sizeof(struct iftot));
540                 SLIST_NEXT(ip, chain) = ipn;
541                 ip = ipn;
542                 off = (u_long)TAILQ_NEXT(&ifnet, if_link);
543         }
544         if ((total = malloc(sizeof(struct iftot))) == NULL) {
545                 printf("malloc failed\n");
546                 exit(1);
547         }
548         memset(total, 0, sizeof(struct iftot));
549         if ((sum = malloc(sizeof(struct iftot))) == NULL) {
550                 printf("malloc failed\n");
551                 exit(1);
552         }
553         memset(sum, 0, sizeof(struct iftot));
554
555
556         (void)signal(SIGALRM, catchalarm);
557         signalled = NO;
558         (void)alarm(interval1);
559         first = 1;
560 banner:
561         printf("%17s %14s %16s", "input",
562             interesting ? interesting->ift_name : "(Total)", "output");
563         putchar('\n');
564         printf("%10s %5s %10s %10s %5s %10s %5s",
565             "packets", "errs", "bytes", "packets", "errs", "bytes", "colls");
566         if (dflag)
567                 printf(" %5.5s", "drops");
568         putchar('\n');
569         fflush(stdout);
570         line = 0;
571 loop:
572         if (interesting != NULL) {
573                 ip = interesting;
574                 if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) {
575                         printf("???\n");
576                         exit(1);
577                 }
578
579                 ifdata_addr = (u_long)ifnet.if_data_pcpu;
580                 if (kread(ifdata_addr, (char *)&ifdata, sizeof(ifdata))) {
581                         printf("ifdata 1\n");
582                         exit(1);
583                 }
584                 ifnet.if_ipackets = ifdata.ifd_ipackets;
585                 ifnet.if_ierrors = ifdata.ifd_ierrors;
586                 ifnet.if_ibytes = ifdata.ifd_ibytes;
587                 ifnet.if_opackets = ifdata.ifd_opackets;
588                 ifnet.if_oerrors = ifdata.ifd_oerrors;
589                 ifnet.if_obytes = ifdata.ifd_obytes;
590                 ifnet.if_collisions = ifdata.ifd_collisions;
591                 ifnet.if_oqdrops = ifdata.ifd_oqdrops;
592
593                 for (cpu = 1; cpu < ncpus; ++cpu) {
594                         if (kread(ifdata_addr + (cpu * sizeof(ifdata)),
595                             (char *)&ifdata, sizeof(ifdata))) {
596                                 printf("ifdata 2\n");
597                                 exit(1);
598                         }
599                         ifnet.if_ipackets += ifdata.ifd_ipackets;
600                         ifnet.if_ierrors += ifdata.ifd_ierrors;
601                         ifnet.if_ibytes += ifdata.ifd_ibytes;
602                         ifnet.if_opackets += ifdata.ifd_opackets;
603                         ifnet.if_oerrors += ifdata.ifd_oerrors;
604                         ifnet.if_obytes += ifdata.ifd_obytes;
605                         ifnet.if_collisions += ifdata.ifd_collisions;
606                         ifnet.if_oqdrops += ifdata.ifd_oqdrops;
607                 }
608
609                 if (!first) {
610                         printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu",
611                                 ifnet.if_ipackets - ip->ift_ip,
612                                 ifnet.if_ierrors - ip->ift_ie,
613                                 ifnet.if_ibytes - ip->ift_ib,
614                                 ifnet.if_opackets - ip->ift_op,
615                                 ifnet.if_oerrors - ip->ift_oe,
616                                 ifnet.if_obytes - ip->ift_ob,
617                                 ifnet.if_collisions - ip->ift_co);
618                         if (dflag)
619                                 printf(" %5lu", ifnet.if_oqdrops - ip->ift_dr);
620                 }
621                 ip->ift_ip = ifnet.if_ipackets;
622                 ip->ift_ie = ifnet.if_ierrors;
623                 ip->ift_ib = ifnet.if_ibytes;
624                 ip->ift_op = ifnet.if_opackets;
625                 ip->ift_oe = ifnet.if_oerrors;
626                 ip->ift_ob = ifnet.if_obytes;
627                 ip->ift_co = ifnet.if_collisions;
628                 ip->ift_dr = ifnet.if_oqdrops;
629         } else {
630                 sum->ift_ip = 0;
631                 sum->ift_ie = 0;
632                 sum->ift_ib = 0;
633                 sum->ift_op = 0;
634                 sum->ift_oe = 0;
635                 sum->ift_ob = 0;
636                 sum->ift_co = 0;
637                 sum->ift_dr = 0;
638                 for (off = firstifnet, ip = iftot;
639                      off && SLIST_NEXT(ip, chain) != NULL;
640                      ip = SLIST_NEXT(ip, chain)) {
641                         if (kread(off, (char *)&ifnet, sizeof ifnet)) {
642                                 off = 0;
643                                 continue;
644                         }
645
646                         ifdata_addr = (u_long)ifnet.if_data_pcpu;
647                         if (kread(ifdata_addr, (char *)&ifdata,
648                             sizeof(ifdata))) {
649                                 printf("ifdata 3\n");
650                                 exit(1);
651                         }
652                         ifnet.if_ipackets = ifdata.ifd_ipackets;
653                         ifnet.if_ierrors = ifdata.ifd_ierrors;
654                         ifnet.if_ibytes = ifdata.ifd_ibytes;
655                         ifnet.if_opackets = ifdata.ifd_opackets;
656                         ifnet.if_oerrors = ifdata.ifd_oerrors;
657                         ifnet.if_obytes = ifdata.ifd_obytes;
658                         ifnet.if_collisions = ifdata.ifd_collisions;
659                         ifnet.if_oqdrops = ifdata.ifd_oqdrops;
660
661                         for (cpu = 1; cpu < ncpus; ++cpu) {
662                                 if (kread(ifdata_addr + (cpu * sizeof(ifdata)),
663                                     (char *)&ifdata, sizeof(ifdata))) {
664                                         printf("ifdata 2\n");
665                                         exit(1);
666                                 }
667                                 ifnet.if_ipackets += ifdata.ifd_ipackets;
668                                 ifnet.if_ierrors += ifdata.ifd_ierrors;
669                                 ifnet.if_ibytes += ifdata.ifd_ibytes;
670                                 ifnet.if_opackets += ifdata.ifd_opackets;
671                                 ifnet.if_oerrors += ifdata.ifd_oerrors;
672                                 ifnet.if_obytes += ifdata.ifd_obytes;
673                                 ifnet.if_collisions += ifdata.ifd_collisions;
674                                 ifnet.if_oqdrops += ifdata.ifd_oqdrops;
675                         }
676
677                         /*
678                          * Don't double-count interfaces that are associated
679                          * with bridges, they will be rolled up by the
680                          * bridge.  Errors and collisions are not rolled up.
681                          */
682                         if (ifnet.if_bridge) {
683                                 sum->ift_ie += ifnet.if_ierrors;
684                                 sum->ift_oe += ifnet.if_oerrors;
685                                 sum->ift_co += ifnet.if_collisions;
686                         } else {
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 += ifnet.if_oqdrops;
695                         }
696                         off = (u_long)TAILQ_NEXT(&ifnet, if_link);
697                 }
698                 if (!first) {
699                         /* %10lu %5lu %10lu %10lu %5lu %10lu %5lu */
700                         show_stat("lu", 10,   sum->ift_ip - total->ift_ip, 1);
701                         show_stat("lu",  5+1, sum->ift_ie - total->ift_ie, 1);
702                         show_stat("lu", 10+1, sum->ift_ib - total->ift_ib, 1);
703                         show_stat("lu", 10+1, sum->ift_op - total->ift_op, 1);
704                         show_stat("lu",  5+1, sum->ift_oe - total->ift_oe, 1);
705                         show_stat("lu", 10+1, sum->ift_ob - total->ift_ob, 1);
706                         show_stat("lu",  5+1, sum->ift_co - total->ift_co, 1);
707                         if (dflag)
708                                 show_stat("u", 5+1, sum->ift_dr - total->ift_dr, 1);
709                 }
710                 *total = *sum;
711         }
712         if (!first)
713                 putchar('\n');
714         fflush(stdout);
715         oldmask = sigblock(sigmask(SIGALRM));
716         if (! signalled) {
717                 sigpause(0);
718         }
719         sigsetmask(oldmask);
720         signalled = NO;
721         (void)alarm(interval1);
722         line++;
723         first = 0;
724         if (line == 21)
725                 goto banner;
726         else
727                 goto loop;
728         /*NOTREACHED*/
729 }
730
731 /*
732  * Called if an interval expires before sidewaysintpr has completed a loop.
733  * Sets a flag to not wait for the alarm.
734  */
735 static void
736 catchalarm(int signo __unused)
737 {
738         signalled = YES;
739 }