]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/netstat/if.c
Copy xen includes in to RELENG_6 branch
[FreeBSD/FreeBSD.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. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #if 0
35 #ifndef lint
36 static char sccsid[] = "@(#)if.c        8.3 (Berkeley) 4/28/95";
37 #endif /* not lint */
38 #endif
39
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
42
43 #include <sys/types.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/sysctl.h>
48 #include <sys/time.h>
49
50 #include <net/if.h>
51 #include <net/if_var.h>
52 #include <net/if_dl.h>
53 #include <net/if_types.h>
54 #include <net/bridge.h>
55 #include <net/ethernet.h>
56 #include <net/pfvar.h>
57 #include <net/if_pfsync.h>
58 #include <netinet/in.h>
59 #include <netinet/in_var.h>
60 #include <netipx/ipx.h>
61 #include <netipx/ipx_if.h>
62 #include <arpa/inet.h>
63
64 #include <err.h>
65 #include <errno.h>
66 #include <libutil.h>
67 #include <signal.h>
68 #include <stdint.h>
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <string.h>
72 #include <unistd.h>
73
74 #include "netstat.h"
75
76 #define YES     1
77 #define NO      0
78
79 static void sidewaysintpr(int, u_long);
80 static void catchalarm(int);
81
82 #ifdef INET6
83 static int bdg_done;
84 static char ntop_buf[INET6_ADDRSTRLEN];         /* for inet_ntop() */
85 #endif
86
87 /* print bridge statistics */
88 void
89 bdg_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
90 {
91     struct bdg_stats s;
92     size_t slen;
93     int i;
94
95     slen = sizeof(s);
96     if (live) {
97         if (sysctlbyname("net.link.ether.bdgstats", &s, &slen, NULL, 0) < 0) {
98             if (errno != ENOENT)
99                 warn("sysctl: net.link.ether.bdgstats");
100             return;
101         }
102     } else
103         kread(off, &s, slen);
104             
105 #ifdef INET6
106     if (bdg_done != 0)
107         return;
108     else
109         bdg_done = 1;
110 #endif
111     printf("-- Bridging statistics (%s) --\n", name) ;
112     printf(
113 "Name          In      Out  Forward     Drop    Bcast    Mcast    Local  Unknown\n");
114     for (i = 0 ; i < 16 ; i++) {
115         if (s.s[i].name[0])
116         printf("%-6s %9ld%9ld%9ld%9ld%9ld%9ld%9ld%9ld\n",
117           s.s[i].name,
118           s.s[i].p_in[(int)BDG_IN],
119           s.s[i].p_in[(int)BDG_OUT],
120           s.s[i].p_in[(int)BDG_FORWARD],
121           s.s[i].p_in[(int)BDG_DROP],
122           s.s[i].p_in[(int)BDG_BCAST],
123           s.s[i].p_in[(int)BDG_MCAST],
124           s.s[i].p_in[(int)BDG_LOCAL],
125           s.s[i].p_in[(int)BDG_UNKNOWN] );
126     }
127 }
128
129 /* 
130  * Dump pfsync statistics structure.
131  */
132 void
133 pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
134 {
135         struct pfsyncstats pfsyncstat, zerostat;
136         size_t len = sizeof(struct pfsyncstats);
137
138         if (live) {
139                 if (zflag)
140                         memset(&zerostat, 0, len);
141                 if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
142                     zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
143                         if (errno != ENOENT)
144                                 warn("sysctl: net.inet.pfsync.stats");
145                         return;
146                 }
147         } else
148                 kread(off, &pfsyncstat, len);
149
150         printf("%s:\n", name);
151
152 #define p(f, m) if (pfsyncstat.f || sflag <= 1) \
153         printf(m, (uintmax_t)pfsyncstat.f, plural(pfsyncstat.f))
154 #define p2(f, m) if (pfsyncstat.f || sflag <= 1) \
155         printf(m, (uintmax_t)pfsyncstat.f)
156
157         p(pfsyncs_ipackets, "\t%ju packet%s received (IPv4)\n");
158         p(pfsyncs_ipackets6, "\t%ju packet%s received (IPv6)\n");
159         p(pfsyncs_badif, "\t\t%ju packet%s discarded for bad interface\n");
160         p(pfsyncs_badttl, "\t\t%ju packet%s discarded for bad ttl\n");
161         p(pfsyncs_hdrops, "\t\t%ju packet%s shorter than header\n");
162         p(pfsyncs_badver, "\t\t%ju packet%s discarded for bad version\n");
163         p(pfsyncs_badauth, "\t\t%ju packet%s discarded for bad HMAC\n");
164         p(pfsyncs_badact,"\t\t%ju packet%s discarded for bad action\n");
165         p(pfsyncs_badlen, "\t\t%ju packet%s discarded for short packet\n");
166         p(pfsyncs_badval, "\t\t%ju state%s discarded for bad values\n");
167         p(pfsyncs_stale, "\t\t%ju stale state%s\n");
168         p(pfsyncs_badstate, "\t\t%ju failed state lookup/insert%s\n");
169         p(pfsyncs_opackets, "\t%ju packet%s sent (IPv4)\n");
170         p(pfsyncs_opackets6, "\t%ju packet%s sent (IPv6)\n");
171         p2(pfsyncs_onomem, "\t\t%ju send failed due to mbuf memory error\n");
172         p2(pfsyncs_oerrors, "\t\t%ju send error\n");
173 #undef p
174 #undef p2
175 }
176
177 /*
178  * Display a formatted value, or a '-' in the same space.
179  */
180 static void
181 show_stat(const char *fmt, int width, u_long value, short showvalue)
182 {
183         const char *lsep, *rsep;
184         char newfmt[32];
185
186         lsep = "";
187         if (strncmp(fmt, "LS", 2) == 0) {
188                 lsep = " ";
189                 fmt += 2;
190         }
191         rsep = " ";
192         if (strncmp(fmt, "NRS", 3) == 0) {
193                 rsep = "";
194                 fmt += 3;
195         }
196         if (showvalue == 0) {
197                 /* Print just dash. */
198                 sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
199                 printf(newfmt, "-");
200                 return;
201         }
202
203         if (hflag) {
204                 char buf[5];
205
206                 /* Format in human readable form. */
207                 humanize_number(buf, sizeof(buf), (int64_t)value, "",
208                     HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL);
209                 sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
210                 printf(newfmt, buf);
211         } else {
212                 /* Construct the format string. */
213                 sprintf(newfmt, "%s%%%d%s%s", lsep, width, fmt, rsep);
214                 printf(newfmt, value);
215         }
216 }
217
218 /*
219  * Print a description of the network interfaces.
220  */
221 void
222 intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
223 {
224         struct ifnet ifnet;
225         struct ifnethead ifnethead;
226         union {
227                 struct ifaddr ifa;
228                 struct in_ifaddr in;
229 #ifdef INET6
230                 struct in6_ifaddr in6;
231 #endif
232                 struct ipx_ifaddr ipx;
233         } ifaddr;
234         u_long ifaddraddr;
235         u_long ifaddrfound;
236         u_long ifnetfound;
237         u_long opackets;
238         u_long ipackets;
239         u_long obytes;
240         u_long ibytes;
241         u_long omcasts;
242         u_long imcasts;
243         u_long oerrors;
244         u_long ierrors;
245         u_long collisions;
246         short timer;
247         int drops;
248         struct sockaddr *sa = NULL;
249         char name[IFNAMSIZ];
250         short network_layer;
251         short link_layer;
252
253         if (ifnetaddr == 0) {
254                 printf("ifnet: symbol not defined\n");
255                 return;
256         }
257         if (interval1) {
258                 sidewaysintpr(interval1, ifnetaddr);
259                 return;
260         }
261         if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead))
262                 return;
263         ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
264         if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
265                 return;
266
267         if (!pfunc) {
268                 if (Wflag)
269                         printf("%-7.7s", "Name");
270                 else
271                         printf("%-5.5s", "Name");
272                 printf(" %5.5s %-13.13s %-17.17s %8.8s %5.5s",
273                     "Mtu", "Network", "Address", "Ipkts", "Ierrs");
274                 if (bflag)
275                         printf(" %10.10s","Ibytes");
276                 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
277                 if (bflag)
278                         printf(" %10.10s","Obytes");
279                 printf(" %5s", "Coll");
280                 if (tflag)
281                         printf(" %s", "Time");
282                 if (dflag)
283                         printf(" %s", "Drop");
284                 putchar('\n');
285         }
286         ifaddraddr = 0;
287         while (ifnetaddr || ifaddraddr) {
288                 struct sockaddr_in *sockin;
289 #ifdef INET6
290                 struct sockaddr_in6 *sockin6;
291 #endif
292                 char *cp;
293                 int n, m;
294
295                 network_layer = 0;
296                 link_layer = 0;
297
298                 if (ifaddraddr == 0) {
299                         ifnetfound = ifnetaddr;
300                         if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
301                                 return;
302                         strlcpy(name, ifnet.if_xname, sizeof(name));
303                         ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link);
304                         if (interface != 0 && (strcmp(name, interface) != 0))
305                                 continue;
306                         cp = index(name, '\0');
307
308                         if (pfunc) {
309                                 (*pfunc)(name);
310                                 continue;
311                         }
312
313                         if ((ifnet.if_flags&IFF_UP) == 0)
314                                 *cp++ = '*';
315                         *cp = '\0';
316                         ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead);
317                 }
318                 ifaddrfound = ifaddraddr;
319
320                 /*
321                  * Get the interface stats.  These may get
322                  * overriden below on a per-interface basis.
323                  */
324                 opackets = ifnet.if_opackets;
325                 ipackets = ifnet.if_ipackets;
326                 obytes = ifnet.if_obytes;
327                 ibytes = ifnet.if_ibytes;
328                 omcasts = ifnet.if_omcasts;
329                 imcasts = ifnet.if_imcasts;
330                 oerrors = ifnet.if_oerrors;
331                 ierrors = ifnet.if_ierrors;
332                 collisions = ifnet.if_collisions;
333                 timer = ifnet.if_timer;
334                 drops = ifnet.if_snd.ifq_drops;
335
336                 if (ifaddraddr == 0) {
337                         if (Wflag)
338                                 printf("%-7.7s", name);
339                         else
340                                 printf("%-5.5s", name);
341                         printf(" %5lu ", ifnet.if_mtu);
342                         printf("%-13.13s ", "none");
343                         printf("%-17.17s ", "none");
344                 } else {
345                         if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
346                                 ifaddraddr = 0;
347                                 continue;
348                         }
349 #define CP(x) ((char *)(x))
350                         cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
351                                 CP(&ifaddr);
352                         sa = (struct sockaddr *)cp;
353                         if (af != AF_UNSPEC && sa->sa_family != af) {
354                                 ifaddraddr =
355                                     (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
356                                 continue;
357                         }
358                         if (Wflag)
359                                 printf("%-7.7s", name);
360                         else
361                                 printf("%-5.5s", name);
362                         printf(" %5lu ", ifnet.if_mtu);
363                         switch (sa->sa_family) {
364                         case AF_UNSPEC:
365                                 printf("%-13.13s ", "none");
366                                 printf("%-15.15s ", "none");
367                                 break;
368                         case AF_INET:
369                                 sockin = (struct sockaddr_in *)sa;
370 #ifdef notdef
371                                 /* can't use inet_makeaddr because kernel
372                                  * keeps nets unshifted.
373                                  */
374                                 in = inet_makeaddr(ifaddr.in.ia_subnet,
375                                         INADDR_ANY);
376                                 printf("%-13.13s ", netname(in.s_addr,
377                                     ifaddr.in.ia_subnetmask));
378 #else
379                                 printf("%-13.13s ",
380                                     netname(htonl(ifaddr.in.ia_subnet),
381                                     ifaddr.in.ia_subnetmask));
382 #endif
383                                 printf("%-17.17s ",
384                                     routename(sockin->sin_addr.s_addr));
385
386                                 network_layer = 1;
387                                 break;
388 #ifdef INET6
389                         case AF_INET6:
390                                 sockin6 = (struct sockaddr_in6 *)sa;
391                                 printf("%-13.13s ",
392                                        netname6(&ifaddr.in6.ia_addr,
393                                                 &ifaddr.in6.ia_prefixmask.sin6_addr));
394                                 printf("%-17.17s ",
395                                     inet_ntop(AF_INET6,
396                                         &sockin6->sin6_addr,
397                                         ntop_buf, sizeof(ntop_buf)));
398
399                                 network_layer = 1;
400                                 break;
401 #endif /*INET6*/
402                         case AF_IPX:
403                                 {
404                                 struct sockaddr_ipx *sipx =
405                                         (struct sockaddr_ipx *)sa;
406                                 u_long net;
407                                 char netnum[10];
408
409                                 *(union ipx_net *) &net = sipx->sipx_addr.x_net;
410                                 sprintf(netnum, "%lx", (u_long)ntohl(net));
411                                 printf("ipx:%-8s  ", netnum);
412 /*                              printf("ipx:%-8s ", netname(net, 0L)); */
413                                 printf("%-17s ",
414                                     ipx_phost((struct sockaddr *)sipx));
415                                 }
416
417                                 network_layer = 1;
418                                 break;
419
420                         case AF_APPLETALK:
421                                 printf("atalk:%-12.12s ",atalk_print(sa,0x10) );
422                                 printf("%-11.11s  ",atalk_print(sa,0x0b) );
423                                 break;
424                         case AF_LINK:
425                                 {
426                                 struct sockaddr_dl *sdl =
427                                         (struct sockaddr_dl *)sa;
428                                 char linknum[10];
429                                 cp = (char *)LLADDR(sdl);
430                                 n = sdl->sdl_alen;
431                                 sprintf(linknum, "<Link#%d>", sdl->sdl_index);
432                                 m = printf("%-13.13s ", linknum);
433                                 }
434                                 goto hexprint;
435                         default:
436                                 m = printf("(%d)", sa->sa_family);
437                                 for (cp = sa->sa_len + (char *)sa;
438                                         --cp > sa->sa_data && (*cp == 0);) {}
439                                 n = cp - sa->sa_data + 1;
440                                 cp = sa->sa_data;
441                         hexprint:
442                                 while (--n >= 0)
443                                         m += printf("%02x%c", *cp++ & 0xff,
444                                                     n > 0 ? ':' : ' ');
445                                 m = 32 - m;
446                                 while (m-- > 0)
447                                         putchar(' ');
448
449                                 link_layer = 1;
450                                 break;
451                         }
452
453                         /*
454                          * Fixup the statistics for interfaces that
455                          * update stats for their network addresses
456                          */
457                         if (network_layer) {
458                                 opackets = ifaddr.in.ia_ifa.if_opackets;
459                                 ipackets = ifaddr.in.ia_ifa.if_ipackets;
460                                 obytes = ifaddr.in.ia_ifa.if_obytes;
461                                 ibytes = ifaddr.in.ia_ifa.if_ibytes;
462                         }
463
464                         ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
465                 }
466
467                 show_stat("lu", 8, ipackets, link_layer|network_layer);
468                 show_stat("lu", 5, ierrors, link_layer);
469                 if (bflag)
470                         show_stat("lu", 10, ibytes, link_layer|network_layer);
471
472                 show_stat("lu", 8, opackets, link_layer|network_layer);
473                 show_stat("lu", 5, oerrors, link_layer);
474                 if (bflag)
475                         show_stat("lu", 10, obytes, link_layer|network_layer);
476
477                 show_stat("NRSlu", 5, collisions, link_layer);
478                 if (tflag)
479                         show_stat("LSd", 4, timer, link_layer);
480                 if (dflag)
481                         show_stat("LSd", 4, drops, link_layer);
482                 putchar('\n');
483
484                 if (aflag && ifaddrfound) {
485                         /*
486                          * Print family's multicast addresses
487                          */
488                         struct ifmultiaddr *multiaddr;
489                         struct ifmultiaddr ifma;
490                         union {
491                                 struct sockaddr sa;
492                                 struct sockaddr_in in;
493 #ifdef INET6
494                                 struct sockaddr_in6 in6;
495 #endif /* INET6 */
496                                 struct sockaddr_dl dl;
497                         } msa;
498                         const char *fmt;
499
500                         TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
501                                 if (kread((u_long)multiaddr, (char *)&ifma,
502                                           sizeof ifma))
503                                         break;
504                                 multiaddr = &ifma;
505                                 if (kread((u_long)ifma.ifma_addr, (char *)&msa,
506                                           sizeof msa))
507                                         break;
508                                 if (msa.sa.sa_family != sa->sa_family)
509                                         continue;
510                                 
511                                 fmt = 0;
512                                 switch (msa.sa.sa_family) {
513                                 case AF_INET:
514                                         fmt = routename(msa.in.sin_addr.s_addr);
515                                         break;
516 #ifdef INET6
517                                 case AF_INET6:
518                                         printf("%*s %-19.19s(refs: %d)\n",
519                                                Wflag ? 27 : 25, "",
520                                                inet_ntop(AF_INET6,
521                                                          &msa.in6.sin6_addr,
522                                                          ntop_buf,
523                                                          sizeof(ntop_buf)),
524                                                ifma.ifma_refcount);
525                                         break;
526 #endif /* INET6 */
527                                 case AF_LINK:
528                                         switch (msa.dl.sdl_type) {
529                                         case IFT_ETHER:
530                                         case IFT_FDDI:
531                                                 fmt = ether_ntoa(
532                                                         (struct ether_addr *)
533                                                         LLADDR(&msa.dl));
534                                                 break;
535                                         }
536                                         break;
537                                 }
538                                 if (fmt) {
539                                         printf("%*s %-17.17s",
540                                             Wflag ? 27 : 25, "", fmt);
541                                         if (msa.sa.sa_family == AF_LINK) {
542                                                 printf(" %8lu", imcasts);
543                                                 printf("%*s",
544                                                     bflag ? 17 : 6, "");
545                                                 printf(" %8lu", omcasts);
546                                         }
547                                         putchar('\n');
548                                 }
549                         }
550                 }
551         }
552 }
553
554 struct  iftot {
555         SLIST_ENTRY(iftot) chain;
556         char    ift_name[IFNAMSIZ];     /* interface name */
557         u_long  ift_ip;                 /* input packets */
558         u_long  ift_ie;                 /* input errors */
559         u_long  ift_op;                 /* output packets */
560         u_long  ift_oe;                 /* output errors */
561         u_long  ift_co;                 /* collisions */
562         u_int   ift_dr;                 /* drops */
563         u_long  ift_ib;                 /* input bytes */
564         u_long  ift_ob;                 /* output bytes */
565 };
566
567 u_char  signalled;                      /* set if alarm goes off "early" */
568
569 /*
570  * Print a running summary of interface statistics.
571  * Repeat display every interval1 seconds, showing statistics
572  * collected over that interval.  Assumes that interval1 is non-zero.
573  * First line printed at top of screen is always cumulative.
574  * XXX - should be rewritten to use ifmib(4).
575  */
576 static void
577 sidewaysintpr(int interval1, u_long off)
578 {
579         struct ifnet ifnet;
580         u_long firstifnet;
581         struct ifnethead ifnethead;
582         struct itimerval interval_it;
583         struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
584         int line;
585         int oldmask, first;
586         u_long interesting_off;
587
588         if (kread(off, (char *)&ifnethead, sizeof ifnethead))
589                 return;
590         firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
591
592         if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
593                 printf("malloc failed\n");
594                 exit(1);
595         }
596         memset(iftot, 0, sizeof(struct iftot));
597
598         interesting = NULL;
599         interesting_off = 0;
600         for (off = firstifnet, ip = iftot; off;) {
601                 char name[IFNAMSIZ];
602
603                 if (kread(off, (char *)&ifnet, sizeof ifnet))
604                         break;
605                 strlcpy(name, ifnet.if_xname, sizeof(name));
606                 if (interface && strcmp(name, interface) == 0) {
607                         interesting = ip;
608                         interesting_off = off;
609                 }
610                 snprintf(ip->ift_name, sizeof(ip->ift_name), "(%s)", name);;
611                 if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
612                         printf("malloc failed\n");
613                         exit(1);
614                 }
615                 memset(ipn, 0, sizeof(struct iftot));
616                 SLIST_NEXT(ip, chain) = ipn;
617                 ip = ipn;
618                 off = (u_long)TAILQ_NEXT(&ifnet, if_link);
619         }
620         if (interface && interesting == NULL)
621                 errx(1, "%s: unknown interface", interface);
622         if ((total = malloc(sizeof(struct iftot))) == NULL) {
623                 printf("malloc failed\n");
624                 exit(1);
625         }
626         memset(total, 0, sizeof(struct iftot));
627         if ((sum = malloc(sizeof(struct iftot))) == NULL) {
628                 printf("malloc failed\n");
629                 exit(1);
630         }
631         memset(sum, 0, sizeof(struct iftot));
632
633         (void)signal(SIGALRM, catchalarm);
634         signalled = NO;
635         interval_it.it_interval.tv_sec = interval1;
636         interval_it.it_interval.tv_usec = 0;
637         interval_it.it_value = interval_it.it_interval;
638         setitimer(ITIMER_REAL, &interval_it, NULL);
639         first = 1;
640 banner:
641         printf("%17s %14s %16s", "input",
642             interesting ? interesting->ift_name : "(Total)", "output");
643         putchar('\n');
644         printf("%10s %5s %10s %10s %5s %10s %5s",
645             "packets", "errs", "bytes", "packets", "errs", "bytes", "colls");
646         if (dflag)
647                 printf(" %5.5s", "drops");
648         putchar('\n');
649         fflush(stdout);
650         line = 0;
651 loop:
652         if (interesting != NULL) {
653                 ip = interesting;
654                 if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) {
655                         printf("???\n");
656                         exit(1);
657                 };
658                 if (!first) {
659                         show_stat("lu", 10, ifnet.if_ipackets - ip->ift_ip, 1);
660                         show_stat("lu", 5, ifnet.if_ierrors - ip->ift_ie, 1);
661                         show_stat("lu", 10, ifnet.if_ibytes - ip->ift_ib, 1);
662                         show_stat("lu", 10, ifnet.if_opackets - ip->ift_op, 1);
663                         show_stat("lu", 5, ifnet.if_oerrors - ip->ift_oe, 1);
664                         show_stat("lu", 10, ifnet.if_obytes - ip->ift_ob, 1);
665                         show_stat("NRSlu", 5, 
666                             ifnet.if_collisions - ip->ift_co, 1);
667                         if (dflag)
668                                 show_stat("LSu", 5,
669                                     ifnet.if_snd.ifq_drops - ip->ift_dr, 1);
670                 }
671                 ip->ift_ip = ifnet.if_ipackets;
672                 ip->ift_ie = ifnet.if_ierrors;
673                 ip->ift_ib = ifnet.if_ibytes;
674                 ip->ift_op = ifnet.if_opackets;
675                 ip->ift_oe = ifnet.if_oerrors;
676                 ip->ift_ob = ifnet.if_obytes;
677                 ip->ift_co = ifnet.if_collisions;
678                 ip->ift_dr = ifnet.if_snd.ifq_drops;
679         } else {
680                 sum->ift_ip = 0;
681                 sum->ift_ie = 0;
682                 sum->ift_ib = 0;
683                 sum->ift_op = 0;
684                 sum->ift_oe = 0;
685                 sum->ift_ob = 0;
686                 sum->ift_co = 0;
687                 sum->ift_dr = 0;
688                 for (off = firstifnet, ip = iftot;
689                      off && SLIST_NEXT(ip, chain) != NULL;
690                      ip = SLIST_NEXT(ip, chain)) {
691                         if (kread(off, (char *)&ifnet, sizeof ifnet)) {
692                                 off = 0;
693                                 continue;
694                         }
695                         sum->ift_ip += ifnet.if_ipackets;
696                         sum->ift_ie += ifnet.if_ierrors;
697                         sum->ift_ib += ifnet.if_ibytes;
698                         sum->ift_op += ifnet.if_opackets;
699                         sum->ift_oe += ifnet.if_oerrors;
700                         sum->ift_ob += ifnet.if_obytes;
701                         sum->ift_co += ifnet.if_collisions;
702                         sum->ift_dr += ifnet.if_snd.ifq_drops;
703                         off = (u_long)TAILQ_NEXT(&ifnet, if_link);
704                 }
705                 if (!first) {
706                         show_stat("lu", 10, sum->ift_ip - total->ift_ip, 1);
707                         show_stat("lu", 5, sum->ift_ie - total->ift_ie, 1);
708                         show_stat("lu", 10, sum->ift_ib - total->ift_ib, 1);
709                         show_stat("lu", 10, sum->ift_op - total->ift_op, 1);
710                         show_stat("lu", 5, sum->ift_oe - total->ift_oe, 1);
711                         show_stat("lu", 10, sum->ift_ob - total->ift_ob, 1);
712                         show_stat("NRSlu", 5, sum->ift_co - total->ift_co, 1);
713                         if (dflag)
714                                 show_stat("LSu", 5,
715                                     sum->ift_dr - total->ift_dr, 1);
716                 }
717                 *total = *sum;
718         }
719         if (!first)
720                 putchar('\n');
721         fflush(stdout);
722         oldmask = sigblock(sigmask(SIGALRM));
723         while (!signalled)
724                 sigpause(0);
725         signalled = NO;
726         sigsetmask(oldmask);
727         line++;
728         first = 0;
729         if (line == 21)
730                 goto banner;
731         else
732                 goto loop;
733         /*NOTREACHED*/
734 }
735
736 /*
737  * Set a flag to indicate that a signal from the periodic itimer has been
738  * caught.
739  */
740 static void
741 catchalarm(int signo __unused)
742 {
743         signalled = YES;
744 }