Index: stable/10/usr.bin/netstat/if.c =================================================================== --- stable/10/usr.bin/netstat/if.c (revision 261206) +++ stable/10/usr.bin/netstat/if.c (revision 261207) @@ -1,732 +1,590 @@ /*- + * Copyright (c) 2013 Gleb Smirnoff * Copyright (c) 1983, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #ifdef INET6 #include #endif #include +#include #include #include #include #include +#include #include #include "netstat.h" -#define YES 1 -#define NO 0 +static void sidewaysintpr(int); -static void sidewaysintpr(int, u_long); -static void catchalarm(int); - #ifdef INET6 static char addr_buf[NI_MAXHOST]; /* for getnameinfo() */ #endif static const char* pfsyncacts[] = { /* PFSYNC_ACT_CLR */ "clear all request", /* PFSYNC_ACT_INS */ "state insert", /* PFSYNC_ACT_INS_ACK */ "state inserted ack", /* PFSYNC_ACT_UPD */ "state update", /* PFSYNC_ACT_UPD_C */ "compressed state update", /* PFSYNC_ACT_UPD_REQ */ "uncompressed state request", /* PFSYNC_ACT_DEL */ "state delete", /* PFSYNC_ACT_DEL_C */ "compressed state delete", /* PFSYNC_ACT_INS_F */ "fragment insert", /* PFSYNC_ACT_DEL_F */ "fragment delete", /* PFSYNC_ACT_BUS */ "bulk update mark", /* PFSYNC_ACT_TDB */ "TDB replay counter update", /* PFSYNC_ACT_EOF */ "end of frame mark", }; static void pfsync_acts_stats(const char *fmt, uint64_t *a) { int i; for (i = 0; i < PFSYNC_ACT_MAX; i++, a++) if (*a || sflag <= 1) printf(fmt, *a, pfsyncacts[i], plural(*a)); } /* * Dump pfsync statistics structure. */ void pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused) { struct pfsyncstats pfsyncstat, zerostat; size_t len = sizeof(struct pfsyncstats); if (live) { if (zflag) memset(&zerostat, 0, len); if (sysctlbyname("net.pfsync.stats", &pfsyncstat, &len, zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { if (errno != ENOENT) warn("sysctl: net.pfsync.stats"); return; } } else kread(off, &pfsyncstat, len); printf("%s:\n", name); #define p(f, m) if (pfsyncstat.f || sflag <= 1) \ printf(m, (uintmax_t)pfsyncstat.f, plural(pfsyncstat.f)) p(pfsyncs_ipackets, "\t%ju packet%s received (IPv4)\n"); p(pfsyncs_ipackets6, "\t%ju packet%s received (IPv6)\n"); pfsync_acts_stats("\t %ju %s%s received\n", &pfsyncstat.pfsyncs_iacts[0]); p(pfsyncs_badif, "\t\t%ju packet%s discarded for bad interface\n"); p(pfsyncs_badttl, "\t\t%ju packet%s discarded for bad ttl\n"); p(pfsyncs_hdrops, "\t\t%ju packet%s shorter than header\n"); p(pfsyncs_badver, "\t\t%ju packet%s discarded for bad version\n"); p(pfsyncs_badauth, "\t\t%ju packet%s discarded for bad HMAC\n"); p(pfsyncs_badact,"\t\t%ju packet%s discarded for bad action\n"); p(pfsyncs_badlen, "\t\t%ju packet%s discarded for short packet\n"); p(pfsyncs_badval, "\t\t%ju state%s discarded for bad values\n"); p(pfsyncs_stale, "\t\t%ju stale state%s\n"); p(pfsyncs_badstate, "\t\t%ju failed state lookup/insert%s\n"); p(pfsyncs_opackets, "\t%ju packet%s sent (IPv4)\n"); p(pfsyncs_opackets6, "\t%ju packet%s sent (IPv6)\n"); pfsync_acts_stats("\t %ju %s%s sent\n", &pfsyncstat.pfsyncs_oacts[0]); p(pfsyncs_onomem, "\t\t%ju failure%s due to mbuf memory error\n"); p(pfsyncs_oerrors, "\t\t%ju send error%s\n"); #undef p } /* * Display a formatted value, or a '-' in the same space. */ static void show_stat(const char *fmt, int width, u_long value, short showvalue) { const char *lsep, *rsep; char newfmt[32]; lsep = ""; if (strncmp(fmt, "LS", 2) == 0) { lsep = " "; fmt += 2; } rsep = " "; if (strncmp(fmt, "NRS", 3) == 0) { rsep = ""; fmt += 3; } if (showvalue == 0) { /* Print just dash. */ sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep); printf(newfmt, "-"); return; } if (hflag) { char buf[5]; /* Format in human readable form. */ humanize_number(buf, sizeof(buf), (int64_t)value, "", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL); sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep); printf(newfmt, buf); } else { /* Construct the format string. */ sprintf(newfmt, "%s%%%d%s%s", lsep, width, fmt, rsep); printf(newfmt, value); } } /* + * Find next multiaddr for a given interface name. + */ +static struct ifmaddrs * +next_ifma(struct ifmaddrs *ifma, const char *name, const sa_family_t family) +{ + + for(; ifma != NULL; ifma = ifma->ifma_next) { + struct sockaddr_dl *sdl; + + sdl = (struct sockaddr_dl *)ifma->ifma_name; + if (ifma->ifma_addr->sa_family == family && + strcmp(sdl->sdl_data, name) == 0) + break; + } + + return (ifma); +} + +/* * Print a description of the network interfaces. */ void -intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *)) +intpr(int interval, void (*pfunc)(char *)) { - struct ifnet ifnet; - struct ifnethead ifnethead; - union { - struct ifaddr ifa; - struct in_ifaddr in; -#ifdef INET6 - struct in6_ifaddr in6; -#endif - struct ipx_ifaddr ipx; - } ifaddr; - u_long ifaddraddr; - u_long ifaddrfound; - u_long opackets; - u_long ipackets; - u_long obytes; - u_long ibytes; - u_long omcasts; - u_long imcasts; - u_long oerrors; - u_long ierrors; - u_long idrops; - u_long collisions; - int drops; - struct sockaddr *sa = NULL; - char name[IFNAMSIZ]; - short network_layer; - short link_layer; + struct ifaddrs *ifap, *ifa; + struct ifmaddrs *ifmap, *ifma; + + if (interval) + return sidewaysintpr(interval); - if (ifnetaddr == 0) { - printf("ifnet: symbol not defined\n"); - return; - } - if (interval1) { - sidewaysintpr(interval1, ifnetaddr); - return; - } - if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead) != 0) - return; - ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead); - if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0) - return; + if (getifaddrs(&ifap) != 0) + err(EX_OSERR, "getifaddrs"); + if (aflag && getifmaddrs(&ifmap) != 0) + err(EX_OSERR, "getifmaddrs"); if (!pfunc) { if (Wflag) printf("%-7.7s", "Name"); else printf("%-5.5s", "Name"); printf(" %5.5s %-13.13s %-17.17s %8.8s %5.5s %5.5s", "Mtu", "Network", "Address", "Ipkts", "Ierrs", "Idrop"); if (bflag) printf(" %10.10s","Ibytes"); printf(" %8.8s %5.5s", "Opkts", "Oerrs"); if (bflag) printf(" %10.10s","Obytes"); printf(" %5s", "Coll"); if (dflag) printf(" %s", "Drop"); putchar('\n'); } - ifaddraddr = 0; - while (ifnetaddr || ifaddraddr) { - struct sockaddr_in *sockin; -#ifdef INET6 - struct sockaddr_in6 *sockin6; -#endif - char *cp; - int n, m; - network_layer = 0; - link_layer = 0; + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + bool network = false, link = false; - if (ifaddraddr == 0) { - if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0) - return; - strlcpy(name, ifnet.if_xname, sizeof(name)); - ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link); - if (interface != 0 && strcmp(name, interface) != 0) - continue; - cp = strchr(name, '\0'); + if (interface != NULL && strcmp(ifa->ifa_name, interface) != 0) + continue; - if (pfunc) { - (*pfunc)(name); - continue; - } + if (pfunc) { + char *name; - if ((ifnet.if_flags&IFF_UP) == 0) - *cp++ = '*'; - *cp = '\0'; - ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead); + name = ifa->ifa_name; + (*pfunc)(name); + + /* + * Skip all ifaddrs belonging to same interface. + */ + while(ifa->ifa_next != NULL && + (strcmp(ifa->ifa_next->ifa_name, name) == 0)) { + ifa = ifa->ifa_next; + } + continue; } - ifaddrfound = ifaddraddr; - /* - * Get the interface stats. These may get - * overriden below on a per-interface basis. - */ - opackets = ifnet.if_opackets; - ipackets = ifnet.if_ipackets; - obytes = ifnet.if_obytes; - ibytes = ifnet.if_ibytes; - omcasts = ifnet.if_omcasts; - imcasts = ifnet.if_imcasts; - oerrors = ifnet.if_oerrors; - ierrors = ifnet.if_ierrors; - idrops = ifnet.if_iqdrops; - collisions = ifnet.if_collisions; - drops = ifnet.if_snd.ifq_drops; + if (af != AF_UNSPEC && ifa->ifa_addr->sa_family != af) + continue; - if (ifaddraddr == 0) { - if (Wflag) - printf("%-7.7s", name); - else - printf("%-5.5s", name); - printf(" %5lu ", ifnet.if_mtu); + if (Wflag) + printf("%-7.7s", ifa->ifa_name); + else + printf("%-5.5s", ifa->ifa_name); + +#define IFA_MTU(ifa) (((struct if_data *)(ifa)->ifa_data)->ifi_mtu) + show_stat("lu", 6, IFA_MTU(ifa), IFA_MTU(ifa)); +#undef IFA_MTU + + switch (ifa->ifa_addr->sa_family) { + case AF_UNSPEC: printf("%-13.13s ", "none"); - printf("%-17.17s ", "none"); - } else { - if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr) - != 0) { - ifaddraddr = 0; - continue; - } -#define CP(x) ((char *)(x)) - cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + - CP(&ifaddr); - sa = (struct sockaddr *)cp; - if (af != AF_UNSPEC && sa->sa_family != af) { - ifaddraddr = - (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link); - continue; - } - if (Wflag) - printf("%-7.7s", name); - else - printf("%-5.5s", name); - printf(" %5lu ", ifnet.if_mtu); - switch (sa->sa_family) { - case AF_UNSPEC: - printf("%-13.13s ", "none"); - printf("%-15.15s ", "none"); - break; - case AF_INET: - sockin = (struct sockaddr_in *)sa; -#ifdef notdef - /* can't use inet_makeaddr because kernel - * keeps nets unshifted. - */ - in = inet_makeaddr(ifaddr.in.ia_subnet, - INADDR_ANY); - printf("%-13.13s ", netname(in.s_addr, - ifaddr.in.ia_subnetmask)); -#else - printf("%-13.13s ", - netname(htonl(ifaddr.in.ia_subnet), - ifaddr.in.ia_subnetmask)); -#endif - printf("%-17.17s ", - routename(sockin->sin_addr.s_addr)); + printf("%-15.15s ", "none"); + break; + case AF_INET: + { + struct sockaddr_in *sin, *mask; - network_layer = 1; - break; + sin = (struct sockaddr_in *)ifa->ifa_addr; + mask = (struct sockaddr_in *)ifa->ifa_netmask; + printf("%-13.13s ", netname(sin->sin_addr.s_addr, + mask->sin_addr.s_addr)); + printf("%-17.17s ", + routename(sin->sin_addr.s_addr)); + + network = true; + break; + } #ifdef INET6 - case AF_INET6: - sockin6 = (struct sockaddr_in6 *)sa; - in6_fillscopeid(&ifaddr.in6.ia_addr); - printf("%-13.13s ", - netname6(&ifaddr.in6.ia_addr, - &ifaddr.in6.ia_prefixmask.sin6_addr)); - in6_fillscopeid(sockin6); - getnameinfo(sa, sa->sa_len, addr_buf, - sizeof(addr_buf), 0, 0, NI_NUMERICHOST); - printf("%-17.17s ", addr_buf); + case AF_INET6: + { + struct sockaddr_in6 *sin6, *mask; - network_layer = 1; - break; -#endif /*INET6*/ - case AF_IPX: - { - struct sockaddr_ipx *sipx = - (struct sockaddr_ipx *)sa; - u_long net; - char netnum[10]; + sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; + mask = (struct sockaddr_in6 *)ifa->ifa_netmask; - *(union ipx_net *) &net = sipx->sipx_addr.x_net; - sprintf(netnum, "%lx", (u_long)ntohl(net)); - printf("ipx:%-8s ", netnum); -/* printf("ipx:%-8s ", netname(net, 0L)); */ - printf("%-17s ", - ipx_phost((struct sockaddr *)sipx)); - } + printf("%-13.13s ", netname6(sin6, &mask->sin6_addr)); + getnameinfo(ifa->ifa_addr, ifa->ifa_addr->sa_len, + addr_buf, sizeof(addr_buf), 0, 0, NI_NUMERICHOST); + printf("%-17.17s ", addr_buf); - network_layer = 1; - break; + network = 1; + break; + } +#endif /* INET6 */ + case AF_IPX: + { + struct sockaddr_ipx *sipx; + u_long net; + char netnum[10]; - case AF_APPLETALK: - printf("atalk:%-12.12s ",atalk_print(sa,0x10) ); - printf("%-11.11s ",atalk_print(sa,0x0b) ); - break; - case AF_LINK: - { - struct sockaddr_dl *sdl = - (struct sockaddr_dl *)sa; - char linknum[10]; - cp = (char *)LLADDR(sdl); - n = sdl->sdl_alen; - sprintf(linknum, "", sdl->sdl_index); - m = printf("%-13.13s ", linknum); - } - goto hexprint; - default: - m = printf("(%d)", sa->sa_family); - for (cp = sa->sa_len + (char *)sa; - --cp > sa->sa_data && (*cp == 0);) {} - n = cp - sa->sa_data + 1; - cp = sa->sa_data; - hexprint: - while ((--n >= 0) && (m < 30)) - m += printf("%02x%c", *cp++ & 0xff, - n > 0 ? ':' : ' '); - m = 32 - m; - while (m-- > 0) - putchar(' '); + sipx = (struct sockaddr_ipx *)ifa->ifa_addr; + *(union ipx_net *) &net = sipx->sipx_addr.x_net; - link_layer = 1; - break; - } + sprintf(netnum, "%lx", (u_long)ntohl(net)); + printf("ipx:%-8s ", netnum); + printf("%-17s ", ipx_phost((struct sockaddr *)sipx)); - /* - * Fixup the statistics for interfaces that - * update stats for their network addresses - */ - if (network_layer) { - opackets = ifaddr.in.ia_ifa.if_opackets; - ipackets = ifaddr.in.ia_ifa.if_ipackets; - obytes = ifaddr.in.ia_ifa.if_obytes; - ibytes = ifaddr.in.ia_ifa.if_ibytes; - } + network = 1; + break; + } + case AF_APPLETALK: + printf("atalk:%-12.12s ", + atalk_print(ifa->ifa_addr, 0x10)); + printf("%-11.11s ", + atalk_print(ifa->ifa_addr, 0x0b)); + break; + case AF_LINK: + { + struct sockaddr_dl *sdl; + char *cp, linknum[10]; + int n, m; - ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link); + sdl = (struct sockaddr_dl *)ifa->ifa_addr; + cp = (char *)LLADDR(sdl); + n = sdl->sdl_alen; + sprintf(linknum, "", sdl->sdl_index); + m = printf("%-13.13s ", linknum); + + while ((--n >= 0) && (m < 30)) + m += printf("%02x%c", *cp++ & 0xff, + n > 0 ? ':' : ' '); + m = 32 - m; + while (m-- > 0) + putchar(' '); + + link = 1; + break; + } } - show_stat("lu", 8, ipackets, link_layer|network_layer); - show_stat("lu", 5, ierrors, link_layer); - show_stat("lu", 5, idrops, link_layer); +#define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s) + show_stat("lu", 8, IFA_STAT(ipackets), link|network); + show_stat("lu", 5, IFA_STAT(ierrors), link); + show_stat("lu", 5, IFA_STAT(iqdrops), link); if (bflag) - show_stat("lu", 10, ibytes, link_layer|network_layer); - - show_stat("lu", 8, opackets, link_layer|network_layer); - show_stat("lu", 5, oerrors, link_layer); + show_stat("lu", 10, IFA_STAT(ibytes), link|network); + show_stat("lu", 8, IFA_STAT(opackets), link|network); + show_stat("lu", 5, IFA_STAT(oerrors), link); if (bflag) - show_stat("lu", 10, obytes, link_layer|network_layer); - - show_stat("NRSlu", 5, collisions, link_layer); - if (dflag) - show_stat("LSd", 4, drops, link_layer); + show_stat("lu", 10, IFA_STAT(obytes), link|network); + show_stat("NRSlu", 5, IFA_STAT(collisions), link); + /* XXXGL: output queue drops */ putchar('\n'); - if (aflag && ifaddrfound) { - /* - * Print family's multicast addresses - */ - struct ifmultiaddr *multiaddr; - struct ifmultiaddr ifma; - union { - struct sockaddr sa; - struct sockaddr_in in; -#ifdef INET6 - struct sockaddr_in6 in6; -#endif /* INET6 */ - struct sockaddr_dl dl; - } msa; - const char *fmt; + if (!aflag) + continue; - TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) { - if (kread((u_long)multiaddr, (char *)&ifma, - sizeof ifma) != 0) - break; - multiaddr = &ifma; - if (kread((u_long)ifma.ifma_addr, (char *)&msa, - sizeof msa) != 0) - break; - if (msa.sa.sa_family != sa->sa_family) - continue; + /* + * Print family's multicast addresses. + */ + for (ifma = next_ifma(ifmap, ifa->ifa_name, + ifa->ifa_addr->sa_family); + ifma != NULL; + ifma = next_ifma(ifma, ifa->ifa_name, + ifa->ifa_addr->sa_family)) { + const char *fmt = NULL; - fmt = 0; - switch (msa.sa.sa_family) { - case AF_INET: - fmt = routename(msa.in.sin_addr.s_addr); - break; + switch (ifma->ifma_addr->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)ifma->ifma_addr; + fmt = routename(sin->sin_addr.s_addr); + break; + } #ifdef INET6 - case AF_INET6: - in6_fillscopeid(&msa.in6); - getnameinfo(&msa.sa, msa.sa.sa_len, - addr_buf, sizeof(addr_buf), 0, 0, - NI_NUMERICHOST); - printf("%*s %-19.19s(refs: %d)\n", - Wflag ? 27 : 25, "", - addr_buf, ifma.ifma_refcount); - break; + case AF_INET6: + + /* in6_fillscopeid(&msa.in6); */ + getnameinfo(ifma->ifma_addr, + ifma->ifma_addr->sa_len, addr_buf, + sizeof(addr_buf), 0, 0, NI_NUMERICHOST); + printf("%*s %s\n", + Wflag ? 27 : 25, "", addr_buf); + break; #endif /* INET6 */ - case AF_LINK: - switch (msa.dl.sdl_type) { - case IFT_ETHER: - case IFT_FDDI: - fmt = ether_ntoa( - (struct ether_addr *) - LLADDR(&msa.dl)); - break; - } + case AF_LINK: + { + struct sockaddr_dl *sdl; + + sdl = (struct sockaddr_dl *)ifma->ifma_addr; + switch (sdl->sdl_type) { + case IFT_ETHER: + case IFT_FDDI: + fmt = ether_ntoa( + (struct ether_addr *)LLADDR(sdl)); break; } - if (fmt) { - printf("%*s %-17.17s", - Wflag ? 27 : 25, "", fmt); - if (msa.sa.sa_family == AF_LINK) { - printf(" %8lu", imcasts); - printf("%*s", - bflag ? 17 : 6, ""); - printf(" %8lu", omcasts); - } - putchar('\n'); + break; + } + } + + if (fmt) { + printf("%*s %-17.17s", + Wflag ? 27 : 25, "", fmt); + if (ifma->ifma_addr->sa_family == AF_LINK) { + printf(" %8lu", IFA_STAT(imcasts)); + printf("%*s", bflag ? 17 : 6, ""); + printf(" %8lu", IFA_STAT(omcasts)); } + putchar('\n'); } + + ifma = ifma->ifma_next; } } + + freeifaddrs(ifap); + if (aflag) + freeifmaddrs(ifmap); } -struct iftot { - SLIST_ENTRY(iftot) chain; - char ift_name[IFNAMSIZ]; /* interface name */ +struct iftot { u_long ift_ip; /* input packets */ u_long ift_ie; /* input errors */ u_long ift_id; /* input drops */ u_long ift_op; /* output packets */ u_long ift_oe; /* output errors */ u_long ift_co; /* collisions */ - u_int ift_dr; /* drops */ u_long ift_ib; /* input bytes */ u_long ift_ob; /* output bytes */ }; -u_char signalled; /* set if alarm goes off "early" */ - /* - * Print a running summary of interface statistics. - * Repeat display every interval1 seconds, showing statistics - * collected over that interval. Assumes that interval1 is non-zero. - * First line printed at top of screen is always cumulative. - * XXX - should be rewritten to use ifmib(4). + * Obtain stats for interface(s). */ static void -sidewaysintpr(int interval1, u_long off) +fill_iftot(struct iftot *st) { - struct ifnet ifnet; - u_long firstifnet; - struct ifnethead ifnethead; - struct itimerval interval_it; - struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting; - int line; - int oldmask, first; - u_long interesting_off; + struct ifaddrs *ifap, *ifa; + bool found = false; - if (kread(off, (char *)&ifnethead, sizeof ifnethead) != 0) - return; - firstifnet = (u_long)TAILQ_FIRST(&ifnethead); + if (getifaddrs(&ifap) != 0) + err(EX_OSERR, "getifaddrs"); - if ((iftot = malloc(sizeof(struct iftot))) == NULL) { - printf("malloc failed\n"); - exit(1); - } - memset(iftot, 0, sizeof(struct iftot)); + bzero(st, sizeof(*st)); - interesting = NULL; - interesting_off = 0; - for (off = firstifnet, ip = iftot; off;) { - char name[IFNAMSIZ]; - - if (kread(off, (char *)&ifnet, sizeof ifnet) != 0) - break; - strlcpy(name, ifnet.if_xname, sizeof(name)); - if (interface && strcmp(name, interface) == 0) { - interesting = ip; - interesting_off = off; + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family != AF_LINK) + continue; + if (interface) { + if (strcmp(ifa->ifa_name, interface) == 0) + found = true; + else + continue; } - snprintf(ip->ift_name, sizeof(ip->ift_name), "(%s)", name); - if ((ipn = malloc(sizeof(struct iftot))) == NULL) { - printf("malloc failed\n"); - exit(1); - } - memset(ipn, 0, sizeof(struct iftot)); - SLIST_NEXT(ip, chain) = ipn; - ip = ipn; - off = (u_long)TAILQ_NEXT(&ifnet, if_link); + + st->ift_ip += IFA_STAT(ipackets); + st->ift_ie += IFA_STAT(ierrors); + st->ift_id += IFA_STAT(iqdrops); + st->ift_ib += IFA_STAT(ibytes); + st->ift_op += IFA_STAT(opackets); + st->ift_oe += IFA_STAT(oerrors); + st->ift_ob += IFA_STAT(obytes); + st->ift_co += IFA_STAT(collisions); } - if (interface && interesting == NULL) - errx(1, "%s: unknown interface", interface); - if ((total = malloc(sizeof(struct iftot))) == NULL) { - printf("malloc failed\n"); - exit(1); - } - memset(total, 0, sizeof(struct iftot)); - if ((sum = malloc(sizeof(struct iftot))) == NULL) { - printf("malloc failed\n"); - exit(1); - } - memset(sum, 0, sizeof(struct iftot)); + if (interface && found == false) + err(EX_DATAERR, "interface %s not found", interface); + + freeifaddrs(ifap); +} + +/* + * Set a flag to indicate that a signal from the periodic itimer has been + * caught. + */ +static sig_atomic_t signalled; +static void +catchalarm(int signo __unused) +{ + signalled = true; +} + +/* + * Print a running summary of interface statistics. + * Repeat display every interval seconds, showing statistics + * collected over that interval. Assumes that interval is non-zero. + * First line printed at top of screen is always cumulative. + */ +static void +sidewaysintpr(int interval) +{ + struct iftot ift[2], *new, *old; + struct itimerval interval_it; + int oldmask, line; + + new = &ift[0]; + old = &ift[1]; + fill_iftot(old); + (void)signal(SIGALRM, catchalarm); - signalled = NO; - interval_it.it_interval.tv_sec = interval1; + signalled = false; + interval_it.it_interval.tv_sec = interval; interval_it.it_interval.tv_usec = 0; interval_it.it_value = interval_it.it_interval; setitimer(ITIMER_REAL, &interval_it, NULL); - first = 1; + banner: printf("%17s %14s %16s", "input", - interesting ? interesting->ift_name : "(Total)", "output"); + interface != NULL ? interface : "(Total)", "output"); putchar('\n'); printf("%10s %5s %5s %10s %10s %5s %10s %5s", "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes", "colls"); if (dflag) printf(" %5.5s", "drops"); putchar('\n'); fflush(stdout); line = 0; + loop: - if (interesting != NULL) { - ip = interesting; - if (kread(interesting_off, (char *)&ifnet, sizeof ifnet) != 0) { - printf("???\n"); - exit(1); - }; - if (!first) { - show_stat("lu", 10, ifnet.if_ipackets - ip->ift_ip, 1); - show_stat("lu", 5, ifnet.if_ierrors - ip->ift_ie, 1); - show_stat("lu", 5, ifnet.if_iqdrops - ip->ift_id, 1); - show_stat("lu", 10, ifnet.if_ibytes - ip->ift_ib, 1); - show_stat("lu", 10, ifnet.if_opackets - ip->ift_op, 1); - show_stat("lu", 5, ifnet.if_oerrors - ip->ift_oe, 1); - show_stat("lu", 10, ifnet.if_obytes - ip->ift_ob, 1); - show_stat("NRSlu", 5, - ifnet.if_collisions - ip->ift_co, 1); - if (dflag) - show_stat("LSu", 5, - ifnet.if_snd.ifq_drops - ip->ift_dr, 1); - } - ip->ift_ip = ifnet.if_ipackets; - ip->ift_ie = ifnet.if_ierrors; - ip->ift_id = ifnet.if_iqdrops; - ip->ift_ib = ifnet.if_ibytes; - ip->ift_op = ifnet.if_opackets; - ip->ift_oe = ifnet.if_oerrors; - ip->ift_ob = ifnet.if_obytes; - ip->ift_co = ifnet.if_collisions; - ip->ift_dr = ifnet.if_snd.ifq_drops; - } else { - sum->ift_ip = 0; - sum->ift_ie = 0; - sum->ift_id = 0; - sum->ift_ib = 0; - sum->ift_op = 0; - sum->ift_oe = 0; - sum->ift_ob = 0; - sum->ift_co = 0; - sum->ift_dr = 0; - for (off = firstifnet, ip = iftot; - off && SLIST_NEXT(ip, chain) != NULL; - ip = SLIST_NEXT(ip, chain)) { - if (kread(off, (char *)&ifnet, sizeof ifnet) != 0) { - off = 0; - continue; - } - sum->ift_ip += ifnet.if_ipackets; - sum->ift_ie += ifnet.if_ierrors; - sum->ift_id += ifnet.if_iqdrops; - sum->ift_ib += ifnet.if_ibytes; - sum->ift_op += ifnet.if_opackets; - sum->ift_oe += ifnet.if_oerrors; - sum->ift_ob += ifnet.if_obytes; - sum->ift_co += ifnet.if_collisions; - sum->ift_dr += ifnet.if_snd.ifq_drops; - off = (u_long)TAILQ_NEXT(&ifnet, if_link); - } - if (!first) { - show_stat("lu", 10, sum->ift_ip - total->ift_ip, 1); - show_stat("lu", 5, sum->ift_ie - total->ift_ie, 1); - show_stat("lu", 5, sum->ift_id - total->ift_id, 1); - show_stat("lu", 10, sum->ift_ib - total->ift_ib, 1); - show_stat("lu", 10, sum->ift_op - total->ift_op, 1); - show_stat("lu", 5, sum->ift_oe - total->ift_oe, 1); - show_stat("lu", 10, sum->ift_ob - total->ift_ob, 1); - show_stat("NRSlu", 5, sum->ift_co - total->ift_co, 1); - if (dflag) - show_stat("LSu", 5, - sum->ift_dr - total->ift_dr, 1); - } - *total = *sum; - } - if (!first) - putchar('\n'); - fflush(stdout); if ((noutputs != 0) && (--noutputs == 0)) exit(0); oldmask = sigblock(sigmask(SIGALRM)); while (!signalled) sigpause(0); - signalled = NO; + signalled = false; sigsetmask(oldmask); line++; - first = 0; + + fill_iftot(new); + + show_stat("lu", 10, new->ift_ip - old->ift_ip, 1); + show_stat("lu", 5, new->ift_ie - old->ift_ie, 1); + show_stat("lu", 5, new->ift_id - old->ift_id, 1); + show_stat("lu", 10, new->ift_ib - old->ift_ib, 1); + show_stat("lu", 10, new->ift_op - old->ift_op, 1); + show_stat("lu", 5, new->ift_oe - old->ift_oe, 1); + show_stat("lu", 10, new->ift_ob - old->ift_ob, 1); + show_stat("NRSlu", 5, new->ift_co - old->ift_co, 1); + /* XXXGL: output queue drops */ + putchar('\n'); + fflush(stdout); + + if (new == &ift[0]) { + new = &ift[1]; + old = &ift[0]; + } else { + new = &ift[0]; + old = &ift[1]; + } + if (line == 21) goto banner; else goto loop; - /*NOTREACHED*/ -} -/* - * Set a flag to indicate that a signal from the periodic itimer has been - * caught. - */ -static void -catchalarm(int signo __unused) -{ - signalled = YES; + /* NOTREACHED */ } Index: stable/10/usr.bin/netstat/main.c =================================================================== --- stable/10/usr.bin/netstat/main.c (revision 261206) +++ stable/10/usr.bin/netstat/main.c (revision 261207) @@ -1,846 +1,845 @@ /*- * Copyright (c) 1983, 1988, 1993 * Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint char const copyright[] = "@(#) Copyright (c) 1983, 1988, 1993\n\ Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #ifdef NETGRAPH #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netstat.h" static struct nlist nl[] = { #define N_IFNET 0 - { .n_name = "_ifnet" }, + { .n_name = "_ifnet" }, /* XXXGL: can be deleted */ #define N_RTSTAT 1 { .n_name = "_rtstat" }, #define N_RTREE 2 { .n_name = "_rt_tables"}, #define N_MRTSTAT 3 { .n_name = "_mrtstat" }, #define N_MFCHASHTBL 4 { .n_name = "_mfchashtbl" }, #define N_VIFTABLE 5 { .n_name = "_viftable" }, #define N_IPX 6 { .n_name = "_ipxpcb_list"}, #define N_IPXSTAT 7 { .n_name = "_ipxstat"}, #define N_SPXSTAT 8 { .n_name = "_spx_istat"}, #define N_DDPSTAT 9 { .n_name = "_ddpstat"}, #define N_DDPCB 10 { .n_name = "_ddpcb"}, #define N_NGSOCKS 11 { .n_name = "_ngsocklist"}, #define N_IP6STAT 12 { .n_name = "_ip6stat" }, #define N_ICMP6STAT 13 { .n_name = "_icmp6stat" }, #define N_IPSECSTAT 14 { .n_name = "_ipsec4stat" }, #define N_IPSEC6STAT 15 { .n_name = "_ipsec6stat" }, #define N_PIM6STAT 16 { .n_name = "_pim6stat" }, #define N_MRT6STAT 17 { .n_name = "_mrt6stat" }, #define N_MF6CTABLE 18 { .n_name = "_mf6ctable" }, #define N_MIF6TABLE 19 { .n_name = "_mif6table" }, #define N_PFKEYSTAT 20 { .n_name = "_pfkeystat" }, #define N_RTTRASH 21 { .n_name = "_rttrash" }, #define N_CARPSTAT 22 { .n_name = "_carpstats" }, #define N_PFSYNCSTAT 23 { .n_name = "_pfsyncstats" }, #define N_AHSTAT 24 { .n_name = "_ahstat" }, #define N_ESPSTAT 25 { .n_name = "_espstat" }, #define N_IPCOMPSTAT 26 { .n_name = "_ipcompstat" }, #define N_TCPSTAT 27 { .n_name = "_tcpstat" }, #define N_UDPSTAT 28 { .n_name = "_udpstat" }, #define N_IPSTAT 29 { .n_name = "_ipstat" }, #define N_ICMPSTAT 30 { .n_name = "_icmpstat" }, #define N_IGMPSTAT 31 { .n_name = "_igmpstat" }, #define N_PIMSTAT 32 { .n_name = "_pimstat" }, #define N_TCBINFO 33 { .n_name = "_tcbinfo" }, #define N_UDBINFO 34 { .n_name = "_udbinfo" }, #define N_DIVCBINFO 35 { .n_name = "_divcbinfo" }, #define N_RIPCBINFO 36 { .n_name = "_ripcbinfo" }, #define N_UNP_COUNT 37 { .n_name = "_unp_count" }, #define N_UNP_GENCNT 38 { .n_name = "_unp_gencnt" }, #define N_UNP_DHEAD 39 { .n_name = "_unp_dhead" }, #define N_UNP_SHEAD 40 { .n_name = "_unp_shead" }, #define N_RIP6STAT 41 { .n_name = "_rip6stat" }, #define N_SCTPSTAT 42 { .n_name = "_sctpstat" }, #define N_MFCTABLESIZE 43 { .n_name = "_mfctablesize" }, #define N_ARPSTAT 44 { .n_name = "_arpstat" }, #define N_UNP_SPHEAD 45 { .n_name = "unp_sphead" }, #define N_SFSTAT 46 { .n_name = "_sfstat"}, { .n_name = NULL }, }; struct protox { int pr_index; /* index into nlist of cb head */ int pr_sindex; /* index into nlist of stat block */ u_char pr_wanted; /* 1 if wanted, 0 otherwise */ void (*pr_cblocks)(u_long, const char *, int, int); /* control blocks printing routine */ void (*pr_stats)(u_long, const char *, int, int); /* statistics printing routine */ void (*pr_istats)(char *); /* per/if statistics printing routine */ const char *pr_name; /* well-known name */ int pr_usesysctl; /* non-zero if we use sysctl, not kvm */ int pr_protocol; } protox[] = { { N_TCBINFO, N_TCPSTAT, 1, protopr, tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { N_UDBINFO, N_UDPSTAT, 1, protopr, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, #ifdef SCTP { -1, N_SCTPSTAT, 1, sctp_protopr, sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP }, #endif #ifdef SDP { -1, -1, 1, protopr, NULL, NULL, "sdp", 1, IPPROTO_TCP }, #endif { N_DIVCBINFO, -1, 1, protopr, NULL, NULL, "divert", 1, IPPROTO_DIVERT }, { N_RIPCBINFO, N_IPSTAT, 1, protopr, ip_stats, NULL, "ip", 1, IPPROTO_RAW }, { N_RIPCBINFO, N_ICMPSTAT, 1, protopr, icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP }, { N_RIPCBINFO, N_IGMPSTAT, 1, protopr, igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP }, #ifdef IPSEC { -1, N_IPSECSTAT, 1, NULL, /* keep as compat */ ipsec_stats, NULL, "ipsec", 0, 0}, { -1, N_AHSTAT, 1, NULL, ah_stats, NULL, "ah", 0, 0}, { -1, N_ESPSTAT, 1, NULL, esp_stats, NULL, "esp", 0, 0}, { -1, N_IPCOMPSTAT, 1, NULL, ipcomp_stats, NULL, "ipcomp", 0, 0}, #endif { N_RIPCBINFO, N_PIMSTAT, 1, protopr, pim_stats, NULL, "pim", 1, IPPROTO_PIM }, { -1, N_CARPSTAT, 1, NULL, carp_stats, NULL, "carp", 1, 0 }, { -1, N_PFSYNCSTAT, 1, NULL, pfsync_stats, NULL, "pfsync", 1, 0 }, { -1, N_ARPSTAT, 1, NULL, arp_stats, NULL, "arp", 1, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #ifdef INET6 struct protox ip6protox[] = { { N_TCBINFO, N_TCPSTAT, 1, protopr, tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { N_UDBINFO, N_UDPSTAT, 1, protopr, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, { N_RIPCBINFO, N_IP6STAT, 1, protopr, ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW }, { N_RIPCBINFO, N_ICMP6STAT, 1, protopr, icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 }, #ifdef SDP { -1, -1, 1, protopr, NULL, NULL, "sdp", 1, IPPROTO_TCP }, #endif #ifdef IPSEC { -1, N_IPSEC6STAT, 1, NULL, ipsec_stats, NULL, "ipsec6", 0, 0 }, #endif #ifdef notyet { -1, N_PIM6STAT, 1, NULL, pim6_stats, NULL, "pim6", 1, 0 }, #endif { -1, N_RIP6STAT, 1, NULL, rip6_stats, NULL, "rip6", 1, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif /*INET6*/ #ifdef IPSEC struct protox pfkeyprotox[] = { { -1, N_PFKEYSTAT, 1, NULL, pfkey_stats, NULL, "pfkey", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif struct protox atalkprotox[] = { { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, ddp_stats, NULL, "ddp", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #ifdef NETGRAPH struct protox netgraphprotox[] = { { N_NGSOCKS, -1, 1, netgraphprotopr, NULL, NULL, "ctrl", 0, 0 }, { N_NGSOCKS, -1, 1, netgraphprotopr, NULL, NULL, "data", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif #ifdef IPX struct protox ipxprotox[] = { { N_IPX, N_IPXSTAT, 1, ipxprotopr, ipx_stats, NULL, "ipx", 0, 0 }, { N_IPX, N_SPXSTAT, 1, ipxprotopr, spx_stats, NULL, "spx", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, 0, 0, 0 } }; #endif struct protox *protoprotox[] = { protox, #ifdef INET6 ip6protox, #endif #ifdef IPSEC pfkeyprotox, #endif #ifdef IPX ipxprotox, #endif atalkprotox, NULL }; static void printproto(struct protox *, const char *); static void usage(void); static struct protox *name2protox(const char *); static struct protox *knownname(const char *); static kvm_t *kvmd; static char *nlistf = NULL, *memf = NULL; int Aflag; /* show addresses of protocol control block */ int aflag; /* show all sockets (including servers) */ int Bflag; /* show information about bpf consumers */ int bflag; /* show i/f total bytes in/out */ int dflag; /* show i/f dropped packets */ int gflag; /* show group (multicast) routing or stats */ int hflag; /* show counters in human readable format */ int iflag; /* show interfaces */ int Lflag; /* show size of listen queues */ int mflag; /* show memory stats */ int noutputs = 0; /* how much outputs before we exit */ int numeric_addr; /* show addresses numerically */ int numeric_port; /* show ports numerically */ static int pflag; /* show given protocol */ int Qflag; /* show netisr information */ int rflag; /* show routing tables (or routing stats) */ int sflag; /* show protocol statistics */ int Wflag; /* wide display */ int Tflag; /* TCP Information */ int xflag; /* extra information, includes all socket buffer info */ int zflag; /* zero stats */ int interval; /* repeat interval for i/f stats */ char *interface; /* desired i/f for stats, or NULL for all i/fs */ int unit; /* unit number for above */ int af; /* address family */ int live; /* true if we are examining a live system */ int main(int argc, char *argv[]) { struct protox *tp = NULL; /* for printing cblocks & stats */ int ch; int fib = -1; char *endptr; af = AF_UNSPEC; while ((ch = getopt(argc, argv, "AaBbdF:f:ghI:iLlM:mN:np:Qq:rSTsuWw:xz")) != -1) switch(ch) { case 'A': Aflag = 1; break; case 'a': aflag = 1; break; case 'B': Bflag = 1; break; case 'b': bflag = 1; break; case 'd': dflag = 1; break; case 'F': fib = strtol(optarg, &endptr, 0); if (*endptr != '\0' || (fib == 0 && (errno == EINVAL || errno == ERANGE))) errx(1, "%s: invalid fib", optarg); break; case 'f': if (strcmp(optarg, "ipx") == 0) af = AF_IPX; else if (strcmp(optarg, "inet") == 0) af = AF_INET; #ifdef INET6 else if (strcmp(optarg, "inet6") == 0) af = AF_INET6; #endif #ifdef IPSEC else if (strcmp(optarg, "pfkey") == 0) af = PF_KEY; #endif else if (strcmp(optarg, "unix") == 0) af = AF_UNIX; else if (strcmp(optarg, "atalk") == 0) af = AF_APPLETALK; #ifdef NETGRAPH else if (strcmp(optarg, "ng") == 0 || strcmp(optarg, "netgraph") == 0) af = AF_NETGRAPH; #endif else if (strcmp(optarg, "link") == 0) af = AF_LINK; else { errx(1, "%s: unknown address family", optarg); } break; case 'g': gflag = 1; break; case 'h': hflag = 1; break; case 'I': { char *cp; iflag = 1; for (cp = interface = optarg; isalpha(*cp); cp++) continue; unit = atoi(cp); break; } case 'i': iflag = 1; break; case 'L': Lflag = 1; break; case 'M': memf = optarg; break; case 'm': mflag = 1; break; case 'N': nlistf = optarg; break; case 'n': numeric_addr = numeric_port = 1; break; case 'p': if ((tp = name2protox(optarg)) == NULL) { errx(1, "%s: unknown or uninstrumented protocol", optarg); } pflag = 1; break; case 'Q': Qflag = 1; break; case 'q': noutputs = atoi(optarg); if (noutputs != 0) noutputs++; break; case 'r': rflag = 1; break; case 's': ++sflag; break; case 'S': numeric_addr = 1; break; case 'u': af = AF_UNIX; break; case 'W': case 'l': Wflag = 1; break; case 'w': interval = atoi(optarg); iflag = 1; break; case 'T': Tflag = 1; break; case 'x': xflag = 1; break; case 'z': zflag = 1; break; case '?': default: usage(); } argv += optind; argc -= optind; #define BACKWARD_COMPATIBILITY #ifdef BACKWARD_COMPATIBILITY if (*argv) { if (isdigit(**argv)) { interval = atoi(*argv); if (interval <= 0) usage(); ++argv; iflag = 1; } if (*argv) { nlistf = *argv; if (*++argv) memf = *argv; } } #endif /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ live = (nlistf == NULL && memf == NULL); if (!live) setgid(getgid()); if (xflag && Tflag) errx(1, "-x and -T are incompatible, pick one."); if (Bflag) { if (!live) usage(); bpf_stats(interface); exit(0); } if (mflag) { if (!live) { if (kread(0, NULL, 0) == 0) mbpr(kvmd, nl[N_SFSTAT].n_value); } else mbpr(NULL, 0); exit(0); } if (Qflag) { if (!live) { if (kread(0, NULL, 0) == 0) netisr_stats(kvmd); } else netisr_stats(NULL); exit(0); } #if 0 /* * Keep file descriptors open to avoid overhead * of open/close on each call to get* routines. */ sethostent(1); setnetent(1); #else /* * This does not make sense any more with DNS being default over * the files. Doing a setXXXXent(1) causes a tcp connection to be * used for the queries, which is slower. */ #endif kread(0, NULL, 0); if (iflag && !sflag) { - intpr(interval, nl[N_IFNET].n_value, NULL); + intpr(interval, NULL); exit(0); } if (rflag) { if (sflag) rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value); else routepr(nl[N_RTREE].n_value, fib); exit(0); } if (gflag) { if (sflag) { if (af == AF_INET || af == AF_UNSPEC) mrt_stats(nl[N_MRTSTAT].n_value); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) mrt6_stats(nl[N_MRT6STAT].n_value); #endif } else { if (af == AF_INET || af == AF_UNSPEC) mroutepr(nl[N_MFCHASHTBL].n_value, nl[N_MFCTABLESIZE].n_value, nl[N_VIFTABLE].n_value); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) mroute6pr(nl[N_MF6CTABLE].n_value, nl[N_MIF6TABLE].n_value); #endif } exit(0); } if (tp) { printproto(tp, tp->pr_name); exit(0); } if (af == AF_INET || af == AF_UNSPEC) for (tp = protox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) for (tp = ip6protox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /*INET6*/ #ifdef IPSEC if (af == PF_KEY || af == AF_UNSPEC) for (tp = pfkeyprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /*IPSEC*/ #ifdef IPX if (af == AF_IPX || af == AF_UNSPEC) { for (tp = ipxprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); } #endif /* IPX */ if (af == AF_APPLETALK || af == AF_UNSPEC) for (tp = atalkprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #ifdef NETGRAPH if (af == AF_NETGRAPH || af == AF_UNSPEC) for (tp = netgraphprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /* NETGRAPH */ if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, nl[N_UNP_SPHEAD].n_value); exit(0); } /* * Print out protocol statistics or control blocks (per sflag). * If the interface was not specifically requested, and the symbol * is not in the namelist, ignore this one. */ static void printproto(struct protox *tp, const char *name) { void (*pr)(u_long, const char *, int, int); u_long off; if (sflag) { if (iflag) { if (tp->pr_istats) - intpr(interval, nl[N_IFNET].n_value, - tp->pr_istats); + intpr(interval, tp->pr_istats); else if (pflag) printf("%s: no per-interface stats routine\n", tp->pr_name); return; } else { pr = tp->pr_stats; if (!pr) { if (pflag) printf("%s: no stats routine\n", tp->pr_name); return; } if (tp->pr_usesysctl && live) off = 0; else if (tp->pr_sindex < 0) { if (pflag) printf( "%s: stats routine doesn't work on cores\n", tp->pr_name); return; } else off = nl[tp->pr_sindex].n_value; } } else { pr = tp->pr_cblocks; if (!pr) { if (pflag) printf("%s: no PCB routine\n", tp->pr_name); return; } if (tp->pr_usesysctl && live) off = 0; else if (tp->pr_index < 0) { if (pflag) printf( "%s: PCB routine doesn't work on cores\n", tp->pr_name); return; } else off = nl[tp->pr_index].n_value; } if (pr != NULL && (off || (live && tp->pr_usesysctl) || af != AF_UNSPEC)) (*pr)(off, name, af, tp->pr_protocol); } static int kvmd_init(void) { char errbuf[_POSIX2_LINE_MAX]; if (kvmd != NULL) return (0); kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); setgid(getgid()); if (kvmd == NULL) { warnx("kvm not available: %s", errbuf); return (-1); } if (kvm_nlist(kvmd, nl) < 0) { if (nlistf) errx(1, "%s: kvm_nlist: %s", nlistf, kvm_geterr(kvmd)); else errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); } if (nl[0].n_type == 0) { if (nlistf) errx(1, "%s: no namelist", nlistf); else errx(1, "no namelist"); } return (0); } /* * Read kernel memory, return 0 on success. */ int kread(u_long addr, void *buf, size_t size) { if (kvmd_init() < 0) return (-1); if (!buf) return (0); if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) { warnx("%s", kvm_geterr(kvmd)); return (-1); } return (0); } /* * Read an array of N counters in kernel memory into array of N uint64_t's. */ int kread_counters(u_long addr, void *buf, size_t size) { uint64_t *c = buf; if (kvmd_init() < 0) return (-1); if (kread(addr, buf, size) < 0) return (-1); while (size != 0) { *c = kvm_counter_u64_fetch(kvmd, *c); size -= sizeof(*c); c++; } return (0); } const char * plural(uintmax_t n) { return (n != 1 ? "s" : ""); } const char * plurales(uintmax_t n) { return (n != 1 ? "es" : ""); } const char * pluralies(uintmax_t n) { return (n != 1 ? "ies" : "y"); } /* * Find the protox for the given "well-known" name. */ static struct protox * knownname(const char *name) { struct protox **tpp, *tp; for (tpp = protoprotox; *tpp; tpp++) for (tp = *tpp; tp->pr_name; tp++) if (strcmp(tp->pr_name, name) == 0) return (tp); return (NULL); } /* * Find the protox corresponding to name. */ static struct protox * name2protox(const char *name) { struct protox *tp; char **alias; /* alias from p->aliases */ struct protoent *p; /* * Try to find the name in the list of "well-known" names. If that * fails, check if name is an alias for an Internet protocol. */ if ((tp = knownname(name)) != NULL) return (tp); setprotoent(1); /* make protocol lookup cheaper */ while ((p = getprotoent()) != NULL) { /* assert: name not same as p->name */ for (alias = p->p_aliases; *alias; alias++) if (strcmp(name, *alias) == 0) { endprotoent(); return (knownname(p->p_name)); } } endprotoent(); return (NULL); } static void usage(void) { (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", "usage: netstat [-AaLnSTWx] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -i | -I interface [-abdhnW] [-f address_family]\n" " [-M core] [-N system]", " netstat -w wait [-I interface] [-d] [-M core] [-N system] [-q howmany]", " netstat -s [-s] [-z] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -i | -I interface -s [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -m [-M core] [-N system]", " netstat -B [-I interface]", " netstat -r [-AanW] [-f address_family] [-M core] [-N system]", " netstat -rs [-s] [-M core] [-N system]", " netstat -g [-W] [-f address_family] [-M core] [-N system]", " netstat -gs [-s] [-f address_family] [-M core] [-N system]", " netstat -Q"); exit(1); } Index: stable/10/usr.bin/netstat/mbuf.c =================================================================== --- stable/10/usr.bin/netstat/mbuf.c (revision 261206) +++ stable/10/usr.bin/netstat/mbuf.c (revision 261207) @@ -1,329 +1,324 @@ /*- * Copyright (c) 1983, 1988, 1993 * The Regents of the University of California. * Copyright (c) 2005 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)mbuf.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netstat.h" /* * Print mbuf statistics. */ void mbpr(void *kvmd, u_long mbaddr) { struct memory_type_list *mtlp; struct memory_type *mtp; uintmax_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size; uintmax_t mbuf_sleeps; - uintmax_t cluster_count, cluster_bytes, cluster_limit, cluster_free; + uintmax_t cluster_count, cluster_limit, cluster_free; uintmax_t cluster_failures, cluster_size, cluster_sleeps; uintmax_t packet_count, packet_bytes, packet_free, packet_failures; uintmax_t packet_sleeps; - uintmax_t tag_count, tag_bytes; - uintmax_t jumbop_count, jumbop_bytes, jumbop_limit, jumbop_free; + uintmax_t tag_bytes; + uintmax_t jumbop_count, jumbop_limit, jumbop_free; uintmax_t jumbop_failures, jumbop_sleeps, jumbop_size; - uintmax_t jumbo9_count, jumbo9_bytes, jumbo9_limit, jumbo9_free; + uintmax_t jumbo9_count, jumbo9_limit, jumbo9_free; uintmax_t jumbo9_failures, jumbo9_sleeps, jumbo9_size; - uintmax_t jumbo16_count, jumbo16_bytes, jumbo16_limit, jumbo16_free; + uintmax_t jumbo16_count, jumbo16_limit, jumbo16_free; uintmax_t jumbo16_failures, jumbo16_sleeps, jumbo16_size; uintmax_t bytes_inuse, bytes_incache, bytes_total; int nsfbufs, nsfbufspeak, nsfbufsused; struct sfstat sfstat; size_t mlen; int error; mtlp = memstat_mtl_alloc(); if (mtlp == NULL) { warn("memstat_mtl_alloc"); return; } /* * Use memstat_*_all() because some mbuf-related memory is in uma(9), * and some malloc(9). */ if (live) { if (memstat_sysctl_all(mtlp, 0) < 0) { warnx("memstat_sysctl_all: %s", memstat_strerror(memstat_mtl_geterror(mtlp))); goto out; } } else { if (memstat_kvm_all(mtlp, kvmd) < 0) { error = memstat_mtl_geterror(mtlp); if (error == MEMSTAT_ERROR_KVM) warnx("memstat_kvm_all: %s", kvm_geterr(kvmd)); else warnx("memstat_kvm_all: %s", memstat_strerror(error)); goto out; } } mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_MEM_NAME); if (mtp == NULL) { warnx("memstat_mtl_find: zone %s not found", MBUF_MEM_NAME); goto out; } mbuf_count = memstat_get_count(mtp); mbuf_bytes = memstat_get_bytes(mtp); mbuf_free = memstat_get_free(mtp); mbuf_failures = memstat_get_failures(mtp); mbuf_sleeps = memstat_get_sleeps(mtp); mbuf_size = memstat_get_size(mtp); mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_PACKET_MEM_NAME); if (mtp == NULL) { warnx("memstat_mtl_find: zone %s not found", MBUF_PACKET_MEM_NAME); goto out; } packet_count = memstat_get_count(mtp); packet_bytes = memstat_get_bytes(mtp); packet_free = memstat_get_free(mtp); packet_sleeps = memstat_get_sleeps(mtp); packet_failures = memstat_get_failures(mtp); mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_CLUSTER_MEM_NAME); if (mtp == NULL) { warnx("memstat_mtl_find: zone %s not found", MBUF_CLUSTER_MEM_NAME); goto out; } cluster_count = memstat_get_count(mtp); - cluster_bytes = memstat_get_bytes(mtp); cluster_limit = memstat_get_countlimit(mtp); cluster_free = memstat_get_free(mtp); cluster_failures = memstat_get_failures(mtp); cluster_sleeps = memstat_get_sleeps(mtp); cluster_size = memstat_get_size(mtp); mtp = memstat_mtl_find(mtlp, ALLOCATOR_MALLOC, MBUF_TAG_MEM_NAME); if (mtp == NULL) { warnx("memstat_mtl_find: malloc type %s not found", MBUF_TAG_MEM_NAME); goto out; } - tag_count = memstat_get_count(mtp); tag_bytes = memstat_get_bytes(mtp); mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBOP_MEM_NAME); if (mtp == NULL) { warnx("memstat_mtl_find: zone %s not found", MBUF_JUMBOP_MEM_NAME); goto out; } jumbop_count = memstat_get_count(mtp); - jumbop_bytes = memstat_get_bytes(mtp); jumbop_limit = memstat_get_countlimit(mtp); jumbop_free = memstat_get_free(mtp); jumbop_failures = memstat_get_failures(mtp); jumbop_sleeps = memstat_get_sleeps(mtp); jumbop_size = memstat_get_size(mtp); mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO9_MEM_NAME); if (mtp == NULL) { warnx("memstat_mtl_find: zone %s not found", MBUF_JUMBO9_MEM_NAME); goto out; } jumbo9_count = memstat_get_count(mtp); - jumbo9_bytes = memstat_get_bytes(mtp); jumbo9_limit = memstat_get_countlimit(mtp); jumbo9_free = memstat_get_free(mtp); jumbo9_failures = memstat_get_failures(mtp); jumbo9_sleeps = memstat_get_sleeps(mtp); jumbo9_size = memstat_get_size(mtp); mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO16_MEM_NAME); if (mtp == NULL) { warnx("memstat_mtl_find: zone %s not found", MBUF_JUMBO16_MEM_NAME); goto out; } jumbo16_count = memstat_get_count(mtp); - jumbo16_bytes = memstat_get_bytes(mtp); jumbo16_limit = memstat_get_countlimit(mtp); jumbo16_free = memstat_get_free(mtp); jumbo16_failures = memstat_get_failures(mtp); jumbo16_sleeps = memstat_get_sleeps(mtp); jumbo16_size = memstat_get_size(mtp); printf("%ju/%ju/%ju mbufs in use (current/cache/total)\n", mbuf_count + packet_count, mbuf_free + packet_free, mbuf_count + packet_count + mbuf_free + packet_free); printf("%ju/%ju/%ju/%ju mbuf clusters in use " "(current/cache/total/max)\n", cluster_count - packet_free, cluster_free + packet_free, cluster_count + cluster_free, cluster_limit); printf("%ju/%ju mbuf+clusters out of packet secondary zone in use " "(current/cache)\n", packet_count, packet_free); printf("%ju/%ju/%ju/%ju %juk (page size) jumbo clusters in use " "(current/cache/total/max)\n", jumbop_count, jumbop_free, jumbop_count + jumbop_free, jumbop_limit, jumbop_size / 1024); printf("%ju/%ju/%ju/%ju 9k jumbo clusters in use " "(current/cache/total/max)\n", jumbo9_count, jumbo9_free, jumbo9_count + jumbo9_free, jumbo9_limit); printf("%ju/%ju/%ju/%ju 16k jumbo clusters in use " "(current/cache/total/max)\n", jumbo16_count, jumbo16_free, jumbo16_count + jumbo16_free, jumbo16_limit); #if 0 printf("%ju mbuf tags in use\n", tag_count); #endif /*- * Calculate in-use bytes as: * - straight mbuf memory * - mbuf memory in packets * - the clusters attached to packets * - and the rest of the non-packet-attached clusters. * - m_tag memory * This avoids counting the clusters attached to packets in the cache. * This currently excludes sf_buf space. */ bytes_inuse = mbuf_bytes + /* straight mbuf memory */ packet_bytes + /* mbufs in packets */ (packet_count * cluster_size) + /* clusters in packets */ /* other clusters */ ((cluster_count - packet_count - packet_free) * cluster_size) + tag_bytes + (jumbop_count * jumbop_size) + /* jumbo clusters */ (jumbo9_count * jumbo9_size) + (jumbo16_count * jumbo16_size); /* * Calculate in-cache bytes as: * - cached straught mbufs * - cached packet mbufs * - cached packet clusters * - cached straight clusters * This currently excludes sf_buf space. */ bytes_incache = (mbuf_free * mbuf_size) + /* straight free mbufs */ (packet_free * mbuf_size) + /* mbufs in free packets */ (packet_free * cluster_size) + /* clusters in free packets */ (cluster_free * cluster_size) + /* free clusters */ (jumbop_free * jumbop_size) + /* jumbo clusters */ (jumbo9_free * jumbo9_size) + (jumbo16_free * jumbo16_size); /* * Total is bytes in use + bytes in cache. This doesn't take into * account various other misc data structures, overhead, etc, but * gives the user something useful despite that. */ bytes_total = bytes_inuse + bytes_incache; printf("%juK/%juK/%juK bytes allocated to network " "(current/cache/total)\n", bytes_inuse / 1024, bytes_incache / 1024, bytes_total / 1024); printf("%ju/%ju/%ju requests for mbufs denied (mbufs/clusters/" "mbuf+clusters)\n", mbuf_failures, cluster_failures, packet_failures); printf("%ju/%ju/%ju requests for mbufs delayed (mbufs/clusters/" "mbuf+clusters)\n", mbuf_sleeps, cluster_sleeps, packet_sleeps); printf("%ju/%ju/%ju requests for jumbo clusters delayed " "(%juk/9k/16k)\n", jumbop_sleeps, jumbo9_sleeps, jumbo16_sleeps, jumbop_size / 1024); printf("%ju/%ju/%ju requests for jumbo clusters denied " "(%juk/9k/16k)\n", jumbop_failures, jumbo9_failures, jumbo16_failures, jumbop_size / 1024); if (live) { mlen = sizeof(nsfbufs); if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL, 0) && !sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused, &mlen, NULL, 0) && !sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak, &mlen, NULL, 0)) printf("%d/%d/%d sfbufs in use (current/peak/max)\n", nsfbufsused, nsfbufspeak, nsfbufs); mlen = sizeof(sfstat); if (sysctlbyname("kern.ipc.sfstat", &sfstat, &mlen, NULL, 0)) { warn("kern.ipc.sfstat"); goto out; } } else { if (kread_counters(mbaddr, (char *)&sfstat, sizeof sfstat) != 0) goto out; } printf("%ju requests for sfbufs denied\n", (uintmax_t)sfstat.sf_allocfail); printf("%ju requests for sfbufs delayed\n", (uintmax_t)sfstat.sf_allocwait); printf("%ju requests for I/O initiated by sendfile\n", (uintmax_t)sfstat.sf_iocnt); out: memstat_mtl_free(mtlp); } Index: stable/10/usr.bin/netstat/netstat.1 =================================================================== --- stable/10/usr.bin/netstat/netstat.1 (revision 261206) +++ stable/10/usr.bin/netstat/netstat.1 (revision 261207) @@ -1,550 +1,548 @@ .\" Copyright (c) 1983, 1990, 1992, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)netstat.1 8.8 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd May 17, 2013 +.Dd October 15, 2013 .Dt NETSTAT 1 .Os .Sh NAME .Nm netstat .Nd show network status .Sh DESCRIPTION The .Nm command symbolically displays the contents of various network-related data structures. There are a number of output formats, depending on the options for the information presented. .Bl -tag -width indent .It Xo .Bk -words .Nm .Op Fl AaLnSTWx .Op Fl f Ar protocol_family | Fl p Ar protocol .Op Fl M Ar core .Op Fl N Ar system .Ek .Xc Display a list of active sockets (protocol control blocks) for each network protocol, for a particular .Ar protocol_family , or for a single .Ar protocol . If .Fl A is also present, show the address of a protocol control block (PCB) associated with a socket; used for debugging. If .Fl a is also present, show the state of all sockets; normally sockets used by server processes are not shown. If .Fl L is also present, show the size of the various listen queues. The first count shows the number of unaccepted connections, the second count shows the amount of unaccepted incomplete connections, and the third count is the maximum number of queued connections. If .Fl S is also present, show network addresses as numbers (as with .Fl n ) but show ports symbolically. If .Fl x is present, display socket buffer and tcp timer statistics for each internet socket. When .Fl T is present, display information from the TCP control block, including retransmits, out-of-order packets received, and zero-sized windows advertised. .It Xo .Bk -words .Nm .Fl i | I Ar interface .Op Fl abdhnW .Op Fl f Ar address_family -.Op Fl M Ar core -.Op Fl N Ar system .Ek .Xc Show the state of all network interfaces or a single .Ar interface which have been auto-configured (interfaces statically configured into a system, but not located at boot time are not shown). An asterisk .Pq Dq Li * after an interface name indicates that the interface is .Dq down . If .Fl a is also present, multicast addresses currently in use are shown for each Ethernet interface and for each IP interface address. Multicast addresses are shown on separate lines following the interface address with which they are associated. If .Fl b is also present, show the number of bytes in and out. If .Fl d is also present, show the number of dropped packets. If .Fl h is also present, print all counters in human readable form. If .Fl W is also present, print interface names using a wider field size. .It Xo .Bk -words .Nm .Fl w Ar wait .Op Fl I Ar interface .Op Fl d .Op Fl M Ar core .Op Fl N Ar system .Op Fl q Ar howmany .Ek .Xc At intervals of .Ar wait seconds, display the information regarding packet traffic on all configured network interfaces or a single .Ar interface . If .Fl q is also present, exit after .Ar howmany outputs. If .Fl d is also present, show the number of dropped packets. .It Xo .Bk -words .Nm .Fl s Op Fl s .Op Fl z .Op Fl f Ar protocol_family | Fl p Ar protocol .Op Fl M Ar core .Op Fl N Ar system .Ek .Xc Display system-wide statistics for each network protocol, for a particular .Ar protocol_family , or for a single .Ar protocol . If .Fl s is repeated, counters with a value of zero are suppressed. If .Fl z is also present, reset statistic counters after displaying them. .It Xo .Bk -words .Nm .Fl i | I Ar interface Fl s .Op Fl f Ar protocol_family | Fl p Ar protocol .Op Fl M Ar core .Op Fl N Ar system .Ek .Xc Display per-interface statistics for each network protocol, for a particular .Ar protocol_family , or for a single .Ar protocol . .It Xo .Bk -words .Nm .Fl m .Op Fl M Ar core .Op Fl N Ar system .Ek .Xc Show statistics recorded by the memory management routines .Pq Xr mbuf 9 . The network manages a private pool of memory buffers. .It Xo .Bk -words .Nm .Fl B .Op Fl z .Op Fl I Ar interface .Ek .Xc Show statistics about .Xr bpf 4 peers. This includes information like how many packets have been matched, dropped and received by the bpf device, also information about current buffer sizes and device states. .It Xo .Bk -words .Nm .Fl r .Op Fl AanW .Op Fl F Ar fibnum .Op Fl f Ar address_family .Op Fl M Ar core .Op Fl N Ar system .Ek .Xc Display the contents of routing tables. When .Fl f is specified, a routing table for a particular .Ar address_family is displayed. When .Fl F is specified, a routing table with the number .Ar fibnum is displayed. If the specified .Ar fibnum is -1 or .Fl F is not specified, the default routing table is displayed. If .Fl A is also present, show the contents of the internal Patricia tree structures; used for debugging. If .Fl a is also present, show protocol-cloned routes (routes generated by an .Dv RTF_PRCLONING parent route); normally these routes are not shown. When .Fl W is also present, show the path MTU for each route, and print interface names with a wider field size. .It Xo .Bk -words .Nm .Fl rs .Op Fl s .Op Fl M Ar core .Op Fl N Ar system .Ek .Xc Display routing statistics. If .Fl s is repeated, counters with a value of zero are suppressed. .It Xo .Bk -words .Nm .Fl g .Op Fl W .Op Fl f Ar address_family .Op Fl M Ar core .Op Fl N Ar system .Ek .Xc Display the contents of the multicast virtual interface tables, and multicast forwarding caches. Entries in these tables will appear only when the kernel is actively forwarding multicast sessions. This option is applicable only to the .Cm inet and .Cm inet6 address families. .It Xo .Bk -words .Nm .Fl gs .Op Fl s .Op Fl f Ar address_family .Op Fl M Ar core .Op Fl N Ar system .Ek .Xc Show multicast routing statistics. If .Fl s is repeated, counters with a value of zero are suppressed. .It Xo .Bk -words .Nm .Fl Q .Ek .Xc Show .Xr netisr 9 statistics. The flags field shows available ISR handlers: .Bl -column ".Li W" ".Dv NETISR_SNP_FLAGS_DRAINEDCPU" .It Li C Ta Dv NETISR_SNP_FLAGS_M2CPUID Ta "Able to map mbuf to cpu id" .It Li D Ta Dv NETISR_SNP_FLAGS_DRAINEDCPU Ta "Has queue drain handler" .It Li F Ta Dv NETISR_SNP_FLAGS_M2FLOW Ta "Able to map mbuf to flow id" .El .El .Pp Some options have the general meaning: .Bl -tag -width flag .It Fl f Ar address_family , Fl p Ar protocol Limit display to those records of the specified .Ar address_family or a single .Ar protocol . The following address families and protocols are recognized: .Pp .Bl -tag -width ".Cm netgraph , ng Pq Dv AF_NETGRAPH" -compact .It Em Family .Em Protocols .It Cm inet Pq Dv AF_INET .Cm divert , icmp , igmp , ip , ipsec , pim, sctp , tcp , udp .It Cm inet6 Pq Dv AF_INET6 .Cm icmp6 , ip6 , ipsec6 , rip6 , tcp , udp .It Cm pfkey Pq Dv PF_KEY .Cm pfkey .It Cm atalk Pq Dv AF_APPLETALK .Cm ddp .It Cm netgraph , ng Pq Dv AF_NETGRAPH .Cm ctrl , data .It Cm ipx Pq Dv AF_IPX .Cm ipx , spx .\".It Cm ns Pq Dv AF_NS .\".Cm idp , ns_err , spp .\".It Cm iso Pq Dv AF_ISO .\".Cm clnp , cltp , esis , tp .It Cm unix Pq Dv AF_UNIX .It Cm link Pq Dv AF_LINK .El .Pp The program will complain if .Ar protocol is unknown or if there is no statistics routine for it. .It Fl M Extract values associated with the name list from the specified core instead of the default .Pa /dev/kmem . .It Fl N Extract the name list from the specified system instead of the default, which is the kernel image the system has booted from. .It Fl n Show network addresses and ports as numbers. Normally .Nm attempts to resolve addresses and ports, and display them symbolically. .It Fl W In certain displays, avoid truncating addresses even if this causes some fields to overflow. .El .Pp The default display, for active sockets, shows the local and remote addresses, send and receive queue sizes (in bytes), protocol, and the internal state of the protocol. Address formats are of the form .Dq host.port or .Dq network.port if a socket's address specifies a network but no specific host address. When known, the host and network addresses are displayed symbolically according to the databases .Xr hosts 5 and .Xr networks 5 , respectively. If a symbolic name for an address is unknown, or if the .Fl n option is specified, the address is printed numerically, according to the address family. For more information regarding the Internet IPv4 .Dq dot format , refer to .Xr inet 3 . Unspecified, or .Dq wildcard , addresses and ports appear as .Dq Li * . .Pp The interface display provides a table of cumulative statistics regarding packets transferred, errors, and collisions. The network addresses of the interface and the maximum transmission unit .Pq Dq mtu are also displayed. .Pp The routing table display indicates the available routes and their status. Each route consists of a destination host or network, and a gateway to use in forwarding packets. The flags field shows a collection of information about the route stored as binary choices. The individual flags are discussed in more detail in the .Xr route 8 and .Xr route 4 manual pages. The mapping between letters and flags is: .Bl -column ".Li W" ".Dv RTF_WASCLONED" .It Li 1 Ta Dv RTF_PROTO1 Ta "Protocol specific routing flag #1" .It Li 2 Ta Dv RTF_PROTO2 Ta "Protocol specific routing flag #2" .It Li 3 Ta Dv RTF_PROTO3 Ta "Protocol specific routing flag #3" .It Li B Ta Dv RTF_BLACKHOLE Ta "Just discard pkts (during updates)" .It Li b Ta Dv RTF_BROADCAST Ta "The route represents a broadcast address" .It Li C Ta Dv RTF_CLONING Ta "Generate new routes on use" .It Li c Ta Dv RTF_PRCLONING Ta "Protocol-specified generate new routes on use" .It Li D Ta Dv RTF_DYNAMIC Ta "Created dynamically (by redirect)" .It Li G Ta Dv RTF_GATEWAY Ta "Destination requires forwarding by intermediary" .It Li H Ta Dv RTF_HOST Ta "Host entry (net otherwise)" .It Li L Ta Dv RTF_LLINFO Ta "Valid protocol to link address translation" .It Li M Ta Dv RTF_MODIFIED Ta "Modified dynamically (by redirect)" .It Li R Ta Dv RTF_REJECT Ta "Host or net unreachable" .It Li S Ta Dv RTF_STATIC Ta "Manually added" .It Li U Ta Dv RTF_UP Ta "Route usable" .It Li W Ta Dv RTF_WASCLONED Ta "Route was generated as a result of cloning" .It Li X Ta Dv RTF_XRESOLVE Ta "External daemon translates proto to link address" .El .Pp Direct routes are created for each interface attached to the local host; the gateway field for such entries shows the address of the outgoing interface. The refcnt field gives the current number of active uses of the route. Connection oriented protocols normally hold on to a single route for the duration of a connection while connectionless protocols obtain a route while sending to the same destination. The use field provides a count of the number of packets sent using that route. The interface entry indicates the network interface utilized for the route. .Pp When .Nm is invoked with the .Fl w option and a .Ar wait interval argument, it displays a running count of statistics related to network interfaces. An obsolescent version of this option used a numeric parameter with no option, and is currently supported for backward compatibility. By default, this display summarizes information for all interfaces. Information for a specific interface may be displayed with the .Fl I option. .Pp The .Xr bpf 4 flags displayed when .Nm is invoked with the .Fl B option represent the underlying parameters of the bpf peer. Each flag is represented as a single lower case letter. The mapping between the letters and flags in order of appearance are: .Bl -column ".Li i" .It Li p Ta Set if listening promiscuously .It Li i Ta Dv BIOCIMMEDIATE No has been set on the device .It Li f Ta Dv BIOCGHDRCMPLT No status: source link addresses are being filled automatically .It Li s Ta Dv BIOCGSEESENT No status: see packets originating locally and remotely on the interface. .It Li a Ta Packet reception generates a signal .It Li l Ta Dv BIOCLOCK No status: descriptor has been locked .El .Pp For more information about these flags, please refer to .Xr bpf 4 . .Pp The .Fl x flag causes .Nm to output all the information recorded about data stored in the socket buffers. The fields are: .Bl -column ".Li R-MBUF" .It Li R-MBUF Ta Number of mbufs in the receive queue. .It Li S-MBUF Ta Number of mbufs in the send queue. .It Li R-CLUS Ta Number of clusters, of any type, in the receive queue. .It Li S-CLUS Ta Number of clusters, of any type, in the send queue. .It Li R-HIWA Ta Receive buffer high water mark, in bytes. .It Li S-HIWA Ta Send buffer high water mark, in bytes. .It Li R-LOWA Ta Receive buffer low water mark, in bytes. .It Li S-LOWA Ta Send buffer low water mark, in bytes. .It Li R-BCNT Ta Receive buffer byte count. .It Li S-BCNT Ta Send buffer byte count. .It Li R-BMAX Ta Maximum bytes that can be used in the receive buffer. .It Li S-BMAX Ta Maximum bytes that can be used in the send buffer. .El .Sh SEE ALSO .Xr fstat 1 , .Xr nfsstat 1 , .Xr procstat 1 , .Xr ps 1 , .Xr sockstat 1 , .Xr bpf 4 , .Xr inet 4 , .Xr route 4 , .Xr unix 4 , .Xr hosts 5 , .Xr networks 5 , .Xr protocols 5 , .Xr services 5 , .Xr iostat 8 , .Xr route 8 , .Xr trpt 8 , .Xr vmstat 8 , .Xr mbuf 9 .Sh HISTORY The .Nm command appeared in .Bx 4.2 . .Pp IPv6 support was added by WIDE/KAME project. .Sh BUGS The notion of errors is ill-defined. Index: stable/10/usr.bin/netstat/netstat.h =================================================================== --- stable/10/usr.bin/netstat/netstat.h (revision 261206) +++ stable/10/usr.bin/netstat/netstat.h (revision 261207) @@ -1,170 +1,170 @@ /*- * Copyright (c) 1992, 1993 * Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)netstat.h 8.2 (Berkeley) 1/4/94 * $FreeBSD$ */ #include extern int Aflag; /* show addresses of protocol control block */ extern int aflag; /* show all sockets (including servers) */ extern int bflag; /* show i/f total bytes in/out */ extern int dflag; /* show i/f dropped packets */ extern int gflag; /* show group (multicast) routing or stats */ extern int hflag; /* show counters in human readable format */ extern int iflag; /* show interfaces */ extern int Lflag; /* show size of listen queues */ extern int mflag; /* show memory stats */ extern int noutputs; /* how much outputs before we exit */ extern int numeric_addr; /* show addresses numerically */ extern int numeric_port; /* show ports numerically */ extern int rflag; /* show routing tables (or routing stats) */ extern int sflag; /* show protocol statistics */ extern int Tflag; /* show TCP control block info */ extern int Wflag; /* wide display */ extern int xflag; /* extended display, includes all socket buffer info */ extern int zflag; /* zero stats */ extern int interval; /* repeat interval for i/f stats */ extern char *interface; /* desired i/f for stats, or NULL for all i/fs */ extern int unit; /* unit number for above */ extern int af; /* address family */ extern int live; /* true if we are examining a live system */ int kread(u_long addr, void *buf, size_t size); int kread_counters(u_long addr, void *buf, size_t size); const char *plural(uintmax_t); const char *plurales(uintmax_t); const char *pluralies(uintmax_t); struct sockaddr; struct socket; struct xsocket; int sotoxsocket(struct socket *, struct xsocket *); void protopr(u_long, const char *, int, int); void tcp_stats(u_long, const char *, int, int); void udp_stats(u_long, const char *, int, int); #ifdef SCTP void sctp_protopr(u_long, const char *, int, int); void sctp_stats(u_long, const char *, int, int); #endif void arp_stats(u_long, const char *, int, int); void ip_stats(u_long, const char *, int, int); void icmp_stats(u_long, const char *, int, int); void igmp_stats(u_long, const char *, int, int); void pim_stats(u_long, const char *, int, int); void carp_stats(u_long, const char *, int, int); void pfsync_stats(u_long, const char *, int, int); #ifdef IPSEC void ipsec_stats(u_long, const char *, int, int); void esp_stats(u_long, const char *, int, int); void ah_stats(u_long, const char *, int, int); void ipcomp_stats(u_long, const char *, int, int); #endif #ifdef INET6 void ip6_stats(u_long, const char *, int, int); void ip6_ifstats(char *); void icmp6_stats(u_long, const char *, int, int); void icmp6_ifstats(char *); void pim6_stats(u_long, const char *, int, int); void rip6_stats(u_long, const char *, int, int); void mroute6pr(u_long, u_long); void mrt6_stats(u_long); struct sockaddr_in6; struct in6_addr; void in6_fillscopeid(struct sockaddr_in6 *); char *routename6(struct sockaddr_in6 *); const char *netname6(struct sockaddr_in6 *, struct in6_addr *); void inet6print(struct in6_addr *, int, const char *, int); #endif /*INET6*/ #ifdef IPSEC void pfkey_stats(u_long, const char *, int, int); #endif void mbpr(void *, u_long); void netisr_stats(void *); void hostpr(u_long, u_long); void impstats(u_long, u_long); -void intpr(int, u_long, void (*)(char *)); +void intpr(int, void (*)(char *)); void pr_rthdr(int); void pr_family(int); void rt_stats(u_long, u_long); char *ipx_pnet(struct sockaddr *); char *ipx_phost(struct sockaddr *); char *ns_phost(struct sockaddr *); void upHex(char *); char *routename(in_addr_t); -char *netname(in_addr_t, u_long); +char *netname(in_addr_t, in_addr_t); char *atalk_print(struct sockaddr *, int); char *atalk_print2(struct sockaddr *, struct sockaddr *, int); char *ipx_print(struct sockaddr *); char *ns_print(struct sockaddr *); void routepr(u_long, int); void ipxprotopr(u_long, const char *, int, int); void spx_stats(u_long, const char *, int, int); void ipx_stats(u_long, const char *, int, int); void ipxerr_stats(u_long, const char *, int, int); void nsprotopr(u_long, const char *, int, int); void spp_stats(u_long, const char *, int, int); void idp_stats(u_long, const char *, int, int); void nserr_stats(u_long, const char *, int, int); void atalkprotopr(u_long, const char *, int, int); void ddp_stats(u_long, const char *, int, int); #ifdef NETGRAPH void netgraphprotopr(u_long, const char *, int, int); #endif void unixpr(u_long, u_long, u_long, u_long, u_long); void esis_stats(u_long, const char *, int, int); void clnp_stats(u_long, const char *, int, int); void cltp_stats(u_long, const char *, int, int); void iso_protopr(u_long, const char *, int, int); void iso_protopr1(u_long, int); void tp_protopr(u_long, const char *, int, int); void tp_inproto(u_long); void tp_stats(caddr_t, caddr_t); void mroutepr(u_long, u_long, u_long); void mrt_stats(u_long); void bpf_stats(char *); Index: stable/10/usr.bin/netstat/route.c =================================================================== --- stable/10/usr.bin/netstat/route.c (revision 261206) +++ stable/10/usr.bin/netstat/route.c (revision 261207) @@ -1,1147 +1,1148 @@ /*- * Copyright (c) 1983, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "From: @(#)route.c 8.6 (Berkeley) 4/28/95"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netstat.h" #define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d))) /* * Definitions for showing gateway flags. */ struct bits { u_long b_mask; char b_val; } bits[] = { { RTF_UP, 'U' }, { RTF_GATEWAY, 'G' }, { RTF_HOST, 'H' }, { RTF_REJECT, 'R' }, { RTF_DYNAMIC, 'D' }, { RTF_MODIFIED, 'M' }, { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ { RTF_XRESOLVE, 'X' }, { RTF_STATIC, 'S' }, { RTF_PROTO1, '1' }, { RTF_PROTO2, '2' }, { RTF_PRCLONING,'c' }, { RTF_PROTO3, '3' }, { RTF_BLACKHOLE,'B' }, { RTF_BROADCAST,'b' }, #ifdef RTF_LLINFO { RTF_LLINFO, 'L' }, #endif #ifdef RTF_WASCLONED { RTF_WASCLONED,'W' }, #endif #ifdef RTF_CLONING { RTF_CLONING, 'C' }, #endif { 0 , 0 } }; typedef union { long dummy; /* Helps align structure. */ struct sockaddr u_sa; u_short u_data[128]; } sa_u; static sa_u pt_u; int do_rtent = 0; struct rtentry rtentry; struct radix_node rnode; struct radix_mask rmask; struct radix_node_head **rt_tables; int NewTree = 0; struct timespec uptime; static struct sockaddr *kgetsa(struct sockaddr *); static void size_cols(int ef, struct radix_node *rn); static void size_cols_tree(struct radix_node *rn); static void size_cols_rtentry(struct rtentry *rt); static void p_tree(struct radix_node *); static void p_rtnode(void); static void ntreestuff(void); static void np_rtentry(struct rt_msghdr *); static void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int); static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags); static void p_flags(int, const char *); static const char *fmt_flags(int f); static void p_rtentry(struct rtentry *); static void domask(char *, in_addr_t, u_long); /* * Print routing tables. */ void routepr(u_long rtree, int fibnum) { struct radix_node_head **rnhp, *rnh, head; size_t intsize; int fam, numfibs; intsize = sizeof(int); if (fibnum == -1 && sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1) fibnum = 0; if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) numfibs = 1; if (fibnum < 0 || fibnum > numfibs - 1) errx(EX_USAGE, "%d: invalid fib", fibnum); rt_tables = calloc(numfibs * (AF_MAX+1), sizeof(struct radix_node_head *)); if (rt_tables == NULL) err(EX_OSERR, "memory allocation failed"); /* * Since kernel & userland use different timebase * (time_uptime vs time_second) and we are reading kernel memory * directly we should do rt_rmx.rmx_expire --> expire_time conversion. */ if (clock_gettime(CLOCK_UPTIME, &uptime) < 0) err(EX_OSERR, "clock_gettime() failed"); printf("Routing tables"); if (fibnum) printf(" (fib: %d)", fibnum); printf("\n"); if (Aflag == 0 && NewTree) ntreestuff(); else { if (rtree == 0) { printf("rt_tables: symbol not in namelist\n"); return; } if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs * (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0) return; for (fam = 0; fam <= AF_MAX; fam++) { int tmpfib; switch (fam) { case AF_INET6: case AF_INET: tmpfib = fibnum; break; default: tmpfib = 0; } rnhp = (struct radix_node_head **)*rt_tables; /* Calculate the in-kernel address. */ rnhp += tmpfib * (AF_MAX+1) + fam; /* Read the in kernel rhn pointer. */ if (kget(rnhp, rnh) != 0) continue; if (rnh == NULL) continue; /* Read the rnh data. */ if (kget(rnh, head) != 0) continue; if (fam == AF_UNSPEC) { if (Aflag && af == 0) { printf("Netmasks:\n"); p_tree(head.rnh_treetop); } } else if (af == AF_UNSPEC || af == fam) { size_cols(fam, head.rnh_treetop); pr_family(fam); do_rtent = 1; pr_rthdr(fam); p_tree(head.rnh_treetop); } } } } /* * Print address family header before a section of the routing table. */ void pr_family(int af1) { const char *afname; switch (af1) { case AF_INET: afname = "Internet"; break; #ifdef INET6 case AF_INET6: afname = "Internet6"; break; #endif /*INET6*/ case AF_IPX: afname = "IPX"; break; case AF_ISO: afname = "ISO"; break; case AF_APPLETALK: afname = "AppleTalk"; break; case AF_CCITT: afname = "X.25"; break; case AF_NETGRAPH: afname = "Netgraph"; break; default: afname = NULL; break; } if (afname) printf("\n%s:\n", afname); else printf("\nProtocol Family %d:\n", af1); } /* column widths; each followed by one space */ #ifndef INET6 #define WID_DST_DEFAULT(af) 18 /* width of destination column */ #define WID_GW_DEFAULT(af) 18 /* width of gateway column */ #define WID_IF_DEFAULT(af) (Wflag ? 8 : 6) /* width of netif column */ #else #define WID_DST_DEFAULT(af) \ ((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18) #define WID_GW_DEFAULT(af) \ ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18) #define WID_IF_DEFAULT(af) ((af) == AF_INET6 ? 8 : (Wflag ? 8 : 6)) #endif /*INET6*/ static int wid_dst; static int wid_gw; static int wid_flags; static int wid_refs; static int wid_use; static int wid_mtu; static int wid_if; static int wid_expire; static void size_cols(int ef __unused, struct radix_node *rn) { wid_dst = WID_DST_DEFAULT(ef); wid_gw = WID_GW_DEFAULT(ef); wid_flags = 6; wid_refs = 6; wid_use = 8; wid_mtu = 6; wid_if = WID_IF_DEFAULT(ef); wid_expire = 6; if (Wflag) size_cols_tree(rn); } static void size_cols_tree(struct radix_node *rn) { again: if (kget(rn, rnode) != 0) return; if (!(rnode.rn_flags & RNF_ACTIVE)) return; if (rnode.rn_bit < 0) { if ((rnode.rn_flags & RNF_ROOT) == 0) { if (kget(rn, rtentry) != 0) return; size_cols_rtentry(&rtentry); } if ((rn = rnode.rn_dupedkey)) goto again; } else { rn = rnode.rn_right; size_cols_tree(rnode.rn_left); size_cols_tree(rn); } } static void size_cols_rtentry(struct rtentry *rt) { static struct ifnet ifnet, *lastif; static char buffer[100]; const char *bp; struct sockaddr *sa; sa_u addr, mask; int len; bzero(&addr, sizeof(addr)); if ((sa = kgetsa(rt_key(rt)))) bcopy(sa, &addr, sa->sa_len); bzero(&mask, sizeof(mask)); if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) bcopy(sa, &mask, sa->sa_len); bp = fmt_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags); len = strlen(bp); wid_dst = MAX(len, wid_dst); bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST); len = strlen(bp); wid_gw = MAX(len, wid_gw); bp = fmt_flags(rt->rt_flags); len = strlen(bp); wid_flags = MAX(len, wid_flags); if (addr.u_sa.sa_family == AF_INET || Wflag) { len = snprintf(buffer, sizeof(buffer), "%d", rt->rt_refcnt); wid_refs = MAX(len, wid_refs); len = snprintf(buffer, sizeof(buffer), "%lu", rt->rt_use); wid_use = MAX(len, wid_use); if (Wflag && rt->rt_rmx.rmx_mtu != 0) { len = snprintf(buffer, sizeof(buffer), "%lu", rt->rt_rmx.rmx_mtu); wid_mtu = MAX(len, wid_mtu); } } if (rt->rt_ifp) { if (rt->rt_ifp != lastif) { if (kget(rt->rt_ifp, ifnet) == 0) len = strlen(ifnet.if_xname); else len = strlen("---"); lastif = rt->rt_ifp; wid_if = MAX(len, wid_if); } if (rt->rt_rmx.rmx_expire) { time_t expire_time; if ((expire_time = rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) { len = snprintf(buffer, sizeof(buffer), "%d", (int)expire_time); wid_expire = MAX(len, wid_expire); } } } } /* * Print header for routing table columns. */ void pr_rthdr(int af1) { if (Aflag) printf("%-8.8s ","Address"); if (af1 == AF_INET || Wflag) { if (Wflag) { printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s\n", wid_dst, wid_dst, "Destination", wid_gw, wid_gw, "Gateway", wid_flags, wid_flags, "Flags", wid_refs, wid_refs, "Refs", wid_use, wid_use, "Use", wid_mtu, wid_mtu, "Mtu", wid_if, wid_if, "Netif", wid_expire, "Expire"); } else { printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n", wid_dst, wid_dst, "Destination", wid_gw, wid_gw, "Gateway", wid_flags, wid_flags, "Flags", wid_refs, wid_refs, "Refs", wid_use, wid_use, "Use", wid_if, wid_if, "Netif", wid_expire, "Expire"); } } else { printf("%-*.*s %-*.*s %-*.*s %*.*s %*s\n", wid_dst, wid_dst, "Destination", wid_gw, wid_gw, "Gateway", wid_flags, wid_flags, "Flags", wid_if, wid_if, "Netif", wid_expire, "Expire"); } } static struct sockaddr * kgetsa(struct sockaddr *dst) { if (kget(dst, pt_u.u_sa) != 0) return (NULL); if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len); return (&pt_u.u_sa); } static void p_tree(struct radix_node *rn) { again: if (kget(rn, rnode) != 0) return; if (!(rnode.rn_flags & RNF_ACTIVE)) return; if (rnode.rn_bit < 0) { if (Aflag) printf("%-8.8lx ", (u_long)rn); if (rnode.rn_flags & RNF_ROOT) { if (Aflag) printf("(root node)%s", rnode.rn_dupedkey ? " =>\n" : "\n"); } else if (do_rtent) { if (kget(rn, rtentry) == 0) { p_rtentry(&rtentry); if (Aflag) p_rtnode(); } } else { p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key), NULL, 0, 44); putchar('\n'); } if ((rn = rnode.rn_dupedkey)) goto again; } else { if (Aflag && do_rtent) { printf("%-8.8lx ", (u_long)rn); p_rtnode(); } rn = rnode.rn_right; p_tree(rnode.rn_left); p_tree(rn); } } char nbuf[20]; static void p_rtnode(void) { struct radix_mask *rm = rnode.rn_mklist; if (rnode.rn_bit < 0) { if (rnode.rn_mask) { printf("\t mask "); p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask), NULL, 0, -1); } else if (rm == 0) return; } else { sprintf(nbuf, "(%d)", rnode.rn_bit); printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_left, (u_long)rnode.rn_right); } while (rm) { if (kget(rm, rmask) != 0) break; sprintf(nbuf, " %d refs, ", rmask.rm_refs); printf(" mk = %8.8lx {(%d),%s", (u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " "); if (rmask.rm_flags & RNF_NORMAL) { struct radix_node rnode_aux; printf(" , "); if (kget(rmask.rm_leaf, rnode_aux) == 0) p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask), NULL, 0, -1); else p_sockaddr(NULL, NULL, 0, -1); } else p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), NULL, 0, -1); putchar('}'); if ((rm = rmask.rm_mklist)) printf(" ->"); } putchar('\n'); } static void ntreestuff(void) { size_t needed; int mib[6]; char *buf, *next, *lim; struct rt_msghdr *rtm; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = 0; mib[4] = NET_RT_DUMP; mib[5] = 0; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { err(1, "sysctl: net.route.0.0.dump estimate"); } if ((buf = malloc(needed)) == 0) { errx(2, "malloc(%lu)", (unsigned long)needed); } if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { err(1, "sysctl: net.route.0.0.dump"); } lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; np_rtentry(rtm); } } static void np_rtentry(struct rt_msghdr *rtm) { struct sockaddr *sa = (struct sockaddr *)(rtm + 1); #ifdef notdef static int masks_done, banner_printed; #endif static int old_af; int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; #ifdef notdef /* for the moment, netmasks are skipped over */ if (!banner_printed) { printf("Netmasks:\n"); banner_printed = 1; } if (masks_done == 0) { if (rtm->rtm_addrs != RTA_DST ) { masks_done = 1; af1 = sa->sa_family; } } else #endif af1 = sa->sa_family; if (af1 != old_af) { pr_family(af1); old_af = af1; } if (rtm->rtm_addrs == RTA_DST) p_sockaddr(sa, NULL, 0, 36); else { p_sockaddr(sa, NULL, rtm->rtm_flags, 16); sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa); p_sockaddr(sa, NULL, 0, 18); } p_flags(rtm->rtm_flags & interesting, "%-6.6s "); putchar('\n'); } static void p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width) { const char *cp; cp = fmt_sockaddr(sa, mask, flags); if (width < 0 ) printf("%s ", cp); else { if (numeric_addr) printf("%-*s ", width, cp); else printf("%-*.*s ", width, width, cp); } } static const char * fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) { static char workbuf[128]; const char *cp; if (sa == NULL) return ("null"); switch(sa->sa_family) { case AF_INET: { struct sockaddr_in *sockin = (struct sockaddr_in *)sa; if ((sockin->sin_addr.s_addr == INADDR_ANY) && mask && ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) ==0L) cp = "default" ; else if (flags & RTF_HOST) cp = routename(sockin->sin_addr.s_addr); else if (mask) cp = netname(sockin->sin_addr.s_addr, - ntohl(((struct sockaddr_in *)mask) - ->sin_addr.s_addr)); + ((struct sockaddr_in *)mask)->sin_addr.s_addr); else - cp = netname(sockin->sin_addr.s_addr, 0L); + cp = netname(sockin->sin_addr.s_addr, INADDR_ANY); break; } #ifdef INET6 case AF_INET6: { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; /* * The sa6->sin6_scope_id must be filled here because * this sockaddr is extracted from kmem(4) directly * and has KAME-specific embedded scope id in * sa6->sin6_addr.s6_addr[2]. */ in6_fillscopeid(sa6); if (flags & RTF_HOST) cp = routename6(sa6); else if (mask) cp = netname6(sa6, &((struct sockaddr_in6 *)mask)->sin6_addr); else { cp = netname6(sa6, NULL); } break; } #endif /*INET6*/ case AF_IPX: { struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; if (ipx_nullnet(satoipx_addr(work))) cp = "default"; else cp = ipx_print(sa); break; } case AF_APPLETALK: { if (!(flags & RTF_HOST) && mask) cp = atalk_print2(sa,mask,9); else cp = atalk_print(sa,11); break; } case AF_NETGRAPH: { strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data, sizeof(workbuf)); cp = workbuf; break; } case AF_LINK: { struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { (void) sprintf(workbuf, "link#%d", sdl->sdl_index); cp = workbuf; } else switch (sdl->sdl_type) { case IFT_ETHER: case IFT_L2VLAN: case IFT_BRIDGE: if (sdl->sdl_alen == ETHER_ADDR_LEN) { cp = ether_ntoa((struct ether_addr *) (sdl->sdl_data + sdl->sdl_nlen)); break; } /* FALLTHROUGH */ default: cp = link_ntoa(sdl); break; } break; } default: { u_char *s = (u_char *)sa->sa_data, *slim; char *cq, *cqlim; cq = workbuf; slim = sa->sa_len + (u_char *) sa; cqlim = cq + sizeof(workbuf) - 6; cq += sprintf(cq, "(%d)", sa->sa_family); while (s < slim && cq < cqlim) { cq += sprintf(cq, " %02x", *s++); if (s < slim) cq += sprintf(cq, "%02x", *s++); } cp = workbuf; } } return (cp); } static void p_flags(int f, const char *format) { printf(format, fmt_flags(f)); } static const char * fmt_flags(int f) { static char name[33]; char *flags; struct bits *p = bits; for (flags = name; p->b_mask; p++) if (p->b_mask & f) *flags++ = p->b_val; *flags = '\0'; return (name); } static void p_rtentry(struct rtentry *rt) { static struct ifnet ifnet, *lastif; static char buffer[128]; static char prettyname[128]; struct sockaddr *sa; sa_u addr, mask; bzero(&addr, sizeof(addr)); if ((sa = kgetsa(rt_key(rt)))) bcopy(sa, &addr, sa->sa_len); bzero(&mask, sizeof(mask)); if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) bcopy(sa, &mask, sa->sa_len); p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst); p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw); snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags); p_flags(rt->rt_flags, buffer); if (addr.u_sa.sa_family == AF_INET || Wflag) { printf("%*d %*lu ", wid_refs, rt->rt_refcnt, wid_use, rt->rt_use); if (Wflag) { if (rt->rt_rmx.rmx_mtu != 0) printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu); else printf("%*s ", wid_mtu, ""); } } if (rt->rt_ifp) { if (rt->rt_ifp != lastif) { if (kget(rt->rt_ifp, ifnet) == 0) strlcpy(prettyname, ifnet.if_xname, sizeof(prettyname)); else strlcpy(prettyname, "---", sizeof(prettyname)); lastif = rt->rt_ifp; } printf("%*.*s", wid_if, wid_if, prettyname); if (rt->rt_rmx.rmx_expire) { time_t expire_time; if ((expire_time = rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) printf(" %*d", wid_expire, (int)expire_time); } if (rt->rt_nodes[0].rn_dupedkey) printf(" =>"); } putchar('\n'); } char * routename(in_addr_t in) { char *cp; static char line[MAXHOSTNAMELEN]; struct hostent *hp; cp = 0; if (!numeric_addr) { hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET); if (hp) { cp = hp->h_name; trimdomain(cp, strlen(cp)); } } if (cp) { strlcpy(line, cp, sizeof(line)); } else { #define C(x) ((x) & 0xff) in = ntohl(in); sprintf(line, "%u.%u.%u.%u", C(in >> 24), C(in >> 16), C(in >> 8), C(in)); } return (line); } #define NSHIFT(m) ( \ (m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT : \ (m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT : \ (m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT : \ 0) static void domask(char *dst, in_addr_t addr __unused, u_long mask) { int b, i; if (mask == 0 || (!numeric_addr && NSHIFT(mask) != 0)) { *dst = '\0'; return; } i = 0; for (b = 0; b < 32; b++) if (mask & (1 << b)) { int bb; i = b; for (bb = b+1; bb < 32; bb++) if (!(mask & (1 << bb))) { i = -1; /* noncontig */ break; } break; } if (i == -1) sprintf(dst, "&0x%lx", mask); else sprintf(dst, "/%d", 32-i); } /* * Return the name of the network whose address is given. - * The address is assumed to be that of a net or subnet, not a host. */ char * -netname(in_addr_t in, u_long mask) +netname(in_addr_t in, in_addr_t mask) { char *cp = 0; static char line[MAXHOSTNAMELEN]; struct netent *np = 0; in_addr_t i; + /* It is ok to supply host address. */ + in &= mask; + i = ntohl(in); if (!numeric_addr && i) { - np = getnetbyaddr(i >> NSHIFT(mask), AF_INET); + np = getnetbyaddr(i >> NSHIFT(ntohl(mask)), AF_INET); if (np != NULL) { cp = np->n_name; trimdomain(cp, strlen(cp)); } } if (cp != NULL) { strlcpy(line, cp, sizeof(line)); } else { inet_ntop(AF_INET, &in, line, sizeof(line) - 1); } - domask(line + strlen(line), i, mask); + domask(line + strlen(line), i, ntohl(mask)); return (line); } #undef NSHIFT #ifdef INET6 void in6_fillscopeid(struct sockaddr_in6 *sa6) { #if defined(__KAME__) /* * XXX: This is a special workaround for KAME kernels. * sin6_scope_id field of SA should be set in the future. */ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&sa6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) { /* XXX: override is ok? */ sa6->sin6_scope_id = ntohs(*(u_int16_t *)&sa6->sin6_addr.s6_addr[2]); sa6->sin6_addr.s6_addr[2] = sa6->sin6_addr.s6_addr[3] = 0; } #endif } const char * netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask) { static char line[MAXHOSTNAMELEN]; u_char *p = (u_char *)mask; u_char *lim; int masklen, illegal = 0, flag = 0; if (mask) { for (masklen = 0, lim = p + 16; p < lim; p++) { switch (*p) { case 0xff: masklen += 8; break; case 0xfe: masklen += 7; break; case 0xfc: masklen += 6; break; case 0xf8: masklen += 5; break; case 0xf0: masklen += 4; break; case 0xe0: masklen += 3; break; case 0xc0: masklen += 2; break; case 0x80: masklen += 1; break; case 0x00: break; default: illegal ++; break; } } if (illegal) fprintf(stderr, "illegal prefixlen\n"); } else masklen = 128; if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)) return("default"); if (numeric_addr) flag |= NI_NUMERICHOST; getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line), NULL, 0, flag); if (numeric_addr) sprintf(&line[strlen(line)], "/%d", masklen); return line; } char * routename6(struct sockaddr_in6 *sa6) { static char line[MAXHOSTNAMELEN]; int flag = 0; /* use local variable for safety */ struct sockaddr_in6 sa6_local; sa6_local.sin6_family = AF_INET6; sa6_local.sin6_len = sizeof(sa6_local); sa6_local.sin6_addr = sa6->sin6_addr; sa6_local.sin6_scope_id = sa6->sin6_scope_id; if (numeric_addr) flag |= NI_NUMERICHOST; getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len, line, sizeof(line), NULL, 0, flag); return line; } #endif /*INET6*/ /* * Print routing statistics */ void rt_stats(u_long rtsaddr, u_long rttaddr) { struct rtstat rtstat; int rttrash; if (rtsaddr == 0) { printf("rtstat: symbol not in namelist\n"); return; } if (rttaddr == 0) { printf("rttrash: symbol not in namelist\n"); return; } kread(rtsaddr, (char *)&rtstat, sizeof (rtstat)); kread(rttaddr, (char *)&rttrash, sizeof (rttrash)); printf("routing:\n"); #define p(f, m) if (rtstat.f || sflag <= 1) \ printf(m, rtstat.f, plural(rtstat.f)) p(rts_badredirect, "\t%hu bad routing redirect%s\n"); p(rts_dynamic, "\t%hu dynamically created route%s\n"); p(rts_newgateway, "\t%hu new gateway%s due to redirects\n"); p(rts_unreach, "\t%hu destination%s found unreachable\n"); p(rts_wildcard, "\t%hu use%s of a wildcard route\n"); #undef p if (rttrash || sflag <= 1) printf("\t%u route%s not in table but not freed\n", rttrash, plural(rttrash)); } char * ipx_print(struct sockaddr *sa) { u_short port; struct servent *sp = 0; const char *net = "", *host = ""; char *p; u_char *q; struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; static char mybuf[50]; char cport[10], chost[15], cnet[15]; port = ntohs(work.x_port); if (ipx_nullnet(work) && ipx_nullhost(work)) { if (port) { if (sp) sprintf(mybuf, "*.%s", sp->s_name); else sprintf(mybuf, "*.%x", port); } else sprintf(mybuf, "*.*"); return (mybuf); } if (ipx_wildnet(work)) net = "any"; else if (ipx_nullnet(work)) net = "*"; else { q = work.x_net.c_net; sprintf(cnet, "%02x%02x%02x%02x", q[0], q[1], q[2], q[3]); for (p = cnet; *p == '0' && p < cnet + 8; p++) continue; net = p; } if (ipx_wildhost(work)) host = "any"; else if (ipx_nullhost(work)) host = "*"; else { q = work.x_host.c_host; sprintf(chost, "%02x%02x%02x%02x%02x%02x", q[0], q[1], q[2], q[3], q[4], q[5]); for (p = chost; *p == '0' && p < chost + 12; p++) continue; host = p; } if (port) { if (strcmp(host, "*") == 0) host = ""; if (sp) snprintf(cport, sizeof(cport), "%s%s", *host ? "." : "", sp->s_name); else snprintf(cport, sizeof(cport), "%s%x", *host ? "." : "", port); } else *cport = 0; snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport); return(mybuf); } char * ipx_phost(struct sockaddr *sa) { struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa; struct sockaddr_ipx work; static union ipx_net ipx_zeronet; char *p; work = *sipx; work.sipx_addr.x_port = 0; work.sipx_addr.x_net = ipx_zeronet; p = ipx_print((struct sockaddr *)&work); if (strncmp("*.", p, 2) == 0) p += 2; return(p); } void upHex(char *p0) { char *p = p0; for (; *p; p++) switch (*p) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': *p += ('A' - 'a'); break; } } Index: stable/10/usr.sbin/crashinfo/crashinfo.sh =================================================================== --- stable/10/usr.sbin/crashinfo/crashinfo.sh (revision 261206) +++ stable/10/usr.sbin/crashinfo/crashinfo.sh (revision 261207) @@ -1,316 +1,310 @@ #!/bin/sh # # Copyright (c) 2008 Yahoo!, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the author nor the names of any co-contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ usage() { echo "usage: crashinfo [-d crashdir] [-n dumpnr] [-k kernel] [core]" exit 1 } find_kernel() { local ivers k kvers ivers=$(awk ' /Version String/ { print nextline=1 next } nextline==1 { if ($0 ~ "^ [A-Za-z ]+: ") { nextline=0 } else { print } }' $INFO) # Look for a matching kernel version. for k in `sysctl -n kern.bootfile` $(ls -t /boot/*/kernel); do kvers=$(echo 'printf " Version String: %s", version' | \ gdb -x /dev/stdin -batch $k 2>/dev/null) if [ "$ivers" = "$kvers" ]; then KERNEL=$k break fi done } CRASHDIR=/var/crash DUMPNR= KERNEL= while getopts "d:n:k:" opt; do case "$opt" in d) CRASHDIR=$OPTARG ;; n) DUMPNR=$OPTARG ;; k) KERNEL=$OPTARG ;; \?) usage ;; esac done shift $((OPTIND - 1)) if [ $# -eq 1 ]; then if [ -n "$DUMPNR" ]; then echo "-n and an explicit vmcore are mutually exclusive" usage fi # Figure out the crash directory and number from the vmcore name. CRASHDIR=`dirname $1` DUMPNR=$(expr $(basename $1) : 'vmcore\.\([0-9]*\)$') if [ -z "$DUMPNR" ]; then echo "Unable to determine dump number from vmcore file $1." exit 1 fi elif [ $# -gt 1 ]; then usage else # If we don't have an explicit dump number, operate on the most # recent dump. if [ -z "$DUMPNR" ]; then if ! [ -r $CRASHDIR/bounds ]; then echo "No crash dumps in $CRASHDIR." exit 1 fi next=`cat $CRASHDIR/bounds` if [ -z "$next" ] || [ "$next" -eq 0 ]; then echo "No crash dumps in $CRASHDIR." exit 1 fi DUMPNR=$(($next - 1)) fi fi VMCORE=$CRASHDIR/vmcore.$DUMPNR INFO=$CRASHDIR/info.$DUMPNR FILE=$CRASHDIR/core.txt.$DUMPNR HOSTNAME=`hostname` if [ ! -e $VMCORE ]; then echo "$VMCORE not found" exit 1 fi if [ ! -e $INFO ]; then echo "$INFO not found" exit 1 fi # If the user didn't specify a kernel, then try to find one. if [ -z "$KERNEL" ]; then find_kernel if [ -z "$KERNEL" ]; then echo "Unable to find matching kernel for $VMCORE" exit 1 fi elif [ ! -e $KERNEL ]; then echo "$KERNEL not found" exit 1 fi echo "Writing crash summary to $FILE." umask 077 # Simulate uname ostype=$(echo -e printf '"%s", ostype' | gdb -x /dev/stdin -batch $KERNEL) osrelease=$(echo -e printf '"%s", osrelease' | gdb -x /dev/stdin -batch $KERNEL) version=$(echo -e printf '"%s", version' | gdb -x /dev/stdin -batch $KERNEL | \ tr '\t\n' ' ') machine=$(echo -e printf '"%s", machine' | gdb -x /dev/stdin -batch $KERNEL) exec > $FILE 2>&1 echo "$HOSTNAME dumped core - see $VMCORE" echo date echo echo "$ostype $HOSTNAME $osrelease $version $machine" echo sed -ne '/^ Panic String: /{s//panic: /;p;}' $INFO echo # XXX: /bin/sh on 7.0+ is broken so we can't simply pipe the commands to # kgdb via stdin and have to use a temporary file instead. file=`mktemp /tmp/crashinfo.XXXXXX` if [ $? -eq 0 ]; then echo "bt" >> $file echo "quit" >> $file kgdb $KERNEL $VMCORE < $file rm -f $file echo fi echo echo "------------------------------------------------------------------------" echo "ps -axlww" echo ps -M $VMCORE -N $KERNEL -axlww echo echo "------------------------------------------------------------------------" echo "vmstat -s" echo vmstat -M $VMCORE -N $KERNEL -s echo echo "------------------------------------------------------------------------" echo "vmstat -m" echo vmstat -M $VMCORE -N $KERNEL -m echo echo "------------------------------------------------------------------------" echo "vmstat -z" echo vmstat -M $VMCORE -N $KERNEL -z echo echo "------------------------------------------------------------------------" echo "vmstat -i" echo vmstat -M $VMCORE -N $KERNEL -i echo echo "------------------------------------------------------------------------" echo "pstat -T" echo pstat -M $VMCORE -N $KERNEL -T echo echo "------------------------------------------------------------------------" echo "pstat -s" echo pstat -M $VMCORE -N $KERNEL -s echo echo "------------------------------------------------------------------------" echo "iostat" echo iostat -M $VMCORE -N $KERNEL echo echo "------------------------------------------------------------------------" echo "ipcs -a" echo ipcs -C $VMCORE -N $KERNEL -a echo echo "------------------------------------------------------------------------" echo "ipcs -T" echo ipcs -C $VMCORE -N $KERNEL -T echo # XXX: This doesn't actually work in 5.x+ if false; then echo "------------------------------------------------------------------------" echo "w -dn" echo w -M $VMCORE -N $KERNEL -dn echo fi echo "------------------------------------------------------------------------" echo "nfsstat" echo nfsstat -M $VMCORE -N $KERNEL echo echo "------------------------------------------------------------------------" echo "netstat -s" echo netstat -M $VMCORE -N $KERNEL -s echo echo "------------------------------------------------------------------------" echo "netstat -m" echo netstat -M $VMCORE -N $KERNEL -m echo echo "------------------------------------------------------------------------" -echo "netstat -idW" -echo -netstat -M $VMCORE -N $KERNEL -idW -echo - -echo "------------------------------------------------------------------------" echo "netstat -anr" echo netstat -M $VMCORE -N $KERNEL -anr echo echo "------------------------------------------------------------------------" echo "netstat -anA" echo netstat -M $VMCORE -N $KERNEL -anA echo echo "------------------------------------------------------------------------" echo "netstat -aL" echo netstat -M $VMCORE -N $KERNEL -aL echo echo "------------------------------------------------------------------------" echo "fstat" echo fstat -M $VMCORE -N $KERNEL echo echo "------------------------------------------------------------------------" echo "dmesg" echo dmesg -a -M $VMCORE -N $KERNEL echo echo "------------------------------------------------------------------------" echo "kernel config" echo config -x $KERNEL echo echo "------------------------------------------------------------------------" echo "ddb capture buffer" echo ddb capture -M $VMCORE -N $KERNEL print Index: stable/10 =================================================================== --- stable/10 (revision 261206) +++ stable/10 (revision 261207) Property changes on: stable/10 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r256510,256512,257376,257469,260052