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