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