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