2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
36 static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95";
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
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>
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>
79 static void sidewaysintpr(int, u_long);
80 static void catchalarm(int);
84 static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
87 /* print bridge statistics */
89 bdg_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
97 if (sysctlbyname("net.link.ether.bdgstats", &s, &slen, NULL, 0) < 0) {
99 warn("sysctl: net.link.ether.bdgstats");
103 kread(off, &s, slen);
111 printf("-- Bridging statistics (%s) --\n", name) ;
113 "Name In Out Forward Drop Bcast Mcast Local Unknown\n");
114 for (i = 0 ; i < 16 ; i++) {
116 printf("%-6s %9ld%9ld%9ld%9ld%9ld%9ld%9ld%9ld\n",
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] );
130 * Dump pfsync statistics structure.
133 pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
135 struct pfsyncstats pfsyncstat, zerostat;
136 size_t len = sizeof(struct pfsyncstats);
140 memset(&zerostat, 0, len);
141 if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
142 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
144 warn("sysctl: net.inet.pfsync.stats");
148 kread(off, &pfsyncstat, len);
150 printf("%s:\n", name);
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)
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");
178 * Display a formatted value, or a '-' in the same space.
181 show_stat(const char *fmt, int width, u_long value, short showvalue)
183 const char *lsep, *rsep;
187 if (strncmp(fmt, "LS", 2) == 0) {
192 if (strncmp(fmt, "NRS", 3) == 0) {
196 if (showvalue == 0) {
197 /* Print just dash. */
198 sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
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);
212 /* Construct the format string. */
213 sprintf(newfmt, "%s%%%d%s%s", lsep, width, fmt, rsep);
214 printf(newfmt, value);
219 * Print a description of the network interfaces.
222 intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
225 struct ifnethead ifnethead;
230 struct in6_ifaddr in6;
232 struct ipx_ifaddr ipx;
248 struct sockaddr *sa = NULL;
253 if (ifnetaddr == 0) {
254 printf("ifnet: symbol not defined\n");
258 sidewaysintpr(interval1, ifnetaddr);
261 if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead))
263 ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
264 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
269 printf("%-7.7s", "Name");
271 printf("%-5.5s", "Name");
272 printf(" %5.5s %-13.13s %-17.17s %8.8s %5.5s",
273 "Mtu", "Network", "Address", "Ipkts", "Ierrs");
275 printf(" %10.10s","Ibytes");
276 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
278 printf(" %10.10s","Obytes");
279 printf(" %5s", "Coll");
281 printf(" %s", "Time");
283 printf(" %s", "Drop");
287 while (ifnetaddr || ifaddraddr) {
288 struct sockaddr_in *sockin;
290 struct sockaddr_in6 *sockin6;
298 if (ifaddraddr == 0) {
299 ifnetfound = ifnetaddr;
300 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
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))
306 cp = index(name, '\0');
313 if ((ifnet.if_flags&IFF_UP) == 0)
316 ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead);
318 ifaddrfound = ifaddraddr;
321 * Get the interface stats. These may get
322 * overriden below on a per-interface basis.
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;
336 if (ifaddraddr == 0) {
338 printf("%-7.7s", name);
340 printf("%-5.5s", name);
341 printf(" %5lu ", ifnet.if_mtu);
342 printf("%-13.13s ", "none");
343 printf("%-17.17s ", "none");
345 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
349 #define CP(x) ((char *)(x))
350 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
352 sa = (struct sockaddr *)cp;
353 if (af != AF_UNSPEC && sa->sa_family != af) {
355 (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
359 printf("%-7.7s", name);
361 printf("%-5.5s", name);
362 printf(" %5lu ", ifnet.if_mtu);
363 switch (sa->sa_family) {
365 printf("%-13.13s ", "none");
366 printf("%-15.15s ", "none");
369 sockin = (struct sockaddr_in *)sa;
371 /* can't use inet_makeaddr because kernel
372 * keeps nets unshifted.
374 in = inet_makeaddr(ifaddr.in.ia_subnet,
376 printf("%-13.13s ", netname(in.s_addr,
377 ifaddr.in.ia_subnetmask));
380 netname(htonl(ifaddr.in.ia_subnet),
381 ifaddr.in.ia_subnetmask));
384 routename(sockin->sin_addr.s_addr));
390 sockin6 = (struct sockaddr_in6 *)sa;
392 netname6(&ifaddr.in6.ia_addr,
393 &ifaddr.in6.ia_prefixmask.sin6_addr));
397 ntop_buf, sizeof(ntop_buf)));
404 struct sockaddr_ipx *sipx =
405 (struct sockaddr_ipx *)sa;
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)); */
414 ipx_phost((struct sockaddr *)sipx));
421 printf("atalk:%-12.12s ",atalk_print(sa,0x10) );
422 printf("%-11.11s ",atalk_print(sa,0x0b) );
426 struct sockaddr_dl *sdl =
427 (struct sockaddr_dl *)sa;
429 cp = (char *)LLADDR(sdl);
431 sprintf(linknum, "<Link#%d>", sdl->sdl_index);
432 m = printf("%-13.13s ", linknum);
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;
443 m += printf("%02x%c", *cp++ & 0xff,
454 * Fixup the statistics for interfaces that
455 * update stats for their network addresses
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;
464 ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
467 show_stat("lu", 8, ipackets, link_layer|network_layer);
468 show_stat("lu", 5, ierrors, link_layer);
470 show_stat("lu", 10, ibytes, link_layer|network_layer);
472 show_stat("lu", 8, opackets, link_layer|network_layer);
473 show_stat("lu", 5, oerrors, link_layer);
475 show_stat("lu", 10, obytes, link_layer|network_layer);
477 show_stat("NRSlu", 5, collisions, link_layer);
479 show_stat("LSd", 4, timer, link_layer);
481 show_stat("LSd", 4, drops, link_layer);
484 if (aflag && ifaddrfound) {
486 * Print family's multicast addresses
488 struct ifmultiaddr *multiaddr;
489 struct ifmultiaddr ifma;
492 struct sockaddr_in in;
494 struct sockaddr_in6 in6;
496 struct sockaddr_dl dl;
500 TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
501 if (kread((u_long)multiaddr, (char *)&ifma,
505 if (kread((u_long)ifma.ifma_addr, (char *)&msa,
508 if (msa.sa.sa_family != sa->sa_family)
512 switch (msa.sa.sa_family) {
514 fmt = routename(msa.in.sin_addr.s_addr);
518 printf("%*s %-19.19s(refs: %d)\n",
528 switch (msa.dl.sdl_type) {
532 (struct ether_addr *)
539 printf("%*s %-17.17s",
540 Wflag ? 27 : 25, "", fmt);
541 if (msa.sa.sa_family == AF_LINK) {
542 printf(" %8lu", imcasts);
545 printf(" %8lu", omcasts);
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 */
567 u_char signalled; /* set if alarm goes off "early" */
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).
577 sidewaysintpr(int interval1, u_long off)
581 struct ifnethead ifnethead;
582 struct itimerval interval_it;
583 struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
586 u_long interesting_off;
588 if (kread(off, (char *)&ifnethead, sizeof ifnethead))
590 firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
592 if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
593 printf("malloc failed\n");
596 memset(iftot, 0, sizeof(struct iftot));
600 for (off = firstifnet, ip = iftot; off;) {
603 if (kread(off, (char *)&ifnet, sizeof ifnet))
605 strlcpy(name, ifnet.if_xname, sizeof(name));
606 if (interface && strcmp(name, interface) == 0) {
608 interesting_off = off;
610 snprintf(ip->ift_name, sizeof(ip->ift_name), "(%s)", name);;
611 if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
612 printf("malloc failed\n");
615 memset(ipn, 0, sizeof(struct iftot));
616 SLIST_NEXT(ip, chain) = ipn;
618 off = (u_long)TAILQ_NEXT(&ifnet, if_link);
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");
626 memset(total, 0, sizeof(struct iftot));
627 if ((sum = malloc(sizeof(struct iftot))) == NULL) {
628 printf("malloc failed\n");
631 memset(sum, 0, sizeof(struct iftot));
633 (void)signal(SIGALRM, catchalarm);
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);
641 printf("%17s %14s %16s", "input",
642 interesting ? interesting->ift_name : "(Total)", "output");
644 printf("%10s %5s %10s %10s %5s %10s %5s",
645 "packets", "errs", "bytes", "packets", "errs", "bytes", "colls");
647 printf(" %5.5s", "drops");
652 if (interesting != NULL) {
654 if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) {
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);
669 ifnet.if_snd.ifq_drops - ip->ift_dr, 1);
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;
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)) {
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);
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);
715 sum->ift_dr - total->ift_dr, 1);
722 oldmask = sigblock(sigmask(SIGALRM));
737 * Set a flag to indicate that a signal from the periodic itimer has been
741 catchalarm(int signo __unused)