Index: usr.bin/nettop/main.c =================================================================== --- usr.bin/nettop/main.c (revision 0) +++ usr.bin/nettop/main.c (revision 0) @@ -0,0 +1,265 @@ +/*- + * Copyright (c) 2009 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include +#include +#include +#include +#include + +static void header(void); +static void footer(void); +static void screen_local(const struct session_type *); +static void screen_inet(const struct session_type *); +static void screen_mbuf(const struct session_type *); + +int +main(int argc, char *argv[]) +{ + char ch; + char running = 1; + int refresh = 0; + void (*screen)(const struct session_type *) = screen_local; + struct session_type *session; + + session = netstat_session_new(NULL); + initscr(); + clear(); + noecho(); + timeout(0); + while (running) { + /* Handle input. */ + ch = getch(); + switch (ch) { + case 'L': + case 'l': + screen = screen_local; + break; + case 'I': + case 'i': + screen = screen_inet; + break; + case 'M': + case 'm': + screen = screen_mbuf; + break; + case 'Q': + case 'q': + running = 0; + break; + } + if (refresh == 0) { + /* Render screen. */ + clear(); + header(); + screen(session); + footer(); + refresh(); + refresh = 3; /* Refresh it only in every 4th cycle */ + } + refresh--; + usleep(250); + } + endwin(); + netstat_session_free(session); + + return 0; +} + +void +header(void) +{ + attron(A_STANDOUT); + mvprintw(0, 0, " Very Simple Network Monitor "); + attroff(A_STANDOUT); +} + +void +footer(void) +{ + attron(A_STANDOUT); + mvprintw(24, 0, " Q - Quit, L - PF_LOCAL, I - PF_INET, M - MBUF "); + attroff(A_STANDOUT); +} + +void +screen_local(const struct session_type *session) +{ + struct socket_type_list *list; + struct socket_type_iterator *stip; + const struct socket_type *stp; + struct sockaddr_type *satp; + int row, st_flags; + + st_flags = NETSTAT_SOCKET_ALL; + list = netstat_stl_alloc(); + netstat_socket(session, PF_LOCAL, 0, 0, list, st_flags); + + attron(A_BOLD); + mvprintw(2, 0, "Active UNIX domain sockets"); + mvprintw(3, 0, + "%-8.8s %-6.6s %-6.6s %-6.6s %8.8s %8.8s %8.8s %8.8s Addr", + "Address", "Type", "Recv-Q", "Send-Q", "Inode", "Conn", + "Refs", "Nextref"); + attroff(A_BOLD); + netstat_sti_alloc(list, &stip); + for (stp = netstat_sti_first(stip), row = 4; stp != NULL && row < 24; + stp = netstat_sti_next(stip), row++) { + mvprintw(row, 0, + "%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx", + (u_long) netstat_st_get_pcb(stp), netstat_st_get_name(stp), + netstat_sbt_get_cc(netstat_st_get_rcv(stp)), + netstat_sbt_get_cc(netstat_st_get_snd(stp)), + (u_long) netstat_st_get_vnode(stp), + (u_long) netstat_st_get_conn(stp), + (u_long) netstat_st_get_refs(stp), + (u_long) netstat_st_get_reflink(stp)); + if (netstat_st_get_addrcnt(stp) > 0) { + satp = netstat_st_get_address(stp, 0); + printw(" %s", netstat_sat_get_name(satp)); + } + } + netstat_sti_free(stip); + netstat_stl_free(list); +} + +void +screen_inet(const struct session_type *session) +{ + struct socket_type_list *list; + struct socket_type_iterator *stip; + const struct socket_type *stp; + struct sockaddr_type *laddr, *faddr; + int row, st_flags; + + st_flags = NETSTAT_SOCKET_ALL; + list = netstat_stl_alloc(); + netstat_socket(session, PF_INET, 0, 0, list, st_flags); + netstat_socket(session, PF_INET6, 0, 0, list, st_flags); + + attron(A_BOLD); + mvprintw(2, 0, "Active Internet connections (including servers)"); + mvprintw(3, 0, + "%-5.5s %-6.6s %-6.6s %-17.17s %-6.6s %-17.17s %-6.6s (state)", + "Proto", "Recv-Q", "Send-Q", + "Local Address", "Port", "Foreign Address", "Port"); + attroff(A_BOLD); + netstat_sti_alloc(list, &stip); + for (stp = netstat_sti_first(stip), row = 4; stp != NULL && row < 24; + stp = netstat_sti_next(stip), row++) { + laddr = netstat_st_get_address(stp, 0); + faddr = netstat_st_get_address(stp, 1); + mvprintw(row, 0, + "%-5.5s %6u %6u %-17.17s %-6.6s %-17.17s %-6.6s %s", + netstat_st_get_extname(stp), + netstat_sbt_get_cc(netstat_st_get_rcv(stp)), + netstat_sbt_get_cc(netstat_st_get_snd(stp)), + netstat_sat_get_name(laddr), + netstat_sat_get_portname(laddr), + netstat_sat_get_name(faddr), + netstat_sat_get_portname(faddr), + netstat_st_get_tcpstate(stp)); + } + netstat_sti_free(stip); + netstat_stl_free(list); +} + +void +screen_mbuf(const struct session_type *session) +{ + struct mbuf_type *stats; + const struct buffer_type *mbuf, *cluster, *packet, *jumbop, *jumbo9, + *jumbo16; + int row; + + const char *hfmt = "%-32.32s %-8.8s %-8.8s %-8.8s %-8.8s"; + const char *fmt2 = "%-32s %-8d %-8d"; + const char *fmt3 = "%-32s %-8d %-8d %-8d"; + const char *fmt3x = "%-32s %-8d %-8d %-8d"; + const char *fmt4 = "%-32s %-8d %-8d %-8d %-8d"; + + stats = netstat_mbt_alloc(); + netstat_mbuf(session, stats, 0); + + mbuf = netstat_mbt_get_mbuf(stats); + cluster = netstat_mbt_get_cluster(stats); + packet = netstat_mbt_get_packet(stats); + jumbop = netstat_mbt_get_jumbop(stats); + jumbo9 = netstat_mbt_get_jumbo9(stats); + jumbo16 = netstat_mbt_get_jumbo16(stats); + + attron(A_BOLD); + mvprintw(2, 0, "Network memory buffers"); + mvprintw(3, 0, hfmt, "Value", "Current", "Cache", "Total", "Max"); + attroff(A_BOLD); + + row = 4; + + mvprintw(row++, 0, fmt3, "mbufs in use", + netstat_bt_get_count(mbuf) + netstat_bt_get_count(packet), + netstat_bt_get_free(mbuf) + netstat_bt_get_free(packet), + netstat_bt_get_count(mbuf) + netstat_bt_get_count(packet) + + netstat_bt_get_free(mbuf) + netstat_bt_get_free(packet)); + + mvprintw(row++, 0, fmt4, "mbuf clusters in use", + netstat_bt_get_count(cluster) - netstat_bt_get_free(packet), + netstat_bt_get_free(cluster) + netstat_bt_get_free(packet), + netstat_bt_get_count(cluster) + netstat_bt_get_free(cluster), + netstat_bt_get_limit(cluster)); + + mvprintw(row++, 0, fmt2, "mbuf+clusters in use", + netstat_bt_get_count(packet), netstat_bt_get_free(packet)); + + mvprintw(row++, 0, fmt4, "4k jumbo clusters in use", + netstat_bt_get_count(jumbop), netstat_bt_get_free(jumbop), + netstat_bt_get_count(jumbop) + netstat_bt_get_free(jumbop), + netstat_bt_get_limit(jumbop), netstat_bt_get_size(jumbop) / 1024); + + mvprintw(row++, 0, fmt4, "9k jumbo clusters in use", + netstat_bt_get_count(jumbo9), netstat_bt_get_free(jumbo9), + netstat_bt_get_count(jumbo9) + netstat_bt_get_free(jumbo9), + netstat_bt_get_limit(jumbo9), netstat_bt_get_size(jumbo9) / 1024); + + mvprintw(row++, 0, fmt4, "16k jumbo clusters in use", + netstat_bt_get_count(jumbo16), netstat_bt_get_free(jumbo16), + netstat_bt_get_count(jumbo16) + netstat_bt_get_free(jumbo16), + netstat_bt_get_limit(jumbo16), netstat_bt_get_size(jumbo16) / 1024); + + mvprintw(row++, 0, fmt3x, "sfbufs in use", + netstat_mbt_get_sf_bufs_inuse(stats), + netstat_mbt_get_sf_bufs(stats), + netstat_mbt_get_sf_bufs_peak(stats)); + + mvprintw(row++, 0, fmt3, "KBs allocated to network", + netstat_mbt_get_bytes_inuse(stats) / 1024, + netstat_mbt_get_bytes_incache(stats) / 1024, + netstat_mbt_get_bytes_total(stats) / 1024); + + netstat_mbt_free(stats); +} Index: usr.bin/nettop/Makefile =================================================================== --- usr.bin/nettop/Makefile (revision 0) +++ usr.bin/nettop/Makefile (revision 0) @@ -0,0 +1,15 @@ +# $FreeBSD$ + +PROG= nettop +SRCS= main.c + +WARNS?= 3 + +CFLAGS+= -I. -I${.CURDIR} + +DPADD= ${LIBTERMCAP} ${LIBM} ${LIBKVM} ${LIBNETSTAT} +LDADD= -ltermcap -lm -lkvm -lnetstat + +WITHOUT_MAN= yes + +.include Index: usr.bin/Makefile =================================================================== --- usr.bin/Makefile (revision 209358) +++ usr.bin/Makefile (working copy) @@ -138,6 +138,7 @@ ${_ncplist} \ ${_ncplogin} \ netstat \ + nettop \ newgrp \ ${_newkey} \ nfsstat \ Index: usr.bin/netstat/if.c =================================================================== --- usr.bin/netstat/if.c (revision 209358) +++ usr.bin/netstat/if.c (working copy) @@ -1,6 +1,8 @@ /*- * Copyright (c) 1983, 1988, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. + * Copyright (c) 2009 Gabor Pali + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -62,7 +64,9 @@ #include #include +#include #include +#include #include #include #include @@ -70,62 +74,43 @@ #include #include -#include "netstat.h" +#include "extern.h" #define YES 1 #define NO 0 -static void sidewaysintpr(int, u_long); +static void sidewaysintpr(const struct session_type *, int); static void catchalarm(int); -#ifdef INET6 -static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */ -#endif - /* * Dump pfsync statistics structure. */ void -pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +pfsync_stats(const struct stat_type *sttp) { - struct pfsyncstats pfsyncstat, zerostat; - size_t len = sizeof(struct pfsyncstats); + const struct pfsync_stat *s; - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - if (errno != ENOENT) - warn("sysctl: net.inet.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)) -#define p2(f, m) if (pfsyncstat.f || sflag <= 1) \ - printf(m, (uintmax_t)pfsyncstat.f) - - p(pfsyncs_ipackets, "\t%ju packet%s received (IPv4)\n"); - p(pfsyncs_ipackets6, "\t%ju packet%s received (IPv6)\n"); - 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"); - p2(pfsyncs_onomem, "\t\t%ju send failed due to mbuf memory error\n"); - p2(pfsyncs_oerrors, "\t\t%ju send error\n"); + s = netstat_get_pfsyncstats(sttp); +#define p(f, m) if (netstat_pfsyncs_get_##f(s) || sflag <= 1) \ + printf(m, netstat_pfsyncs_get_##f(s), plural(netstat_pfsyncs_get_##f(s))) +#define p2(f, m) if (netstat_pfsyncs_get_##f(s) || sflag <= 1) \ + printf(m, netstat_pfsyncs_get_##f(s)) + p(ipackets, "\t%ju packet%s received (IPv4)\n"); + p(ipackets6, "\t%ju packet%s received (IPv6)\n"); + p(badif, "\t\t%ju packet%s discarded for bad interface\n"); + p(badttl, "\t\t%ju packet%s discarded for bad ttl\n"); + p(hdrops, "\t\t%ju packet%s shorter than header\n"); + p(badver, "\t\t%ju packet%s discarded for bad version\n"); + p(badauth, "\t\t%ju packet%s discarded for bad HMAC\n"); + p(badact,"\t\t%ju packet%s discarded for bad action\n"); + p(badlen, "\t\t%ju packet%s discarded for short packet\n"); + p(badval, "\t\t%ju state%s discarded for bad values\n"); + p(stale, "\t\t%ju stale state%s\n"); + p(badstate, "\t\t%ju failed state lookup/insert%s\n"); + p(opackets, "\t%ju packet%s sent (IPv4)\n"); + p(opackets6, "\t%ju packet%s sent (IPv6)\n"); + p2(onomem, "\t\t%ju send failed due to mbuf memory error\n"); + p2(oerrors, "\t\t%ju send error\n"); #undef p #undef p2 } @@ -175,51 +160,49 @@ * Print a description of the network interfaces. */ void -intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *)) +intpr(const struct session_type *session, int interval1, 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 ifnetfound; - 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; + int it_flags; - if (ifnetaddr == 0) { - printf("ifnet: symbol not defined\n"); - return; - } + struct interface_type_list *itlp; + struct interface_type_iterator *itip; + + const struct face_type *fin, *fout; + const struct interface_type *itp; + const struct intfaddr_type *iatp; + + char if_name[16]; + int error, i, network_layer, link_layer; + if (interval1) { - sidewaysintpr(interval1, ifnetaddr); + sidewaysintpr(session, interval1); return; } - if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead) != 0) + + it_flags = 0; + it_flags |= NETSTAT_INTERFACE_ALL; + + itlp = netstat_itl_alloc(); + if (itlp == NULL) { + warn("netstat_itl_alloc()"); return; - ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead); - if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0) - return; + } + if (netstat_interface(session, interface, af, itlp, it_flags) < 0) { + error = netstat_itl_geterror(itlp); + if (error == NETSTAT_ERROR_KVM) { + warnx("netstat_interface: %s", + netstat_kvmerror(session)); + } else + warnx("netstat_interface: %s", netstat_strerror(error)); + goto out; + } + + if (netstat_iti_alloc(itlp, &itip) < 0) { + warn("netstat_iti_alloc()"); + goto out; + } + if (!pfunc) { if (Wflag) printf("%-7.7s", "Name"); @@ -228,286 +211,110 @@ 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(" %10.10s", "Ibytes"); printf(" %8.8s %5.5s", "Opkts", "Oerrs"); if (bflag) - printf(" %10.10s","Obytes"); + 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 (itp = netstat_iti_first(itip); itp != NULL; + itp = netstat_iti_next(itip)) { + strlcpy(if_name, netstat_it_get_name(itp), sizeof(if_name)); + if (pfunc) { + pfunc(if_name); + continue; + } - if (ifaddraddr == 0) { - ifnetfound = ifnetaddr; - 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 = index(name, '\0'); + for (i = 0; i < netstat_it_get_addrcnt(itp); i++) { + iatp = netstat_it_get_address(itp, i); + + network_layer = + (netstat_iat_get_layer(iatp) == layer_Network); + link_layer = + (netstat_iat_get_layer(iatp) == layer_Link); - if (pfunc) { - (*pfunc)(name); - continue; + if ((netstat_it_get_flags(itp) & NETSTAT_IF_UP) == 0) { + strcat(if_name, "*"); } - - if ((ifnet.if_flags&IFF_UP) == 0) - *cp++ = '*'; - *cp = '\0'; - ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead); + printf(Wflag ? "%-7.7s" : "%-5.5s", if_name); + printf(" %5ju ", netstat_it_get_mtu(itp)); + printf("%-13.13s ", + netstat_iat_get_network(iatp, numeric_addr)); + printf("%-17.17s ", + netstat_iat_get_address(iatp, numeric_addr)); + fin = netstat_it_get_in(itp); + fout = netstat_it_get_out(itp); + show_stat("lu", 8, + network_layer ? + netstat_iat_get_ipackets(iatp) : + netstat_ft_get_packets(fin), + network_layer|link_layer); + show_stat("lu", 5, netstat_ft_get_errors(fin), + link_layer); + show_stat("lu", 5, netstat_ft_get_drops(fin), + link_layer); + if (bflag) + show_stat("lu", 10, + network_layer ? + netstat_iat_get_ibytes(iatp) : + netstat_ft_get_bytes(fin), + network_layer|link_layer); + show_stat("lu", 8, + network_layer ? + netstat_iat_get_opackets(iatp) : + netstat_ft_get_packets(fout), + network_layer|link_layer); + show_stat("lu", 5, netstat_ft_get_errors(fout), + link_layer); + if (bflag) + show_stat("lu", 10, + network_layer ? + netstat_iat_get_obytes(iatp) : + netstat_ft_get_bytes(fout), + network_layer|link_layer); + show_stat("NRSlu", 5, netstat_it_get_collisions(itp), + link_layer); + if (dflag) + show_stat("LSd", 4, netstat_it_get_drops(itp), + link_layer); + putchar('\n'); } - 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 (!aflag) + continue; - if (ifaddraddr == 0) { - if (Wflag) - printf("%-7.7s", name); - else - printf("%-5.5s", name); - printf(" %5lu ", ifnet.if_mtu); - 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)); + for (i = 0; i < netstat_it_get_mcast_addrcnt(itp); i++) { + iatp = netstat_it_get_mcast_address(itp, i); - network_layer = 1; - break; -#ifdef INET6 - case AF_INET6: - sockin6 = (struct sockaddr_in6 *)sa; - printf("%-13.13s ", - netname6(&ifaddr.in6.ia_addr, - &ifaddr.in6.ia_prefixmask.sin6_addr)); - printf("%-17.17s ", - inet_ntop(AF_INET6, - &sockin6->sin6_addr, - ntop_buf, sizeof(ntop_buf))); - - network_layer = 1; - break; -#endif /*INET6*/ - case AF_IPX: - { - struct sockaddr_ipx *sipx = - (struct sockaddr_ipx *)sa; - u_long net; - char netnum[10]; - - *(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)); - } - - network_layer = 1; - break; - - 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 += printf("%02x%c", *cp++ & 0xff, - n > 0 ? ':' : ' '); - m = 32 - m; - while (m-- > 0) - putchar(' '); - - link_layer = 1; - break; + if (netstat_iat_get_family(iatp) == PF_INET6) { + printf("%*s %-19.19s(refs: %d)", + Wflag ? 27 : 25, "", + netstat_iat_get_address(iatp, numeric_addr), + netstat_iat_get_refcount(iatp)); + } else { + printf("%*s %-17.17s", Wflag ? 27 : 25, "", + netstat_iat_get_address(iatp, numeric_addr)); } - /* - * 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; + if (netstat_iat_get_family(iatp) == PF_LINK) { + printf(" %8ju", netstat_ft_get_mcasts(fin)); + printf("%*s", bflag ? 17 : 6, ""); + printf(" %8ju", netstat_ft_get_mcasts(fout)); } - ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link); + putchar('\n'); } - - show_stat("lu", 8, ipackets, link_layer|network_layer); - show_stat("lu", 5, ierrors, link_layer); - show_stat("lu", 5, idrops, link_layer); - 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); - 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); - 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; - - 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; - - fmt = 0; - switch (msa.sa.sa_family) { - case AF_INET: - fmt = routename(msa.in.sin_addr.s_addr); - break; -#ifdef INET6 - case AF_INET6: - printf("%*s %-19.19s(refs: %d)\n", - Wflag ? 27 : 25, "", - inet_ntop(AF_INET6, - &msa.in6.sin6_addr, - ntop_buf, - sizeof(ntop_buf)), - ifma.ifma_refcount); - 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; - } - 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'); - } - } - } } +out: + netstat_itl_free(itlp); + netstat_iti_free(itip); } struct iftot { - SLIST_ENTRY(iftot) chain; - char ift_name[IFNAMSIZ]; /* interface name */ u_long ift_ip; /* input packets */ u_long ift_ie; /* input errors */ u_long ift_id; /* input drops */ @@ -526,65 +333,27 @@ * 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). */ static void -sidewaysintpr(int interval1, u_long off) +sidewaysintpr(const struct session_type *session, int interval1) { - struct ifnet ifnet; - u_long firstifnet; - struct ifnethead ifnethead; + int it_flags; + struct itimerval interval_it; - struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting; - int line; + struct iftot total, sum; + int line, error; int oldmask, first; - u_long interesting_off; + char ift_name[IFNAMSIZ]; - if (kread(off, (char *)&ifnethead, sizeof ifnethead) != 0) - return; - firstifnet = (u_long)TAILQ_FIRST(&ifnethead); + struct interface_type_list *itlp; + struct interface_type_iterator *itip; - if ((iftot = malloc(sizeof(struct iftot))) == NULL) { - printf("malloc failed\n"); - exit(1); - } - memset(iftot, 0, sizeof(struct iftot)); + const struct face_type *fin, *fout; + const struct interface_type *itp; - interesting = NULL; - interesting_off = 0; - for (off = firstifnet, ip = iftot; off;) { - char name[IFNAMSIZ]; + it_flags = 0; + it_flags |= NETSTAT_INTERFACE_ALL; - 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; - } - 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); - } - 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)); - (void)signal(SIGALRM, catchalarm); signalled = NO; interval_it.it_interval.tv_sec = interval1; @@ -592,9 +361,32 @@ interval_it.it_value = interval_it.it_interval; setitimer(ITIMER_REAL, &interval_it, NULL); first = 1; + + itlp = netstat_itl_alloc(); + if (itlp == NULL) { + warn("netstat_itl_alloc()"); + return; + } + if (netstat_interface(session, interface, PF_UNSPEC, itlp, + it_flags) < 0) { + error = netstat_itl_geterror(itlp); + if (error == NETSTAT_ERROR_KVM) { + warnx("netstat_interface: %s", netstat_kvmerror(session)); + } else + warnx("netstat_interface: %s", netstat_strerror(error)); + netstat_itl_free(itlp); + return; + } + if (interface != NULL && netstat_itl_length(itlp) == 0) { + netstat_itl_free(itlp); + errx(1, "%s: unknown interface", interface); + } + + if (interface != NULL) + sprintf(ift_name, "(%s)", interface); banner: printf("%17s %14s %16s", "input", - interesting ? interesting->ift_name : "(Total)", "output"); + interface ? ift_name : "(Total)", "output"); putchar('\n'); printf("%10s %5s %5s %10s %10s %5s %10s %5s", "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes", @@ -605,81 +397,61 @@ 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_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; + itlp = netstat_itl_alloc(); + if (itlp == NULL) { + warn("netstat_itl_alloc()"); + return; } + if (netstat_interface(session, interface, PF_UNSPEC, itlp, + it_flags) < 0) { + error = netstat_itl_geterror(itlp); + if (error == NETSTAT_ERROR_KVM) { + warnx("netstat_interface: %s", + netstat_kvmerror(session)); + } else + warnx("netstat_interface: %s", netstat_strerror(error)); + netstat_itl_free(itlp); + return; + } + if (netstat_iti_alloc(itlp, &itip) < 0) { + warn("netstat_iti_alloc()"); + netstat_itl_free(itlp); + return; + } + bzero(&sum, sizeof(struct iftot)); + for (itp = netstat_iti_first(itip); itp != NULL; + itp = netstat_iti_next(itip)) { + fin = netstat_it_get_in(itp); + fout = netstat_it_get_out(itp); + sum.ift_ip += netstat_ft_get_packets(fin); + sum.ift_ie += netstat_ft_get_errors(fin); + sum.ift_id += netstat_ft_get_drops(fin); + sum.ift_ib += netstat_ft_get_bytes(fin); + sum.ift_op += netstat_ft_get_packets(fout); + sum.ift_oe += netstat_ft_get_errors(fout); + sum.ift_ob += netstat_ft_get_bytes(fout); + sum.ift_co += netstat_it_get_collisions(itp); + sum.ift_dr += netstat_it_get_drops(itp); + } + 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; + netstat_itl_free(itlp); if (!first) putchar('\n'); fflush(stdout); - if ((noutputs != 0) && (--noutputs == 0)) + if ((noutputs != 0) && (--noutputs == 0)) exit(0); oldmask = sigblock(sigmask(SIGALRM)); while (!signalled) Index: usr.bin/netstat/route.c =================================================================== --- usr.bin/netstat/route.c (revision 209358) +++ usr.bin/netstat/route.c (working copy) @@ -1,6 +1,8 @@ /*- * Copyright (c) 1983, 1988, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. + * Copyright (c) 2009 Gabor Pali + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,41 +42,18 @@ #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 -#include -#include -#include "netstat.h" +#include +#include +#include "extern.h" -#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d))) - /* * Definitions for showing gateway flags. */ @@ -82,182 +61,139 @@ 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' }, + { NETSTAT_RT_UP, 'U' }, + { NETSTAT_RT_GATEWAY, 'G' }, + { NETSTAT_RT_HOST, 'H' }, + { NETSTAT_RT_REJECT, 'R' }, + { NETSTAT_RT_DYNAMIC, 'D' }, + { NETSTAT_RT_MODIFIED, 'M' }, + { NETSTAT_RT_DONE, 'd' }, + { NETSTAT_RT_XRESOLVE, 'X' }, + { NETSTAT_RT_STATIC, 'S' }, + { NETSTAT_RT_PROTO1, '1' }, + { NETSTAT_RT_PROTO2, '2' }, + { NETSTAT_RT_PRCLONING, 'c' }, + { NETSTAT_RT_PROTO3, '3' }, + { NETSTAT_RT_BLACKHOLE, 'B' }, + { NETSTAT_RT_BROADCAST, 'b' }, #ifdef RTF_LLINFO - { RTF_LLINFO, 'L' }, + { NETSTAT_RT_LLINFO, 'L' }, #endif #ifdef RTF_WASCLONED - { RTF_WASCLONED,'W' }, + { NETSTAT_RT_WASCLONED, 'W' }, #endif #ifdef RTF_CLONING - { RTF_CLONING, 'C' }, + { NETSTAT_RT_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 fibnum; -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 void size_cols(int ef, struct route_type_iterator *); +static void size_cols_rtentry(const struct route_type *); static const char *fmt_flags(int f); -static void p_rtentry(struct rtentry *); -static void domask(char *, in_addr_t, u_long); +static void p_rtnode(const struct routenode_type *); +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; + /* * Print routing tables. */ void -routepr(u_long rtree) +routepr(const struct session_type *session, int domain) { - struct radix_node_head **rnhp, *rnh, head; - size_t intsize; - int i; - int numfibs; + struct route_type_list *rtlp; + struct route_type_iterator *rtip; - intsize = sizeof(int); - if (sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1) - fibnum = 0; - if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) - numfibs = 1; - 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"); + const struct route_type *rtp; + const struct routeaddr_type *dst, *gw; + const struct routenode_type *rntp; + int error, last_domain, dom, flags; + int rt_flags; + rtlp = netstat_rtl_alloc(); + if (rtlp == NULL) { + warn("netstat_rtl_alloc()"); + return; + } + + rt_flags = 0; + if (Aflag) + rt_flags |= NETSTAT_ROUTE_ALL; + if (netstat_route(session, 0, domain, rtlp, rt_flags)) { + error = netstat_rtl_geterror(rtlp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_route: %s", netstat_kvmerror(session)); + else + warnx("netstat_route: %s", netstat_strerror(error)); + goto out; + } + + if (netstat_rti_alloc(rtlp, &rtip) < 0) { + warn("netstat_rti_alloc()"); + goto out; + } + printf("Routing tables\n"); - if (Aflag == 0 && NewTree) - ntreestuff(); - else { - if (rtree == 0) { - printf("rt_tables: symbol not in namelist\n"); - return; + /* + * It should be guaranteed (somehow) by libnetstat that returned + * routes are not interleaved by protocol families. + */ + + last_domain = -1; + for (rtp = netstat_rti_first(rtip); rtp != NULL; + rtp = netstat_rti_next(rtip)) { + dom = netstat_rt_get_family(rtp); + if (dom != last_domain) { + printf("\n%s:\n", netstat_family_name(dom)); + size_cols(dom, NULL); + pr_rthdr(dom); + last_domain = dom; } + flags = netstat_rt_get_flags(rtp); + dst = netstat_rt_get_destination(rtp); + gw = netstat_rt_get_gateway(rtp); + rntp = netstat_rt_get_node(rtp); + if (Aflag) { + printf("%-8.8lx ", + (u_long)netstat_rnt_get_address(rntp)); + } - if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs * - (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0) - return; - for (i = 0; i <= AF_MAX; i++) { - int tmpfib; - if (i != AF_INET) - tmpfib = 0; - else - tmpfib = fibnum; - rnhp = (struct radix_node_head **)*rt_tables; - /* Calculate the in-kernel address. */ - rnhp += tmpfib * (AF_MAX+1) + i; - /* 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 (i == AF_UNSPEC) { - if (Aflag && af == 0) { - printf("Netmasks:\n"); - p_tree(head.rnh_treetop); - } - } else if (af == AF_UNSPEC || af == i) { - size_cols(i, head.rnh_treetop); - pr_family(i); - do_rtent = 1; - pr_rthdr(i); - p_tree(head.rnh_treetop); + if (dst != NULL && gw != NULL) { + printf("%-*.*s %-*.*s %-*.*s", + wid_dst, wid_dst, + netstat_rat_get_name(dst, numeric_addr), + wid_gw, wid_gw, + netstat_rat_get_name(gw, numeric_addr), + wid_flags, wid_flags, fmt_flags(flags)); + if (dom == PF_INET) { + printf(" %*ju %*ju", + wid_refs, netstat_rt_get_refs(rtp), + wid_use, netstat_rt_get_used(rtp)); + if (Wflag) + printf(" %*d", + wid_mtu, netstat_rt_get_mtu(rtp)); } + printf(" %*s", + wid_if, netstat_rt_get_interface(rtp)); + if (flags & NETSTAT_RT_EXPIRES) + printf(" %*ju", wid_expire, + netstat_rt_get_expire(rtp)); } + if (Aflag) + p_rtnode(rntp); + putchar('\n'); } -} -/* - * 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); + netstat_rti_free(rtip); +out: netstat_rtl_free(rtlp); } /* column widths; each followed by one space */ @@ -273,18 +209,11 @@ #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) +void +size_cols(int ef, struct route_type_iterator *rtip) { + const struct route_type *rtp; + wid_dst = WID_DST_DEFAULT(ef); wid_gw = WID_GW_DEFAULT(ef); wid_flags = 6; @@ -294,95 +223,108 @@ 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) + if (!Wflag) 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); + + for (rtp = netstat_rti_first(rtip); rtp != NULL; + rtp = netstat_rti_next(rtip)) { + size_cols_rtentry(rtp); } } -static void -size_cols_rtentry(struct rtentry *rt) +void +size_cols_rtentry(const struct route_type *rtp) { - static struct ifnet ifnet, *lastif; - static char buffer[100]; - const char *bp; - struct sockaddr *sa; - sa_u addr, mask; + const struct routeaddr_type *addr; int len; + char buffer[100]; - 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); + addr = netstat_rt_get_destination(rtp); + if (addr != NULL) { + len = strlen(netstat_rat_get_name(addr, numeric_addr)); + wid_dst = MAX(wid_dst, len); + } + addr = netstat_rt_get_gateway(rtp); + if (addr != NULL) { + len = strlen(netstat_rat_get_name(addr, numeric_addr)); + wid_gw = MAX(wid_gw, len); + } + len = strlen(fmt_flags(netstat_rt_get_flags(rtp))); + wid_flags = MAX(wid_flags, len); + len = snprintf(buffer, sizeof(buffer), "%ju", netstat_rt_get_refs(rtp)); + wid_refs = MAX(wid_refs, len); + len = snprintf(buffer, sizeof(buffer), "%ju", netstat_rt_get_used(rtp)); + wid_use = MAX(wid_use, len); + len = snprintf(buffer, sizeof(buffer), "%u", netstat_rt_get_mtu(rtp)); + wid_mtu = MAX(wid_mtu, len); + len = strlen(netstat_rt_get_interface(rtp)); + wid_if = MAX(wid_if, len); + if (netstat_rt_get_flags(rtp) & NETSTAT_RT_EXPIRES) { + len = snprintf(buffer, sizeof(buffer), "%ju", + netstat_rt_get_expire(rtp)); + wid_expire = MAX(wid_expire, len); + } +} - bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST); - len = strlen(bp); - wid_gw = MAX(len, wid_gw); +static const char * +fmt_flags(int f) +{ + static char name[33]; + char *flags; + struct bits *p = bits; - bp = fmt_flags(rt->rt_flags); - len = strlen(bp); - wid_flags = MAX(len, wid_flags); + for (flags = name; p->b_mask; p++) + if (p->b_mask & f) + *flags++ = p->b_val; + *flags = '\0'; + return (name); +} - 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; +void p_rtnode(const struct routenode_type *rntp) +{ + const struct routemask_type *rmtp; + const struct routeaddr_type *mask; + char nbuf[20]; + int bit, i, flags; - 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); - } + flags = netstat_rnt_get_flags(rntp); + if (flags & NETSTAT_RTN_ROOT) { + printf("(root node)%s", + flags & NETSTAT_RTN_DUPEDKEY ? " =>" : ""); + } else { + bit = netstat_rnt_get_bit(rntp); + if (bit < 0) { + mask = netstat_rnt_get_netmask(rntp); + if (mask != NULL) { + printf(" mask "); + printf("%s", + netstat_rat_get_name(mask, numeric_addr)); + } else if (netstat_rnt_get_mkcnt(rntp) == 0) + return; + } else { + sprintf(nbuf, "(%d)", bit); + printf("%6.6s %8.8lx : %8.8lx", nbuf, + (u_long)netstat_rnt_get_left(rntp), + (u_long)netstat_rnt_get_right(rntp)); } + for (i = 0; i < netstat_rnt_get_mkcnt(rntp); i++) { + if (i > 0) + printf(" ->"); + rmtp = netstat_rnt_get_mask(rntp, i); + sprintf(nbuf, " %ju refs, ", netstat_rmt_get_refs(rmtp)); + printf(" mk = %8.8lx { (%d),%s", + (u_long)netstat_rmt_get_address(rmtp), + -1 - netstat_rmt_get_bit(rmtp), + netstat_rmt_get_refs(rmtp) > 0 ? nbuf : " "); + if (netstat_rmt_get_flags(rmtp) & NETSTAT_RTM_NORMAL) + printf(", "); + mask = netstat_rmt_get_netmask(rmtp); + printf("%s ", netstat_rat_get_name(mask, numeric_addr)); + putchar('}'); + } } } - /* * Print header for routing table columns. */ @@ -423,601 +365,24 @@ } } -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)); - else - cp = netname(sockin->sin_addr.s_addr, 0L); - break; - } - -#ifdef INET6 - case AF_INET6: - { - struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; - struct in6_addr *in6 = &sa6->sin6_addr; - - /* - * 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(in6) || - IN6_IS_ADDR_MC_LINKLOCAL(in6)) { - /* XXX: override is ok? */ - sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]); - *(u_short *)&in6->s6_addr[2] = 0; - } - - 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) -{ - char *cp = 0; - static char line[MAXHOSTNAMELEN]; - struct netent *np = 0; - in_addr_t i; - - i = ntohl(in); - if (!numeric_addr && i) { - np = getnetbyaddr(i >> NSHIFT(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); - return (line); -} - -#undef NSHIFT - -#ifdef INET6 -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) +rt_stats(const struct stat_type *sttp) { - struct rtstat rtstat; - int rttrash; + const struct route_stat *s; - 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"); + s = netstat_get_routestats(sttp); +#define p(f, m) if (netstat_routes_get_##f(s) || sflag <= 1) \ + printf(m, netstat_routes_get_##f(s), plural(netstat_routes_get_##f(s))) + p(badredirect, "\t%ju bad routing redirect%s\n"); + p(dynamic, "\t%ju dynamically created route%s\n"); + p(newgateway, "\t%ju new gateway%s due to redirects\n"); + p(unreach, "\t%ju destination%s found unreachable\n"); + p(wildcard, "\t%ju use%s of a wildcard route\n"); + p(trash, "\t%ju route%s not in table but not freed\n"); #undef p - - if (rttrash || sflag <= 1) - printf("\t%u route%s not in table but not freed\n", - rttrash, plural(rttrash)); } char * Index: usr.bin/netstat/inet.c =================================================================== --- usr.bin/netstat/inet.c (revision 209358) +++ usr.bin/netstat/inet.c (working copy) @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2009 Gabor Pali * Copyright (c) 1983, 1988, 1993, 1995 * The Regents of the University of California. All rights reserved. * @@ -84,500 +85,163 @@ #include #include #include -#include "netstat.h" +#include +#include +#include "extern.h" + +#define USE_ITERATOR_TYPE + char *inetname(struct in_addr *); void inetprint(struct in_addr *, int, const char *, int); #ifdef INET6 static int udp_done, tcp_done; #endif /* INET6 */ +void addr_print(struct sockaddr_type *satp, const char *proto, int numeric); -static int -pcblist_sysctl(int proto, char **bufp, int istcp) -{ - const char *mibvar; - char *buf; - size_t len; - - switch (proto) { - case IPPROTO_TCP: - mibvar = "net.inet.tcp.pcblist"; - break; - case IPPROTO_UDP: - mibvar = "net.inet.udp.pcblist"; - break; - case IPPROTO_DIVERT: - mibvar = "net.inet.divert.pcblist"; - break; - default: - mibvar = "net.inet.raw.pcblist"; - break; - } - - len = 0; - if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { - if (errno != ENOENT) - warn("sysctl: %s", mibvar); - return (0); - } - if ((buf = malloc(len)) == 0) { - warnx("malloc %lu bytes", (u_long)len); - return (0); - } - if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { - warn("sysctl: %s", mibvar); - free(buf); - return (0); - } - *bufp = buf; - return (1); -} - /* - * Copied directly from uipc_socket2.c. We leave out some fields that are in - * nested structures that aren't used to avoid extra work. + * Print a summary of connections related to an Internet + * protocol. For TCP, also give state of connection. + * Listening processes (aflag) are suppressed unless the + * -a (all) flag is specified. */ -static void -sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb) +void +inetpr(const struct session_type *session, int family, int proto) { - xsb->sb_cc = sb->sb_cc; - xsb->sb_hiwat = sb->sb_hiwat; - xsb->sb_mbcnt = sb->sb_mbcnt; - xsb->sb_mcnt = sb->sb_mcnt; - xsb->sb_ccnt = sb->sb_ccnt; - xsb->sb_mbmax = sb->sb_mbmax; - xsb->sb_lowat = sb->sb_lowat; - xsb->sb_flags = sb->sb_flags; - xsb->sb_timeo = sb->sb_timeo; -} + struct socket_type_list *stlp; + int error, st_flags; +#ifdef USE_ITERATOR_TYPE + struct socket_type_iterator *stip; + const struct socket_type *stp; +#endif -int -sotoxsocket(struct socket *so, struct xsocket *xso) -{ - struct protosw proto; - struct domain domain; - - bzero(xso, sizeof *xso); - xso->xso_len = sizeof *xso; - xso->xso_so = so; - xso->so_type = so->so_type; - xso->so_options = so->so_options; - xso->so_linger = so->so_linger; - xso->so_state = so->so_state; - xso->so_pcb = so->so_pcb; - if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0) - return (-1); - xso->xso_protocol = proto.pr_protocol; - if (kread((uintptr_t)proto.pr_domain, &domain, sizeof(domain)) != 0) - return (-1); - xso->xso_family = domain.dom_family; - xso->so_qlen = so->so_qlen; - xso->so_incqlen = so->so_incqlen; - xso->so_qlimit = so->so_qlimit; - xso->so_timeo = so->so_timeo; - xso->so_error = so->so_error; - xso->so_oobmark = so->so_oobmark; - sbtoxsockbuf(&so->so_snd, &xso->so_snd); - sbtoxsockbuf(&so->so_rcv, &xso->so_rcv); - return (0); -} - -static int -pcblist_kvm(u_long off, char **bufp, int istcp) -{ - struct inpcbinfo pcbinfo; - struct inpcbhead listhead; - struct inpcb *inp; - struct xinpcb xi; - struct xinpgen xig; - struct xtcpcb xt; - struct socket so; - struct xsocket *xso; - char *buf, *p; - size_t len; - - if (off == 0) - return (0); - kread(off, &pcbinfo, sizeof(pcbinfo)); - if (istcp) - len = 2 * sizeof(xig) + - (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) * - sizeof(struct xtcpcb); - else - len = 2 * sizeof(xig) + - (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) * - sizeof(struct xinpcb); - if ((buf = malloc(len)) == 0) { - warnx("malloc %lu bytes", (u_long)len); - return (0); + stlp = netstat_stl_alloc(); + if (stlp == NULL) { + warn("netstat_stl_alloc"); + return; } - p = buf; -#define COPYOUT(obj, size) do { \ - if (len < (size)) { \ - warnx("buffer size exceeded"); \ - goto fail; \ - } \ - bcopy((obj), p, (size)); \ - len -= (size); \ - p += (size); \ -} while (0) - -#define KREAD(off, buf, len) do { \ - if (kread((uintptr_t)(off), (buf), (len)) != 0) \ - goto fail; \ -} while (0) - - /* Write out header. */ - xig.xig_len = sizeof xig; - xig.xig_count = pcbinfo.ipi_count; - xig.xig_gen = pcbinfo.ipi_gencnt; - xig.xig_sogen = 0; - COPYOUT(&xig, sizeof xig); - - /* Walk the PCB list. */ - xt.xt_len = sizeof xt; - xi.xi_len = sizeof xi; - if (istcp) - xso = &xt.xt_socket; - else - xso = &xi.xi_socket; - KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead)); - LIST_FOREACH(inp, &listhead, inp_list) { - if (istcp) { - KREAD(inp, &xt.xt_inp, sizeof(*inp)); - inp = &xt.xt_inp; - } else { - KREAD(inp, &xi.xi_inp, sizeof(*inp)); - inp = &xi.xi_inp; - } - - if (inp->inp_gencnt > pcbinfo.ipi_gencnt) - continue; - - if (istcp) { - if (inp->inp_ppcb == NULL) - bzero(&xt.xt_tp, sizeof xt.xt_tp); - else if (inp->inp_flags & INP_TIMEWAIT) { - bzero(&xt.xt_tp, sizeof xt.xt_tp); - xt.xt_tp.t_state = TCPS_TIME_WAIT; - } else - KREAD(inp->inp_ppcb, &xt.xt_tp, - sizeof xt.xt_tp); - } - if (inp->inp_socket) { - KREAD(inp->inp_socket, &so, sizeof(so)); - if (sotoxsocket(&so, xso) != 0) - goto fail; - } else { - bzero(xso, sizeof(*xso)); - if (istcp) - xso->xso_protocol = IPPROTO_TCP; - } - if (istcp) - COPYOUT(&xt, sizeof xt); + st_flags = 0; + if (aflag) + st_flags |= NETSTAT_SOCKET_ALL; + + if (netstat_socket(session, family, 0, proto, stlp, st_flags) < 0) { + error = netstat_stl_geterror(stlp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_socket: %s", netstat_kvmerror(session)); else - COPYOUT(&xi, sizeof xi); + warnx("netstat_socket: %s", netstat_strerror(error)); + return; } - /* Reread the pcbinfo and write out the footer. */ - kread(off, &pcbinfo, sizeof(pcbinfo)); - xig.xig_count = pcbinfo.ipi_count; - xig.xig_gen = pcbinfo.ipi_gencnt; - COPYOUT(&xig, sizeof xig); - - *bufp = buf; - return (1); - -fail: - free(buf); - return (0); -#undef COPYOUT -#undef KREAD +#ifdef USE_ITERATOR_TYPE + if (netstat_sti_alloc(stlp, &stip) < 0) { + warnx("netstat_sti_alloc"); + return; + } + for (stp = netstat_sti_first(stip); stp != NULL; + stp = netstat_sti_next(stip)) { + inetppr(stp); + } + netstat_sti_free(stip); + netstat_stl_free(stlp); +#else + netstat_stl_iterate(stlp, inetppr); +#endif } -/* - * Print a summary of connections related to an Internet - * protocol. For TCP, also give state of connection. - * Listening processes (aflag) are suppressed unless the - * -a (all) flag is specified. - */ void -protopr(u_long off, const char *name, int af1, int proto) +inetppr(const struct socket_type *stp) { - int istcp; static int first = 1; - char *buf; - const char *vchar; - struct tcpcb *tp = NULL; - struct inpcb *inp; - struct xinpgen *xig, *oxig; - struct xsocket *so; - struct xtcp_timer *timer; + char buf1[15]; + struct sockaddr_type *laddr, *faddr; - istcp = 0; - switch (proto) { - case IPPROTO_TCP: -#ifdef INET6 - if (tcp_done != 0) - return; - else - tcp_done = 1; -#endif - istcp = 1; - break; - case IPPROTO_UDP: -#ifdef INET6 - if (udp_done != 0) - return; - else - udp_done = 1; -#endif - break; - } - if (live) { - if (!pcblist_sysctl(proto, &buf, istcp)) - return; - } else { - if (!pcblist_kvm(off, &buf, istcp)) - return; - } - - oxig = xig = (struct xinpgen *)buf; - for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); - xig->xig_len > sizeof(struct xinpgen); - xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { - if (istcp) { - timer = &((struct xtcpcb *)xig)->xt_timer; - tp = &((struct xtcpcb *)xig)->xt_tp; - inp = &((struct xtcpcb *)xig)->xt_inp; - so = &((struct xtcpcb *)xig)->xt_socket; - } else { - inp = &((struct xinpcb *)xig)->xi_inp; - so = &((struct xinpcb *)xig)->xi_socket; - timer = NULL; - } - - /* Ignore sockets for protocols other than the desired one. */ - if (so->xso_protocol != proto) - continue; - - /* Ignore PCBs which were freed during copyout. */ - if (inp->inp_gencnt > oxig->xig_gen) - continue; - - if ((af1 == AF_INET && (inp->inp_vflag & INP_IPV4) == 0) -#ifdef INET6 - || (af1 == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0) -#endif /* INET6 */ - || (af1 == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0 -#ifdef INET6 - && (inp->inp_vflag & INP_IPV6) == 0 -#endif /* INET6 */ - )) - ) - continue; - if (!aflag && - ( - (istcp && tp->t_state == TCPS_LISTEN) - || (af1 == AF_INET && - inet_lnaof(inp->inp_laddr) == INADDR_ANY) -#ifdef INET6 - || (af1 == AF_INET6 && - IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) -#endif /* INET6 */ - || (af1 == AF_UNSPEC && - (((inp->inp_vflag & INP_IPV4) != 0 && - inet_lnaof(inp->inp_laddr) == INADDR_ANY) -#ifdef INET6 - || ((inp->inp_vflag & INP_IPV6) != 0 && - IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) -#endif - )) - )) - continue; - - if (first) { - if (!Lflag) { - printf("Active Internet connections"); - if (aflag) - printf(" (including servers)"); - } else + if (first) { + if (!Lflag) { + printf("Active Internet connections"); + if (aflag) + printf(" (including servers)"); + } else + printf( + "Current listen queue sizes (qlen/incqlen/maxqlen)"); + putchar('\n'); + if (Aflag) + printf("%-8.8s ", "Tcpcb"); + if (Lflag) + printf("%-5.5s %-14.14s %-22.22s\n", + "Proto", "Listen", "Local Address"); + else { + printf((Aflag && !Wflag) ? + "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s" : + "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s", + "Proto", "Recv-Q", "Send-Q", + "Local Address", "Foreign Address"); + if (xflag) printf( - "Current listen queue sizes (qlen/incqlen/maxqlen)"); - putchar('\n'); - if (Aflag) - printf("%-8.8s ", "Tcpcb"); - if (Lflag) - printf("%-5.5s %-14.14s %-22.22s\n", - "Proto", "Listen", "Local Address"); - else { - printf((Aflag && !Wflag) ? - "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s" : - "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s", - "Proto", "Recv-Q", "Send-Q", - "Local Address", "Foreign Address"); - if (xflag) { - printf("%-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s ", - "R-MBUF", "S-MBUF", "R-CLUS", - "S-CLUS", "R-HIWA", "S-HIWA", - "R-LOWA", "S-LOWA", "R-BCNT", - "S-BCNT", "R-BMAX", "S-BMAX"); - printf("%7.7s %7.7s %7.7s %7.7s %7.7s %7.7s %s\n", - "rexmt", "persist", "keep", - "2msl", "delack", "rcvtime", - "(state)"); - } else - printf("(state)\n"); - } - first = 0; - } - if (Lflag && so->so_qlimit == 0) - continue; - if (Aflag) { - if (istcp) - printf("%8lx ", (u_long)inp->inp_ppcb); + "%-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %s\n", + "R-MBUF", "S-MBUF", "R-CLUS", + "S-CLUS", "R-HIWA", "S-HIWA", + "R-LOWA", "S-LOWA", "R-BCNT", + "S-BCNT", "R-BMAX", "S-BMAX", + "(state)"); else - printf("%8lx ", (u_long)so->so_pcb); + printf("(state)\n"); } -#ifdef INET6 - if ((inp->inp_vflag & INP_IPV6) != 0) - vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? - "46" : "6 "; - else -#endif - vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? - "4 " : " "; - printf("%-3.3s%-2.2s ", name, vchar); - if (Lflag) { - char buf1[15]; - - snprintf(buf1, 15, "%d/%d/%d", so->so_qlen, - so->so_incqlen, so->so_qlimit); - printf("%-14.14s ", buf1); - } else { - printf("%6u %6u ", so->so_rcv.sb_cc, so->so_snd.sb_cc); - } - if (numeric_port) { - if (inp->inp_vflag & INP_IPV4) { - inetprint(&inp->inp_laddr, (int)inp->inp_lport, - name, 1); - if (!Lflag) - inetprint(&inp->inp_faddr, - (int)inp->inp_fport, name, 1); - } -#ifdef INET6 - else if (inp->inp_vflag & INP_IPV6) { - inet6print(&inp->in6p_laddr, - (int)inp->inp_lport, name, 1); - if (!Lflag) - inet6print(&inp->in6p_faddr, - (int)inp->inp_fport, name, 1); - } /* else nothing printed now */ -#endif /* INET6 */ - } else if (inp->inp_flags & INP_ANONPORT) { - if (inp->inp_vflag & INP_IPV4) { - inetprint(&inp->inp_laddr, (int)inp->inp_lport, - name, 1); - if (!Lflag) - inetprint(&inp->inp_faddr, - (int)inp->inp_fport, name, 0); - } -#ifdef INET6 - else if (inp->inp_vflag & INP_IPV6) { - inet6print(&inp->in6p_laddr, - (int)inp->inp_lport, name, 1); - if (!Lflag) - inet6print(&inp->in6p_faddr, - (int)inp->inp_fport, name, 0); - } /* else nothing printed now */ -#endif /* INET6 */ - } else { - if (inp->inp_vflag & INP_IPV4) { - inetprint(&inp->inp_laddr, (int)inp->inp_lport, - name, 0); - if (!Lflag) - inetprint(&inp->inp_faddr, - (int)inp->inp_fport, name, - inp->inp_lport != inp->inp_fport); - } -#ifdef INET6 - else if (inp->inp_vflag & INP_IPV6) { - inet6print(&inp->in6p_laddr, - (int)inp->inp_lport, name, 0); - if (!Lflag) - inet6print(&inp->in6p_faddr, - (int)inp->inp_fport, name, - inp->inp_lport != inp->inp_fport); - } /* else nothing printed now */ -#endif /* INET6 */ - } - if (xflag) { - if (Lflag) - printf("%21s %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ", - " ", - so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt, - so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt, - so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat, - so->so_rcv.sb_lowat, so->so_snd.sb_lowat, - so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt, - so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax); - else { - printf("%6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ", - so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt, - so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt, - so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat, - so->so_rcv.sb_lowat, so->so_snd.sb_lowat, - so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt, - so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax); - if (timer != NULL) - printf("%4d.%02d %4d.%02d %4d.%02d %4d.%02d %4d.%02d %4d.%02d ", - timer->tt_rexmt / 1000, (timer->tt_rexmt % 1000) / 10, - timer->tt_persist / 1000, (timer->tt_persist % 1000) / 10, - timer->tt_keep / 1000, (timer->tt_keep % 1000) / 10, - timer->tt_2msl / 1000, (timer->tt_2msl % 1000) / 10, - timer->tt_delack / 1000, (timer->tt_delack % 1000) / 10, - timer->t_rcvtime / 1000, (timer->t_rcvtime % 1000) / 10); - } - } - if (istcp && !Lflag) { - if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) - printf("%d", tp->t_state); - else { - printf("%s", tcpstates[tp->t_state]); -#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) - /* Show T/TCP `hidden state' */ - if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) - putchar('*'); -#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ - } - } - putchar('\n'); + first = 0; } - if (xig != oxig && xig->xig_gen != oxig->xig_gen) { - if (oxig->xig_count > xig->xig_count) { - printf("Some %s sockets may have been deleted.\n", - name); - } else if (oxig->xig_count < xig->xig_count) { - printf("Some %s sockets may have been created.\n", - name); - } else { - printf( - "Some %s sockets may have been created or deleted.\n", - name); - } + if (Lflag && netstat_st_get_qlimit(stp) == 0) + return; + if (Aflag) + printf("%8lx ", (u_long) netstat_st_get_pcb(stp)); + printf("%-5.5s ", netstat_st_get_extname(stp)); + if (Lflag) { + snprintf(buf1, 15, "%d/%d/%d", netstat_st_get_qlen(stp), + netstat_st_get_incqlen(stp), netstat_st_get_qlimit(stp)); + printf("%-14.14s", buf1); + } else { + printf("%6u %6u ", + netstat_sbt_get_cc(netstat_st_get_rcv(stp)), + netstat_sbt_get_cc(netstat_st_get_snd(stp))); } - free(buf); + laddr = netstat_st_get_address(stp, 0); /* local */ + faddr = netstat_st_get_address(stp, 1); /* foreign */ + addr_print(laddr, netstat_st_get_name(stp), numeric_port); + if (!Lflag) { + addr_print(faddr, netstat_st_get_name(stp), + numeric_port || + netstat_sat_get_port(laddr) != netstat_sat_get_port(faddr)); + } + if (xflag) { + if (Lflag) + printf("%21s", " "); + printf("%6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u", + netstat_sbt_get_mcnt(netstat_st_get_rcv(stp)), + netstat_sbt_get_mcnt(netstat_st_get_snd(stp)), + netstat_sbt_get_ccnt(netstat_st_get_rcv(stp)), + netstat_sbt_get_ccnt(netstat_st_get_snd(stp)), + netstat_sbt_get_hiwat(netstat_st_get_rcv(stp)), + netstat_sbt_get_hiwat(netstat_st_get_snd(stp)), + netstat_sbt_get_lowat(netstat_st_get_rcv(stp)), + netstat_sbt_get_lowat(netstat_st_get_snd(stp)), + netstat_sbt_get_mbcnt(netstat_st_get_rcv(stp)), + netstat_sbt_get_mbcnt(netstat_st_get_snd(stp)), + netstat_sbt_get_mbmax(netstat_st_get_rcv(stp)), + netstat_sbt_get_mbmax(netstat_st_get_snd(stp))); + } + if (!Lflag) { + printf("%s", netstat_st_get_tcpstate(stp)); + } + putchar('\n'); } /* * Dump TCP statistics structure. */ void -tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +tcp_stats(const struct stat_type *sttp) { - struct tcpstat tcpstat, zerostat; - size_t len = sizeof tcpstat; + const struct tcp_stat *s; #ifdef INET6 if (tcp_done != 0) @@ -585,126 +249,115 @@ else tcp_done = 1; #endif + s = netstat_get_tcpstats(sttp); +#define p(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f(s), plural(netstat_tcps_get_##f(s))) +#define p1a(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f(s)) +#define p2(f1, f2, m) if (netstat_tcps_get_##f1(s) || netstat_tcps_get_##f2(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f1(s), plural(netstat_tcps_get_##f1(s)), \ + netstat_tcps_get_##f2(s), plural(netstat_tcps_get_##f2(s))) +#define p2a(f1, f2, m) if (netstat_tcps_get_##f1(s) || netstat_tcps_get_##f2(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f1(s), plural(netstat_tcps_get_##f1(s)), \ + netstat_tcps_get_##f2(s)) +#define p3(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f(s), plural(netstat_tcps_get_##f(s))) - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - warn("sysctl: net.inet.tcp.stats"); - return; - } - } else - kread(off, &tcpstat, len); + p(sndtotal, "\t%ju packet%s sent\n"); + p2(sndpack,sndbyte, "\t\t%ju data packet%s (%ju byte%s)\n"); + p2(sndrexmitpack, sndrexmitbyte, + "\t\t%ju data packet%s (%ju byte%s) retransmitted\n"); + p(sndrexmitbad, + "\t\t%ju data packet%s unnecessarily retransmitted\n"); + p(mturesent, "\t\t%ju resend%s initiated by MTU discovery\n"); + p2a(sndacks, delack, + "\t\t%ju ack-only packet%s (%ju delayed)\n"); + p(sndurg, "\t\t%ju URG only packet%s\n"); + p(sndprobe, "\t\t%ju window probe packet%s\n"); + p(sndwinup, "\t\t%ju window update packet%s\n"); + p(sndctrl, "\t\t%ju control packet%s\n"); + p(rcvtotal, "\t%ju packet%s received\n"); + p2(rcvackpack, rcvackbyte, + "\t\t%ju ack%s (for %ju byte%s)\n"); + p(rcvdupack, "\t\t%ju duplicate ack%s\n"); + p(rcvacktoomuch, "\t\t%ju ack%s for unsent data\n"); + p2(rcvpack, rcvbyte, + "\t\t%ju packet%s (%ju byte%s) received in-sequence\n"); + p2(rcvduppack, rcvdupbyte, + "\t\t%ju completely duplicate packet%s (%ju byte%s)\n"); + p(pawsdrop, "\t\t%ju old duplicate packet%s\n"); + p2(rcvpartduppack, rcvpartdupbyte, + "\t\t%ju packet%s with some dup. data (%ju byte%s duped)\n"); + p2(rcvoopack, rcvoobyte, + "\t\t%ju out-of-order packet%s (%ju byte%s)\n"); + p2(rcvpackafterwin, rcvbyteafterwin, + "\t\t%ju packet%s (%ju byte%s) of data after window\n"); + p(rcvwinprobe, "\t\t%ju window probe%s\n"); + p(rcvwinupd, "\t\t%ju window update packet%s\n"); + p(rcvafterclose, "\t\t%ju packet%s received after close\n"); + p(rcvbadsum, "\t\t%ju discarded for bad checksum%s\n"); + p(rcvbadoff, "\t\t%ju discarded for bad header offset field%s\n"); + p1a(rcvshort, "\t\t%ju discarded because packet too short\n"); + p1a(rcvmemdrop, "\t\t%ju discarded due to memory problems\n"); + p(connattempt, "\t%ju connection request%s\n"); + p(accepts, "\t%ju connection accept%s\n"); + p(badsyn, "\t%ju bad connection attempt%s\n"); + p(listendrop, "\t%ju listen queue overflow%s\n"); + p(badrst, "\t%ju ignored RSTs in the window%s\n"); + p(connects, "\t%ju connection%s established (including accepts)\n"); + p2(closed, drops, + "\t%ju connection%s closed (including %ju drop%s)\n"); + p(cachedrtt, "\t\t%ju connection%s updated cached RTT on close\n"); + p(cachedrttvar, + "\t\t%ju connection%s updated cached RTT variance on close\n"); + p(cachedssthresh, + "\t\t%ju connection%s updated cached ssthresh on close\n"); + p(conndrops, "\t%ju embryonic connection%s dropped\n"); + p2(rttupdated, segstimed, + "\t%ju segment%s updated rtt (of %ju attempt%s)\n"); + p(rexmttimeo, "\t%ju retransmit timeout%s\n"); + p(timeoutdrop, "\t\t%ju connection%s dropped by rexmit timeout\n"); + p(persisttimeo, "\t%ju persist timeout%s\n"); + p(persistdrop, "\t\t%ju connection%s dropped by persist timeout\n"); + p(finwait2_drops, + "\t%ju Connection%s (fin_wait_2) dropped because of timeout\n"); + p(keeptimeo, "\t%ju keepalive timeout%s\n"); + p(keepprobe, "\t\t%ju keepalive probe%s sent\n"); + p(keepdrops, "\t\t%ju connection%s dropped by keepalive\n"); + p(predack, "\t%ju correct ACK header prediction%s\n"); + p(preddat, "\t%ju correct data packet header prediction%s\n"); - printf ("%s:\n", name); + p3(sc_added, "\t%ju syncache entr%s added\n"); + p1a(sc_retransmitted, "\t\t%ju retransmitted\n"); + p1a(sc_dupsyn, "\t\t%ju dupsyn\n"); + p1a(sc_dropped, "\t\t%ju dropped\n"); + p1a(sc_completed, "\t\t%ju completed\n"); + p1a(sc_bucketoverflow, "\t\t%ju bucket overflow\n"); + p1a(sc_cacheoverflow, "\t\t%ju cache overflow\n"); + p1a(sc_reset, "\t\t%ju reset\n"); + p1a(sc_stale, "\t\t%ju stale\n"); + p1a(sc_aborted, "\t\t%ju aborted\n"); + p1a(sc_badack, "\t\t%ju badack\n"); + p1a(sc_unreach, "\t\t%ju unreach\n"); + p(sc_zonefail, "\t\t%ju zone failure%s\n"); + p(sc_sendcookie, "\t%ju cookie%s sent\n"); + p(sc_recvcookie, "\t%ju cookie%s received\n"); -#define p(f, m) if (tcpstat.f || sflag <= 1) \ - printf(m, tcpstat.f, plural(tcpstat.f)) -#define p1a(f, m) if (tcpstat.f || sflag <= 1) \ - printf(m, tcpstat.f) -#define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ - printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) -#define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ - printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) -#define p3(f, m) if (tcpstat.f || sflag <= 1) \ - printf(m, tcpstat.f, pluralies(tcpstat.f)) + p(sack_recovery_episode, "\t%ju SACK recovery episode%s\n"); + p(sack_rexmits, + "\t%ju segment rexmit%s in SACK recovery episodes\n"); + p(sack_rexmit_bytes, + "\t%ju byte rexmit%s in SACK recovery episodes\n"); + p(sack_rcv_blocks, + "\t%ju SACK option%s (SACK blocks) received\n"); + p(sack_send_blocks, "\t%ju SACK option%s (SACK blocks) sent\n"); + p1a(sack_sboverflow, "\t%ju SACK scoreboard overflow\n"); - p(tcps_sndtotal, "\t%lu packet%s sent\n"); - p2(tcps_sndpack,tcps_sndbyte, "\t\t%lu data packet%s (%lu byte%s)\n"); - p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, - "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); - p(tcps_sndrexmitbad, - "\t\t%lu data packet%s unnecessarily retransmitted\n"); - p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); - p2a(tcps_sndacks, tcps_delack, - "\t\t%lu ack-only packet%s (%lu delayed)\n"); - p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); - p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); - p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); - p(tcps_sndctrl, "\t\t%lu control packet%s\n"); - p(tcps_rcvtotal, "\t%lu packet%s received\n"); - p2(tcps_rcvackpack, tcps_rcvackbyte, - "\t\t%lu ack%s (for %lu byte%s)\n"); - p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); - p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); - p2(tcps_rcvpack, tcps_rcvbyte, - "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); - p2(tcps_rcvduppack, tcps_rcvdupbyte, - "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); - p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n"); - p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, - "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); - p2(tcps_rcvoopack, tcps_rcvoobyte, - "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); - p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, - "\t\t%lu packet%s (%lu byte%s) of data after window\n"); - p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); - p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); - p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); - p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); - p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); - p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); - p1a(tcps_rcvmemdrop, "\t\t%lu discarded due to memory problems\n"); - p(tcps_connattempt, "\t%lu connection request%s\n"); - p(tcps_accepts, "\t%lu connection accept%s\n"); - p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); - p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); - p(tcps_badrst, "\t%lu ignored RSTs in the window%s\n"); - p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); - p2(tcps_closed, tcps_drops, - "\t%lu connection%s closed (including %lu drop%s)\n"); - p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); - p(tcps_cachedrttvar, - "\t\t%lu connection%s updated cached RTT variance on close\n"); - p(tcps_cachedssthresh, - "\t\t%lu connection%s updated cached ssthresh on close\n"); - p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); - p2(tcps_rttupdated, tcps_segstimed, - "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); - p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); - p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); - p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); - p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); - p(tcps_finwait2_drops, - "\t%lu Connection%s (fin_wait_2) dropped because of timeout\n"); - p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); - p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); - p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); - p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); - p(tcps_preddat, "\t%lu correct data packet header prediction%s\n"); - - p3(tcps_sc_added, "\t%lu syncache entr%s added\n"); - p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n"); - p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n"); - p1a(tcps_sc_dropped, "\t\t%lu dropped\n"); - p1a(tcps_sc_completed, "\t\t%lu completed\n"); - p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n"); - p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n"); - p1a(tcps_sc_reset, "\t\t%lu reset\n"); - p1a(tcps_sc_stale, "\t\t%lu stale\n"); - p1a(tcps_sc_aborted, "\t\t%lu aborted\n"); - p1a(tcps_sc_badack, "\t\t%lu badack\n"); - p1a(tcps_sc_unreach, "\t\t%lu unreach\n"); - p(tcps_sc_zonefail, "\t\t%lu zone failure%s\n"); - p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n"); - p(tcps_sc_recvcookie, "\t%lu cookie%s received\n"); - - p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n"); - p(tcps_sack_rexmits, - "\t%lu segment rexmit%s in SACK recovery episodes\n"); - p(tcps_sack_rexmit_bytes, - "\t%lu byte rexmit%s in SACK recovery episodes\n"); - p(tcps_sack_rcv_blocks, - "\t%lu SACK option%s (SACK blocks) received\n"); - p(tcps_sack_send_blocks, "\t%lu SACK option%s (SACK blocks) sent\n"); - p1a(tcps_sack_sboverflow, "\t%lu SACK scoreboard overflow\n"); - - p(tcps_ecn_ce, "\t%lu packet%s with ECN CE bit set\n"); - p(tcps_ecn_ect0, "\t%lu packet%s with ECN ECT(0) bit set\n"); - p(tcps_ecn_ect1, "\t%lu packet%s with ECN ECT(1) bit set\n"); - p(tcps_ecn_shs, "\t%lu successful ECN handshake%s\n"); - p(tcps_ecn_rcwnd, "\t%lu time%s ECN reduced the congestion window\n"); + p(ecn_ce, "\t%ju packet%s with ECN CE bit set\n"); + p(ecn_ect0, "\t%ju packet%s with ECN ECT(0) bit set\n"); + p(ecn_ect1, "\t%ju packet%s with ECN ECT(1) bit set\n"); + p(ecn_shs, "\t%ju successful ECN handshake%s\n"); + p(ecn_rcwnd, "\t%ju time%s ECN reduced the congestion window\n"); #undef p #undef p1a #undef p2 @@ -716,11 +369,9 @@ * Dump UDP statistics structure. */ void -udp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +udp_stats(const struct stat_type *sttp) { - struct udpstat udpstat, zerostat; - size_t len = sizeof udpstat; - u_long delivered; + const struct udp_stat *s; #ifdef INET6 if (udp_done != 0) @@ -728,46 +379,26 @@ else udp_done = 1; #endif - - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - warn("sysctl: net.inet.udp.stats"); - return; - } - } else - kread(off, &udpstat, len); - - printf("%s:\n", name); -#define p(f, m) if (udpstat.f || sflag <= 1) \ - printf(m, udpstat.f, plural(udpstat.f)) -#define p1a(f, m) if (udpstat.f || sflag <= 1) \ - printf(m, udpstat.f) - p(udps_ipackets, "\t%lu datagram%s received\n"); - p1a(udps_hdrops, "\t%lu with incomplete header\n"); - p1a(udps_badlen, "\t%lu with bad data length field\n"); - p1a(udps_badsum, "\t%lu with bad checksum\n"); - p1a(udps_nosum, "\t%lu with no checksum\n"); - p1a(udps_noport, "\t%lu dropped due to no socket\n"); - p(udps_noportbcast, - "\t%lu broadcast/multicast datagram%s undelivered\n"); - p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); - p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n"); - delivered = udpstat.udps_ipackets - - udpstat.udps_hdrops - - udpstat.udps_badlen - - udpstat.udps_badsum - - udpstat.udps_noport - - udpstat.udps_noportbcast - - udpstat.udps_fullsock; - if (delivered || sflag <= 1) - printf("\t%lu delivered\n", delivered); - p(udps_opackets, "\t%lu datagram%s output\n"); + s = netstat_get_udpstats(sttp); +#define p(f, m) if (netstat_udps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_udps_get_##f(s), plural(netstat_udps_get_##f(s))) +#define p1a(f, m) if (netstat_udps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_udps_get_##f(s)) + p(ipackets, "\t%ju datagram%s received\n"); + p1a(hdrops, "\t%ju with incomplete header\n"); + p1a(badlen, "\t%ju with bad data length field\n"); + p1a(badsum, "\t%ju with bad checksum\n"); + p1a(nosum, "\t%ju with no checksum\n"); + p1a(noport, "\t%ju dropped due to no socket\n"); + p(noportbcast, + "\t%ju broadcast/multicast datagram%s undelivered\n"); + p1a(fullsock, "\t%ju dropped due to full socket buffers\n"); + p1a(pcbhashmiss, "\t%ju not for hashed pcb\n"); + p1a(delivered, "\t%ju delivered\n"); + p(opackets, "\t%ju datagram%s output\n"); /* the next statistic is cumulative in udps_noportbcast */ - p(udps_filtermcast, - "\t%lu time%s multicast source filter matched\n"); + p(filtermcast, + "\t%ju time%s multicast source filter matched\n"); #undef p #undef p1a } @@ -776,48 +407,30 @@ * Dump CARP statistics structure. */ void -carp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +carp_stats(const struct stat_type *sttp) { - struct carpstats carpstat, zerostat; - size_t len = sizeof(struct carpstats); + const struct carp_stat *s; - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.carp.stats", &carpstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - if (errno != ENOENT) - warn("sysctl: net.inet.carp.stats"); - return; - } - } else { - if (off == 0) - return; - kread(off, &carpstat, len); - } - - printf("%s:\n", name); - -#define p(f, m) if (carpstat.f || sflag <= 1) \ - printf(m, (uintmax_t)carpstat.f, plural(carpstat.f)) -#define p2(f, m) if (carpstat.f || sflag <= 1) \ - printf(m, (uintmax_t)carpstat.f) - - p(carps_ipackets, "\t%ju packet%s received (IPv4)\n"); - p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n"); - p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n"); - p(carps_hdrops, "\t\t%ju packet%s shorter than header\n"); - p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n"); - p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n"); - p2(carps_badlen, "\t\t%ju discarded because packet too short\n"); - p2(carps_badauth, "\t\t%ju discarded for bad authentication\n"); - p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n"); - p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n"); - p(carps_opackets, "\t%ju packet%s sent (IPv4)\n"); - p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n"); - p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n"); + s = netstat_get_carpstats(sttp); +#define p(f, m) if (netstat_carps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_carps_get_##f(s), plural(netstat_carps_get_##f(s))) +#define p2(f, m) if (netstat_carps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_carps_get_##f(s)) + p(ipackets, "\t%ju packet%s received (IPv4)\n"); + p(ipackets6, "\t%ju packet%s received (IPv6)\n"); + p(badttl, "\t\t%ju packet%s discarded for wrong TTL\n"); + p(hdrops, "\t\t%ju packet%s shorter than header\n"); + p(badsum, "\t\t%ju discarded for bad checksum%s\n"); + p(badver, "\t\t%ju discarded packet%s with a bad version\n"); + p2(badlen, "\t\t%ju discarded because packet too short\n"); + p2(badauth, "\t\t%ju discarded for bad authentication\n"); + p2(badvhid, "\t\t%ju discarded for bad vhid\n"); + p2(badaddrs, "\t\t%ju discarded because of a bad address list\n"); + p(opackets, "\t%ju packet%s sent (IPv4)\n"); + p(opackets6, "\t%ju packet%s sent (IPv6)\n"); + p2(onomem, "\t\t%ju send failed due to mbuf memory error\n"); #if notyet - p(carps_ostates, "\t\t%s state update%s sent\n"); + p(ostates, "\t\t%s state update%s sent\n"); #endif #undef p #undef p2 @@ -827,62 +440,48 @@ * Dump IP statistics structure. */ void -ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +ip_stats(const struct stat_type *sttp) { - struct ipstat ipstat, zerostat; - size_t len = sizeof ipstat; + const struct ip_stat *s; - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - warn("sysctl: net.inet.ip.stats"); - return; - } - } else - kread(off, &ipstat, len); - - printf("%s:\n", name); - -#define p(f, m) if (ipstat.f || sflag <= 1) \ - printf(m, ipstat.f, plural(ipstat.f)) -#define p1a(f, m) if (ipstat.f || sflag <= 1) \ - printf(m, ipstat.f) - - p(ips_total, "\t%lu total packet%s received\n"); - p(ips_badsum, "\t%lu bad header checksum%s\n"); - p1a(ips_toosmall, "\t%lu with size smaller than minimum\n"); - p1a(ips_tooshort, "\t%lu with data size < data length\n"); - p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n"); - p1a(ips_badhlen, "\t%lu with header length < data size\n"); - p1a(ips_badlen, "\t%lu with data length < header length\n"); - p1a(ips_badoptions, "\t%lu with bad options\n"); - p1a(ips_badvers, "\t%lu with incorrect version number\n"); - p(ips_fragments, "\t%lu fragment%s received\n"); - p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); - p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); - p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); - p(ips_delivered, "\t%lu packet%s for this host\n"); - p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); - p(ips_forward, "\t%lu packet%s forwarded"); - p(ips_fastforward, " (%lu packet%s fast forwarded)"); - if (ipstat.ips_forward || sflag <= 1) + s = netstat_get_ipstats(sttp); +#define p(f, m) if (netstat_ips_get_##f(s) || sflag <= 1) \ + printf(m, netstat_ips_get_##f(s), plural(netstat_ips_get_##f(s))) +#define p1a(f, m) if (netstat_ips_get_##f(s) || sflag <= 1) \ + printf(m, netstat_ips_get_##f(s)) + p(total, "\t%ju total packet%s received\n"); + p(badsum, "\t%ju bad header checksum%s\n"); + p1a(toosmall, "\t%ju with size smaller than minimum\n"); + p1a(tooshort, "\t%ju with data size < data length\n"); + p1a(toolong, "\t%ju with ip length > max ip packet size\n"); + p1a(badhlen, "\t%ju with header length < data size\n"); + p1a(badlen, "\t%ju with data length < header length\n"); + p1a(badoptions, "\t%ju with bad options\n"); + p1a(badvers, "\t%ju with incorrect version number\n"); + p(fragments, "\t%ju fragment%s received\n"); + p(fragdropped, "\t%ju fragment%s dropped (dup or out of space)\n"); + p(fragtimeout, "\t%ju fragment%s dropped after timeout\n"); + p(reassembled, "\t%ju packet%s reassembled ok\n"); + p(delivered, "\t%ju packet%s for this host\n"); + p(noproto, "\t%ju packet%s for unknown/unsupported protocol\n"); + p(forward, "\t%ju packet%s forwarded"); + p(fastforward, " (%ju packet%s fast forwarded)"); + if (netstat_ips_get_forward(s) || sflag <= 1) putchar('\n'); - p(ips_cantforward, "\t%lu packet%s not forwardable\n"); - p(ips_notmember, - "\t%lu packet%s received for unknown multicast group\n"); - p(ips_redirectsent, "\t%lu redirect%s sent\n"); - p(ips_localout, "\t%lu packet%s sent from this host\n"); - p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); - p(ips_odropped, - "\t%lu output packet%s dropped due to no bufs, etc.\n"); - p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); - p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); - p(ips_ofragments, "\t%lu fragment%s created\n"); - p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); - p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n"); - p(ips_badaddr, "\t%lu datagram%s with bad address in header\n"); + p(cantforward, "\t%ju packet%s not forwardable\n"); + p(notmember, + "\t%ju packet%s received for unknown multicast group\n"); + p(redirectsent, "\t%ju redirect%s sent\n"); + p(localout, "\t%ju packet%s sent from this host\n"); + p(rawout, "\t%ju packet%s sent with fabricated ip header\n"); + p(odropped, + "\t%ju output packet%s dropped due to no bufs, etc.\n"); + p(noroute, "\t%ju output packet%s discarded due to no route\n"); + p(fragmented, "\t%ju output datagram%s fragmented\n"); + p(ofragments, "\t%ju fragment%s created\n"); + p(cantfrag, "\t%ju datagram%s that can't be fragmented\n"); + p(nogif, "\t%ju tunneling packet%s that can't find gif\n"); + p(badaddr, "\t%ju datagram%s with bad address in header\n"); #undef p #undef p1a } @@ -890,6 +489,8 @@ /* * Dump ARP statistics structure. */ + /* XXX: ARP stats */ +#if 0 void arp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) { @@ -925,254 +526,101 @@ #undef p #undef p2 } +#endif -static const char *icmpnames[ICMP_MAXTYPE + 1] = { - "echo reply", /* RFC 792 */ - "#1", - "#2", - "destination unreachable", /* RFC 792 */ - "source quench", /* RFC 792 */ - "routing redirect", /* RFC 792 */ - "#6", - "#7", - "echo", /* RFC 792 */ - "router advertisement", /* RFC 1256 */ - "router solicitation", /* RFC 1256 */ - "time exceeded", /* RFC 792 */ - "parameter problem", /* RFC 792 */ - "time stamp", /* RFC 792 */ - "time stamp reply", /* RFC 792 */ - "information request", /* RFC 792 */ - "information request reply", /* RFC 792 */ - "address mask request", /* RFC 950 */ - "address mask reply", /* RFC 950 */ - "#19", - "#20", - "#21", - "#22", - "#23", - "#24", - "#25", - "#26", - "#27", - "#28", - "#29", - "icmp traceroute", /* RFC 1393 */ - "datagram conversion error", /* RFC 1475 */ - "mobile host redirect", - "IPv6 where-are-you", - "IPv6 i-am-here", - "mobile registration req", - "mobile registration reply", - "domain name request", /* RFC 1788 */ - "domain name reply", /* RFC 1788 */ - "icmp SKIP", - "icmp photuris", /* RFC 2521 */ -}; - /* * Dump ICMP statistics. */ void -icmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +icmp_stats(const struct stat_type *sttp) { - struct icmpstat icmpstat, zerostat; + const struct icmp_stat *s; int i, first; - size_t len; - len = sizeof icmpstat; - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - warn("sysctl: net.inet.icmp.stats"); - return; - } - } else - kread(off, &icmpstat, len); - - printf("%s:\n", name); - -#define p(f, m) if (icmpstat.f || sflag <= 1) \ - printf(m, icmpstat.f, plural(icmpstat.f)) -#define p1a(f, m) if (icmpstat.f || sflag <= 1) \ - printf(m, icmpstat.f) -#define p2(f, m) if (icmpstat.f || sflag <= 1) \ - printf(m, icmpstat.f, plurales(icmpstat.f)) - - p(icps_error, "\t%lu call%s to icmp_error\n"); - p(icps_oldicmp, - "\t%lu error%s not generated in response to an icmp message\n"); + s = netstat_get_icmpstats(sttp); +#define p(f, m) if (netstat_icmps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_icmps_get_##f(s), plural(netstat_icmps_get_##f(s))) +#define p1a(f, m) if (netstat_icmps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_icmps_get_##f(s)) +#define p2(f, m) if (netstat_icmps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_icmps_get_##f(s), plurales(netstat_icmps_get_##f(s))) + p(error, "\t%ju call%s to icmp_error\n"); + p(oldicmp, + "\t%ju error%s not generated in response to an icmp message\n"); for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) - if (icmpstat.icps_outhist[i] != 0) { + if (netstat_icmps_get_outhist(s, i) != 0) { if (first) { printf("\tOutput histogram:\n"); first = 0; } - if (icmpnames[i] != NULL) - printf("\t\t%s: %lu\n", icmpnames[i], - icmpstat.icps_outhist[i]); + if (netstat_icmpname(i) != NULL) + printf("\t\t%s: %ju\n", netstat_icmpname(i), + netstat_icmps_get_outhist(s, i)); else - printf("\t\tunknown ICMP #%d: %lu\n", i, - icmpstat.icps_outhist[i]); + printf("\t\tunknown ICMP #%d: %ju\n", i, + netstat_icmps_get_outhist(s, i)); } - p(icps_badcode, "\t%lu message%s with bad code fields\n"); - p(icps_tooshort, "\t%lu message%s less than the minimum length\n"); - p(icps_checksum, "\t%lu message%s with bad checksum\n"); - p(icps_badlen, "\t%lu message%s with bad length\n"); - p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n"); - p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n"); + p(badcode, "\t%ju message%s with bad code fields\n"); + p(tooshort, "\t%ju message%s less than the minimum length\n"); + p(checksum, "\t%ju message%s with bad checksum\n"); + p(badlen, "\t%ju message%s with bad length\n"); + p1a(bmcastecho, "\t%ju multicast echo requests ignored\n"); + p1a(bmcasttstamp, "\t%ju multicast timestamp requests ignored\n"); for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) - if (icmpstat.icps_inhist[i] != 0) { + if (netstat_icmps_get_inhist(s, i) != 0) { if (first) { printf("\tInput histogram:\n"); first = 0; } - if (icmpnames[i] != NULL) - printf("\t\t%s: %lu\n", icmpnames[i], - icmpstat.icps_inhist[i]); + if (netstat_icmpname(i) != NULL) + printf("\t\t%s: %ju\n", netstat_icmpname(i), + netstat_icmps_get_inhist(s, i)); else - printf("\t\tunknown ICMP #%d: %lu\n", i, - icmpstat.icps_inhist[i]); + printf("\t\tunknown ICMP #%d: %ju\n", i, + netstat_icmps_get_inhist(s, i)); } - p(icps_reflect, "\t%lu message response%s generated\n"); - p2(icps_badaddr, "\t%lu invalid return address%s\n"); - p(icps_noroute, "\t%lu no return route%s\n"); + p(reflect, "\t%ju message response%s generated\n"); + p2(badaddr, "\t%ju invalid return address%s\n"); + p(noroute, "\t%ju no return route%s\n"); #undef p #undef p1a #undef p2 - if (live) { - len = sizeof i; - if (sysctlbyname("net.inet.icmp.maskrepl", &i, &len, NULL, 0) < - 0) - return; - printf("\tICMP address mask responses are %sabled\n", - i ? "en" : "dis"); - } } -#ifndef BURN_BRIDGES /* - * Dump IGMP statistics structure (pre 8.x kernel). - */ -static void -igmp_stats_live_old(u_long off, const char *name) -{ - struct oigmpstat oigmpstat, zerostat; - size_t len = sizeof(oigmpstat); - - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.igmp.stats", &oigmpstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - warn("sysctl: net.inet.igmp.stats"); - return; - } - - printf("%s:\n", name); - -#define p(f, m) if (oigmpstat.f || sflag <= 1) \ - printf(m, oigmpstat.f, plural(oigmpstat.f)) -#define py(f, m) if (oigmpstat.f || sflag <= 1) \ - printf(m, oigmpstat.f, oigmpstat.f != 1 ? "ies" : "y") - p(igps_rcv_total, "\t%u message%s received\n"); - p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); - p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); - py(igps_rcv_queries, "\t%u membership quer%s received\n"); - py(igps_rcv_badqueries, - "\t%u membership quer%s received with invalid field(s)\n"); - p(igps_rcv_reports, "\t%u membership report%s received\n"); - p(igps_rcv_badreports, - "\t%u membership report%s received with invalid field(s)\n"); - p(igps_rcv_ourreports, -"\t%u membership report%s received for groups to which we belong\n"); - p(igps_snd_reports, "\t%u membership report%s sent\n"); -#undef p -#undef py -} -#endif /* !BURN_BRIDGES */ - -/* * Dump IGMP statistics structure. */ void -igmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +igmp_stats(const struct stat_type *sttp) { - struct igmpstat igmpstat, zerostat; - size_t len; + const struct igmp_stat *s; -#ifndef BURN_BRIDGES - if (live) { - /* - * Detect if we are being run against a pre-IGMPv3 kernel. - * We cannot do this for a core file as the legacy - * struct igmpstat has no size field, nor does it - * export it in any readily-available symbols. - */ - len = 0; - if (sysctlbyname("net.inet.igmp.stats", NULL, &len, NULL, - 0) < 0) { - warn("sysctl: net.inet.igmp.stats"); - return; - } - if (len < sizeof(igmpstat)) { - igmp_stats_live_old(off, name); - return; - } - } -#endif /* !BURN_BRIDGES */ - - len = sizeof(igmpstat); - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - warn("sysctl: net.inet.igmp.stats"); - return; - } - } else { - len = sizeof(igmpstat); - kread(off, &igmpstat, len); - } - - if (igmpstat.igps_version != IGPS_VERSION_3) { - warnx("%s: version mismatch (%d != %d)", __func__, - igmpstat.igps_version, IGPS_VERSION_3); - } - if (igmpstat.igps_len != IGPS_VERSION3_LEN) { - warnx("%s: size mismatch (%d != %d)", __func__, - igmpstat.igps_len, IGPS_VERSION3_LEN); - } - - printf("%s:\n", name); - -#define p64(f, m) if (igmpstat.f || sflag <= 1) \ - printf(m, (uintmax_t) igmpstat.f, plural(igmpstat.f)) -#define py64(f, m) if (igmpstat.f || sflag <= 1) \ - printf(m, (uintmax_t) igmpstat.f, pluralies(igmpstat.f)) - p64(igps_rcv_total, "\t%ju message%s received\n"); - p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n"); - p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n"); - p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n"); - py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n"); - py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n"); - py64(igps_rcv_badqueries, + s = netstat_get_igmpstats(sttp); +#define p64(f, m) if (netstat_igmps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_igmps_get_##f(s), plural(netstat_igmps_get_##f(s))) +#define py64(f, m) if (netstat_igmps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_igmps_get_##f(s), pluralies(netstat_igmps_get_##f(s))) + p64(rcv_total, "\t%ju message%s received\n"); + p64(rcv_tooshort, "\t%ju message%s received with too few bytes\n"); + p64(rcv_badttl, "\t%ju message%s received with wrong TTL\n"); + p64(rcv_badsum, "\t%ju message%s received with bad checksum\n"); + py64(rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n"); + py64(rcv_v3_queries, "\t%ju V3 membership quer%s received\n"); + py64(rcv_badqueries, "\t%ju membership quer%s received with invalid field(s)\n"); - py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n"); - py64(igps_rcv_group_queries, "\t%ju group quer%s received\n"); - py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n"); - py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n"); - p64(igps_rcv_reports, "\t%ju membership report%s received\n"); - p64(igps_rcv_badreports, + py64(rcv_gen_queries, "\t%ju general quer%s received\n"); + py64(rcv_group_queries, "\t%ju group quer%s received\n"); + py64(rcv_gsr_queries, "\t%ju group-source quer%s received\n"); + py64(drop_gsr_queries, "\t%ju group-source quer%s dropped\n"); + p64(rcv_reports, "\t%ju membership report%s received\n"); + p64(rcv_badreports, "\t%ju membership report%s received with invalid field(s)\n"); - p64(igps_rcv_ourreports, + p64(rcv_ourreports, "\t%ju membership report%s received for groups to which we belong\n"); - p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n"); - p64(igps_snd_reports, "\t%ju membership report%s sent\n"); + p64(rcv_nora, "\t%ju V3 report%s received without Router Alert\n"); + p64(snd_reports, "\t%ju membership report%s sent\n"); #undef p64 #undef py64 } @@ -1181,45 +629,27 @@ * Dump PIM statistics structure. */ void -pim_stats(u_long off __unused, const char *name, int af1 __unused, - int proto __unused) +pim_stats(const struct stat_type *sttp) { - struct pimstat pimstat, zerostat; - size_t len = sizeof pimstat; + const struct pim_stat *s; - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.pim.stats", &pimstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - if (errno != ENOENT) - warn("sysctl: net.inet.pim.stats"); - return; - } - } else { - if (off == 0) - return; - kread(off, &pimstat, len); - } - - printf("%s:\n", name); - -#define p(f, m) if (pimstat.f || sflag <= 1) \ - printf(m, (uintmax_t)pimstat.f, plural(pimstat.f)) -#define py(f, m) if (pimstat.f || sflag <= 1) \ - printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y") - p(pims_rcv_total_msgs, "\t%ju message%s received\n"); - p(pims_rcv_total_bytes, "\t%ju byte%s received\n"); - p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n"); - p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n"); - p(pims_rcv_badversion, "\t%ju message%s received with bad version\n"); - p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n"); - p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n"); - p(pims_rcv_registers_wrongiif, + s = netstat_get_pimstats(sttp); +#define p(f, m) if (netstat_pims_get_##f(s) || sflag <= 1) \ + printf(m, netstat_pims_get_##f(s), plural(netstat_pims_get_##f(s))) +#define py(f, m) if (netstat_pims_get_##f(s) || sflag <= 1) \ + printf(m, netstat_pims_get_##f(s), netstat_pims_get_##f(s) != 1 ? "ies" : "y") + p(rcv_total_msgs, "\t%ju message%s received\n"); + p(rcv_total_bytes, "\t%ju byte%s received\n"); + p(rcv_tooshort, "\t%ju message%s received with too few bytes\n"); + p(rcv_badsum, "\t%ju message%s received with bad checksum\n"); + p(rcv_badversion, "\t%ju message%s received with bad version\n"); + p(rcv_registers_msgs, "\t%ju data register message%s received\n"); + p(rcv_registers_bytes, "\t%ju data register byte%s received\n"); + p(rcv_registers_wrongiif, "\t%ju data register message%s received on wrong iif\n"); - p(pims_rcv_badregisters, "\t%ju bad register%s received\n"); - p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n"); - p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n"); + p(rcv_badregisters, "\t%ju bad register%s received\n"); + p(snd_registers_msgs, "\t%ju data register message%s sent\n"); + p(snd_registers_bytes, "\t%ju data register byte%s sent\n"); #undef p #undef py } @@ -1295,3 +725,21 @@ } return (line); } + +void +addr_print(struct sockaddr_type *satp, const char *proto, int numeric) +{ + int width; + char line[80], *cp; + + sprintf(line, "%.*s.", Wflag ? 39 : (Aflag && !numeric) ? 12 : 16, + numeric_addr ? netstat_sat_get_numeric(satp) : + netstat_sat_get_name(satp)); + cp = index(line, '\0'); + if (numeric && (netstat_sat_get_port(satp) > 0)) + sprintf(cp, "%d ", netstat_sat_get_port(satp)); + else + sprintf(cp, "%.15s ", netstat_sat_get_portname(satp)); + width = Wflag ? 45 : Aflag ? 18 : 22; + printf("%-*.*s ", width, width, line); +} Index: usr.bin/netstat/ipx.c =================================================================== --- usr.bin/netstat/ipx.c (revision 209358) +++ usr.bin/netstat/ipx.c (working copy) @@ -69,7 +69,7 @@ #include #include #include -#include "netstat.h" +#include "extern.h" static char *ipx_prpr(struct ipx_addr *); @@ -154,101 +154,98 @@ * Dump SPX statistics structure. */ void -spx_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +spx_stats(const struct stat_type *sttp) { - struct spx_istat spx_istat; -#define spxstat spx_istat.newstats + const struct spx_stat *s; - if (off == 0) - return; - kread(off, (char *)&spx_istat, sizeof (spx_istat)); - printf("%s:\n", name); - ANY(spx_istat.nonucn, "connection", " dropped due to no new sockets "); - ANY(spx_istat.gonawy, "connection", " terminated due to our end dying"); - ANY(spx_istat.nonucn, "connection", - " dropped due to inability to connect"); - ANY(spx_istat.noconn, "connection", - " dropped due to inability to connect"); - ANY(spx_istat.notme, "connection", - " incompleted due to mismatched id's"); - ANY(spx_istat.wrncon, "connection", " dropped due to mismatched id's"); - ANY(spx_istat.bdreas, "packet", " dropped out of sequence"); - ANY(spx_istat.lstdup, "packet", " duplicating the highest packet"); - ANY(spx_istat.notyet, "packet", " refused as exceeding allocation"); - ANYl(spxstat.spxs_connattempt, "connection", " initiated"); - ANYl(spxstat.spxs_accepts, "connection", " accepted"); - ANYl(spxstat.spxs_connects, "connection", " established"); - ANYl(spxstat.spxs_drops, "connection", " dropped"); - ANYl(spxstat.spxs_conndrops, "embryonic connection", " dropped"); - ANYl(spxstat.spxs_closed, "connection", " closed (includes drops)"); - ANYl(spxstat.spxs_segstimed, "packet", " where we tried to get rtt"); - ANYl(spxstat.spxs_rttupdated, "time", " we got rtt"); - ANYl(spxstat.spxs_delack, "delayed ack", " sent"); - ANYl(spxstat.spxs_timeoutdrop, "connection", - " dropped in rxmt timeout"); - ANYl(spxstat.spxs_rexmttimeo, "retransmit timeout", ""); - ANYl(spxstat.spxs_persisttimeo, "persist timeout", ""); - ANYl(spxstat.spxs_keeptimeo, "keepalive timeout", ""); - ANYl(spxstat.spxs_keepprobe, "keepalive probe", " sent"); - ANYl(spxstat.spxs_keepdrops, "connection", " dropped in keepalive"); - ANYl(spxstat.spxs_sndtotal, "total packet", " sent"); - ANYl(spxstat.spxs_sndpack, "data packet", " sent"); - ANYl(spxstat.spxs_sndbyte, "data byte", " sent"); - ANYl(spxstat.spxs_sndrexmitpack, "data packet", " retransmitted"); - ANYl(spxstat.spxs_sndrexmitbyte, "data byte", " retransmitted"); - ANYl(spxstat.spxs_sndacks, "ack-only packet", " sent"); - ANYl(spxstat.spxs_sndprobe, "window probe", " sent"); - ANYl(spxstat.spxs_sndurg, "packet", " sent with URG only"); - ANYl(spxstat.spxs_sndwinup, "window update-only packet", " sent"); - ANYl(spxstat.spxs_sndctrl, "control (SYN|FIN|RST) packet", " sent"); - ANYl(spxstat.spxs_sndvoid, "request", " to send a non-existant packet"); - ANYl(spxstat.spxs_rcvtotal, "total packet", " received"); - ANYl(spxstat.spxs_rcvpack, "packet", " received in sequence"); - ANYl(spxstat.spxs_rcvbyte, "byte", " received in sequence"); - ANYl(spxstat.spxs_rcvbadsum, "packet", " received with ccksum errs"); - ANYl(spxstat.spxs_rcvbadoff, "packet", " received with bad offset"); - ANYl(spxstat.spxs_rcvshort, "packet", " received too short"); - ANYl(spxstat.spxs_rcvduppack, "duplicate-only packet", " received"); - ANYl(spxstat.spxs_rcvdupbyte, "duplicate-only byte", " received"); - ANYl(spxstat.spxs_rcvpartduppack, "packet", - " with some duplicate data"); - ANYl(spxstat.spxs_rcvpartdupbyte, "dup. byte", " in part-dup. packet"); - ANYl(spxstat.spxs_rcvoopack, "out-of-order packet", " received"); - ANYl(spxstat.spxs_rcvoobyte, "out-of-order byte", " received"); - ANYl(spxstat.spxs_rcvpackafterwin, "packet", " with data after window"); - ANYl(spxstat.spxs_rcvbyteafterwin, "byte", " rcvd after window"); - ANYl(spxstat.spxs_rcvafterclose, "packet", " rcvd after 'close'"); - ANYl(spxstat.spxs_rcvwinprobe, "rcvd window probe packet", ""); - ANYl(spxstat.spxs_rcvdupack, "rcvd duplicate ack", ""); - ANYl(spxstat.spxs_rcvacktoomuch, "rcvd ack", " for unsent data"); - ANYl(spxstat.spxs_rcvackpack, "rcvd ack packet", ""); - ANYl(spxstat.spxs_rcvackbyte, "byte", " acked by rcvd acks"); - ANYl(spxstat.spxs_rcvwinupd, "rcvd window update packet", ""); + s = netstat_get_spxstats(sttp); +#define p(x,y,z) \ + if (netstat_spxs_get_##x(s) || sflag <= 1) \ + printf("\t%ju %s%s%s\n", netstat_spxs_get_##x(s), y, \ + plural(netstat_spxs_get_##x(s)), z) + p(nonucn, "connection", " dropped due to no new sockets "); + p(gonawy, "connection", " terminated due to our end dying"); + p(nonucn, "connection", " dropped due to inability to connect"); + p(noconn, "connection", " dropped due to inability to connect"); + p(notme, "connection", " incompleted due to mismatched id's"); + p(wrncon, "connection", " dropped due to mismatched id's"); + p(bdreas, "packet", " dropped out of sequence"); + p(lstdup, "packet", " duplicating the highest packet"); + p(notyet, "packet", " refused as exceeding allocation"); + p(connattempt, "connection", " initiated"); + p(accepts, "connection", " accepted"); + p(connects, "connection", " established"); + p(drops, "connection", " dropped"); + p(conndrops, "embryonic connection", " dropped"); + p(closed, "connection", " closed (includes drops)"); + p(segstimed, "packet", " where we tried to get rtt"); + p(rttupdated, "time", " we got rtt"); + p(delack, "delayed ack", " sent"); + p(timeoutdrop, "connection", " dropped in rxmt timeout"); + p(rexmttimeo, "retransmit timeout", ""); + p(persisttimeo, "persist timeout", ""); + p(keeptimeo, "keepalive timeout", ""); + p(keepprobe, "keepalive probe", " sent"); + p(keepdrops, "connection", " dropped in keepalive"); + p(sndtotal, "total packet", " sent"); + p(sndpack, "data packet", " sent"); + p(sndbyte, "data byte", " sent"); + p(sndrexmitpack, "data packet", " retransmitted"); + p(sndrexmitbyte, "data byte", " retransmitted"); + p(sndacks, "ack-only packet", " sent"); + p(sndprobe, "window probe", " sent"); + p(sndurg, "packet", " sent with URG only"); + p(sndwinup, "window update-only packet", " sent"); + p(sndctrl, "control (SYN|FIN|RST) packet", " sent"); + p(sndvoid, "request", " to send a non-existant packet"); + p(rcvtotal, "total packet", " received"); + p(rcvpack, "packet", " received in sequence"); + p(rcvbyte, "byte", " received in sequence"); + p(rcvbadsum, "packet", " received with ccksum errs"); + p(rcvbadoff, "packet", " received with bad offset"); + p(rcvshort, "packet", " received too short"); + p(rcvduppack, "duplicate-only packet", " received"); + p(rcvdupbyte, "duplicate-only byte", " received"); + p(rcvpartduppack, "packet", " with some duplicate data"); + p(rcvpartdupbyte, "dup. byte", " in part-dup. packet"); + p(rcvoopack, "out-of-order packet", " received"); + p(rcvoobyte, "out-of-order byte", " received"); + p(rcvpackafterwin, "packet", " with data after window"); + p(rcvbyteafterwin, "byte", " rcvd after window"); + p(rcvafterclose, "packet", " rcvd after 'close'"); + p(rcvwinprobe, "rcvd window probe packet", ""); + p(rcvdupack, "rcvd duplicate ack", ""); + p(rcvacktoomuch, "rcvd ack", " for unsent data"); + p(rcvackpack, "rcvd ack packet", ""); + p(rcvackbyte, "byte", " acked by rcvd acks"); + p(rcvwinupd, "rcvd window update packet", ""); +#undef p } /* * Dump IPX statistics structure. */ void -ipx_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +ipx_stats(const struct stat_type *sttp) { - struct ipxstat ipxstat; - - if (off == 0) - return; - kread(off, (char *)&ipxstat, sizeof (ipxstat)); - printf("%s:\n", name); - ANYl(ipxstat.ipxs_total, "total packet", " received"); - ANYl(ipxstat.ipxs_badsum, "packet", " with bad checksums"); - ANYl(ipxstat.ipxs_tooshort, "packet", " smaller than advertised"); - ANYl(ipxstat.ipxs_toosmall, "packet", " smaller than a header"); - ANYl(ipxstat.ipxs_forward, "packet", " forwarded"); - ANYl(ipxstat.ipxs_cantforward, "packet", " not forwardable"); - ANYl(ipxstat.ipxs_delivered, "packet", " for this host"); - ANYl(ipxstat.ipxs_localout, "packet", " sent from this host"); - ANYl(ipxstat.ipxs_odropped, "packet", " dropped due to no bufs, etc."); - ANYl(ipxstat.ipxs_noroute, "packet", " discarded due to no route"); - ANYl(ipxstat.ipxs_mtutoosmall, "packet", " too big"); + const struct ipx_stat *s; +#define p(x,y,z) \ + if (netstat_ipxs_get_##x(s) || sflag <= 1) \ + printf("\t%ju %s%s%s\n", netstat_ipxs_get_##x(s), y, \ + plural(netstat_ipxs_get_##x(s)), z) + s = netstat_get_ipxstats(sttp); + p(total, "total packet", " received"); + p(badsum, "packet", " with bad checksums"); + p(tooshort, "packet", " smaller than advertised"); + p(toosmall, "packet", " smaller than a header"); + p(forward, "packet", " forwarded"); + p(cantforward, "packet", " not forwardable"); + p(delivered, "packet", " for this host"); + p(localout, "packet", " sent from this host"); + p(odropped, "packet", " dropped due to no bufs, etc."); + p(noroute, "packet", " discarded due to no route"); + p(mtutoosmall, "packet", " too big"); +#undef p } #ifdef IPXERRORMSGS Index: usr.bin/netstat/mroute6.c =================================================================== --- usr.bin/netstat/mroute6.c (revision 209358) +++ usr.bin/netstat/mroute6.c (working copy) @@ -93,12 +93,133 @@ #include #undef KERNEL -#include "netstat.h" +#include +#include "extern.h" +#define USE_LIBNETSTAT + #define WID_ORG (Wflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */ #define WID_GRP (Wflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */ +#ifdef USE_LIBNETSTAT void +mroute6pr(const struct session_type *session) +{ + int mifi, maxmif; + int error; + + struct mcastif_type_list *mitlp; + struct mcastif_type_iterator *mitip; + struct mroute_type_list *mrtlp; + struct mroute_type_iterator *mrtip; + + const struct mcastif_type *mitp; + const struct mroute_type *mrtp; + const struct routeaddr_type *addr; + + mitlp = netstat_mitl_alloc(); + if (mitlp == NULL) { + warn("netstat_mitl_alloc()"); + return; + } + + if (netstat_mif(session, PF_INET6, mitlp, 0)) { + error = netstat_mitl_geterror(mitlp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_mif: %s", netstat_kvmerror(session)); + else + warnx("netstat_mif: %s", netstat_strerror(error)); + goto out; + } + + maxmif = 0; + + if (netstat_mitl_length(mitlp) > 0) { + printf("\nIPv6 Multicast Interface Table\n" + " Mif Rate PhyIF " + "Pkts-In Pkts-Out\n"); + } else { + printf("\nIPv6 Multicast Interface Table is empty\n"); + printf("\n"); + goto out; + } + + if (netstat_miti_alloc(mitlp, &mitip) < 0) { + warn("netstat_miti_alloc()"); + goto out; + } + + for (mitp = netstat_miti_first(mitip); mitp != NULL; + mitp = netstat_miti_next(mitip)) { + maxmif = netstat_mit_get_index(mitp); + printf(" %2u %4u %5s %9ju %9ju\n", + netstat_mit_get_index(mitp), + netstat_mit_get_limit(mitp), + netstat_mit_get_ifname(mitp), + netstat_mit_get_packets_in(mitp), + netstat_mit_get_packets_out(mitp)); + } + printf("\n"); + + mrtlp = netstat_mrtl_alloc(); + if (mrtlp == NULL) { + warn("netstat_mrtl_alloc()"); + goto out; + } + + if (netstat_mroute(session, PF_INET6, mrtlp, 0)) { + error = netstat_mrtl_geterror(mrtlp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_mroute: %s", netstat_kvmerror(session)); + else + warnx("netstat_mroute: %s", netstat_strerror(error)); + goto out2; + } + + if (netstat_mrtl_length(mrtlp) > 0) { + printf("\nIPv6 Multicast Forwarding Cache\n"); + printf(" %-*.*s %-*.*s %s", + WID_ORG, WID_ORG, "Origin", + WID_GRP, WID_GRP, "Group", + " Packets Waits In-Mif Out-Mifs\n"); + } else { + printf("\nIPv6 Multicast Forwarding Table is empty\n"); + printf("\n"); + goto out2; + } + + if (netstat_mrti_alloc(mrtlp, &mrtip) < 0) { + warn("netstat_mrti_alloc()"); + goto out2; + } + + for (mrtp = netstat_mrti_first(mrtip); mrtp != NULL; + mrtp = netstat_mrti_next(mrtip)) { + addr = netstat_mrt_get_origin(mrtp); + printf(" %-*.*s", WID_ORG, WID_ORG, + netstat_rat_get_name(addr, 1)); + addr = netstat_mrt_get_group(mrtp); + printf(" %-*.*s", WID_GRP, WID_GRP, + netstat_rat_get_name(addr, 1)); + printf(" %3ju", netstat_mrt_get_waitings(mrtp)); + if (netstat_mrt_get_parent(mrtp) == + NETSTAT_MROUTE_INCOMPLETE_PARENT) + printf(" --- "); + else + printf(" %3u ", netstat_mrt_get_parent(mrtp)); + for (mifi = 0; mifi <= maxmif; mifi++) + if (netstat_mrt_get_is_mif_set(mrtp, mifi)) + printf(" %u", mifi); + } + printf("\n"); + + netstat_mrti_free(mrtip); +out2: netstat_mrtl_free(mrtlp); + netstat_miti_free(mitip); +out: netstat_mitl_free(mitlp); +} +#else +void mroute6pr(u_long mfcaddr, u_long mifaddr) { struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp; @@ -215,45 +336,31 @@ printf("\n"); numeric_addr = saved_numeric_addr; } +#endif void -mrt6_stats(u_long mstaddr) +mrt6_stats(const struct stat_type *sttp) { - struct mrt6stat mrtstat; - size_t len = sizeof mrtstat; + const struct mroute6_stat *s; - if (live) { - if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len, - NULL, 0) < 0) { - warn("sysctl: net.inet6.ip6.mrt6stat"); - return; - } - } else - kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat)); - - printf("IPv6 multicast forwarding:\n"); - -#define p(f, m) if (mrtstat.f || sflag <= 1) \ - printf(m, (uintmax_t)mrtstat.f, plural(mrtstat.f)) -#define p2(f, m) if (mrtstat.f || sflag <= 1) \ - printf(m, (uintmax_t)mrtstat.f, plurales(mrtstat.f)) - - p(mrt6s_mfc_lookups, "\t%ju multicast forwarding cache lookup%s\n"); - p2(mrt6s_mfc_misses, "\t%ju multicast forwarding cache miss%s\n"); - p(mrt6s_upcalls, "\t%ju upcall%s to multicast routing daemon\n"); - p(mrt6s_upq_ovflw, "\t%ju upcall queue overflow%s\n"); - p(mrt6s_upq_sockfull, - "\t%ju upcall%s dropped due to full socket buffer\n"); - p(mrt6s_cache_cleanups, "\t%ju cache cleanup%s\n"); - p(mrt6s_no_route, "\t%ju datagram%s with no route for origin\n"); - p(mrt6s_bad_tunnel, "\t%ju datagram%s arrived with bad tunneling\n"); - p(mrt6s_cant_tunnel, "\t%ju datagram%s could not be tunneled\n"); - p(mrt6s_wrong_if, "\t%ju datagram%s arrived on wrong interface\n"); - p(mrt6s_drop_sel, "\t%ju datagram%s selectively dropped\n"); - p(mrt6s_q_overflow, - "\t%ju datagram%s dropped due to queue overflow\n"); - p(mrt6s_pkt2large, "\t%ju datagram%s dropped for being too large\n"); - + s = netstat_get_mroute6stats(sttp); +#define p(f, m) if (netstat_mroute6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_mroute6s_get_##f(s), plural(netstat_mroute6s_get_##f(s))) +#define p2(f, m) if (netstat_mroute6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_mroute6s_get_##f(s), plurales(netstat_mroute6s_get_##f(s))) + p(mfc_lookups, "\t%ju multicast forwarding cache lookup%s\n"); + p2(mfc_misses, "\t%ju multicast forwarding cache miss%s\n"); + p(upcalls, "\t%ju upcall%s to multicast routing daemon\n"); + p(upq_ovflw, "\t%ju upcall queue overflow%s\n"); + p(upq_sockfull, "\t%ju upcall%s dropped due to full socket buffer\n"); + p(cache_cleanups, "\t%ju cache cleanup%s\n"); + p(no_route, "\t%ju datagram%s with no route for origin\n"); + p(bad_tunnel, "\t%ju datagram%s arrived with bad tunneling\n"); + p(cant_tunnel, "\t%ju datagram%s could not be tunneled\n"); + p(wrong_if, "\t%ju datagram%s arrived on wrong interface\n"); + p(drop_sel, "\t%ju datagram%s selectively dropped\n"); + p(q_overflow, "\t%ju datagram%s dropped due to queue overflow\n"); + p(pkt2large, "\t%ju datagram%s dropped for being too large\n"); #undef p2 #undef p } Index: usr.bin/netstat/ipsec.c =================================================================== --- usr.bin/netstat/ipsec.c (revision 209358) +++ usr.bin/netstat/ipsec.c (working copy) @@ -27,6 +27,7 @@ */ /*- * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * Copyright (c) 2009 Gabor Pali * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -95,128 +96,23 @@ #include __FBSDID("$FreeBSD$"); -#include -#include -#include -#include +#include -#include - -#ifdef IPSEC -#include -#include -#include -#include -#endif - -#include #include -#include -#include -#include "netstat.h" +#include +#include "extern.h" -#ifdef IPSEC -struct val2str { - int val; - const char *str; -}; - -static struct val2str ipsec_ahnames[] = { - { SADB_AALG_NONE, "none", }, - { SADB_AALG_MD5HMAC, "hmac-md5", }, - { SADB_AALG_SHA1HMAC, "hmac-sha1", }, - { SADB_X_AALG_MD5, "md5", }, - { SADB_X_AALG_SHA, "sha", }, - { SADB_X_AALG_NULL, "null", }, -#ifdef SADB_X_AALG_SHA2_256 - { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, -#endif -#ifdef SADB_X_AALG_SHA2_384 - { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, -#endif -#ifdef SADB_X_AALG_SHA2_512 - { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, -#endif -#ifdef SADB_X_AALG_RIPEMD160HMAC - { SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", }, -#endif -#ifdef SADB_X_AALG_AES_XCBC_MAC - { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", }, -#endif - { -1, NULL }, -}; - -static struct val2str ipsec_espnames[] = { - { SADB_EALG_NONE, "none", }, - { SADB_EALG_DESCBC, "des-cbc", }, - { SADB_EALG_3DESCBC, "3des-cbc", }, - { SADB_EALG_NULL, "null", }, - { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, - { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, -#ifdef SADB_X_EALG_RIJNDAELCBC - { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, -#endif -#ifdef SADB_X_EALG_AESCTR - { SADB_X_EALG_AESCTR, "aes-ctr", }, -#endif - { -1, NULL }, -}; - -static struct val2str ipsec_compnames[] = { - { SADB_X_CALG_NONE, "none", }, - { SADB_X_CALG_OUI, "oui", }, - { SADB_X_CALG_DEFLATE, "deflate", }, - { SADB_X_CALG_LZS, "lzs", }, - { -1, NULL }, -}; - -static void ipsec_hist(const u_quad_t *hist, size_t histmax, - const struct val2str *name, const char *title); -static void print_ipsecstats(const struct ipsecstat *ipsecstat); - - -/* - * Dump IPSEC statistics structure. - */ -static void -ipsec_hist(const u_quad_t *hist, size_t histmax, const struct val2str *name, - const char *title) +void +ipsec_stats(const struct stat_type *sttp) { - int first; - size_t proto; - const struct val2str *p; + const struct ipsec_stat *s; + int first, proto; - first = 1; - for (proto = 0; proto < histmax; proto++) { - if (hist[proto] <= 0) - continue; - if (first) { - printf("\t%s histogram:\n", title); - first = 0; - } - for (p = name; p && p->str; p++) { - if (p->val == (int)proto) - break; - } - if (p && p->str) { - printf("\t\t%s: %ju\n", p->str, (uintmax_t)hist[proto]); - } else { - printf("\t\t#%ld: %ju\n", (long)proto, - (uintmax_t)hist[proto]); - } - } -} - -static void -print_ipsecstats(const struct ipsecstat *ipsecstat) -{ -#define p(f, m) if (ipsecstat->f || sflag <= 1) \ - printf(m, (uintmax_t)ipsecstat->f, plural(ipsecstat->f)) -#define pes(f, m) if (ipsecstat->f || sflag <= 1) \ - printf(m, (uintmax_t)ipsecstat->f, plurales(ipsecstat->f)) -#define hist(f, n, t) \ - ipsec_hist((f), sizeof(f)/sizeof(f[0]), (n), (t)); - + s = netstat_get_ipsecstats(sttp); +#define p(f, m) if (netstat_ipsecs_get_##f(s) || sflag <= 1) \ + printf(m, (uintmax_t)netstat_ipsecs_get_##f(s), plural(netstat_ipsecs_get_##f(s))) +#define pes(f, m) if (netstat_ipsecs_get_##f(s) || sflag <= 1) \ + printf(m, netstat_ipsecs_get_##f(s), plurales(netstat_ipsecs_get_##f(s))) p(in_success, "\t%ju inbound packet%s processed successfully\n"); p(in_polvio, "\t%ju inbound packet%s violated process security " "policy\n"); @@ -228,10 +124,39 @@ p(in_espreplay, "\t%ju inbound packet%s failed on ESP replay check\n"); p(in_ahauthsucc, "\t%ju inbound packet%s considered authentic\n"); p(in_ahauthfail, "\t%ju inbound packet%s failed on authentication\n"); - hist(ipsecstat->in_ahhist, ipsec_ahnames, "AH input"); - hist(ipsecstat->in_esphist, ipsec_espnames, "ESP input"); - hist(ipsecstat->in_comphist, ipsec_compnames, "IPComp input"); - + first = 1; + for (proto = 0; proto < NETSTAT_IPSEC_AH_HIST_MAX; proto++) { + if (netstat_ipsecs_get_in_ahhist(s, proto) == 0) + continue; + if (first != 0) { + printf("\tAH input histogram:\n"); + first = 0; + } + printf("\t\t%s: %ju\n", netstat_ipsec_ahname(proto), + netstat_ipsecs_get_in_ahhist(s, proto)); + } + first = 1; + for (proto = 0; proto < NETSTAT_IPSEC_ESP_HIST_MAX; proto++) { + if (netstat_ipsecs_get_in_esphist(s, proto) == 0) + continue; + if (first != 0) { + printf("\tESP input histogram:\n"); + first = 0; + } + printf("\t\t%s: %ju\n", netstat_ipsec_espname(proto), + netstat_ipsecs_get_in_esphist(s, proto)); + } + first = 1; + for (proto = 0; proto < NETSTAT_IPSEC_IPCOMP_HIST_MAX; proto++) { + if (netstat_ipsecs_get_in_comphist(s, proto) == 0) + continue; + if (first != 0) { + printf("\tIPcomp input histogram:\n"); + first = 0; + } + printf("\t\t%s: %ju\n", netstat_ipsec_ipcompname(proto), + netstat_ipsecs_get_in_comphist(s, proto)); + } p(out_success, "\t%ju outbound packet%s processed successfully\n"); p(out_polvio, "\t%ju outbound packet%s violated process security " "policy\n"); @@ -239,13 +164,42 @@ p(out_inval, "\t%ju invalid outbound packet%s\n"); p(out_nomem, "\t%ju outbound packet%s failed due to insufficient memory\n"); p(out_noroute, "\t%ju outbound packet%s with no route\n"); - hist(ipsecstat->out_ahhist, ipsec_ahnames, "AH output"); - hist(ipsecstat->out_esphist, ipsec_espnames, "ESP output"); - hist(ipsecstat->out_comphist, ipsec_compnames, "IPComp output"); + first = 1; + for (proto = 0; proto < NETSTAT_IPSEC_AH_HIST_MAX; proto++) { + if (netstat_ipsecs_get_out_ahhist(s, proto) == 0) + continue; + if (first != 0) { + printf("\tAH output histogram:\n"); + first = 0; + } + printf("\t\t%s: %ju\n", netstat_ipsec_ahname(proto), + netstat_ipsecs_get_out_ahhist(s, proto)); + } + first = 1; + for (proto = 0; proto < NETSTAT_IPSEC_ESP_HIST_MAX; proto++) { + if (netstat_ipsecs_get_out_esphist(s, proto) == 0) + continue; + if (first != 0) { + printf("\tESP output histogram:\n"); + first = 0; + } + printf("\t\t%s: %ju\n", netstat_ipsec_espname(proto), + netstat_ipsecs_get_out_esphist(s, proto)); + } + first = 1; + for (proto = 0; proto < NETSTAT_IPSEC_IPCOMP_HIST_MAX; proto++) { + if (netstat_ipsecs_get_out_comphist(s, proto) == 0) + continue; + if (first != 0) { + printf("\tIPcomp output histogram:\n"); + first = 0; + } + printf("\t\t%s: %ju\n", netstat_ipsec_ipcompname(proto), + netstat_ipsecs_get_out_comphist(s, proto)); + } p(spdcachelookup, "\t%ju SPD cache lookup%s\n"); pes(spdcachemiss, "\t%ju SPD cache miss%s\n"); #undef pes -#undef hist p(ips_in_polvio, "\t%ju inbound packet%s violated process " "security policy\n"); p(ips_out_polvio, "\t%ju outbound packet%s violated process " @@ -265,210 +219,138 @@ } void -ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +ah_stats(const struct stat_type *sttp) { - struct ipsecstat ipsecstat; + const struct ah_stat *s; + int first, proto; - if (off == 0) - return; - printf ("%s:\n", name); - kread(off, (char *)&ipsecstat, sizeof(ipsecstat)); - - print_ipsecstats(&ipsecstat); -} - - -static void ipsec_hist_new(const u_int32_t *hist, size_t histmax, - const struct val2str *name, const char *title); -static void print_ahstats(const struct ahstat *ahstat); -static void print_espstats(const struct espstat *espstat); -static void print_ipcompstats(const struct ipcompstat *ipcompstat); - -/* - * Dump IPSEC statistics structure. - */ -static void -ipsec_hist_new(const u_int32_t *hist, size_t histmax, - const struct val2str *name, const char *title) -{ - int first; - size_t proto; - const struct val2str *p; - + s = netstat_get_ahstats(sttp); +#define p32(f, m) if (netstat_ahs_get_##f(s) || sflag <= 1) \ + printf("\t%u" m, netstat_ahs_get_##f(s), plural(netstat_ahs_get_##f(s))) +#define p64(f, m) if (netstat_ahs_get_##f(s) || sflag <= 1) \ + printf("\t%ju" m, netstat_ahs_get_##f(s), plural(netstat_ahs_get_##f(s))) + p32(hdrops, " packet%s shorter than header shows\n"); + p32(nopf, " packet%s dropped; protocol family not supported\n"); + p32(notdb, " packet%s dropped; no TDB\n"); + p32(badkcr, " packet%s dropped; bad KCR\n"); + p32(qfull, " packet%s dropped; queue full\n"); + p32(noxform, " packet%s dropped; no transform\n"); + p32(wrap, " replay counter wrap%s\n"); + p32(badauth, " packet%s dropped; bad authentication detected\n"); + p32(badauthl, " packet%s dropped; bad authentication length\n"); + p32(replay, " possible replay packet%s detected\n"); + p32(input, " packet%s in\n"); + p32(output, " packet%s out\n"); + p32(invalid, " packet%s dropped; invalid TDB\n"); + p64(ibytes, " byte%s in\n"); + p64(obytes, " byte%s out\n"); + p32(toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); + p32(pdrops, " packet%s blocked due to policy\n"); + p32(crypto, " crypto processing failure%s\n"); + p32(tunnel, " tunnel sanity check failure%s\n"); first = 1; - for (proto = 0; proto < histmax; proto++) { - if (hist[proto] <= 0) + for (proto = 0; proto < NETSTAT_AH_HIST_MAX; proto++) { + if (netstat_ahs_get_hist(s, proto) == 0) continue; - if (first) { - printf("\t%s histogram:\n", title); + if (first != 0) { + printf("\tAH output histogram:\n"); first = 0; } - for (p = name; p && p->str; p++) { - if (p->val == (int)proto) - break; - } - if (p && p->str) { - printf("\t\t%s: %u\n", p->str, hist[proto]); - } else { - printf("\t\t#%lu: %u\n", (unsigned long)proto, - hist[proto]); - } + printf("\t\t%s: %u\n", netstat_ipsec_ahname(proto), + netstat_ahs_get_hist(s, proto)); } -} - -static void -print_ahstats(const struct ahstat *ahstat) -{ -#define p32(f, m) if (ahstat->f || sflag <= 1) \ - printf("\t%u" m, (unsigned int)ahstat->f, plural(ahstat->f)) -#define p64(f, m) if (ahstat->f || sflag <= 1) \ - printf("\t%ju" m, (uintmax_t)ahstat->f, plural(ahstat->f)) -#define hist(f, n, t) \ - ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); - - p32(ahs_hdrops, " packet%s shorter than header shows\n"); - p32(ahs_nopf, " packet%s dropped; protocol family not supported\n"); - p32(ahs_notdb, " packet%s dropped; no TDB\n"); - p32(ahs_badkcr, " packet%s dropped; bad KCR\n"); - p32(ahs_qfull, " packet%s dropped; queue full\n"); - p32(ahs_noxform, " packet%s dropped; no transform\n"); - p32(ahs_wrap, " replay counter wrap%s\n"); - p32(ahs_badauth, " packet%s dropped; bad authentication detected\n"); - p32(ahs_badauthl, " packet%s dropped; bad authentication length\n"); - p32(ahs_replay, " possible replay packet%s detected\n"); - p32(ahs_input, " packet%s in\n"); - p32(ahs_output, " packet%s out\n"); - p32(ahs_invalid, " packet%s dropped; invalid TDB\n"); - p64(ahs_ibytes, " byte%s in\n"); - p64(ahs_obytes, " byte%s out\n"); - p32(ahs_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); - p32(ahs_pdrops, " packet%s blocked due to policy\n"); - p32(ahs_crypto, " crypto processing failure%s\n"); - p32(ahs_tunnel, " tunnel sanity check failure%s\n"); - hist(ahstat->ahs_hist, ipsec_ahnames, "AH output"); - #undef p32 #undef p64 -#undef hist } void -ah_stats(u_long off, const char *name, int family __unused, int proto __unused) +esp_stats(const struct stat_type *sttp) { - struct ahstat ahstat; + const struct esp_stat *s; + int first, proto; - if (off == 0) - return; - printf ("%s:\n", name); - kread(off, (char *)&ahstat, sizeof(ahstat)); - - print_ahstats(&ahstat); -} - -static void -print_espstats(const struct espstat *espstat) -{ -#define p32(f, m) if (espstat->f || sflag <= 1) \ - printf("\t%u" m, (unsigned int)espstat->f, plural(espstat->f)) -#define p64(f, m) if (espstat->f || sflag <= 1) \ - printf("\t%ju" m, (uintmax_t)espstat->f, plural(espstat->f)) -#define hist(f, n, t) \ - ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); - - p32(esps_hdrops, " packet%s shorter than header shows\n"); - p32(esps_nopf, " packet%s dropped; protocol family not supported\n"); - p32(esps_notdb, " packet%s dropped; no TDB\n"); - p32(esps_badkcr, " packet%s dropped; bad KCR\n"); - p32(esps_qfull, " packet%s dropped; queue full\n"); - p32(esps_noxform, " packet%s dropped; no transform\n"); - p32(esps_badilen, " packet%s dropped; bad ilen\n"); - p32(esps_wrap, " replay counter wrap%s\n"); - p32(esps_badenc, " packet%s dropped; bad encryption detected\n"); - p32(esps_badauth, " packet%s dropped; bad authentication detected\n"); - p32(esps_replay, " possible replay packet%s detected\n"); - p32(esps_input, " packet%s in\n"); - p32(esps_output, " packet%s out\n"); - p32(esps_invalid, " packet%s dropped; invalid TDB\n"); - p64(esps_ibytes, " byte%s in\n"); - p64(esps_obytes, " byte%s out\n"); - p32(esps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); - p32(esps_pdrops, " packet%s blocked due to policy\n"); - p32(esps_crypto, " crypto processing failure%s\n"); - p32(esps_tunnel, " tunnel sanity check failure%s\n"); - hist(espstat->esps_hist, ipsec_espnames, "ESP output"); - + s = netstat_get_espstats(sttp); +#define p32(f, m) if (netstat_esps_get_##f(s) || sflag <= 1) \ + printf("\t%u" m, netstat_esps_get_##f(s), plural(netstat_esps_get_##f(s))) +#define p64(f, m) if (netstat_esps_get_##f(s) || sflag <= 1) \ + printf("\t%ju" m, netstat_esps_get_##f(s), plural(netstat_esps_get_##f(s))) + p32(hdrops, " packet%s shorter than header shows\n"); + p32(nopf, " packet%s dropped; protocol family not supported\n"); + p32(notdb, " packet%s dropped; no TDB\n"); + p32(badkcr, " packet%s dropped; bad KCR\n"); + p32(qfull, " packet%s dropped; queue full\n"); + p32(noxform, " packet%s dropped; no transform\n"); + p32(badilen, " packet%s dropped; bad ilen\n"); + p32(wrap, " replay counter wrap%s\n"); + p32(badenc, " packet%s dropped; bad encryption detected\n"); + p32(badauth, " packet%s dropped; bad authentication detected\n"); + p32(replay, " possible replay packet%s detected\n"); + p32(input, " packet%s in\n"); + p32(output, " packet%s out\n"); + p32(invalid, " packet%s dropped; invalid TDB\n"); + p64(ibytes, " byte%s in\n"); + p64(obytes, " byte%s out\n"); + p32(toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); + p32(pdrops, " packet%s blocked due to policy\n"); + p32(crypto, " crypto processing failure%s\n"); + p32(tunnel, " tunnel sanity check failure%s\n"); + first = 1; + for (proto = 0; proto < NETSTAT_ESP_HIST_MAX; proto++) { + if (netstat_esps_get_hist(s, proto) == 0) + continue; + if (first != 0) { + printf("\tESP output histogram:\n"); + first = 0; + } + printf("\t\t%s: %u\n", netstat_ipsec_espname(proto), + netstat_esps_get_hist(s, proto)); + } #undef p32 #undef p64 -#undef hist } void -esp_stats(u_long off, const char *name, int family __unused, int proto __unused) +ipcomp_stats(const struct stat_type *sttp) { - struct espstat espstat; + const struct ipcomp_stat *s; + int first, proto; - if (off == 0) - return; - printf ("%s:\n", name); - kread(off, (char *)&espstat, sizeof(espstat)); - - print_espstats(&espstat); -} - -static void -print_ipcompstats(const struct ipcompstat *ipcompstat) -{ - uint32_t version; -#define p32(f, m) if (ipcompstat->f || sflag <= 1) \ - printf("\t%u" m, (unsigned int)ipcompstat->f, plural(ipcompstat->f)) -#define p64(f, m) if (ipcompstat->f || sflag <= 1) \ - printf("\t%ju" m, (uintmax_t)ipcompstat->f, plural(ipcompstat->f)) -#define hist(f, n, t) \ - ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t)); - -#ifndef IPCOMPSTAT_VERSION - version = 0; -#else - version = ipcompstat->version; -#endif - p32(ipcomps_hdrops, " packet%s shorter than header shows\n"); - p32(ipcomps_nopf, " packet%s dropped; protocol family not supported\n"); - p32(ipcomps_notdb, " packet%s dropped; no TDB\n"); - p32(ipcomps_badkcr, " packet%s dropped; bad KCR\n"); - p32(ipcomps_qfull, " packet%s dropped; queue full\n"); - p32(ipcomps_noxform, " packet%s dropped; no transform\n"); - p32(ipcomps_wrap, " replay counter wrap%s\n"); - p32(ipcomps_input, " packet%s in\n"); - p32(ipcomps_output, " packet%s out\n"); - p32(ipcomps_invalid, " packet%s dropped; invalid TDB\n"); - p64(ipcomps_ibytes, " byte%s in\n"); - p64(ipcomps_obytes, " byte%s out\n"); - p32(ipcomps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); - p32(ipcomps_pdrops, " packet%s blocked due to policy\n"); - p32(ipcomps_crypto, " crypto processing failure%s\n"); - hist(ipcompstat->ipcomps_hist, ipsec_compnames, "COMP output"); - if (version >= 1) { - p32(ipcomps_threshold, " packet%s sent uncompressed; size < compr. algo. threshold\n"); - p32(ipcomps_uncompr, " packet%s sent uncompressed; compression was useless\n"); + s = netstat_get_ipcompstats(sttp); +#define p32(f, m) if (netstat_ipcomps_get_##f(s) || sflag <= 1) \ + printf("\t%u" m, netstat_ipcomps_get_##f(s), plural(netstat_ipcomps_get_##f(s))) +#define p64(f, m) if (netstat_ipcomps_get_##f(s) || sflag <= 1) \ + printf("\t%ju" m, netstat_ipcomps_get_##f(s), plural(netstat_ipcomps_get_##f(s))) + p32(hdrops, " packet%s shorter than header shows\n"); + p32(nopf, " packet%s dropped; protocol family not supported\n"); + p32(notdb, " packet%s dropped; no TDB\n"); + p32(badkcr, " packet%s dropped; bad KCR\n"); + p32(qfull, " packet%s dropped; queue full\n"); + p32(noxform, " packet%s dropped; no transform\n"); + p32(wrap, " replay counter wrap%s\n"); + p32(input, " packet%s in\n"); + p32(output, " packet%s out\n"); + p32(invalid, " packet%s dropped; invalid TDB\n"); + p64(ibytes, " byte%s in\n"); + p64(obytes, " byte%s out\n"); + p32(toobig, " packet%s dropped; larger than IP_MAXPACKET\n"); + p32(pdrops, " packet%s blocked due to policy\n"); + p32(crypto, " crypto processing failure%s\n"); + first = 1; + for (proto = 0; proto < NETSTAT_IPCOMP_HIST_MAX; proto++) { + if (netstat_ipcomps_get_hist(s, proto) == 0) + continue; + if (first != 0) { + printf("\tCOMP output histogram:\n"); + first = 0; + } + printf("\t\t%s: %u\n", netstat_ipsec_ipcompname(proto), + netstat_ipcomps_get_hist(s, proto)); } - + + if (netstat_ipcomps_get_version(s) >= 1) { + p32(threshold, " packet%s sent uncompressed; size < compr. algo. threshold\n"); + p32(uncompr, " packet%s sent uncompressed; compression was useless\n"); + } #undef p32 #undef p64 -#undef hist } - -void -ipcomp_stats(u_long off, const char *name, int family __unused, - int proto __unused) -{ - struct ipcompstat ipcompstat; - - if (off == 0) - return; - printf ("%s:\n", name); - kread(off, (char *)&ipcompstat, sizeof(ipcompstat)); - - print_ipcompstats(&ipcompstat); -} - -#endif /*IPSEC*/ Index: usr.bin/netstat/netisr.c =================================================================== --- usr.bin/netstat/netisr.c (revision 209358) +++ usr.bin/netstat/netisr.c (working copy) @@ -48,6 +48,7 @@ #include #include +#include "extern.h" #include "netstat.h" /* Index: usr.bin/netstat/bpf.c =================================================================== --- usr.bin/netstat/bpf.c (revision 209358) +++ usr.bin/netstat/bpf.c (working copy) @@ -1,5 +1,6 @@ /*- * Copyright (c) 2005 Christian S.J. Peron + * Copyright (c) 2009 Gabor Pali * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,115 +29,80 @@ __FBSDID("$FreeBSD$"); #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include -#include -#include +#include #include #include -#include -#include +#include +#include "extern.h" -#include "netstat.h" - -/* print bpf stats */ - -static char * -bpf_pidname(pid_t pid) -{ - struct kinfo_proc newkp; - int error, mib[4]; - size_t size; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - size = sizeof(newkp); - error = sysctl(mib, 4, &newkp, &size, NULL, 0); - if (error < 0) { - warn("kern.proc.pid failed"); - return (strdup("??????")); - } - return (strdup(newkp.ki_comm)); -} - +/* FIXME: zerostat support */ static void -bpf_flags(struct xbpf_d *bd, char *flagbuf) +bpf_flags(const struct bpf_type *btp, char *flagbuf) { + int flags; - *flagbuf++ = bd->bd_promisc ? 'p' : '-'; - *flagbuf++ = bd->bd_immediate ? 'i' : '-'; - *flagbuf++ = bd->bd_hdrcmplt ? '-' : 'f'; - *flagbuf++ = (bd->bd_direction == BPF_D_IN) ? '-' : - ((bd->bd_direction == BPF_D_OUT) ? 'o' : 's'); - *flagbuf++ = bd->bd_feedback ? 'b' : '-'; - *flagbuf++ = bd->bd_async ? 'a' : '-'; - *flagbuf++ = bd->bd_locked ? 'l' : '-'; + flags = netstat_bpt_get_flags(btp); + *flagbuf++ = flags & NETSTAT_BPF_PROMISC ? 'p' : '-'; + *flagbuf++ = flags & NETSTAT_BPF_IMMEDIATE ? 'i' : '-'; + *flagbuf++ = flags & NETSTAT_BPF_HDRCMPLT ? '-' : 'f'; + *flagbuf++ = (netstat_bpt_get_direction(btp) == bpfdir_In) ? '-' : + ((netstat_bpt_get_direction(btp) == bpfdir_Out) ? 'o' : 's'); + *flagbuf++ = flags & NETSTAT_BPF_FEEDBACK ? 'b' : '-'; + *flagbuf++ = flags & NETSTAT_BPF_ASYNC ? 'a' : '-'; + *flagbuf++ = flags & NETSTAT_BPF_LOCKED ? 'l' : '-'; *flagbuf++ = '\0'; } +/* print bpf stats */ void -bpf_stats(char *ifname) +bpf_stats(const struct session_type *session, char *ifname) { - struct xbpf_d *d, *bd, zerostat; - char *pname, flagbuf[12]; - size_t size; + struct bpf_type_list *bptlp; + struct bpf_type_iterator *bptip = NULL; - if (zflag) { - bzero(&zerostat, sizeof(zerostat)); - if (sysctlbyname("net.bpf.stats", NULL, NULL, - &zerostat, sizeof(zerostat)) < 0) - warn("failed to zero bpf counters"); + const struct bpf_type *bptp; + + int error; + char flagbuf[12]; + + bptlp = netstat_bptl_alloc(); + if (bptlp == NULL) { + warn("netstat_btl_alloc()"); return; } - if (sysctlbyname("net.bpf.stats", NULL, &size, - NULL, 0) < 0) { - warn("net.bpf.stats"); - return; + + if (netstat_bpf(session, ifname, bptlp, 0)) { + error = netstat_bptl_geterror(bptlp); + if (error == NETSTAT_ERROR_KVM) { + warnx("netstat_bpf: %s", netstat_kvmerror(session)); + } else { + warnx("netstat_bpf: %s", netstat_strerror(error)); + } + goto out; } - if (size == 0) - return; - bd = malloc(size); - if (bd == NULL) { - warn("malloc failed"); - return; + + if (netstat_bpti_alloc(bptlp, &bptip) < 0) { + warn("netstat_bti_alloc()"); + goto out; } - if (sysctlbyname("net.bpf.stats", bd, &size, - NULL, 0) < 0) { - warn("net.bpf.stats"); - free(bd); - return; - } + (void) printf("%5s %6s %7s %9s %9s %9s %5s %5s %s\n", "Pid", "Netif", "Flags", "Recv", "Drop", "Match", "Sblen", "Hblen", "Command"); - for (d = &bd[0]; d < &bd[size / sizeof(*d)]; d++) { - if (d->bd_structsize != sizeof(*d)) { - warnx("bpf_stats_extended: version mismatch"); - return; - } - if (ifname && strcmp(ifname, d->bd_ifname) != 0) - continue; - bpf_flags(d, flagbuf); - pname = bpf_pidname(d->bd_pid); - (void) printf("%5d %6s %7s %9ju %9ju %9ju %5d %5d %s\n", - d->bd_pid, d->bd_ifname, flagbuf, - d->bd_rcount, d->bd_dcount, d->bd_fcount, - d->bd_slen, d->bd_hlen, pname); - free(pname); + for (bptp = netstat_bpti_first(bptip); bptp != NULL; + bptp = netstat_bpti_next(bptip)) { + bpf_flags(bptp, flagbuf); + (void) printf("%5d %6s %7s %9ju %9ju %9ju %5ju %5ju %s\n", + netstat_bpt_get_pid(bptp), netstat_bpt_get_ifname(bptp), + flagbuf, netstat_bpt_get_recv(bptp), + netstat_bpt_get_drop(bptp), netstat_bpt_get_match(bptp), + netstat_bpt_get_slen(bptp), netstat_bpt_get_hlen(bptp), + netstat_bpt_get_pidname(bptp)); } - free(bd); +out: + if (bptip != NULL) + netstat_bpti_free(bptip); + netstat_bptl_free(bptlp); } Index: usr.bin/netstat/netgraph.c =================================================================== --- usr.bin/netstat/netgraph.c (revision 209358) +++ usr.bin/netstat/netgraph.c (working copy) @@ -56,7 +56,7 @@ #include #include #include -#include "netstat.h" +#include "extern.h" static int first = 1; static int csock = -1; Index: usr.bin/netstat/sctp.c =================================================================== --- usr.bin/netstat/sctp.c (revision 209358) +++ usr.bin/netstat/sctp.c (working copy) @@ -59,7 +59,7 @@ #include #include #include -#include "netstat.h" +#include "extern.h" #ifdef SCTP @@ -510,179 +510,159 @@ * Dump SCTP statistics structure. */ void -sctp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +sctp_stats(const struct stat_type *sttp) { - struct sctpstat sctpstat, zerostat; - size_t len = sizeof(sctpstat); + const struct sctp_stat *s; - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.sctp.stats", &sctpstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - warn("sysctl: net.inet.sctp.stats"); - return; - } - } else - kread(off, &sctpstat, len); - - printf ("%s:\n", name); - -#define p(f, m) if (sctpstat.f || sflag <= 1) \ - printf(m, (uintmax_t)sctpstat.f, plural(sctpstat.f)) -#define p1a(f, m) if (sctpstat.f || sflag <= 1) \ - printf(m, (uintmax_t)sctpstat.f) - + s = netstat_get_sctpstats(sttp); +#define p(f, m) if (netstat_sctps_get_##f(s) || sflag <= 1) \ + printf(m, (uintmax_t)netstat_sctps_get_##f(s), plural(netstat_sctps_get_##f(s))) +#define p1a(f, m) if (netstat_sctps_get_##f(s) || sflag <= 1) \ + printf(m, (uintmax_t)netstat_sctps_get_##f(s)) /* * input statistics */ - p(sctps_recvpackets, "\t%ju input packet%s\n"); - p(sctps_recvdatagrams, "\t\t%ju datagram%s\n"); - p(sctps_recvpktwithdata, "\t\t%ju packet%s that had data\n"); - p(sctps_recvsacks, "\t\t%ju input SACK chunk%s\n"); - p(sctps_recvdata, "\t\t%ju input DATA chunk%s\n"); - p(sctps_recvdupdata, "\t\t%ju duplicate DATA chunk%s\n"); - p(sctps_recvheartbeat, "\t\t%ju input HB chunk%s\n"); - p(sctps_recvheartbeatack, "\t\t%ju HB-ACK chunk%s\n"); - p(sctps_recvecne, "\t\t%ju input ECNE chunk%s\n"); - p(sctps_recvauth, "\t\t%ju input AUTH chunk%s\n"); - p(sctps_recvauthmissing, "\t\t%ju chunk%s missing AUTH\n"); - p(sctps_recvivalhmacid, "\t\t%ju invalid HMAC id%s received\n"); - p(sctps_recvivalkeyid, "\t\t%ju invalid secret id%s received\n"); - p1a(sctps_recvauthfailed, "\t\t%ju auth failed\n"); - p1a(sctps_recvexpress, "\t\t%ju fast path receives all one chunk\n"); - p1a(sctps_recvexpressm, "\t\t%ju fast path multi-part data\n"); - + p(recvpackets, "\t%ju input packet%s\n"); + p(recvdatagrams, "\t\t%ju datagram%s\n"); + p(recvpktwithdata, "\t\t%ju packet%s that had data\n"); + p(recvsacks, "\t\t%ju input SACK chunk%s\n"); + p(recvdata, "\t\t%ju input DATA chunk%s\n"); + p(recvdupdata, "\t\t%ju duplicate DATA chunk%s\n"); + p(recvheartbeat, "\t\t%ju input HB chunk%s\n"); + p(recvheartbeatack, "\t\t%ju HB-ACK chunk%s\n"); + p(recvecne, "\t\t%ju input ECNE chunk%s\n"); + p(recvauth, "\t\t%ju input AUTH chunk%s\n"); + p(recvauthmissing, "\t\t%ju chunk%s missing AUTH\n"); + p(recvivalhmacid, "\t\t%ju invalid HMAC id%s received\n"); + p(recvivalkeyid, "\t\t%ju invalid secret id%s received\n"); + p1a(recvauthfailed, "\t\t%ju auth failed\n"); + p1a(recvexpress, "\t\t%ju fast path receives all one chunk\n"); + p1a(recvexpressm, "\t\t%ju fast path multi-part data\n"); /* * output statistics */ - p(sctps_sendpackets, "\t%ju output packet%s\n"); - p(sctps_sendsacks, "\t\t%ju output SACK%s\n"); - p(sctps_senddata, "\t\t%ju output DATA chunk%s\n"); - p(sctps_sendretransdata, "\t\t%ju retransmitted DATA chunk%s\n"); - p(sctps_sendfastretrans, "\t\t%ju fast retransmitted DATA chunk%s\n"); - p(sctps_sendmultfastretrans, "\t\t%ju FR'%s that happened more " + p(sendpackets, "\t%ju output packet%s\n"); + p(sendsacks, "\t\t%ju output SACK%s\n"); + p(senddata, "\t\t%ju output DATA chunk%s\n"); + p(sendretransdata, "\t\t%ju retransmitted DATA chunk%s\n"); + p(sendfastretrans, "\t\t%ju fast retransmitted DATA chunk%s\n"); + p(sendmultfastretrans, "\t\t%ju FR'%s that happened more " "than once to same chunk\n"); - p(sctps_sendheartbeat, "\t\t%ju intput HB chunk%s\n"); - p(sctps_sendecne, "\t\t%ju output ECNE chunk%s\n"); - p(sctps_sendauth, "\t\t%ju output AUTH chunk%s\n"); - p1a(sctps_senderrors, "\t\t%ju ip_output error counter\n"); - + p(sendheartbeat, "\t\t%ju intput HB chunk%s\n"); + p(sendecne, "\t\t%ju output ECNE chunk%s\n"); + p(sendauth, "\t\t%ju output AUTH chunk%s\n"); + p1a(senderrors, "\t\t%ju ip_output error counter\n"); /* * PCKDROPREP statistics */ printf("\tPacket drop statistics:\n"); - p1a(sctps_pdrpfmbox, "\t\t%ju from middle box\n"); - p1a(sctps_pdrpfehos, "\t\t%ju from end host\n"); - p1a(sctps_pdrpmbda, "\t\t%ju with data\n"); - p1a(sctps_pdrpmbct, "\t\t%ju non-data, non-endhost\n"); - p1a(sctps_pdrpbwrpt, "\t\t%ju non-endhost, bandwidth rep only\n"); - p1a(sctps_pdrpcrupt, "\t\t%ju not enough for chunk header\n"); - p1a(sctps_pdrpnedat, "\t\t%ju not enough data to confirm\n"); - p1a(sctps_pdrppdbrk, "\t\t%ju where process_chunk_drop said break\n"); - p1a(sctps_pdrptsnnf, "\t\t%ju failed to find TSN\n"); - p1a(sctps_pdrpdnfnd, "\t\t%ju attempt reverse TSN lookup\n"); - p1a(sctps_pdrpdiwnp, "\t\t%ju e-host confirms zero-rwnd\n"); - p1a(sctps_pdrpdizrw, "\t\t%ju midbox confirms no space\n"); - p1a(sctps_pdrpbadd, "\t\t%ju data did not match TSN\n"); - p(sctps_pdrpmark, "\t\t%ju TSN'%s marked for Fast Retran\n"); - + p1a(pdrpfmbox, "\t\t%ju from middle box\n"); + p1a(pdrpfehos, "\t\t%ju from end host\n"); + p1a(pdrpmbda, "\t\t%ju with data\n"); + p1a(pdrpmbct, "\t\t%ju non-data, non-endhost\n"); + p1a(pdrpbwrpt, "\t\t%ju non-endhost, bandwidth rep only\n"); + p1a(pdrpcrupt, "\t\t%ju not enough for chunk header\n"); + p1a(pdrpnedat, "\t\t%ju not enough data to confirm\n"); + p1a(pdrppdbrk, "\t\t%ju where process_chunk_drop said break\n"); + p1a(pdrptsnnf, "\t\t%ju failed to find TSN\n"); + p1a(pdrpdnfnd, "\t\t%ju attempt reverse TSN lookup\n"); + p1a(pdrpdiwnp, "\t\t%ju e-host confirms zero-rwnd\n"); + p1a(pdrpdizrw, "\t\t%ju midbox confirms no space\n"); + p1a(pdrpbadd, "\t\t%ju data did not match TSN\n"); + p(pdrpmark, "\t\t%ju TSN'%s marked for Fast Retran\n"); /* * Timeouts */ printf("\tTimeouts:\n"); - p(sctps_timoiterator, "\t\t%ju iterator timer%s fired\n"); - p(sctps_timodata, "\t\t%ju T3 data time out%s\n"); - p(sctps_timowindowprobe, "\t\t%ju window probe (T3) timer%s fired\n"); - p(sctps_timoinit, "\t\t%ju INIT timer%s fired\n"); - p(sctps_timosack, "\t\t%ju sack timer%s fired\n"); - p(sctps_timoshutdown, "\t\t%ju shutdown timer%s fired\n"); - p(sctps_timoheartbeat, "\t\t%ju heartbeat timer%s fired\n"); - p1a(sctps_timocookie, "\t\t%ju a cookie timeout fired\n"); - p1a(sctps_timosecret, "\t\t%ju an endpoint changed its cookie" + p(timoiterator, "\t\t%ju iterator timer%s fired\n"); + p(timodata, "\t\t%ju T3 data time out%s\n"); + p(timowindowprobe, "\t\t%ju window probe (T3) timer%s fired\n"); + p(timoinit, "\t\t%ju INIT timer%s fired\n"); + p(timosack, "\t\t%ju sack timer%s fired\n"); + p(timoshutdown, "\t\t%ju shutdown timer%s fired\n"); + p(timoheartbeat, "\t\t%ju heartbeat timer%s fired\n"); + p1a(timocookie, "\t\t%ju a cookie timeout fired\n"); + p1a(timosecret, "\t\t%ju an endpoint changed its cookie" "secret\n"); - p(sctps_timopathmtu, "\t\t%ju PMTU timer%s fired\n"); - p(sctps_timoshutdownack, "\t\t%ju shutdown ack timer%s fired\n"); - p(sctps_timoshutdownguard, "\t\t%ju shutdown guard timer%s fired\n"); - p(sctps_timostrmrst, "\t\t%ju stream reset timer%s fired\n"); - p(sctps_timoearlyfr, "\t\t%ju early FR timer%s fired\n"); - p1a(sctps_timoasconf, "\t\t%ju an asconf timer fired\n"); - p1a(sctps_timoautoclose, "\t\t%ju auto close timer fired\n"); - p(sctps_timoassockill, "\t\t%ju asoc free timer%s expired\n"); - p(sctps_timoinpkill, "\t\t%ju inp free timer%s expired\n"); - + p(timopathmtu, "\t\t%ju PMTU timer%s fired\n"); + p(timoshutdownack, "\t\t%ju shutdown ack timer%s fired\n"); + p(timoshutdownguard, "\t\t%ju shutdown guard timer%s fired\n"); + p(timostrmrst, "\t\t%ju stream reset timer%s fired\n"); + p(timoearlyfr, "\t\t%ju early FR timer%s fired\n"); + p1a(timoasconf, "\t\t%ju an asconf timer fired\n"); + p1a(timoautoclose, "\t\t%ju auto close timer fired\n"); + p(timoassockill, "\t\t%ju asoc free timer%s expired\n"); + p(timoinpkill, "\t\t%ju inp free timer%s expired\n"); #if 0 /* * Early fast retransmission counters */ - p(sctps_earlyfrstart, "\t%ju TODO:sctps_earlyfrstart\n"); - p(sctps_earlyfrstop, "\t%ju TODO:sctps_earlyfrstop\n"); - p(sctps_earlyfrmrkretrans, "\t%ju TODO:sctps_earlyfrmrkretrans\n"); - p(sctps_earlyfrstpout, "\t%ju TODO:sctps_earlyfrstpout\n"); - p(sctps_earlyfrstpidsck1, "\t%ju TODO:sctps_earlyfrstpidsck1\n"); - p(sctps_earlyfrstpidsck2, "\t%ju TODO:sctps_earlyfrstpidsck2\n"); - p(sctps_earlyfrstpidsck3, "\t%ju TODO:sctps_earlyfrstpidsck3\n"); - p(sctps_earlyfrstpidsck4, "\t%ju TODO:sctps_earlyfrstpidsck4\n"); - p(sctps_earlyfrstrid, "\t%ju TODO:sctps_earlyfrstrid\n"); - p(sctps_earlyfrstrout, "\t%ju TODO:sctps_earlyfrstrout\n"); - p(sctps_earlyfrstrtmr, "\t%ju TODO:sctps_earlyfrstrtmr\n"); + p(earlyfrstart, "\t%ju TODO:sctps_earlyfrstart\n"); + p(earlyfrstop, "\t%ju TODO:sctps_earlyfrstop\n"); + p(earlyfrmrkretrans, "\t%ju TODO:sctps_earlyfrmrkretrans\n"); + p(earlyfrstpout, "\t%ju TODO:sctps_earlyfrstpout\n"); + p(earlyfrstpidsck1, "\t%ju TODO:sctps_earlyfrstpidsck1\n"); + p(earlyfrstpidsck2, "\t%ju TODO:sctps_earlyfrstpidsck2\n"); + p(earlyfrstpidsck3, "\t%ju TODO:sctps_earlyfrstpidsck3\n"); + p(earlyfrstpidsck4, "\t%ju TODO:sctps_earlyfrstpidsck4\n"); + p(earlyfrstrid, "\t%ju TODO:sctps_earlyfrstrid\n"); + p(earlyfrstrout, "\t%ju TODO:sctps_earlyfrstrout\n"); + p(earlyfrstrtmr, "\t%ju TODO:sctps_earlyfrstrtmr\n"); #endif - /* * Others */ - p1a(sctps_hdrops, "\t%ju packet shorter than header\n"); - p1a(sctps_badsum, "\t%ju checksum error\n"); - p1a(sctps_noport, "\t%ju no endpoint for port\n"); - p1a(sctps_badvtag, "\t%ju bad v-tag\n"); - p1a(sctps_badsid, "\t%ju bad SID\n"); - p1a(sctps_nomem, "\t%ju no memory\n"); - p1a(sctps_fastretransinrtt, "\t%ju number of multiple FR in a RTT " + p1a(hdrops, "\t%ju packet shorter than header\n"); + p1a(badsum, "\t%ju checksum error\n"); + p1a(noport, "\t%ju no endpoint for port\n"); + p1a(badvtag, "\t%ju bad v-tag\n"); + p1a(badsid, "\t%ju bad SID\n"); + p1a(nomem, "\t%ju no memory\n"); + p1a(fastretransinrtt, "\t%ju number of multiple FR in a RTT " "window\n"); #if 0 - p(sctps_markedretrans, "\t%ju TODO:sctps_markedretrans\n"); + p(markedretrans, "\t%ju TODO:sctps_markedretrans\n"); #endif - p1a(sctps_naglesent, "\t%ju RFC813 allowed sending\n"); - p1a(sctps_naglequeued, "\t%ju RFC813 does not allow sending\n"); - p1a(sctps_maxburstqueued, "\t%ju times max burst prohibited sending\n"); - p1a(sctps_ifnomemqueued, "\t%ju look ahead tells us no memory in " + p1a(naglesent, "\t%ju RFC813 allowed sending\n"); + p1a(naglequeued, "\t%ju RFC813 does not allow sending\n"); + p1a(maxburstqueued, "\t%ju times max burst prohibited sending\n"); + p1a(ifnomemqueued, "\t%ju look ahead tells us no memory in " "interface\n"); - p(sctps_windowprobed, "\t%ju number%s of window probes sent\n"); - p(sctps_lowlevelerr, "\t%ju time%s an output error to clamp " + p(windowprobed, "\t%ju number%s of window probes sent\n"); + p(lowlevelerr, "\t%ju time%s an output error to clamp " "down on next user send\n"); - p(sctps_lowlevelerrusr, "\t%ju time%s sctp_senderrors were " + p(lowlevelerrusr, "\t%ju time%s sctp_senderrors were " "caused from a user\n"); - p(sctps_datadropchklmt, "\t%ju number of in data drop%s due to " + p(datadropchklmt, "\t%ju number of in data drop%s due to " "chunk limit reached\n"); - p(sctps_datadroprwnd, "\t%ju number of in data drop%s due to rwnd " + p(datadroprwnd, "\t%ju number of in data drop%s due to rwnd " "limit reached\n"); - p(sctps_ecnereducedcwnd, "\t%ju time%s a ECN reduced " + p(ecnereducedcwnd, "\t%ju time%s a ECN reduced " "the cwnd\n"); - p1a(sctps_vtagexpress, "\t%ju used express lookup via vtag\n"); - p1a(sctps_vtagbogus, "\t%ju collision in express lookup\n"); - p(sctps_primary_randry, "\t%ju time%s the sender ran dry " + p1a(vtagexpress, "\t%ju used express lookup via vtag\n"); + p1a(vtagbogus, "\t%ju collision in express lookup\n"); + p(primary_randry, "\t%ju time%s the sender ran dry " "of user data on primary\n"); - p1a(sctps_cmt_randry, "\t%ju same for above\n"); - p(sctps_slowpath_sack, "\t%ju sack%s the slow way\n"); - p(sctps_wu_sacks_sent, "\t%ju window update only sack%s sent\n"); - p(sctps_sends_with_flags, "\t%ju send%s with sinfo_flags !=0\n"); - p(sctps_sends_with_unord, "\t%ju unordered send%s\n"); - p(sctps_sends_with_eof, "\t%ju send%s with EOF flag set\n"); - p(sctps_sends_with_abort, "\t%ju send%s with ABORT flag set\n"); - p(sctps_protocol_drain_calls, "\t%ju time%s protocol drain called\n"); - p(sctps_protocol_drains_done, "\t%ju time%s we did a protocol " + p1a(cmt_randry, "\t%ju same for above\n"); + p(slowpath_sack, "\t%ju sack%s the slow way\n"); + p(wu_sacks_sent, "\t%ju window update only sack%s sent\n"); + p(sends_with_flags, "\t%ju send%s with sinfo_flags !=0\n"); + p(sends_with_unord, "\t%ju unordered send%s\n"); + p(sends_with_eof, "\t%ju send%s with EOF flag set\n"); + p(sends_with_abort, "\t%ju send%s with ABORT flag set\n"); + p(protocol_drain_calls, "\t%ju time%s protocol drain called\n"); + p(protocol_drains_done, "\t%ju time%s we did a protocol " "drain\n"); - p(sctps_read_peeks, "\t%ju time%s recv was called with peek\n"); - p(sctps_cached_chk, "\t%ju cached chunk%s used\n"); - p1a(sctps_cached_strmoq, "\t%ju cached stream oq's used\n"); - p(sctps_left_abandon, "\t%ju unread message%s abandonded by close\n"); - p1a(sctps_send_burst_avoid, "\t%ju send burst avoidance, already " + p(read_peeks, "\t%ju time%s recv was called with peek\n"); + p(cached_chk, "\t%ju cached chunk%s used\n"); + p1a(cached_strmoq, "\t%ju cached stream oq's used\n"); + p(left_abandon, "\t%ju unread message%s abandonded by close\n"); + p1a(send_burst_avoid, "\t%ju send burst avoidance, already " "max burst inflight to net\n"); - p1a(sctps_send_cwnd_avoid, "\t%ju send cwnd full avoidance, already " + p1a(send_cwnd_avoid, "\t%ju send cwnd full avoidance, already " "max burst inflight to net\n"); - p(sctps_fwdtsn_map_over, "\t%ju number of map array over-run%s via " + p(fwdtsn_map_over, "\t%ju number of map array over-run%s via " "fwd-tsn's\n"); - #undef p #undef p1a } Index: usr.bin/netstat/extern.h =================================================================== --- usr.bin/netstat/extern.h (revision 209358) +++ usr.bin/netstat/extern.h (working copy) @@ -35,6 +35,9 @@ */ #include +#include +#include +#include extern int Aflag; /* show addresses of protocol control block */ extern int aflag; /* show all sockets (including servers) */ @@ -50,6 +53,7 @@ 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 i/f watchdog timers */ extern int Wflag; /* wide display */ extern int xflag; /* extended display, includes all socket buffer info */ extern int zflag; /* zero stats */ @@ -67,40 +71,39 @@ 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); +void inetpr(const struct session_type *, int, int); +void inetppr(const struct socket_type *); +void unixdomainpr(const struct socket_type *); +void tcp_stats(const struct stat_type *); +void udp_stats(const struct stat_type *); #ifdef SCTP void sctp_protopr(u_long, const char *, int, int); -void sctp_stats(u_long, const char *, int, int); +void sctp_stats(const struct stat_type *); #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); +void ip_stats(const struct stat_type *); +void icmp_stats(const struct stat_type *); +void igmp_stats(const struct stat_type *); +void pim_stats(const struct stat_type *); +void carp_stats(const struct stat_type *); +void pfsync_stats(const struct stat_type *); #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); +void ipsec_stats(const struct stat_type *); +void esp_stats(const struct stat_type *); +void ah_stats(const struct stat_type *); +void ipcomp_stats(const struct stat_type *); +void pfkey_stats(const struct stat_type *); #endif #ifdef INET6 -void ip6_stats(u_long, const char *, int, int); +void ip6_stats(const struct stat_type *); void ip6_ifstats(char *); -void icmp6_stats(u_long, const char *, int, int); +void icmp6_stats(const struct stat_type *); 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); +void pim6_stats(const struct stat_type *); +void rip6_stats(const struct stat_type *); +void mroute6pr(const struct session_type *); +void mrt6_stats(const struct stat_type *); struct sockaddr_in6; struct in6_addr; @@ -109,22 +112,18 @@ 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(const struct session_type *); -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(const struct session_type *, int, void (*)(char *)); void pr_rthdr(int); void pr_family(int); -void rt_stats(u_long, u_long); +void rt_stats(const struct stat_type *); char *ipx_pnet(struct sockaddr *); char *ipx_phost(struct sockaddr *); char *ns_phost(struct sockaddr *); @@ -136,11 +135,11 @@ char *atalk_print2(struct sockaddr *, struct sockaddr *, int); char *ipx_print(struct sockaddr *); char *ns_print(struct sockaddr *); -void routepr(u_long); +void routepr(const struct session_type *, 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 spx_stats(const struct stat_type *); +void ipx_stats(const struct stat_type *); void ipxerr_stats(u_long, const char *, int, int); void nsprotopr(u_long, const char *, int, int); @@ -149,13 +148,13 @@ 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); +void ddp_stats(const struct stat_type *); #ifdef NETGRAPH void netgraphprotopr(u_long, const char *, int, int); #endif -void unixpr(u_long, u_long, u_long, u_long, u_long); +void unixpr(const struct session_type *); void esis_stats(u_long, const char *, int, int); void clnp_stats(u_long, const char *, int, int); @@ -166,6 +165,6 @@ 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 *); +void mroutepr(const struct session_type *); +void mrt_stats(const struct stat_type *); +void bpf_stats(const struct session_type *, char *); Index: usr.bin/netstat/mroute.c =================================================================== --- usr.bin/netstat/mroute.c (revision 209358) +++ usr.bin/netstat/mroute.c (working copy) @@ -68,9 +68,130 @@ #include #include #include -#include "netstat.h" +#include +#include "extern.h" +#define USE_LIBNETSTAT + +#ifdef USE_LIBNETSTAT +void +mroutepr(const struct session_type *session) +{ + int vifi, maxvif; + int error; + + struct mcastif_type_list *mitlp; + struct mcastif_type_iterator *mitip; + struct mroute_type_list *mrtlp; + struct mroute_type_iterator *mrtip; + + const struct mcastif_type *mitp; + const struct mroute_type *mrtp; + const struct routeaddr_type *addr; + + mitlp = netstat_mitl_alloc(); + if (mitlp == NULL) { + warn("netstat_mitl_alloc()"); + return; + } + + if (netstat_mif(session, PF_INET, mitlp, 0)) { + error = netstat_mitl_geterror(mitlp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_mif: %s", netstat_kvmerror(session)); + else + warnx("netstat_mif: %s", netstat_strerror(error)); + goto out; + } + + + maxvif = 0; + + if (netstat_mitl_length(mitlp) > 0) { + printf("\nIPv4 Virtual Interface Table\n" + " Vif Thresh Local-Address " + "Remote-Address Pkts-In Pkts-Out\n"); + } else { + printf("\nIPv4 Virtual Interface Table is empty\n"); + printf("\n"); + goto out; + } + + if (netstat_miti_alloc(mitlp, &mitip) < 0) { + warn("netstat_miti_alloc()"); + goto out; + } + + for (mitp = netstat_miti_first(mitip); mitp != NULL; + mitp = netstat_miti_next(mitip)) { + maxvif = netstat_mit_get_index(mitp); + addr = netstat_mit_get_address(mitp); + printf(" %2u %6u %-15.15s", + netstat_mit_get_index(mitp), + netstat_mit_get_limit(mitp), + netstat_rat_get_name(addr, 1)); + if (netstat_mit_get_flags(mitp) & NETSTAT_MIF_TUNNEL) { + addr = netstat_mit_get_remote_address(mitp); + printf(" %-15.15s", netstat_rat_get_name(addr, 1)); + } + printf(" %9ju %9ju\n", + netstat_mit_get_packets_in(mitp), + netstat_mit_get_packets_out(mitp)); + } + printf("\n"); + + mrtlp = netstat_mrtl_alloc(); + if (mrtlp == NULL) { + warn("netstat_mrtl_alloc()"); + goto out; + } + + if (netstat_mroute(session, PF_INET, mrtlp, 0)) { + error = netstat_mrtl_geterror(mrtlp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_mroute: %s", netstat_kvmerror(session)); + else + warnx("netstat_mroute: %s", netstat_strerror(error)); + goto out2; + } + + if (netstat_mrtl_length(mrtlp) > 0) { + printf("\nIPv4 Multicast Forwarding Table\n" + " Origin Group " + " Packets In-Vif Out-Vifs:Ttls\n"); + } else { + printf("\nIPv4 Multicast Forwarding Table is empty\n"); + printf("\n"); + goto out2; + } + + if (netstat_mrti_alloc(mrtlp, &mrtip) < 0) { + warn("netstat_mrti_alloc()"); + goto out2; + } + + for (mrtp = netstat_mrti_first(mrtip); mrtp != NULL; + mrtp = netstat_mrti_next(mrtip)) { + addr = netstat_mrt_get_origin(mrtp); + printf(" %-15.15s", netstat_rat_get_name(addr, 1)); + addr = netstat_mrt_get_group(mrtp); + printf(" %-15.15s", netstat_rat_get_name(addr, 1)); + printf(" %9ju", netstat_mrt_get_packets(mrtp)); + printf(" %3u ", netstat_mrt_get_parent(mrtp)); + for (vifi = 0; vifi <= maxvif; vifi++) + if (netstat_mrt_get_ttl(mrtp, vifi) > 0) + printf(" %u:%u", vifi, + netstat_mrt_get_ttl(mrtp, vifi)); + } + printf("\n"); + + netstat_mrti_free(mrtip); +out2: netstat_mrtl_free(mrtlp); + netstat_miti_free(mitip); +out: netstat_mitl_free(mitlp); +} +#else static void print_bw_meter(struct bw_meter *, int *); static void print_mfc(struct mfc *, int, int *); @@ -336,44 +457,31 @@ printf("\n"); numeric_addr = saved_numeric_addr; } +#endif /* !USE_LIBNETSTAT */ void -mrt_stats(u_long mstaddr) +mrt_stats(const struct stat_type *sttp) { - struct mrtstat mrtstat; - size_t len = sizeof mrtstat; + const struct mroute_stat *s; - if (live) { - if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, NULL, - 0) < 0) { - warn("sysctl: net.inet.ip.mrtstat"); - return; - } - } else - kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat)); - - printf("IPv4 multicast forwarding:\n"); - -#define p(f, m) if (mrtstat.f || sflag <= 1) \ - printf(m, mrtstat.f, plural(mrtstat.f)) -#define p2(f, m) if (mrtstat.f || sflag <= 1) \ - printf(m, mrtstat.f, plurales(mrtstat.f)) - - p(mrts_mfc_lookups, "\t%lu multicast forwarding cache lookup%s\n"); - p2(mrts_mfc_misses, "\t%lu multicast forwarding cache miss%s\n"); - p(mrts_upcalls, "\t%lu upcall%s to multicast routing daemon\n"); - p(mrts_upq_ovflw, "\t%lu upcall queue overflow%s\n"); - p(mrts_upq_sockfull, - "\t%lu upcall%s dropped due to full socket buffer\n"); - p(mrts_cache_cleanups, "\t%lu cache cleanup%s\n"); - p(mrts_no_route, "\t%lu datagram%s with no route for origin\n"); - p(mrts_bad_tunnel, "\t%lu datagram%s arrived with bad tunneling\n"); - p(mrts_cant_tunnel, "\t%lu datagram%s could not be tunneled\n"); - p(mrts_wrong_if, "\t%lu datagram%s arrived on wrong interface\n"); - p(mrts_drop_sel, "\t%lu datagram%s selectively dropped\n"); - p(mrts_q_overflow, "\t%lu datagram%s dropped due to queue overflow\n"); - p(mrts_pkt2large, "\t%lu datagram%s dropped for being too large\n"); - + s = netstat_get_mroutestats(sttp); +#define p(f, m) if (netstat_mroutes_get_##f(s) || sflag <= 1) \ + printf(m, netstat_mroutes_get_##f(s), plural(netstat_mroutes_get_##f(s))) +#define p2(f, m) if (netstat_mroutes_get_##f(s) || sflag <= 1) \ + printf(m, netstat_mroutes_get_##f(s), plurales(netstat_mroutes_get_##f(s))) + p(mfc_lookups, "\t%ju multicast forwarding cache lookup%s\n"); + p2(mfc_misses, "\t%ju multicast forwarding cache miss%s\n"); + p(upcalls, "\t%ju upcall%s to multicast routing daemon\n"); + p(upq_ovflw, "\t%ju upcall queue overflow%s\n"); + p(upq_sockfull, "\t%ju upcall%s dropped due to full socket buffer\n"); + p(cache_cleanups, "\t%ju cache cleanup%s\n"); + p(no_route, "\t%ju datagram%s with no route for origin\n"); + p(bad_tunnel, "\t%ju datagram%s arrived with bad tunneling\n"); + p(cant_tunnel, "\t%ju datagram%s could not be tunneled\n"); + p(wrong_if, "\t%ju datagram%s arrived on wrong interface\n"); + p(drop_sel, "\t%ju datagram%s selectively dropped\n"); + p(q_overflow, "\t%ju datagram%s dropped due to queue overflow\n"); + p(pkt2large, "\t%ju datagram%s dropped for being too large\n"); #undef p2 #undef p } Index: usr.bin/netstat/pfkey.c =================================================================== --- usr.bin/netstat/pfkey.c (revision 209358) +++ usr.bin/netstat/pfkey.c (working copy) @@ -2,6 +2,7 @@ /* $KAME: ipsec.c,v 1.25 2001/03/12 09:04:39 itojun Exp $ */ /*- * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * Copyright (c) 2009 Gabor Pali * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -70,78 +71,35 @@ #include __FBSDID("$FreeBSD$"); -#include -#include -#include -#include +#include -#include - -#ifdef IPSEC -#include -#endif - -#include #include -#include -#include -#include "netstat.h" +#include +#include "extern.h" -#ifdef IPSEC - -static const char *pfkey_msgtypenames[] = { - "reserved", "getspi", "update", "add", "delete", - "get", "acquire", "register", "expire", "flush", - "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd", - "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush", - "x_spdsetidx", "x_spdexpire", "x_spddelete2" -}; - -static const char *pfkey_msgtype_names (int); - - -static const char * -pfkey_msgtype_names(int x) -{ - const int max = - sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]); - static char buf[20]; - - if (x < max && pfkey_msgtypenames[x]) - return pfkey_msgtypenames[x]; - snprintf(buf, sizeof(buf), "#%d", x); - return buf; -} - void -pfkey_stats(u_long off, const char *name, int family __unused, - int proto __unused) +pfkey_stats(const struct stat_type *sttp) { - struct pfkeystat pfkeystat; + const struct pfkey_stat *s; unsigned first, type; - if (off == 0) - return; - printf ("%s:\n", name); - kread(off, (char *)&pfkeystat, sizeof(pfkeystat)); - -#define p(f, m) if (pfkeystat.f || sflag <= 1) \ - printf(m, (uintmax_t)pfkeystat.f, plural(pfkeystat.f)) - - /* userland -> kernel */ + s = netstat_get_pfkeystats(sttp); +#define p(f, m) if (netstat_pfkeys_get_##f(s) || sflag <= 1) \ + printf(m, netstat_pfkeys_get_##f(s), plural(netstat_pfkeys_get_##f(s))) +#define pa(f,i,m) if (netstat_pfkeys_get_##f(s,i) || sflag <= 1) \ + printf(m, netstat_pfkeys_get_##f(s,i), plural(netstat_pfkeys_get_##f(s,i))) p(out_total, "\t%ju request%s sent from userland\n"); p(out_bytes, "\t%ju byte%s sent from userland\n"); - for (first = 1, type = 0; - type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]); - type++) { - if (pfkeystat.out_msgtype[type] <= 0) + for (first = 1, type = 0; type < NETSTAT_PFKEY_OUT_MSGTYPE_MAX; + type++) { + if (netstat_pfkeys_get_out_msgtype(s, type) <= 0) continue; if (first) { printf("\thistogram by message type:\n"); first = 0; } - printf("\t\t%s: %ju\n", pfkey_msgtype_names(type), - (uintmax_t)pfkeystat.out_msgtype[type]); + printf("\t\t%s: %ju\n", netstat_pfkey_msgtype_name(type), + netstat_pfkeys_get_out_msgtype(s, type)); } p(out_invlen, "\t%ju message%s with invalid length field\n"); p(out_invver, "\t%ju message%s with invalid version field\n"); @@ -152,29 +110,26 @@ p(out_invexttype, "\t%ju message%s with invalid extension type\n"); p(out_invsatype, "\t%ju message%s with invalid sa type\n"); p(out_invaddr, "\t%ju message%s with invalid address extension\n"); - - /* kernel -> userland */ p(in_total, "\t%ju request%s sent to userland\n"); p(in_bytes, "\t%ju byte%s sent to userland\n"); - for (first = 1, type = 0; - type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]); - type++) { - if (pfkeystat.in_msgtype[type] <= 0) + for (first = 1, type = 0; type < NETSTAT_PFKEY_IN_MSGTYPE_MAX; + type++) { + if (netstat_pfkeys_get_in_msgtype(s, type) <= 0) continue; if (first) { printf("\thistogram by message type:\n"); first = 0; } - printf("\t\t%s: %ju\n", pfkey_msgtype_names(type), - (uintmax_t)pfkeystat.in_msgtype[type]); + printf("\t\t%s: %ju\n", netstat_pfkey_msgtype_name(type), + netstat_pfkeys_get_in_msgtype(s, type)); } - p(in_msgtarget[KEY_SENDUP_ONE], + pa(in_msgtarget,pfkey_Sendup_One, "\t%ju message%s toward single socket\n"); - p(in_msgtarget[KEY_SENDUP_ALL], + pa(in_msgtarget,pfkey_Sendup_All, "\t%ju message%s toward all sockets\n"); - p(in_msgtarget[KEY_SENDUP_REGISTERED], + pa(in_msgtarget,pfkey_Sendup_Registered, "\t%ju message%s toward registered sockets\n"); p(in_nomem, "\t%ju message%s with memory allocation failure\n"); #undef p +#undef pa } -#endif /* IPSEC */ Index: usr.bin/netstat/unix.c =================================================================== --- usr.bin/netstat/unix.c (revision 209358) +++ usr.bin/netstat/unix.c (working copy) @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2009 Gabor Pali * Copyright (c) 1983, 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -43,234 +44,76 @@ /* * Display protocol blocks in the unix domain. */ -#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" +#include "extern.h" -static void unixdomainpr(struct xunpcb *, struct xsocket *); +#define USE_ITERATOR_TYPE -static const char *const socktype[] = - { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" }; - -static int -pcblist_sysctl(int type, char **bufp) +void +unixpr(const struct session_type *session) { - char *buf; - size_t len; - char mibvar[sizeof "net.local.seqpacket.pcblist"]; + struct socket_type_list *stlp; + int error, st_flags; +#ifdef USE_ITERATOR_TYPE + struct socket_type_iterator *stip; + const struct socket_type *stp; +#endif - sprintf(mibvar, "net.local.%s.pcblist", socktype[type]); - - len = 0; - if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { - if (errno != ENOENT) - warn("sysctl: %s", mibvar); - return (-1); + stlp = netstat_stl_alloc(); + if (stlp == NULL) { + warn("netstat_stl_alloc"); + return; } - if ((buf = malloc(len)) == 0) { - warnx("malloc %lu bytes", (u_long)len); - return (-2); - } - if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { - warn("sysctl: %s", mibvar); - free(buf); - return (-2); - } - *bufp = buf; - return (0); -} -static int -pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp) -{ - struct unp_head head; - struct unpcb *unp, unp_conn; - u_char sun_len; - struct socket so; - struct xunpgen xug; - struct xunpcb xu; - unp_gen_t unp_gencnt; - u_int unp_count; - char *buf, *p; - size_t len; - - if (count_off == 0 || gencnt_off == 0) - return (-2); - if (head_off == 0) - return (-1); - kread(count_off, &unp_count, sizeof(unp_count)); - len = 2 * sizeof(xug) + (unp_count + unp_count / 8) * sizeof(xu); - if ((buf = malloc(len)) == 0) { - warnx("malloc %lu bytes", (u_long)len); - return (-2); + st_flags = 0; + /* Get all the local sockets, regardless their types. */ + if (netstat_socket(session, PF_LOCAL, 0, 0, stlp, st_flags) < 0) { + error = netstat_stl_geterror(stlp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_socket: %s", netstat_kvmerror(session)); + else + warnx("netstat_socket: %s", netstat_strerror(error)); + goto out; } - p = buf; -#define COPYOUT(obj, size) do { \ - if (len < (size)) { \ - warnx("buffer size exceeded"); \ - goto fail; \ - } \ - bcopy((obj), p, (size)); \ - len -= (size); \ - p += (size); \ -} while (0) - -#define KREAD(off, buf, len) do { \ - if (kread((uintptr_t)(off), (buf), (len)) != 0) \ - goto fail; \ -} while (0) - - /* Write out header. */ - kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt)); - xug.xug_len = sizeof xug; - xug.xug_count = unp_count; - xug.xug_gen = unp_gencnt; - xug.xug_sogen = 0; - COPYOUT(&xug, sizeof xug); - - /* Walk the PCB list. */ - xu.xu_len = sizeof xu; - KREAD(head_off, &head, sizeof(head)); - LIST_FOREACH(unp, &head, unp_link) { - xu.xu_unpp = unp; - KREAD(unp, &xu.xu_unp, sizeof (*unp)); - unp = &xu.xu_unp; - - if (unp->unp_gencnt > unp_gencnt) - continue; - if (unp->unp_addr != NULL) { - KREAD(unp->unp_addr, &sun_len, sizeof(sun_len)); - KREAD(unp->unp_addr, &xu.xu_addr, sun_len); - } - if (unp->unp_conn != NULL) { - KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn)); - if (unp_conn.unp_addr != NULL) { - KREAD(unp_conn.unp_addr, &sun_len, - sizeof(sun_len)); - KREAD(unp_conn.unp_addr, &xu.xu_caddr, sun_len); - } - } - KREAD(unp->unp_socket, &so, sizeof(so)); - if (sotoxsocket(&so, &xu.xu_socket) != 0) - goto fail; - COPYOUT(&xu, sizeof(xu)); + /* + * Display received data by iterating the socket_type_list. + * + * It should be guaranteed (by libnetstat) that only active PCBs are + * returned. + */ +#ifdef USE_ITERATOR_TYPE + if (netstat_sti_alloc(stlp, &stip) < 0) { + warnx("netstat_sti_alloc"); + goto out; } - - /* Reread the counts and write the footer. */ - kread(count_off, &unp_count, sizeof(unp_count)); - kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt)); - xug.xug_count = unp_count; - xug.xug_gen = unp_gencnt; - COPYOUT(&xug, sizeof xug); - - *bufp = buf; - return (0); - -fail: - free(buf); - return (-1); -#undef COPYOUT -#undef KREAD + for (stp = netstat_sti_first(stip); stp != NULL; + stp = netstat_sti_next(stip)) + unixdomainpr(stp); + netstat_sti_free(stip); +out: + netstat_stl_free(stlp); +#else + netstat_stl_iterate(stlp, unixdomainpr); +out: + netstat_stl_free(sltp); +#endif } void -unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off, - u_long sphead_off) +unixdomainpr(const struct socket_type *stp) { - char *buf; - int ret, type; - struct xsocket *so; - struct xunpgen *xug, *oxug; - struct xunpcb *xunp; - u_long head_off; - - for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) { - if (live) - ret = pcblist_sysctl(type, &buf); - else { - head_off = 0; - switch (type) { - case SOCK_STREAM: - head_off = shead_off; - break; - - case SOCK_DGRAM: - head_off = dhead_off; - break; - - case SOCK_SEQPACKET: - head_off = sphead_off; - break; - } - ret = pcblist_kvm(count_off, gencnt_off, head_off, - &buf); - } - if (ret == -1) - continue; - if (ret < 0) - return; - - oxug = xug = (struct xunpgen *)buf; - for (xug = (struct xunpgen *)((char *)xug + xug->xug_len); - xug->xug_len > sizeof(struct xunpgen); - xug = (struct xunpgen *)((char *)xug + xug->xug_len)) { - xunp = (struct xunpcb *)xug; - so = &xunp->xu_socket; - - /* Ignore PCBs which were freed during copyout. */ - if (xunp->xu_unp.unp_gencnt > oxug->xug_gen) - continue; - unixdomainpr(xunp, so); - } - if (xug != oxug && xug->xug_gen != oxug->xug_gen) { - if (oxug->xug_count > xug->xug_count) { - printf("Some %s sockets may have been deleted.\n", - socktype[type]); - } else if (oxug->xug_count < xug->xug_count) { - printf("Some %s sockets may have been created.\n", - socktype[type]); - } else { - printf("Some %s sockets may have been created or deleted", - socktype[type]); - } - } - free(buf); - } -} - -static void -unixdomainpr(struct xunpcb *xunp, struct xsocket *so) -{ - struct unpcb *unp; - struct sockaddr_un *sa; static int first = 1; char buf1[15]; + struct sockaddr_type *addr; - unp = &xunp->xu_unp; - if (unp->unp_addr) - sa = &xunp->xu_addr; - else - sa = (struct sockaddr_un *)0; - if (first && !Lflag) { printf("Active UNIX domain sockets\n"); printf( @@ -280,23 +123,26 @@ first = 0; } - if (Lflag && so->so_qlimit == 0) + if (Lflag && netstat_st_get_qlimit(stp) == 0) return; if (Lflag) { - snprintf(buf1, 15, "%d/%d/%d", so->so_qlen, - so->so_incqlen, so->so_qlimit); + snprintf(buf1, 15, "%d/%d/%d", netstat_st_get_qlen(stp), + netstat_st_get_incqlen(stp), netstat_st_get_qlimit(stp)); printf("unix %-14.14s", buf1); } else { printf("%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx", - (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc, - so->so_snd.sb_cc, (long)unp->unp_vnode, (long)unp->unp_conn, - (long)LIST_FIRST(&unp->unp_refs), - (long)LIST_NEXT(unp, unp_reflink)); + (u_long) netstat_st_get_pcb(stp), netstat_st_get_name(stp), + netstat_sbt_get_cc(netstat_st_get_rcv(stp)), + netstat_sbt_get_cc(netstat_st_get_snd(stp)), + (u_long) netstat_st_get_vnode(stp), + (u_long) netstat_st_get_conn(stp), + (u_long) netstat_st_get_refs(stp), + (u_long) netstat_st_get_reflink(stp)); } - if (sa) - printf(" %.*s", - (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)), - sa->sun_path); + if (netstat_st_get_addrcnt(stp) > 0) { + addr = netstat_st_get_address(stp, 0); + printf(" %s", netstat_sat_get_name(addr)); + } putchar('\n'); } Index: usr.bin/netstat/main.c =================================================================== --- usr.bin/netstat/main.c (revision 209358) +++ usr.bin/netstat/main.c (working copy) @@ -71,119 +71,18 @@ #include #include #include -#include "netstat.h" +#include "extern.h" +#include + + static struct nlist nl[] = { -#define N_IFNET 0 - { .n_name = "_ifnet" }, -#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 +#define N_IPX 0 { .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 +#define N_DDPCB 1 { .n_name = "_ddpcb"}, -#define N_NGSOCKS 11 +#define N_NGSOCKS 2 { .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_MBSTAT 21 - { .n_name = "_mbstat" }, -#define N_MBTYPES 22 - { .n_name = "_mbtypes" }, -#define N_NMBCLUSTERS 23 - { .n_name = "_nmbclusters" }, -#define N_NMBUFS 24 - { .n_name = "_nmbufs" }, -#define N_MBHI 25 - { .n_name = "_mbuf_hiwm" }, -#define N_CLHI 26 - { .n_name = "_clust_hiwm" }, -#define N_NCPUS 27 - { .n_name = "_smp_cpus" }, -#define N_PAGESZ 28 - { .n_name = "_pagesize" }, -#define N_MBPSTAT 29 - { .n_name = "_mb_statpcpu" }, -#define N_RTTRASH 30 - { .n_name = "_rttrash" }, -#define N_MBLO 31 - { .n_name = "_mbuf_lowm" }, -#define N_CLLO 32 - { .n_name = "_clust_lowm" }, -#define N_CARPSTAT 33 - { .n_name = "_carpstats" }, -#define N_PFSYNCSTAT 34 - { .n_name = "_pfsyncstats" }, -#define N_AHSTAT 35 - { .n_name = "_ahstat" }, -#define N_ESPSTAT 36 - { .n_name = "_espstat" }, -#define N_IPCOMPSTAT 37 - { .n_name = "_ipcompstat" }, -#define N_TCPSTAT 38 - { .n_name = "_tcpstat" }, -#define N_UDPSTAT 39 - { .n_name = "_udpstat" }, -#define N_IPSTAT 40 - { .n_name = "_ipstat" }, -#define N_ICMPSTAT 41 - { .n_name = "_icmpstat" }, -#define N_IGMPSTAT 42 - { .n_name = "_igmpstat" }, -#define N_PIMSTAT 43 - { .n_name = "_pimstat" }, -#define N_TCBINFO 44 - { .n_name = "_tcbinfo" }, -#define N_UDBINFO 45 - { .n_name = "_udbinfo" }, -#define N_DIVCBINFO 46 - { .n_name = "_divcbinfo" }, -#define N_RIPCBINFO 47 - { .n_name = "_ripcbinfo" }, -#define N_UNP_COUNT 48 - { .n_name = "_unp_count" }, -#define N_UNP_GENCNT 49 - { .n_name = "_unp_gencnt" }, -#define N_UNP_DHEAD 50 - { .n_name = "_unp_dhead" }, -#define N_UNP_SHEAD 51 - { .n_name = "_unp_shead" }, -#define N_RIP6STAT 52 - { .n_name = "_rip6stat" }, -#define N_SCTPSTAT 53 - { .n_name = "_sctpstat" }, -#define N_MFCTABLESIZE 54 - { .n_name = "_mfctablesize" }, #define N_ARPSTAT 55 { .n_name = "_arpstat" }, #define N_UNP_SPHEAD 56 @@ -193,113 +92,111 @@ 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); + void (*pr_stats)(const struct stat_type *); /* statistics printing routine */ + enum stat pr_stx; 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 }, + { 0, 1, NULL, tcp_stats, stat_TCP, + NULL, "tcp", 1, IPPROTO_TCP }, + { 0, 1, NULL, udp_stats, stat_UDP, + NULL, "udp", 1, IPPROTO_UDP }, #ifdef SCTP - { -1, N_SCTPSTAT, 1, sctp_protopr, - sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP }, + { -1, 1, sctp_protopr, sctp_stats, stat_SCTP, + NULL, "sctp", 1, IPPROTO_SCTP }, #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 }, + { 0, 1, NULL, NULL, stat_MAX, + NULL, "divert", 1, IPPROTO_DIVERT }, + { 0, 1, NULL, ip_stats, stat_IP, + NULL, "ip", 1, IPPROTO_RAW }, + { 0, 1, NULL, icmp_stats, stat_ICMP, + NULL, "icmp", 1, IPPROTO_ICMP }, + { 0, 1, NULL, igmp_stats, stat_IGMP, + 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}, + { -1, 1, NULL, ipsec_stats, stat_IPsec, /* keep as compat */ + NULL, "ipsec", 0, 0}, + { -1, 1, NULL, ah_stats, stat_AH, + NULL, "ah", 0, 0}, + { -1, 1, NULL, esp_stats, stat_ESP, + NULL, "esp", 0, 0}, + { -1, 1, NULL, ipcomp_stats, stat_IPcomp, + 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 } + { 0, 1, NULL, pim_stats, stat_PIM, + NULL, "pim", 1, IPPROTO_PIM }, + { -1, 1, NULL, carp_stats, stat_CARP, + NULL, "carp", 1, 0 }, + { -1, 1, NULL, pfsync_stats, stat_pfsync, + NULL, "pfsync", 1, 0 }, + { -1, 0, NULL, NULL, stat_MAX, + 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 }, + { 0, 1, NULL, tcp_stats, stat_TCP, + NULL, "tcp", 1, IPPROTO_TCP }, + { 0, 1, NULL, udp_stats, stat_UDP, + NULL, "udp", 1, IPPROTO_UDP }, + { 0, 1, NULL, ip6_stats, stat_IP6, + ip6_ifstats, "ip6", 1, IPPROTO_RAW }, + { 0, 1, NULL, icmp6_stats, stat_ICMP6, + icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 }, #ifdef IPSEC - { -1, N_IPSEC6STAT, 1, NULL, - ipsec_stats, NULL, "ipsec6", 0, 0 }, + { -1, 1, NULL, ipsec_stats, stat_IPsec, + NULL, "ipsec6", 0, 0 }, #endif #ifdef notyet - { -1, N_PIM6STAT, 1, NULL, - pim6_stats, NULL, "pim6", 1, 0 }, + { -1, 1, NULL, pim6_stats, stat_PIM6, + 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 } + { -1, 1, NULL, rip6_stats, stat_RIP6, + NULL, "rip6", 1, 0 }, + { -1, 0, NULL, NULL, stat_MAX, + 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 } + { -1, 1, NULL, pfkey_stats, stat_pfkey, + NULL, "pfkey", 0, 0 }, + { -1, 0, NULL, NULL, stat_MAX, + 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 } + { N_DDPCB, 1, atalkprotopr, ddp_stats, stat_DDP, + NULL, "ddp", 0, 0 }, + { -1, 0, NULL, NULL, stat_MAX, + 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 } + { N_NGSOCKS, 1, netgraphprotopr, NULL, stat_MAX, + NULL, "ctrl", 0, 0 }, + { N_NGSOCKS, 1, netgraphprotopr, NULL, stat_MAX, + NULL, "data", 0, 0 }, + { -1, 0, NULL, NULL, stat_MAX, + 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 } + { N_IPX, 1, ipxprotopr, ipx_stats, stat_IPX, + NULL, "ipx", 0, 0 }, + { N_IPX, 1, ipxprotopr, spx_stats, stat_SPX, + NULL, "spx", 0, 0 }, + { -1, 0, NULL, NULL, stat_MAX, + NULL, 0, 0, 0 } }; #endif @@ -316,12 +213,16 @@ #endif atalkprotox, NULL }; -static void printproto(struct protox *, const char *); +static void connpr(const struct socket_type *); +static void statpr(const struct session_type *, + void (*)(const struct stat_type *), enum stat, const char *); +static void printproto(const struct session_type *, 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*/ kvm_t *kvmd; static char *nlistf = NULL, *memf = NULL; int Aflag; /* show addresses of protocol control block */ @@ -359,6 +260,12 @@ struct protox *tp = NULL; /* for printing cblocks & stats */ int ch; + struct socket_type_list *stlp; + int error, st_flags; + struct socket_type_iterator *stip; + const struct socket_type *stp; + struct session_type *session; + af = AF_UNSPEC; while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:Qq:rSsuWw:xz")) @@ -517,16 +424,18 @@ if (Bflag) { if (!live) - usage(); - bpf_stats(interface); + kread(0, NULL, 0); + session = netstat_session_new(kvmd); + bpf_stats(session, interface); + netstat_session_free(session); exit(0); } if (mflag) { - if (!live) { - if (kread(0, NULL, 0) == 0) - mbpr(kvmd, nl[N_MBSTAT].n_value); - } else - mbpr(NULL, 0); + if (!live) + kread(0, NULL, 0); + session = netstat_session_new(kvmd); + mbpr(session); + netstat_session_free(session); exit(0); } if (Qflag) { @@ -551,85 +460,177 @@ * used for the queries, which is slower. */ #endif - kread(0, NULL, 0); if (iflag && !sflag) { - intpr(interval, nl[N_IFNET].n_value, NULL); + kread(0, NULL, 0); + session = netstat_session_new(kvmd); + intpr(session, interval, NULL); + netstat_session_free(session); 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); + if (sflag) { + if (!live) + kread(0, NULL, 0); + session = netstat_session_new(kvmd); + statpr(session, rt_stats, stat_route, "routing"); + netstat_session_free(session); + } + else { + kread(0, NULL, 0); + session = netstat_session_new(kvmd); + routepr(session, af); + netstat_session_free(session); + } exit(0); } if (gflag) { + kread(0, NULL, 0); + session = netstat_session_new(kvmd); if (sflag) { if (af == AF_INET || af == AF_UNSPEC) - mrt_stats(nl[N_MRTSTAT].n_value); + statpr(session, mrt_stats, stat_mroute, + "IPv4 multicast forwarding"); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) - mrt6_stats(nl[N_MRT6STAT].n_value); + statpr(session, mrt6_stats, stat_mroute6, + "IPv6 multicast forwarding"); #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); + mroutepr(session); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) - mroute6pr(nl[N_MF6CTABLE].n_value, - nl[N_MIF6TABLE].n_value); + mroute6pr(session); #endif } + netstat_session_free(session); exit(0); } if (tp) { - printproto(tp, tp->pr_name); + if (!live) + kread(0, NULL, 0); + session = netstat_session_new(kvmd); + printproto(session, tp, tp->pr_name); + netstat_session_free(session); 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) + if (af == PF_KEY || af == AF_UNSPEC) { + session = netstat_session_new(kvmd); for (tp = pfkeyprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); + printproto(session, tp, tp->pr_name); + netstat_session_free(session); + } #endif /*IPSEC*/ #ifdef IPX if (af == AF_IPX || af == AF_UNSPEC) { + session = netstat_session_new(kvmd); for (tp = ipxprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); + printproto(session, tp, tp->pr_name); + netstat_session_free(session); } #endif /* IPX */ - if (af == AF_APPLETALK || af == AF_UNSPEC) + if (af == AF_APPLETALK || af == AF_UNSPEC) { + session = netstat_session_new(kvmd); for (tp = atalkprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); + printproto(session, tp, tp->pr_name); + netstat_session_free(session); + } #ifdef NETGRAPH - if (af == AF_NETGRAPH || af == AF_UNSPEC) + if (af == AF_NETGRAPH || af == AF_UNSPEC) { + session = netstat_session_new(kvmd); for (tp = netgraphprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); + printproto(session, tp, tp->pr_name); + netstat_session_free(session); + } #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); + /* XXX: SPHEAD */ + if (af == AF_UNIX && !sflag) { + if (!live) + kread(0, NULL, 0); + session = netstat_session_new(kvmd); + unixpr(session); + netstat_session_free(session); + } + if ((af == AF_UNSPEC || af == AF_INET +#ifdef INET6 + || af == AF_INET6 +#endif + ) && !sflag) { + stlp = netstat_stl_alloc(); + if (stlp == NULL) { + warn("netstat_stl_alloc"); + exit(-1); + } + st_flags = 0; + if (!live) { + kread(0, NULL, 0); + } + session = netstat_session_new(kvmd); + if (aflag) + st_flags |= NETSTAT_SOCKET_ALL; + /* + * There should be guaranteed that sockets are not mixed (i.e. + * they are coming ordered by family/protocol). + */ + if (netstat_socket(session, af, 0, 0, stlp, st_flags) < 0) { + error = netstat_stl_geterror(stlp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_socket: %s", kvm_geterr(kvmd)); + else + warnx("netstat_socket: %s", + netstat_strerror(error)); + exit(-1); + } + if (netstat_sti_alloc(stlp, &stip) < 0) { + warnx("netstat_sti_alloc"); + exit(-1); + } + for (stp = netstat_sti_first(stip); stp != NULL; + stp = netstat_sti_next(stip)) { + connpr(stp); + } + netstat_sti_free(stip); + netstat_stl_free(stlp); + netstat_session_free(session); + } + + if (sflag && af == AF_UNSPEC) { + if (!live) + kread(0, NULL, 0); + session = netstat_session_new(kvmd); + for (tp = protox; tp->pr_name; tp++) + printproto(session, tp, tp->pr_name); + netstat_session_free(session); + } exit(0); } +static void +connpr(const struct socket_type *stp) +{ + switch (netstat_st_get_family(stp)) { + case PF_INET: + case PF_INET6: + inetppr(stp); + break; + case PF_LOCAL: + unixdomainpr(stp); + break; + default: + break; + } +} + /* * 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(tp, name) +printproto(session, tp, name) + const struct session_type *session; struct protox *tp; const char *name; { @@ -639,38 +640,24 @@ if (sflag) { if (iflag) { if (tp->pr_istats) - intpr(interval, nl[N_IFNET].n_value, - tp->pr_istats); + intpr(session, 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) + if (tp->pr_stats != NULL) + statpr(session, tp->pr_stats, tp->pr_stx, + tp->pr_name); + else + 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; + return; + } } } 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) { @@ -682,11 +669,74 @@ } 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); + + if (sflag) + return; + + if ((off || (live && tp->pr_usesysctl) || + af != AF_UNSPEC)) { + /* XXX: temp. hack */ + switch (tp->pr_protocol) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_DIVERT: + case IPPROTO_RAW: + case IPPROTO_ICMP: + case IPPROTO_IGMP: + case IPPROTO_PIM: + case IPPROTO_ICMPV6: + inetpr(session, (af == PF_INET6) ? af : PF_INET, + tp->pr_protocol); + break; + default: + if (pr != NULL) + (*pr)(off, name, af, tp->pr_protocol); + else if (pflag) + printf("%s: no PCB routine\n", tp->pr_name); + break; + } + } } +void +statpr(const struct session_type *session, + void (*stats_routine)(const struct stat_type *), enum stat sts, + const char *name) +{ + struct stat_type *sttp; + int error; + + if (zflag) { + netstat_zerostat(session, sts); + return; + } + + sttp = netstat_stat_alloc(); + if (sttp == NULL) { + warn("netstat_stat_alloc"); + return; + } + + if (netstat_stat(session, sts, sttp, 0) < 0) { + error = netstat_stat_geterror(sttp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_stat: %s", kvm_geterr(kvmd)); + else + warnx("netstat_stat: %s", netstat_strerror(error)); + goto out; + } + + printf("%s:\n", name); + stats_routine(sttp); + + /* XXX: Well... it is a hack :) */ + if (sts == stat_ICMP) + printf("\tICMP address mask responses are %sabled\n", + netstat_icmp_get_maskrepl(session) ? "en" : "dis"); +out: + netstat_stat_free(sttp); +} + /* * Read kernel memory, return 0 on success. */ @@ -804,7 +854,7 @@ " 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 -B [-I interface] [-M core] [-N system]", " 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]", Index: usr.bin/netstat/inet6.c =================================================================== --- usr.bin/netstat/inet6.c (revision 209358) +++ usr.bin/netstat/inet6.c (working copy) @@ -41,7 +41,7 @@ #include __FBSDID("$FreeBSD$"); -#ifdef INET6 +#include #include #include #include @@ -72,7 +72,8 @@ #include #include #include -#include "netstat.h" +#include +#include "extern.h" struct socket sockb; @@ -80,446 +81,153 @@ static char ntop_buf[INET6_ADDRSTRLEN]; -static const char *ip6nh[] = { - "hop by hop", - "ICMP", - "IGMP", - "#3", - "IP", - "#5", - "TCP", - "#7", - "#8", - "#9", - "#10", - "#11", - "#12", - "#13", - "#14", - "#15", - "#16", - "UDP", - "#18", - "#19", - "#20", - "#21", - "IDP", - "#23", - "#24", - "#25", - "#26", - "#27", - "#28", - "TP", - "#30", - "#31", - "#32", - "#33", - "#34", - "#35", - "#36", - "#37", - "#38", - "#39", - "#40", - "IP6", - "#42", - "routing", - "fragment", - "#45", - "#46", - "#47", - "#48", - "#49", - "ESP", - "AH", - "#52", - "#53", - "#54", - "#55", - "#56", - "#57", - "ICMP6", - "no next header", - "destination option", - "#61", - "mobility", - "#63", - "#64", - "#65", - "#66", - "#67", - "#68", - "#69", - "#70", - "#71", - "#72", - "#73", - "#74", - "#75", - "#76", - "#77", - "#78", - "#79", - "ISOIP", - "#81", - "#82", - "#83", - "#84", - "#85", - "#86", - "#87", - "#88", - "OSPF", - "#80", - "#91", - "#92", - "#93", - "#94", - "#95", - "#96", - "Ethernet", - "#98", - "#99", - "#100", - "#101", - "#102", - "PIM", - "#104", - "#105", - "#106", - "#107", - "#108", - "#109", - "#110", - "#111", - "#112", - "#113", - "#114", - "#115", - "#116", - "#117", - "#118", - "#119", - "#120", - "#121", - "#122", - "#123", - "#124", - "#125", - "#126", - "#127", - "#128", - "#129", - "#130", - "#131", - "#132", - "#133", - "#134", - "#135", - "#136", - "#137", - "#138", - "#139", - "#140", - "#141", - "#142", - "#143", - "#144", - "#145", - "#146", - "#147", - "#148", - "#149", - "#150", - "#151", - "#152", - "#153", - "#154", - "#155", - "#156", - "#157", - "#158", - "#159", - "#160", - "#161", - "#162", - "#163", - "#164", - "#165", - "#166", - "#167", - "#168", - "#169", - "#170", - "#171", - "#172", - "#173", - "#174", - "#175", - "#176", - "#177", - "#178", - "#179", - "#180", - "#181", - "#182", - "#183", - "#184", - "#185", - "#186", - "#187", - "#188", - "#189", - "#180", - "#191", - "#192", - "#193", - "#194", - "#195", - "#196", - "#197", - "#198", - "#199", - "#200", - "#201", - "#202", - "#203", - "#204", - "#205", - "#206", - "#207", - "#208", - "#209", - "#210", - "#211", - "#212", - "#213", - "#214", - "#215", - "#216", - "#217", - "#218", - "#219", - "#220", - "#221", - "#222", - "#223", - "#224", - "#225", - "#226", - "#227", - "#228", - "#229", - "#230", - "#231", - "#232", - "#233", - "#234", - "#235", - "#236", - "#237", - "#238", - "#239", - "#240", - "#241", - "#242", - "#243", - "#244", - "#245", - "#246", - "#247", - "#248", - "#249", - "#250", - "#251", - "#252", - "#253", - "#254", - "#255", -}; - -static char *srcrule_str[] = { - "first candidate", - "same address", - "appropriate scope", - "deprecated address", - "home address", - "outgoing interface", - "matching label", - "public/temporary address", - "alive interface", - "preferred interface", - "rule #10", - "rule #11", - "rule #12", - "rule #13", - "longest match", - "rule #15", -}; - /* * Dump IP6 statistics structure. */ void -ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +ip6_stats(const struct stat_type *sttp) { - struct ip6stat ip6stat; + const struct ip6_stat *s; int first, i; - size_t len; - len = sizeof ip6stat; - if (live) { - memset(&ip6stat, 0, len); - if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len, NULL, - 0) < 0) { - if (errno != ENOENT) - warn("sysctl: net.inet6.ip6.stats"); - return; - } - } else - kread(off, &ip6stat, len); - - printf("%s:\n", name); - -#define p(f, m) if (ip6stat.f || sflag <= 1) \ - printf(m, (uintmax_t)ip6stat.f, plural(ip6stat.f)) -#define p1a(f, m) if (ip6stat.f || sflag <= 1) \ - printf(m, (uintmax_t)ip6stat.f) - - p(ip6s_total, "\t%ju total packet%s received\n"); - p1a(ip6s_toosmall, "\t%ju with size smaller than minimum\n"); - p1a(ip6s_tooshort, "\t%ju with data size < data length\n"); - p1a(ip6s_badoptions, "\t%ju with bad options\n"); - p1a(ip6s_badvers, "\t%ju with incorrect version number\n"); - p(ip6s_fragments, "\t%ju fragment%s received\n"); - p(ip6s_fragdropped, "\t%ju fragment%s dropped (dup or out of space)\n"); - p(ip6s_fragtimeout, "\t%ju fragment%s dropped after timeout\n"); - p(ip6s_fragoverflow, "\t%ju fragment%s that exceeded limit\n"); - p(ip6s_reassembled, "\t%ju packet%s reassembled ok\n"); - p(ip6s_delivered, "\t%ju packet%s for this host\n"); - p(ip6s_forward, "\t%ju packet%s forwarded\n"); - p(ip6s_cantforward, "\t%ju packet%s not forwardable\n"); - p(ip6s_redirectsent, "\t%ju redirect%s sent\n"); - p(ip6s_localout, "\t%ju packet%s sent from this host\n"); - p(ip6s_rawout, "\t%ju packet%s sent with fabricated ip header\n"); - p(ip6s_odropped, "\t%ju output packet%s dropped due to no bufs, etc.\n"); - p(ip6s_noroute, "\t%ju output packet%s discarded due to no route\n"); - p(ip6s_fragmented, "\t%ju output datagram%s fragmented\n"); - p(ip6s_ofragments, "\t%ju fragment%s created\n"); - p(ip6s_cantfrag, "\t%ju datagram%s that can't be fragmented\n"); - p(ip6s_badscope, "\t%ju packet%s that violated scope rules\n"); - p(ip6s_notmember, "\t%ju multicast packet%s which we don't join\n"); - for (first = 1, i = 0; i < 256; i++) - if (ip6stat.ip6s_nxthist[i] != 0) { + s = netstat_get_ip6stats(sttp); +#define p(f, m) if (netstat_ip6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_ip6s_get_##f(s), plural(netstat_ip6s_get_##f(s))) +#define pa(f,i,m) if (netstat_ip6s_get_##f(s,i) || sflag <= 1) \ + printf(m, netstat_ip6s_get_##f(s,i), plural(netstat_ip6s_get_##f(s,i))) +#define p1a(f, m) if (netstat_ip6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_ip6s_get_##f(s)) + p(total, "\t%ju total packet%s received\n"); + p1a(toosmall, "\t%ju with size smaller than minimum\n"); + p1a(tooshort, "\t%ju with data size < data length\n"); + p1a(badoptions, "\t%ju with bad options\n"); + p1a(badvers, "\t%ju with incorrect version number\n"); + p(fragments, "\t%ju fragment%s received\n"); + p(fragdropped, "\t%ju fragment%s dropped (dup or out of space)\n"); + p(fragtimeout, "\t%ju fragment%s dropped after timeout\n"); + p(fragoverflow, "\t%ju fragment%s that exceeded limit\n"); + p(reassembled, "\t%ju packet%s reassembled ok\n"); + p(delivered, "\t%ju packet%s for this host\n"); + p(forward, "\t%ju packet%s forwarded\n"); + p(cantforward, "\t%ju packet%s not forwardable\n"); + p(redirectsent, "\t%ju redirect%s sent\n"); + p(localout, "\t%ju packet%s sent from this host\n"); + p(rawout, "\t%ju packet%s sent with fabricated ip header\n"); + p(odropped, "\t%ju output packet%s dropped due to no bufs, etc.\n"); + p(noroute, "\t%ju output packet%s discarded due to no route\n"); + p(fragmented, "\t%ju output datagram%s fragmented\n"); + p(ofragments, "\t%ju fragment%s created\n"); + p(cantfrag, "\t%ju datagram%s that can't be fragmented\n"); + p(badscope, "\t%ju packet%s that violated scope rules\n"); + p(notmember, "\t%ju multicast packet%s which we don't join\n"); + for (first = 1, i = 0; i < NETSTAT_IP6_NHIST_MAX; i++) + if (netstat_ip6s_get_nxthist(s, i) != 0) { if (first) { printf("\tInput histogram:\n"); first = 0; } - printf("\t\t%s: %ju\n", ip6nh[i], - (uintmax_t)ip6stat.ip6s_nxthist[i]); + printf("\t\t%s: %ju\n", netstat_ip6_nhist_name(i), + netstat_ip6s_get_nxthist(s, i)); } printf("\tMbuf statistics:\n"); - printf("\t\t%ju one mbuf\n", (uintmax_t)ip6stat.ip6s_m1); - for (first = 1, i = 0; i < 32; i++) { + printf("\t\t%ju one mbuf\n", netstat_ip6s_get_m1(s)); + for (first = 1, i = 0; i < NETSTAT_IP6_MBUF_MAX; i++) { char ifbuf[IFNAMSIZ]; - if (ip6stat.ip6s_m2m[i] != 0) { + if (netstat_ip6s_get_m2m(s, i) != 0) { if (first) { printf("\t\ttwo or more mbuf:\n"); first = 0; } printf("\t\t\t%s= %ju\n", if_indextoname(i, ifbuf), - (uintmax_t)ip6stat.ip6s_m2m[i]); + netstat_ip6s_get_m2m(s, i)); } } - printf("\t\t%ju one ext mbuf\n", - (uintmax_t)ip6stat.ip6s_mext1); - printf("\t\t%ju two or more ext mbuf\n", - (uintmax_t)ip6stat.ip6s_mext2m); - p(ip6s_exthdrtoolong, + printf("\t\t%ju one ext mbuf\n", netstat_ip6s_get_mext1(s)); + printf("\t\t%ju two or more ext mbuf\n", netstat_ip6s_get_mext2m(s)); + p(exthdrtoolong, "\t%ju packet%s whose headers are not continuous\n"); - p(ip6s_nogif, "\t%ju tunneling packet%s that can't find gif\n"); - p(ip6s_toomanyhdr, + p(nogif, "\t%ju tunneling packet%s that can't find gif\n"); + p(toomanyhdr, "\t%ju packet%s discarded because of too many headers\n"); /* for debugging source address selection */ -#define PRINT_SCOPESTAT(s,i) do {\ +#define PRINT_SCOPESTAT(f,i) do {\ switch(i) { /* XXX hardcoding in each case */\ case 1:\ - p(s, "\t\t%ju node-local%s\n");\ + pa(f, i, "\t\t%ju node-local%s\n");\ break;\ case 2:\ - p(s,"\t\t%ju link-local%s\n");\ + pa(f, i, "\t\t%ju link-local%s\n");\ break;\ case 5:\ - p(s,"\t\t%ju site-local%s\n");\ + pa(f, i, "\t\t%ju site-local%s\n");\ break;\ case 14:\ - p(s,"\t\t%ju global%s\n");\ + pa(f, i, "\t\t%ju global%s\n");\ break;\ default:\ printf("\t\t%ju addresses scope=%x\n",\ - (uintmax_t)ip6stat.s, i);\ + netstat_ip6s_get_##f(s,i), i);\ }\ } while (0); - p(ip6s_sources_none, - "\t%ju failure%s of source address selection\n"); - for (first = 1, i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_sameif[i]) { + p(sources_none, "\t%ju failure%s of source address selection\n"); + for (first = 1, i = 0; i < NETSTAT_IP6_IF_MAX; i++) { + if (netstat_ip6s_get_sources_sameif(s, i)) { if (first) { printf("\tsource addresses on an outgoing I/F\n"); first = 0; } - PRINT_SCOPESTAT(ip6s_sources_sameif[i], i); + PRINT_SCOPESTAT(sources_sameif,i); } } - for (first = 1, i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_otherif[i]) { + for (first = 1, i = 0; i < NETSTAT_IP6_IF_MAX; i++) { + if (netstat_ip6s_get_sources_otherif(s, i)) { if (first) { printf("\tsource addresses on a non-outgoing I/F\n"); first = 0; } - PRINT_SCOPESTAT(ip6s_sources_otherif[i], i); + PRINT_SCOPESTAT(sources_otherif,i); } } - for (first = 1, i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_samescope[i]) { + for (first = 1, i = 0; i < NETSTAT_IP6_IF_MAX; i++) { + if (netstat_ip6s_get_sources_samescope(s, i)) { if (first) { printf("\tsource addresses of same scope\n"); first = 0; } - PRINT_SCOPESTAT(ip6s_sources_samescope[i], i); + PRINT_SCOPESTAT(sources_samescope,i); } } - for (first = 1, i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_otherscope[i]) { + for (first = 1, i = 0; i < NETSTAT_IP6_IF_MAX; i++) { + if (netstat_ip6s_get_sources_otherscope(s, i)) { if (first) { printf("\tsource addresses of a different scope\n"); first = 0; } - PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i); + PRINT_SCOPESTAT(sources_otherscope,i); } } - for (first = 1, i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_deprecated[i]) { + for (first = 1, i = 0; i < NETSTAT_IP6_IF_MAX; i++) { + if (netstat_ip6s_get_sources_deprecated(s, i)) { if (first) { printf("\tdeprecated source addresses\n"); first = 0; } - PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i); + PRINT_SCOPESTAT(sources_deprecated,i); } } printf("\tSource addresses selection rule applied:\n"); - for (i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_rule[i]) + for (i = 0; i < NETSTAT_IP6_IF_MAX; i++) { + if (netstat_ip6s_get_sources_rule(s, i)) printf("\t\t%ju %s\n", - (uintmax_t)ip6stat.ip6s_sources_rule[i], - srcrule_str[i]); + netstat_ip6s_get_sources_rule(s, i), + netstat_ip6_srcrule_name(i)); } #undef p +#undef pa #undef p1a } @@ -579,349 +287,72 @@ #undef p_5 } -static const char *icmp6names[] = { - "#0", - "unreach", - "packet too big", - "time exceed", - "parameter problem", - "#5", - "#6", - "#7", - "#8", - "#9", - "#10", - "#11", - "#12", - "#13", - "#14", - "#15", - "#16", - "#17", - "#18", - "#19", - "#20", - "#21", - "#22", - "#23", - "#24", - "#25", - "#26", - "#27", - "#28", - "#29", - "#30", - "#31", - "#32", - "#33", - "#34", - "#35", - "#36", - "#37", - "#38", - "#39", - "#40", - "#41", - "#42", - "#43", - "#44", - "#45", - "#46", - "#47", - "#48", - "#49", - "#50", - "#51", - "#52", - "#53", - "#54", - "#55", - "#56", - "#57", - "#58", - "#59", - "#60", - "#61", - "#62", - "#63", - "#64", - "#65", - "#66", - "#67", - "#68", - "#69", - "#70", - "#71", - "#72", - "#73", - "#74", - "#75", - "#76", - "#77", - "#78", - "#79", - "#80", - "#81", - "#82", - "#83", - "#84", - "#85", - "#86", - "#87", - "#88", - "#89", - "#80", - "#91", - "#92", - "#93", - "#94", - "#95", - "#96", - "#97", - "#98", - "#99", - "#100", - "#101", - "#102", - "#103", - "#104", - "#105", - "#106", - "#107", - "#108", - "#109", - "#110", - "#111", - "#112", - "#113", - "#114", - "#115", - "#116", - "#117", - "#118", - "#119", - "#120", - "#121", - "#122", - "#123", - "#124", - "#125", - "#126", - "#127", - "echo", - "echo reply", - "multicast listener query", - "MLDv1 listener report", - "MLDv1 listener done", - "router solicitation", - "router advertisement", - "neighbor solicitation", - "neighbor advertisement", - "redirect", - "router renumbering", - "node information request", - "node information reply", - "inverse neighbor solicitation", - "inverse neighbor advertisement", - "MLDv2 listener report", - "#144", - "#145", - "#146", - "#147", - "#148", - "#149", - "#150", - "#151", - "#152", - "#153", - "#154", - "#155", - "#156", - "#157", - "#158", - "#159", - "#160", - "#161", - "#162", - "#163", - "#164", - "#165", - "#166", - "#167", - "#168", - "#169", - "#170", - "#171", - "#172", - "#173", - "#174", - "#175", - "#176", - "#177", - "#178", - "#179", - "#180", - "#181", - "#182", - "#183", - "#184", - "#185", - "#186", - "#187", - "#188", - "#189", - "#180", - "#191", - "#192", - "#193", - "#194", - "#195", - "#196", - "#197", - "#198", - "#199", - "#200", - "#201", - "#202", - "#203", - "#204", - "#205", - "#206", - "#207", - "#208", - "#209", - "#210", - "#211", - "#212", - "#213", - "#214", - "#215", - "#216", - "#217", - "#218", - "#219", - "#220", - "#221", - "#222", - "#223", - "#224", - "#225", - "#226", - "#227", - "#228", - "#229", - "#230", - "#231", - "#232", - "#233", - "#234", - "#235", - "#236", - "#237", - "#238", - "#239", - "#240", - "#241", - "#242", - "#243", - "#244", - "#245", - "#246", - "#247", - "#248", - "#249", - "#250", - "#251", - "#252", - "#253", - "#254", - "#255", -}; /* * Dump ICMP6 statistics. */ void -icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +icmp6_stats(const struct stat_type *sttp) { - struct icmp6stat icmp6stat; + const struct icmp6_stat *s; int i, first; - size_t len; - len = sizeof icmp6stat; - if (live) { - memset(&icmp6stat, 0, len); - if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len, - NULL, 0) < 0) { - if (errno != ENOENT) - warn("sysctl: net.inet6.icmp6.stats"); - return; - } - } else - kread(off, &icmp6stat, len); - - printf("%s:\n", name); - -#define p(f, m) if (icmp6stat.f || sflag <= 1) \ - printf(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f)) -#define p_5(f, m) if (icmp6stat.f || sflag <= 1) \ - printf(m, (uintmax_t)icmp6stat.f) - - p(icp6s_error, "\t%ju call%s to icmp6_error\n"); - p(icp6s_canterror, + s = netstat_get_icmp6stats(sttp); +#define p(f, m) if (netstat_icmp6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_icmp6s_get_##f(s), plural(netstat_icmp6s_get_##f(s))) +#define p_5(f, m) if (netstat_icmp6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_icmp6s_get_##f(s)) + p(error, "\t%ju call%s to icmp6_error\n"); + p(canterror, "\t%ju error%s not generated in response to an icmp6 message\n"); - p(icp6s_toofreq, + p(toofreq, "\t%ju error%s not generated because of rate limitation\n"); -#define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0])) - for (first = 1, i = 0; i < NELEM; i++) - if (icmp6stat.icp6s_outhist[i] != 0) { + for (first = 1, i = 0; i < 256; i++) + if (netstat_icmp6s_get_outhist(s, i) != 0) { if (first) { printf("\tOutput histogram:\n"); first = 0; } - printf("\t\t%s: %ju\n", icmp6names[i], - (uintmax_t)icmp6stat.icp6s_outhist[i]); + printf("\t\t%s: %ju\n", netstat_icmp6name(i), + netstat_icmp6s_get_outhist(s, i)); } -#undef NELEM - p(icp6s_badcode, "\t%ju message%s with bad code fields\n"); - p(icp6s_tooshort, "\t%ju message%s < minimum length\n"); - p(icp6s_checksum, "\t%ju bad checksum%s\n"); - p(icp6s_badlen, "\t%ju message%s with bad length\n"); -#define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0])) - for (first = 1, i = 0; i < NELEM; i++) - if (icmp6stat.icp6s_inhist[i] != 0) { + p(badcode, "\t%ju message%s with bad code fields\n"); + p(tooshort, "\t%ju message%s < minimum length\n"); + p(checksum, "\t%ju bad checksum%s\n"); + p(badlen, "\t%ju message%s with bad length\n"); + for (first = 1, i = 0; i < 256; i++) + if (netstat_icmp6s_get_inhist(s, i) != 0) { if (first) { printf("\tInput histogram:\n"); first = 0; } - printf("\t\t%s: %ju\n", icmp6names[i], - (uintmax_t)icmp6stat.icp6s_inhist[i]); + printf("\t\t%s: %ju\n", netstat_icmp6name(i), + netstat_icmp6s_get_inhist(s, i)); } -#undef NELEM printf("\tHistogram of error messages to be generated:\n"); - p_5(icp6s_odst_unreach_noroute, "\t\t%ju no route\n"); - p_5(icp6s_odst_unreach_admin, "\t\t%ju administratively prohibited\n"); - p_5(icp6s_odst_unreach_beyondscope, "\t\t%ju beyond scope\n"); - p_5(icp6s_odst_unreach_addr, "\t\t%ju address unreachable\n"); - p_5(icp6s_odst_unreach_noport, "\t\t%ju port unreachable\n"); - p_5(icp6s_opacket_too_big, "\t\t%ju packet too big\n"); - p_5(icp6s_otime_exceed_transit, "\t\t%ju time exceed transit\n"); - p_5(icp6s_otime_exceed_reassembly, "\t\t%ju time exceed reassembly\n"); - p_5(icp6s_oparamprob_header, "\t\t%ju erroneous header field\n"); - p_5(icp6s_oparamprob_nextheader, "\t\t%ju unrecognized next header\n"); - p_5(icp6s_oparamprob_option, "\t\t%ju unrecognized option\n"); - p_5(icp6s_oredirect, "\t\t%ju redirect\n"); - p_5(icp6s_ounknown, "\t\t%ju unknown\n"); + p_5(odst_unreach_noroute, "\t\t%ju no route\n"); + p_5(odst_unreach_admin, "\t\t%ju administratively prohibited\n"); + p_5(odst_unreach_beyondscope, "\t\t%ju beyond scope\n"); + p_5(odst_unreach_addr, "\t\t%ju address unreachable\n"); + p_5(odst_unreach_noport, "\t\t%ju port unreachable\n"); + p_5(opacket_too_big, "\t\t%ju packet too big\n"); + p_5(otime_exceed_transit, "\t\t%ju time exceed transit\n"); + p_5(otime_exceed_reassembly, "\t\t%ju time exceed reassembly\n"); + p_5(oparamprob_header, "\t\t%ju erroneous header field\n"); + p_5(oparamprob_nextheader, "\t\t%ju unrecognized next header\n"); + p_5(oparamprob_option, "\t\t%ju unrecognized option\n"); + p_5(oredirect, "\t\t%ju redirect\n"); + p_5(ounknown, "\t\t%ju unknown\n"); - p(icp6s_reflect, "\t%ju message response%s generated\n"); - p(icp6s_nd_toomanyopt, "\t%ju message%s with too many ND options\n"); - p(icp6s_nd_badopt, "\t%ju message%s with bad ND options\n"); - p(icp6s_badns, "\t%ju bad neighbor solicitation message%s\n"); - p(icp6s_badna, "\t%ju bad neighbor advertisement message%s\n"); - p(icp6s_badrs, "\t%ju bad router solicitation message%s\n"); - p(icp6s_badra, "\t%ju bad router advertisement message%s\n"); - p(icp6s_badredirect, "\t%ju bad redirect message%s\n"); - p(icp6s_pmtuchg, "\t%ju path MTU change%s\n"); + p(reflect, "\t%ju message response%s generated\n"); + p(nd_toomanyopt, "\t%ju message%s with too many ND options\n"); + p(nd_badopt, "\t%ju message%s with bad ND options\n"); + p(badns, "\t%ju bad neighbor solicitation message%s\n"); + p(badna, "\t%ju bad neighbor advertisement message%s\n"); + p(badrs, "\t%ju bad router solicitation message%s\n"); + p(badra, "\t%ju bad router advertisement message%s\n"); + p(badredirect, "\t%ju bad redirect message%s\n"); + p(pmtuchg, "\t%ju path MTU change%s\n"); #undef p #undef p_5 } @@ -997,37 +428,20 @@ * Dump PIM statistics structure. */ void -pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +pim6_stats(const struct stat_type *sttp) { - struct pim6stat pim6stat, zerostat; - size_t len = sizeof pim6stat; + const struct pim6_stat *s; - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - if (errno != ENOENT) - warn("sysctl: net.inet6.pim.stats"); - return; - } - } else { - if (off == 0) - return; - kread(off, &pim6stat, len); - } - - printf("%s:\n", name); - -#define p(f, m) if (pim6stat.f || sflag <= 1) \ - printf(m, (uintmax_t)pim6stat.f, plural(pim6stat.f)) - p(pim6s_rcv_total, "\t%ju message%s received\n"); - p(pim6s_rcv_tooshort, "\t%ju message%s received with too few bytes\n"); - p(pim6s_rcv_badsum, "\t%ju message%s received with bad checksum\n"); - p(pim6s_rcv_badversion, "\t%ju message%s received with bad version\n"); - p(pim6s_rcv_registers, "\t%ju register%s received\n"); - p(pim6s_rcv_badregisters, "\t%ju bad register%s received\n"); - p(pim6s_snd_registers, "\t%ju register%s sent\n"); + s = netstat_get_pim6stats(sttp); +#define p(f, m) if (netstat_pim6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_pim6s_get_##f(s), plural(netstat_pim6s_get_##f(s))) + p(rcv_total, "\t%ju message%s received\n"); + p(rcv_tooshort, "\t%ju message%s received with too few bytes\n"); + p(rcv_badsum, "\t%ju message%s received with bad checksum\n"); + p(rcv_badversion, "\t%ju message%s received with bad version\n"); + p(rcv_registers, "\t%ju register%s received\n"); + p(rcv_badregisters, "\t%ju bad register%s received\n"); + p(snd_registers, "\t%ju register%s sent\n"); #undef p } @@ -1035,44 +449,25 @@ * Dump raw ip6 statistics structure. */ void -rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +rip6_stats(const struct stat_type *sttp) { - struct rip6stat rip6stat; - u_quad_t delivered; - size_t len; + const struct rip6_stat *s; - len = sizeof(rip6stat); - if (live) { - if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len, - NULL, 0) < 0) { - if (errno != ENOENT) - warn("sysctl: net.inet6.ip6.rip6stats"); - return; - } - } else - kread(off, &rip6stat, len); - - printf("%s:\n", name); - -#define p(f, m) if (rip6stat.f || sflag <= 1) \ - printf(m, (uintmax_t)rip6stat.f, plural(rip6stat.f)) - p(rip6s_ipackets, "\t%ju message%s received\n"); - p(rip6s_isum, "\t%ju checksum calculation%s on inbound\n"); - p(rip6s_badsum, "\t%ju message%s with bad checksum\n"); - p(rip6s_nosock, "\t%ju message%s dropped due to no socket\n"); - p(rip6s_nosockmcast, - "\t%ju multicast message%s dropped due to no socket\n"); - p(rip6s_fullsock, - "\t%ju message%s dropped due to full socket buffers\n"); - delivered = rip6stat.rip6s_ipackets - - rip6stat.rip6s_badsum - - rip6stat.rip6s_nosock - - rip6stat.rip6s_nosockmcast - - rip6stat.rip6s_fullsock; - if (delivered || sflag <= 1) - printf("\t%ju delivered\n", (uintmax_t)delivered); - p(rip6s_opackets, "\t%ju datagram%s output\n"); + s = netstat_get_rip6stats(sttp); +#define p(f, m) if (netstat_rip6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_rip6s_get_##f(s), plural(netstat_rip6s_get_##f(s))) +#define p_5(f, m) if (netstat_rip6s_get_##f(s) || sflag <= 1) \ + printf(m, netstat_rip6s_get_##f(s)) + p(ipackets, "\t%ju message%s received\n"); + p(isum, "\t%ju checksum calculation%s on inbound\n"); + p(badsum, "\t%ju message%s with bad checksum\n"); + p(nosock, "\t%ju message%s dropped due to no socket\n"); + p(nosockmcast, "\t%ju multicast message%s dropped due to no socket\n"); + p(fullsock, "\t%ju message%s dropped due to full socket buffers\n"); + p_5(delivered,"\t%ju delivered\n"); + p(opackets, "\t%ju datagram%s output\n"); #undef p +#undef p_5 } /* @@ -1152,4 +547,3 @@ sizeof(ntop_buf))); return (line); } -#endif /*INET6*/ Index: usr.bin/netstat/netstat.h =================================================================== --- usr.bin/netstat/netstat.h (revision 209358) +++ usr.bin/netstat/netstat.h (working copy) @@ -1,171 +0,0 @@ -/*- - * 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. - * 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. - * - * @(#)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 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); -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; -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 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 *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); - -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: usr.bin/netstat/mbuf.c =================================================================== --- usr.bin/netstat/mbuf.c (revision 209358) +++ usr.bin/netstat/mbuf.c (working copy) @@ -2,6 +2,7 @@ * Copyright (c) 1983, 1988, 1993 * The Regents of the University of California. * Copyright (c) 2005 Robert N. M. Watson + * Copyright (c) 2009, 2010 Gabor Pali * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,272 +43,115 @@ #include __FBSDID("$FreeBSD$"); -#include -#include -#include -#include -#include -#include - +#include #include #include -#include -#include +#include #include #include -#include -#include "netstat.h" +#include "extern.h" /* * Print mbuf statistics. */ void -mbpr(void *kvmd, u_long mbaddr) +mbpr(const struct session_type *session) { - struct memory_type_list *mtlp; - struct memory_type *mtp; - uintmax_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size; - uintmax_t cluster_count, cluster_bytes, cluster_limit, cluster_free; - uintmax_t cluster_failures, cluster_size; - uintmax_t packet_count, packet_bytes, packet_free, packet_failures; - uintmax_t tag_count, tag_bytes; - uintmax_t jumbop_count, jumbop_bytes, jumbop_limit, jumbop_free; - uintmax_t jumbop_failures, jumbop_size; - uintmax_t jumbo9_count, jumbo9_bytes, jumbo9_limit, jumbo9_free; - uintmax_t jumbo9_failures, jumbo9_size; - uintmax_t jumbo16_count, jumbo16_bytes, jumbo16_limit, jumbo16_free; - uintmax_t jumbo16_failures, jumbo16_size; - uintmax_t bytes_inuse, bytes_incache, bytes_total; - int nsfbufs, nsfbufspeak, nsfbufsused; - struct mbstat mbstat; - size_t mlen; + struct mbuf_type *mbtp; + const struct buffer_type *mbuf, *cluster, *packet, *tag, *jumbop, + *jumbo9, *jumbo16; int error; - mtlp = memstat_mtl_alloc(); - if (mtlp == NULL) { - warn("memstat_mtl_alloc"); + mbtp = netstat_mbt_alloc(); + if (mbtp == NULL) { + warn("netstat_mbtp_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); + if (netstat_mbuf(session, mbtp, 0) < 0) { + error = netstat_mbt_get_error(mbtp); + if (error == NETSTAT_ERROR_KVM) + warnx("netstat_mbuf: %s", netstat_kvmerror(session)); + else + warnx("netstat_mbuf: %s", netstat_strerror(error)); 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_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_failures = memstat_get_failures(mtp); + mbuf = netstat_mbt_get_mbuf(mbtp); + cluster = netstat_mbt_get_cluster(mbtp); + packet = netstat_mbt_get_packet(mbtp); + tag = netstat_mbt_get_tag(mbtp); + jumbop = netstat_mbt_get_jumbop(mbtp); + jumbo9 = netstat_mbt_get_jumbo9(mbtp); + jumbo16 = netstat_mbt_get_jumbo16(mbtp); - 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_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_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_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_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); + netstat_bt_get_count(mbuf) + netstat_bt_get_count(packet), + netstat_bt_get_free(mbuf) + netstat_bt_get_free(packet), + netstat_bt_get_count(mbuf) + netstat_bt_get_count(packet) + + netstat_bt_get_free(mbuf) + netstat_bt_get_free(packet)); 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); + netstat_bt_get_count(cluster) - netstat_bt_get_free(packet), + netstat_bt_get_free(cluster) + netstat_bt_get_free(packet), + netstat_bt_get_count(cluster) + netstat_bt_get_free(cluster), + netstat_bt_get_limit(cluster)); printf("%ju/%ju mbuf+clusters out of packet secondary zone in use " "(current/cache)\n", - packet_count, packet_free); + netstat_bt_get_count(packet), netstat_bt_get_free(packet)); 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); + netstat_bt_get_count(jumbop), netstat_bt_get_free(jumbop), + netstat_bt_get_count(jumbop) + netstat_bt_get_free(jumbop), + netstat_bt_get_limit(jumbop), netstat_bt_get_size(jumbop) / 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); + netstat_bt_get_count(jumbo9), netstat_bt_get_free(jumbo9), + netstat_bt_get_count(jumbo9) + netstat_bt_get_free(jumbo9), + netstat_bt_get_limit(jumbo9)); 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); + netstat_bt_get_count(jumbo16), netstat_bt_get_free(jumbo16), + netstat_bt_get_count(jumbo16) + netstat_bt_get_free(jumbo16), + netstat_bt_get_limit(jumbo16)); #if 0 - printf("%ju mbuf tags in use\n", tag_count); + printf("%ju mbuf tags in use\n", netstat_bt_get_count(tag)); #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); + "(current/cache/total)\n", + netstat_mbt_get_bytes_inuse(mbtp) / 1024, + netstat_mbt_get_bytes_incache(mbtp) / 1024, + netstat_mbt_get_bytes_total(mbtp) / 1024); printf("%ju/%ju/%ju requests for mbufs denied (mbufs/clusters/" - "mbuf+clusters)\n", mbuf_failures, cluster_failures, - packet_failures); + "mbuf+clusters)\n", netstat_bt_get_failures(mbuf), + netstat_bt_get_failures(cluster), netstat_bt_get_failures(packet)); printf("%ju/%ju/%ju requests for jumbo clusters denied " - "(%juk/9k/16k)\n", jumbop_failures, jumbo9_failures, - jumbo16_failures, jumbop_size / 1024); + "(%juk/9k/16k)\n", netstat_bt_get_failures(jumbop), + netstat_bt_get_failures(jumbo9), netstat_bt_get_failures(jumbo16), + netstat_bt_get_size(jumbop) / 1024); + + printf("%ju/%ju/%ju sfbufs in use (current/peak/max)\n", + netstat_mbt_get_sf_bufs_inuse(mbtp), + netstat_mbt_get_sf_bufs_peak(mbtp), + netstat_mbt_get_sf_bufs(mbtp)); - 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(mbstat); - if (sysctlbyname("kern.ipc.mbstat", &mbstat, &mlen, NULL, 0)) { - warn("kern.ipc.mbstat"); - goto out; - } - } else { - if (kread(mbaddr, (char *)&mbstat, sizeof mbstat) != 0) - goto out; - } - printf("%lu requests for sfbufs denied\n", mbstat.sf_allocfail); - printf("%lu requests for sfbufs delayed\n", mbstat.sf_allocwait); - printf("%lu requests for I/O initiated by sendfile\n", - mbstat.sf_iocnt); - printf("%lu calls to protocol drain routines\n", mbstat.m_drain); + printf("%ju requests for sfbufs denied\n", + netstat_mbt_get_sf_allocfail(mbtp)); + printf("%ju requests for sfbufs delayed\n", + netstat_mbt_get_sf_allocwait(mbtp)); + printf("%ju requests for I/O initiated by sendfile\n", + netstat_mbt_get_sf_iocnt(mbtp)); + printf("%ju calls to protocol drain routines\n", + netstat_mbt_get_drain(mbtp)); out: - memstat_mtl_free(mtlp); + netstat_mbt_free(mbtp); } Index: usr.bin/netstat/atalk.c =================================================================== --- usr.bin/netstat/atalk.c (revision 209358) +++ usr.bin/netstat/atalk.c (working copy) @@ -58,7 +58,8 @@ #include #include #include -#include "netstat.h" +#include +#include "extern.h" struct ddpcb ddpcb; struct socket sockb; @@ -260,30 +261,26 @@ } } -#define ANY(x,y,z) if (x || sflag <= 1) \ - printf("\t%lu %s%s%s\n",x,y,plural(x),z) - /* * Dump DDP statistics structure. */ void -ddp_stats(u_long off __unused, const char *name, int af1 __unused, - int proto __unused) +ddp_stats(const struct stat_type *sttp) { - struct ddpstat ddpstat; + const struct ddp_stat *s; - if (off == 0) - return; - kread(off, (char *)&ddpstat, sizeof (ddpstat)); - printf("%s:\n", name); - ANY(ddpstat.ddps_short, "packet", " with short headers "); - ANY(ddpstat.ddps_long, "packet", " with long headers "); - ANY(ddpstat.ddps_nosum, "packet", " with no checksum "); - ANY(ddpstat.ddps_tooshort, "packet", " too short "); - ANY(ddpstat.ddps_badsum, "packet", " with bad checksum "); - ANY(ddpstat.ddps_toosmall, "packet", " with not enough data "); - ANY(ddpstat.ddps_forward, "packet", " forwarded "); - ANY(ddpstat.ddps_encap, "packet", " encapsulated "); - ANY(ddpstat.ddps_cantforward, "packet", " rcvd for unreachable dest "); - ANY(ddpstat.ddps_nosockspace, "packet", " dropped due to no socket space "); + s = netstat_get_ddpstats(sttp); +#define ANY(x,y,z) if (netstat_ddps_get_##x(s) || sflag <= 1) \ + printf("\t%ju %s%s%s\n",netstat_ddps_get_##x(s),y,\ + plural(netstat_ddps_get_##x(s)),z) + ANY(short, "packet", " with short headers "); + ANY(long, "packet", " with long headers "); + ANY(nosum, "packet", " with no checksum "); + ANY(tooshort, "packet", " too short "); + ANY(badsum, "packet", " with bad checksum "); + ANY(toosmall, "packet", " with not enough data "); + ANY(forward, "packet", " forwarded "); + ANY(encap, "packet", " encapsulated "); + ANY(cantforward, "packet", " rcvd for unreachable dest "); + ANY(nosockspace, "packet", " dropped due to no socket space "); } Index: usr.bin/netstat/Makefile =================================================================== --- usr.bin/netstat/Makefile (revision 209358) +++ usr.bin/netstat/Makefile (working copy) @@ -5,12 +5,14 @@ PROG= netstat SRCS= if.c inet.c main.c mbuf.c mroute.c netisr.c route.c \ - unix.c atalk.c mroute6.c ipsec.c bpf.c pfkey.c sctp.c + unix.c atalk.c mroute6.c bpf.c sctp.c WARNS?= 3 CFLAGS+=-fno-strict-aliasing CFLAGS+=-DIPSEC +SRCS+= pfkey.c ipsec.c + CFLAGS+=-DSCTP .if ${MK_INET6_SUPPORT} != "no" @@ -20,9 +22,13 @@ BINGRP= kmem BINMODE=2555 -DPADD= ${LIBKVM} ${LIBMEMSTAT} ${LIBUTIL} -LDADD= -lkvm -lmemstat -lutil +DPADD= ${LIBKVM} ${LIBMEMSTAT} ${LIBUTIL} ${LIBNETSTAT} +LDADD= -lkvm -lmemstat -lutil -lnetstat +# XXX: temp. solution +#CFLAGS+= -I../../lib/libnetstat -g +#LDFLAGS+= -L../../lib/libnetstat + .if ${MK_NETGRAPH_SUPPORT} != "no" SRCS+= netgraph.c DPADD+= ${LIBNETGRAPH} Index: contrib/bsnmp/snmp_mibII/mibII_tcp.c =================================================================== --- contrib/bsnmp/snmp_mibII/mibII_tcp.c (revision 209358) +++ contrib/bsnmp/snmp_mibII/mibII_tcp.c (working copy) @@ -38,16 +38,15 @@ #include #include #include +#include struct tcp_index { struct asn_oid index; - struct xtcpcb *tp; + enum tcp_state tcp_state; }; static uint64_t tcp_tick; static struct tcpstat tcpstat; -static struct xinpgen *xinpgen; -static size_t xinpgen_len; static u_int tcp_count; static u_int tcp_total; @@ -67,11 +66,20 @@ fetch_tcp(void) { size_t len; - struct xinpgen *ptr; - struct xtcpcb *tp; struct tcp_index *oid; + + struct socket_type_list *stlp; + struct socket_type_iterator *stip; + const struct socket_type *stp; + struct sockaddr_type *satp; + struct session_type *session; + int error; + + struct in_addr in; in_addr_t inaddr; + session = netstat_session_new(NULL); + len = sizeof(tcpstat); if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, NULL, 0) == -1) { syslog(LOG_ERR, "net.inet.tcp.stats: %m"); @@ -82,39 +90,32 @@ return (-1); } - len = 0; - if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) == -1) { - syslog(LOG_ERR, "net.inet.tcp.pcblist: %m"); + stlp = netstat_stl_alloc(); + if (stlp == NULL) { + syslog(LOG_ERR, "netstat_stl_alloc() in fetch_tcp()"); return (-1); } - if (len > xinpgen_len) { - if ((ptr = realloc(xinpgen, len)) == NULL) { - syslog(LOG_ERR, "%zu: %m", len); - return (-1); - } - xinpgen = ptr; - xinpgen_len = len; + if (netstat_socket(session, PF_INET, 0, IPPROTO_TCP, stlp, + NETSTAT_SOCKET_ALL) < 0) { + error = netstat_stl_geterror(stlp); + syslog(LOG_ERR, "netstat_socket: %s", netstat_strerror(error)); + return (-1); } - if (sysctlbyname("net.inet.tcp.pcblist", xinpgen, &len, NULL, 0) == -1) { - syslog(LOG_ERR, "net.inet.tcp.pcblist: %m"); + if (netstat_sti_alloc(stlp, &stip) < 0) { + netstat_stl_free(stlp); + syslog(LOG_ERR, "netstat_sti_alloc() in fetch_tcp()"); return (-1); } tcp_tick = get_ticks(); - tcp_count = 0; tcp_total = 0; - for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); - ptr->xig_len > sizeof(struct xinpgen); - ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { - tp = (struct xtcpcb *)ptr; - if (tp->xt_inp.inp_gencnt > xinpgen->xig_gen || - (tp->xt_inp.inp_vflag & INP_IPV4) == 0) - continue; + for (stp = netstat_sti_first(stip); stp != NULL; + stp = netstat_sti_next(stip)) { tcp_total++; - if (tp->xt_tp.t_state == TCPS_ESTABLISHED || - tp->xt_tp.t_state == TCPS_CLOSE_WAIT) + if (netstat_st_get_tcps(stp) == tcps_Established || + netstat_st_get_tcps(stp) == tcps_CloseWait) tcp_count++; } @@ -130,32 +131,34 @@ } oid = tcpoids; - for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); - ptr->xig_len > sizeof(struct xinpgen); - ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { - tp = (struct xtcpcb *)ptr; - if (tp->xt_inp.inp_gencnt > xinpgen->xig_gen || - (tp->xt_inp.inp_vflag & INP_IPV4) == 0) - continue; - oid->tp = tp; + + for (stp = netstat_sti_first(stip); stp != NULL; + stp = netstat_sti_next(stip)) { + oid->tcp_state = netstat_st_get_tcps(stp); oid->index.len = 10; - inaddr = ntohl(tp->xt_inp.inp_laddr.s_addr); + satp = netstat_st_get_address(stp, 0); + netstat_sat_get_address(satp, (char *) &in, sizeof(in)); + inaddr = ntohl(in.s_addr); oid->index.subs[0] = (inaddr >> 24) & 0xff; oid->index.subs[1] = (inaddr >> 16) & 0xff; oid->index.subs[2] = (inaddr >> 8) & 0xff; - oid->index.subs[3] = (inaddr >> 0) & 0xff; - oid->index.subs[4] = ntohs(tp->xt_inp.inp_lport); - inaddr = ntohl(tp->xt_inp.inp_faddr.s_addr); + oid->index.subs[3] = (inaddr ) & 0xff; + oid->index.subs[4] = netstat_sat_get_port(satp); + satp = netstat_st_get_address(stp, 1); + netstat_sat_get_address(satp, (char *) &in, sizeof(in)); + inaddr = ntohl(in.s_addr); oid->index.subs[5] = (inaddr >> 24) & 0xff; oid->index.subs[6] = (inaddr >> 16) & 0xff; oid->index.subs[7] = (inaddr >> 8) & 0xff; - oid->index.subs[8] = (inaddr >> 0) & 0xff; - oid->index.subs[9] = ntohs(tp->xt_inp.inp_fport); + oid->index.subs[8] = (inaddr ) & 0xff; + oid->index.subs[9] = netstat_sat_get_port(satp); oid++; } qsort(tcpoids, tcp_total, sizeof(tcpoids[0]), tcp_compare); - + netstat_sti_free(stip); + netstat_stl_free(stlp); + netstat_session_free(session); return (0); } @@ -290,39 +293,39 @@ switch (value->var.subs[sub - 1]) { case LEAF_tcpConnState: - switch (tcpoids[i].tp->xt_tp.t_state) { + switch (tcpoids[i].tcp_state) { - case TCPS_CLOSED: + case tcps_Closed: value->v.integer = 1; break; - case TCPS_LISTEN: + case tcps_Listen: value->v.integer = 2; break; - case TCPS_SYN_SENT: + case tcps_SynSent: value->v.integer = 3; break; - case TCPS_SYN_RECEIVED: + case tcps_SynReceived: value->v.integer = 4; break; - case TCPS_ESTABLISHED: + case tcps_Established: value->v.integer = 5; break; - case TCPS_CLOSE_WAIT: + case tcps_CloseWait: value->v.integer = 8; break; - case TCPS_FIN_WAIT_1: + case tcps_FinWait1: value->v.integer = 6; break; - case TCPS_CLOSING: + case tcps_Closing: value->v.integer = 10; break; - case TCPS_LAST_ACK: + case tcps_LastAck: value->v.integer = 9; break; - case TCPS_FIN_WAIT_2: + case tcps_FinWait2: value->v.integer = 7; break; - case TCPS_TIME_WAIT: + case tcps_TimeWait: value->v.integer = 11; break; default: Index: contrib/bsnmp/snmp_mibII/mibII_udp.c =================================================================== --- contrib/bsnmp/snmp_mibII/mibII_udp.c (revision 209358) +++ contrib/bsnmp/snmp_mibII/mibII_udp.c (working copy) @@ -37,39 +37,41 @@ #include #include #include +#include -struct udp_index { - struct asn_oid index; - struct xinpcb *inp; -}; - static uint64_t udp_tick; static struct udpstat udpstat; -static struct xinpgen *xinpgen; -static size_t xinpgen_len; static u_int udp_total; static u_int oidnum; -static struct udp_index *udpoids; +static struct asn_oid *udpoids; static int udp_compare(const void *p1, const void *p2) { - const struct udp_index *t1 = p1; - const struct udp_index *t2 = p2; + const struct asn_oid *t1 = p1; + const struct asn_oid *t2 = p2; - return (asn_compare_oid(&t1->index, &t2->index)); + return (asn_compare_oid(t1, t2)); } static int fetch_udp(void) { size_t len; - struct xinpgen *ptr; - struct xinpcb *inp; - struct udp_index *oid; + struct socket_type_list *stlp; + struct socket_type_iterator *stip; + const struct socket_type *stp; + struct sockaddr_type *satp; + struct session_type *session; + int error; + + struct asn_oid *oid; + struct in_addr in; in_addr_t inaddr; + session = netstat_session_new(NULL); + len = sizeof(udpstat); if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, NULL, 0) == -1) { syslog(LOG_ERR, "net.inet.udp.stats: %m"); @@ -80,38 +82,26 @@ return (-1); } - udp_tick = get_ticks(); - - len = 0; - if (sysctlbyname("net.inet.udp.pcblist", NULL, &len, NULL, 0) == -1) { - syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); + stlp = netstat_stl_alloc(); + if (stlp == NULL) { + syslog(LOG_ERR, "netstat_stl_alloc() in fetch_udp()"); return (-1); } - if (len > xinpgen_len) { - if ((ptr = realloc(xinpgen, len)) == NULL) { - syslog(LOG_ERR, "%zu: %m", len); - return (-1); - } - xinpgen = ptr; - xinpgen_len = len; + if (netstat_socket(session, PF_INET, 0, IPPROTO_UDP, stlp, + NETSTAT_SOCKET_ALL) < 0) { + error = netstat_stl_geterror(stlp); + syslog(LOG_ERR, "netstat_socket: %s", netstat_strerror(error)); + return (-1); } - if (sysctlbyname("net.inet.udp.pcblist", xinpgen, &len, NULL, 0) == -1) { - syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); + if (netstat_sti_alloc(stlp, &stip) < 0) { + netstat_stl_free(stlp); + syslog(LOG_ERR, "netstat_sti_alloc() in fetch_udp()"); return (-1); } - udp_total = 0; - for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); - ptr->xig_len > sizeof(struct xinpgen); - ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { - inp = (struct xinpcb *)ptr; - if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen || - (inp->xi_inp.inp_vflag & INP_IPV4) == 0) - continue; + udp_tick = get_ticks(); + udp_total = netstat_stl_length(stlp); - udp_total++; - } - if (oidnum < udp_total) { oid = realloc(udpoids, udp_total * sizeof(udpoids[0])); if (oid == NULL) { @@ -124,26 +114,25 @@ } oid = udpoids; - for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); - ptr->xig_len > sizeof(struct xinpgen); - ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { - inp = (struct xinpcb *)ptr; - if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen || - (inp->xi_inp.inp_vflag & INP_IPV4) == 0) - continue; - oid->inp = inp; - oid->index.len = 5; - inaddr = ntohl(inp->xi_inp.inp_laddr.s_addr); - oid->index.subs[0] = (inaddr >> 24) & 0xff; - oid->index.subs[1] = (inaddr >> 16) & 0xff; - oid->index.subs[2] = (inaddr >> 8) & 0xff; - oid->index.subs[3] = (inaddr >> 0) & 0xff; - oid->index.subs[4] = ntohs(inp->xi_inp.inp_lport); + + for (stp = netstat_sti_first(stip); stp != NULL; + stp = netstat_sti_next(stip)) { + oid->len = 5; + satp = netstat_st_get_address(stp, 0); + netstat_sat_get_address(satp, (char *) &in, sizeof(in)); + inaddr = ntohl(in.s_addr); + oid->subs[0] = (inaddr << 24) & 0xff; + oid->subs[1] = (inaddr << 16) & 0xff; + oid->subs[2] = (inaddr << 8) & 0xff; + oid->subs[3] = (inaddr ) & 0xff; + oid->subs[4] = netstat_sat_get_port(satp); oid++; } qsort(udpoids, udp_total, sizeof(udpoids[0]), udp_compare); - + netstat_sti_free(stip); + netstat_stl_free(stlp); + netstat_session_free(session); return (0); } @@ -211,16 +200,16 @@ case SNMP_OP_GETNEXT: for (i = 0; i < udp_total; i++) - if (index_compare(&value->var, sub, &udpoids[i].index) < 0) + if (index_compare(&value->var, sub, &udpoids[i]) < 0) break; if (i == udp_total) return (SNMP_ERR_NOSUCHNAME); - index_append(&value->var, sub, &udpoids[i].index); + index_append(&value->var, sub, &udpoids[i]); break; case SNMP_OP_GET: for (i = 0; i < udp_total; i++) - if (index_compare(&value->var, sub, &udpoids[i].index) == 0) + if (index_compare(&value->var, sub, &udpoids[i]) == 0) break; if (i == udp_total) return (SNMP_ERR_NOSUCHNAME); @@ -238,14 +227,14 @@ switch (value->var.subs[sub - 1]) { case LEAF_udpLocalAddress: - value->v.ipaddress[0] = udpoids[i].index.subs[0]; - value->v.ipaddress[1] = udpoids[i].index.subs[1]; - value->v.ipaddress[2] = udpoids[i].index.subs[2]; - value->v.ipaddress[3] = udpoids[i].index.subs[3]; + value->v.ipaddress[0] = udpoids[i].subs[0]; + value->v.ipaddress[1] = udpoids[i].subs[1]; + value->v.ipaddress[2] = udpoids[i].subs[2]; + value->v.ipaddress[3] = udpoids[i].subs[3]; break; case LEAF_udpLocalPort: - value->v.integer = udpoids[i].index.subs[4]; + value->v.integer = udpoids[i].subs[4]; break; } Index: share/mk/bsd.libnames.mk =================================================================== --- share/mk/bsd.libnames.mk (revision 209358) +++ share/mk/bsd.libnames.mk (working copy) @@ -98,6 +98,7 @@ LIBNCURSES?= ${DESTDIR}${LIBDIR}/libncurses.a LIBNCURSESW?= ${DESTDIR}${LIBDIR}/libncursesw.a LIBNETGRAPH?= ${DESTDIR}${LIBDIR}/libnetgraph.a +LIBNETSTAT?= ${DESTDIR}${LIBDIR}/libnetstat.a LIBNGATM?= ${DESTDIR}${LIBDIR}/libngatm.a LIBNVPAIR?= ${DESTDIR}${LIBDIR}/libnvpair.a LIBOBJC?= ${DESTDIR}${LIBDIR}/libobjc.a Index: usr.sbin/bsnmpd/modules/snmp_mibII/Makefile =================================================================== --- usr.sbin/bsnmpd/modules/snmp_mibII/Makefile (revision 209358) +++ usr.sbin/bsnmpd/modules/snmp_mibII/Makefile (working copy) @@ -13,9 +13,13 @@ ipForward ifIndex linkDown linkUp MAN= snmp_mibII.3 -CFLAGS+= -I${CONTRIB}/lib -I${CONTRIB}/snmpd +CFLAGS+= -I${CONTRIB}/lib -I${CONTRIB}/snmpd -I../../../../lib/libnetstat CFLAGS+= -DHAVE_ERR_H -DHAVE_GETADDRINFO -DHAVE_STRLCPY -DHAVE_SYS_TREE_H +DPADD= ${LIBNETSTAT} +LDADD= -lnetstat +LDFLAGS+= -L../../../../lib/libnetstat + DEFS= ${MOD}_tree.def INCS= snmp_${MOD}.h BMIBS= BEGEMOT-IP-MIB.txt BEGEMOT-MIB2-MIB.txt Index: lib/Makefile =================================================================== --- lib/Makefile (revision 209358) +++ lib/Makefile (working copy) @@ -82,7 +82,8 @@ ${_libmilter} \ ${_libmp} \ ${_libncp} \ - ${_libngatm} \ + libnetstat \ + ${_libngatm} \ libopie \ libpam \ libpcap \ Index: lib/libnetstat/netstat_util.c =================================================================== --- lib/libnetstat/netstat_util.c (revision 0) +++ lib/libnetstat/netstat_util.c (revision 0) @@ -0,0 +1,3340 @@ +/*- + * Copyright (c) 2009, 2010 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef INET6 +#define _KERNEL +#include +#undef _KERNEL +#endif /* !INET6 */ + +#include +#include +#include +#include +#include +#include + +#include "netstat.h" +#include "netstat_internal.h" + +/* Macros used to allocate memory for allocators and iterators */ +#define MALLOC_PTR(pointer) pointer = malloc(sizeof(*pointer)); \ + if (pointer == NULL) \ + return(NULL); \ + +#define MALLOC_ITR(pointer) pointer = malloc(sizeof(*pointer)); \ + if (pointer == NULL) \ + return(-1); \ + +int +kread_data(kvm_t *kvm, u_long kvm_pointer, void *address, size_t size) +{ + ssize_t ret; + + ret = kvm_read(kvm, kvm_pointer, address, size); + if (ret < 0) + return (NETSTAT_ERROR_KVM); + if ((size_t)ret != size) + return (NETSTAT_ERROR_KVM_SHORTREAD); + return (0); +} + +int +kread_string(kvm_t *kvm, u_long kvm_pointer, char *buffer, int buflen) +{ + ssize_t ret; + int i; + + for (i = 0; i < buflen; i++) { + ret = kvm_read(kvm, kvm_pointer + i, &(buffer[i]), + sizeof(char)); + if (ret < 0) + return (NETSTAT_ERROR_KVM); + if ((size_t)ret != sizeof(char)) + return (NETSTAT_ERROR_KVM_SHORTREAD); + if (buffer[i] == '\0') + return (0); + } + buffer[i - 1] = '\0'; + return (0); +} + +/* + * Copied directly from uip_socket2.c. We leave out some fields that are in + * nested structures that aren't used to avoid extra work. + */ +static void +sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb) +{ + xsb->sb_cc = sb->sb_cc; + xsb->sb_hiwat = sb->sb_hiwat; + xsb->sb_mbcnt = sb->sb_mbcnt; + xsb->sb_mcnt = sb->sb_mcnt; + xsb->sb_ccnt = sb->sb_ccnt; + xsb->sb_mbmax = sb->sb_mbmax; + xsb->sb_lowat = sb->sb_lowat; + xsb->sb_flags = sb->sb_flags; + xsb->sb_timeo = sb->sb_timeo; +} + +int +sotoxsocket(kvm_t *kvm, struct socket *so, struct xsocket *xso) +{ + struct protosw proto; + struct domain domain; + + bzero(xso, sizeof *xso); + xso->xso_len = sizeof *xso; + xso->xso_so = so; + xso->so_type = so->so_type; + xso->so_options = so->so_options; + xso->so_linger = so->so_linger; + xso->so_state = so->so_state; + xso->so_pcb = so->so_pcb; + if (kread_data(kvm, (uintptr_t)so->so_proto, &proto, sizeof(proto)) + != 0) + return (-1); + xso->xso_protocol = proto.pr_protocol; + if (kread_data(kvm, (uintptr_t)proto.pr_domain, &domain, + sizeof(domain)) != 0) + return (-1); + xso->xso_family = domain.dom_family; + xso->so_qlen = so->so_qlen; + xso->so_incqlen = so->so_incqlen; + xso->so_qlimit = so->so_qlimit; + xso->so_timeo = so->so_timeo; + xso->so_error = so->so_error; + xso->so_oobmark = so->so_oobmark; + sbtoxsockbuf(&so->so_snd, &xso->so_snd); + sbtoxsockbuf(&so->so_rcv, &xso->so_rcv); + return (0); +} + +#ifdef INET6 +int +_mrt6_get_nstall_kvm(kvm_t *kvm, struct mf6c *m) +{ + int result; + struct rtdetq rte, *rtep; + + result = 0; + for (rtep = m->mf6c_stall; rtep != NULL; rtep = rte.next) { + kread_data(kvm, (uintptr_t)rtep, &rte, sizeof(rte)); + result++; + } + + return (result); +} +#endif /* !INET6 */ + +const char * +netstat_strerror(int error) +{ + switch (error) { + case NETSTAT_ERROR_NOMEMORY: + return ("Cannot allocate memory"); + case NETSTAT_ERROR_VERSION: + return ("Version mismatch"); + case NETSTAT_ERROR_KVM: + return ("KVM error"); + case NETSTAT_ERROR_KVM_NOSYMBOL: + return ("KVM unable to find symbol"); + case NETSTAT_ERROR_KVM_SHORTREAD: + return ("KVM short read"); + case NETSTAT_ERROR_UNSUPPORTED: + return ("Unsupported operation"); + case NETSTAT_ERROR_UNDEFINED: + default: + return ("Unknown error"); + } +} + +const char * +netstat_kvmerror(const struct session_type *session) +{ + if (session->sst_flags & NETSTAT_SESSION_KVM) + return (kvm_geterr(session->sst_kvm)); + return ("Unknown error"); +} + +const char * +netstat_family_name(int pf) +{ + const char *pfname; + static char buf[64]; + + switch (pf) { + case PF_INET: + pfname = "Internet"; + break; +#ifdef INET6 + case PF_INET6: + pfname = "Internet6"; + break; +#endif + case PF_IPX: + pfname = "IPX"; + break; + case PF_ISO: + pfname = "ISO"; + break; + case PF_APPLETALK: + pfname = "AppleTalk"; + break; + case PF_CCITT: + pfname = "X.25"; + break; + case PF_NETGRAPH: + pfname = "Netgraph"; + break; + default: + pfname = NULL; + break; + } + + if (pfname != NULL) + snprintf(buf, sizeof(buf), "%s", pfname); + else + snprintf(buf, sizeof(buf), "Protocol Family %d", pf); + + return (buf); +} + +struct session_type * +netstat_session_new(void *kvm_handle) +{ + struct session_type *sstp; + + MALLOC_PTR(sstp); + + bzero(sstp, sizeof(*sstp)); + + if (kvm_handle != NULL) { + sstp->sst_flags |= NETSTAT_SESSION_KVM; + sstp->sst_kvm = (kvm_t *)kvm_handle; + } + return (sstp); +} + +void +netstat_session_free(struct session_type *session) +{ + free(session); +} + +struct socket_type_list * +netstat_stl_alloc(void) +{ + struct socket_type_list *stlp; + + MALLOC_PTR(stlp); + + LIST_INIT(&stlp->stl_list); + stlp->stl_error = NETSTAT_ERROR_UNDEFINED; + stlp->stl_length = 0; + return (stlp); +} + +void +netstat_stl_iterate(struct socket_type_list *list, + void (*func)(struct socket_type *)) +{ + struct socket_type *stp; + + /* XXX: Keep eye on disappering connections. */ + LIST_FOREACH(stp, &list->stl_list, st_list) + func(stp); +} + +void +_netstat_stl_empty(struct socket_type_list *list) +{ + struct socket_type *stp; + + while ((stp = LIST_FIRST(&list->stl_list))) { + LIST_REMOVE(stp, st_list); + netstat_st_free(stp); + } + + list->stl_length = 0; +} + +void +netstat_st_free(struct socket_type *stp) +{ + int i; + + for (i = 0; i < stp->st_addrcnt; i++) + netstat_sat_free(stp->st_address[i]); + free(stp); +} + +void +netstat_stl_free(struct socket_type_list *list) +{ + _netstat_stl_empty(list); + free(list); +} + +int +netstat_stl_geterror(struct socket_type_list *list) +{ + return (list->stl_error); +} + +int +netstat_stl_refresh(struct socket_type_list *list) +{ + /* XXX: it is a dummy yet */ + return (0); +} + +int +netstat_stl_length(struct socket_type_list *list) +{ + return (list->stl_length); +} + +struct socket_type * +netstat_stl_find(struct socket_type_list *list, unsigned short family, + const char *name) +{ + struct socket_type *stp; + + /* XXX: Keep eye on disappering connections. */ + LIST_FOREACH(stp, &list->stl_list, st_list) { + if ((stp->st_family == family || + family == PF_UNSPEC) && + strcmp(stp->st_name, name) == 0) + return (stp); + } + return (NULL); +} + +struct socket_type * +_netstat_st_allocate(struct socket_type_list *list, unsigned short family, + unsigned short protocol, const char *name) +{ + struct socket_type *stp; + + MALLOC_PTR(stp); + + bzero(stp, sizeof(*stp)); + + stp->st_family = family; + stp->st_protocol = protocol; + stp->st_flags = 0; + strlcpy(stp->st_name, name, SOCKTYPE_MAXNAME); + LIST_INSERT_HEAD(&list->stl_list, stp, st_list); + list->stl_length += 1; + return (stp); +} + +void +_netstat_st_reset_stats(struct socket_type *stp) +{ + /* XXX: empty */ +} + +/* Socket type iterator. */ +int +netstat_sti_alloc(struct socket_type_list *list, + struct socket_type_iterator **iterator) +{ + struct socket_type_iterator *itp; + + MALLOC_ITR(itp); + + bzero(itp, sizeof(*itp)); + + itp->sti_list = list; + itp->sti_first = LIST_FIRST(&list->stl_list); + itp->sti_next = LIST_NEXT(itp->sti_first, st_list); + *iterator = itp; + return (0); +} + +const struct socket_type * +netstat_sti_first(struct socket_type_iterator *iterator) +{ + /* "Reset" iteration. */ + iterator->sti_next = LIST_NEXT(iterator->sti_first, st_list); + return (iterator->sti_first); +} + +const struct socket_type * +netstat_sti_next(struct socket_type_iterator *iterator) +{ + const struct socket_type *stp; + + /* "Step" iteration. */ + stp = iterator->sti_next; + if (iterator->sti_next != NULL) + iterator->sti_next = LIST_NEXT(iterator->sti_next, st_list); + + return (stp); +} + +void +netstat_sti_free(struct socket_type_iterator *iterator) +{ + free(iterator); +} + +/* Socket address type */ +struct sockaddr_type * +_netstat_sat_allocate(struct socket_type *parent, int type, const char *name, + char *address, int addr_len) +{ + struct sockaddr_type *satp; + + MALLOC_PTR(satp); + + bzero(satp, sizeof(*satp)); + satp->sat_type = type; + satp->sat_parent = parent; + strlcpy(satp->sat_name, name, 1024); + if (address != NULL && addr_len > 0) { + satp->sat_address = (char *)malloc(addr_len); + if (satp->sat_address == NULL) { + free(satp); + satp = NULL; + } else { + memcpy(satp->sat_address, address, addr_len); + satp->sat_address_len = addr_len; + } + } + return (satp); +} + +void +netstat_sat_free(struct sockaddr_type *satp) +{ + if (satp->sat_address != NULL) + free(satp->sat_address); + free(satp); +} + + +/* Accessor macros. */ + +#define ACCESSOR(returns, tp, type, field) \ +returns \ +netstat_##tp##t_get_##field(const struct type##_type *a) \ +{ \ + return (a->tp##t_##field); \ +} + +#define ACCESSORP(returns, tp, type, field) \ +returns \ +netstat_##tp##t_get_##field(const struct type##_type *a) \ +{ \ + return (&a->tp##t_##field); \ +} + + +/* Accessor functions. */ + +#define SOCKET_ACC(returns, field) \ + ACCESSOR(returns, s, socket, field) + +#define SOCKET_ACCP(returns, field) \ + ACCESSORP(returns, s, socket, field) + +SOCKET_ACC (int, family); +SOCKET_ACC (int, protocol); +SOCKET_ACC (const char *, name); +SOCKET_ACC (const char *, extname); +SOCKET_ACCP(const struct sockbuf_type *, snd); +SOCKET_ACCP(const struct sockbuf_type *, rcv); +SOCKET_ACC (u_int16_t, qlen); +SOCKET_ACC (u_int16_t, incqlen); +SOCKET_ACC (u_int16_t, qlimit); +SOCKET_ACC (u_int64_t, pcb); +SOCKET_ACC (u_int64_t, vnode); +SOCKET_ACC (u_int64_t, conn); +SOCKET_ACC (u_int64_t, refs); +SOCKET_ACC (u_int64_t, reflink); +SOCKET_ACC (const char *, tcpstate); +SOCKET_ACC (enum tcp_state, tcps); +SOCKET_ACC (int, addrcnt); + +struct sockaddr_type * +netstat_st_get_address(const struct socket_type *stp, + int index) +{ + if (0 <= index && index < stp->st_addrcnt) { + return (stp->st_address[index]); + } + + return (NULL); +} + +#undef SOCKET_ACC +#undef SOCKET_ACCP + +#define SOCKADDR_ACC(returns, field) \ + ACCESSOR(returns, sa, sockaddr, field) + +SOCKADDR_ACC(const char *, numeric); +SOCKADDR_ACC(u_int16_t, port); + +const char * +netstat_sat_get_name(struct sockaddr_type *satp) +{ + if ((satp->sat_flags & SOCKADDRTYPE_NAME_RESOLVED) == 0) { + _netstat_sat_resolve_name(satp); + } + return (satp->sat_name); +} + +int +netstat_sat_get_address(const struct sockaddr_type *satp, char *addr, int size) +{ + if ((satp->sat_address != NULL) && (addr != NULL) && + (satp->sat_address_len <= size)) { + memcpy(addr, satp->sat_address, satp->sat_address_len); + return (satp->sat_address_len); + } + + return (0); +} + +const char * +netstat_sat_get_portname(struct sockaddr_type *satp) +{ + if ((satp->sat_flags & SOCKADDRTYPE_PORT_RESOLVED) == 0) { + _netstat_sat_resolve_portname(satp); + } + return (satp->sat_portname); +} + +#undef SOCKADDR_ACC + +#define SOCKBUF_ACC(returns, field) \ + ACCESSOR(returns, sb, sockbuf, field) + +SOCKBUF_ACC(u_int32_t, cc); +SOCKBUF_ACC(u_int32_t, hiwat); +SOCKBUF_ACC(u_int32_t, lowat); +SOCKBUF_ACC(u_int32_t, mbcnt); +SOCKBUF_ACC(u_int32_t, mcnt); +SOCKBUF_ACC(u_int32_t, ccnt); +SOCKBUF_ACC(u_int32_t, mbmax); + +#undef SOCKBUF_ACC + +/* Memory buffer type */ +struct mbuf_type * +netstat_mbt_alloc(void) +{ + struct mbuf_type *mbtp; + + MALLOC_PTR(mbtp); + + bzero(mbtp, sizeof(*mbtp)); + return (mbtp); +} + +void +netstat_mbt_free(struct mbuf_type *mbtp) +{ + free(mbtp); +} + +#define MBUF_ACC(returns, field) \ + ACCESSOR(returns, mb, mbuf, field) + +#define MBUF_ACCP(returns, field) \ + ACCESSORP(returns, mb, mbuf, field) + +MBUF_ACC (int, error); +MBUF_ACCP(const struct buffer_type *, mbuf); +MBUF_ACCP(const struct buffer_type *, cluster); +MBUF_ACCP(const struct buffer_type *, packet); +MBUF_ACCP(const struct buffer_type *, tag); +MBUF_ACCP(const struct buffer_type *, jumbop); +MBUF_ACCP(const struct buffer_type *, jumbo9); +MBUF_ACCP(const struct buffer_type *, jumbo16); +MBUF_ACC (u_int64_t, bytes_inuse); +MBUF_ACC (u_int64_t, bytes_incache); +MBUF_ACC (u_int64_t, bytes_total); +MBUF_ACC (u_int64_t, drain); +MBUF_ACC (u_int64_t, sf_bufs); +MBUF_ACC (u_int64_t, sf_bufs_peak); +MBUF_ACC (u_int64_t, sf_bufs_inuse); +MBUF_ACC (u_int64_t, sf_iocnt); +MBUF_ACC (u_int64_t, sf_allocfail); +MBUF_ACC (u_int64_t, sf_allocwait); + +#undef MBUF_ACC +#undef MBUF_ACCP + +/* Buffer type */ + +#define BUFFER_ACC(returns, field) \ + ACCESSOR(returns, b, buffer, field) + +BUFFER_ACC(u_int64_t, count); +BUFFER_ACC(u_int64_t, bytes); +BUFFER_ACC(u_int64_t, free); +BUFFER_ACC(u_int64_t, failures); +BUFFER_ACC(u_int64_t, size); +BUFFER_ACC(u_int64_t, limit); + +#undef BUFFER_ACC + +struct interface_type * +_netstat_it_allocate(struct interface_type_list *list, int type, int physical, + const char *name) +{ + struct interface_type *itp; + + MALLOC_PTR(itp); + + bzero(itp, sizeof(*itp)); + + itp->it_type = type; + itp->it_physical = physical; + strlcpy(itp->it_name, name, IFTYPE_MAXNAME); + TAILQ_INSERT_TAIL(&list->itl_list, itp, it_list); + list->itl_length += 1; + return (itp); +} + +struct intfaddr_type * +_netstat_iat_allocate(int family, int type) +{ + struct intfaddr_type *iatp; + + MALLOC_PTR(iatp); + + bzero(iatp, sizeof(*iatp)); + iatp->iat_family = family; + iatp->iat_type = type; + iatp->iat_layer = layer_None; + return (iatp); +} + +struct interface_type_list * +netstat_itl_alloc(void) +{ + struct interface_type_list *itlp; + + MALLOC_PTR(itlp); + + TAILQ_INIT(&itlp->itl_list); + itlp->itl_error = NETSTAT_ERROR_UNDEFINED; + itlp->itl_length = 0; + return (itlp); +} + +void +_netstat_itl_empty(struct interface_type_list *list) +{ + struct interface_type *itp; + + while ((itp = TAILQ_FIRST(&list->itl_list))) { + TAILQ_REMOVE(&list->itl_list, itp, it_list); + netstat_it_free(itp); + } + + list->itl_length = 0; +} + +void +netstat_itl_free(struct interface_type_list *list) +{ + _netstat_itl_empty(list); + free(list); +} + +int +netstat_itl_geterror(const struct interface_type_list *list) +{ + return (list->itl_error); +} + +int +netstat_itl_length(const struct interface_type_list *list) +{ + return (list->itl_length); +} + +int +netstat_iti_alloc(struct interface_type_list *list, + struct interface_type_iterator **iterator) +{ + struct interface_type_iterator *itp; + + MALLOC_ITR(itp); + + bzero(itp, sizeof(*itp)); + + itp->iti_list = list; + itp->iti_first = TAILQ_FIRST(&list->itl_list); + if (itp->iti_first != NULL) + itp->iti_next = TAILQ_NEXT(itp->iti_first, it_list); + *iterator = itp; + return (0); +} + +const struct interface_type * +netstat_iti_first(struct interface_type_iterator *itip) +{ + itip->iti_next = TAILQ_NEXT(itip->iti_first, it_list); + return (itip->iti_first); +} + +const struct interface_type * +netstat_iti_next(struct interface_type_iterator *itip) +{ + const struct interface_type *itp; + + itp = itip->iti_next; + if (itip->iti_next != NULL) + itip->iti_next = TAILQ_NEXT(itip->iti_next, it_list); + + return (itp); +} + +void +netstat_iti_free(struct interface_type_iterator *itip) +{ + free(itip); +} + +void +netstat_it_free(struct interface_type *itp) +{ + int i; + + for (i = 0; itp->it_address[i] != NULL && i < IFTYPE_MAXADDRCNT; i++) + netstat_iat_free(itp->it_address[i]); + + for (i = 0; itp->it_maddress[i] != NULL && i < IFTYPE_MAXADDRCNT; i++) + netstat_iat_free(itp->it_maddress[i]); + + free(itp); +} + +void +netstat_iat_free(struct intfaddr_type *iatp) +{ + free(iatp->iat_address); + free(iatp->iat_network); + free(iatp->iat_sockaddr); + free(iatp->iat_ifaddr); + free(iatp); +} + + +#define INTERFACE_ACC(returns, field) \ + ACCESSOR(returns, i, interface, field) + +#define INTERFACE_ACCP(returns, field) \ + ACCESSORP(returns, i, interface, field) + +INTERFACE_ACC (const char *, name); +INTERFACE_ACC (u_int64_t, mtu); +INTERFACE_ACC (int, flags); +INTERFACE_ACC (u_int64_t, collisions); +INTERFACE_ACC (u_int64_t, drops); +INTERFACE_ACCP(const struct face_type *, in); +INTERFACE_ACCP(const struct face_type *, out); +INTERFACE_ACC (int, addrcnt); +INTERFACE_ACC (int, mcast_addrcnt); + +const struct intfaddr_type * +netstat_it_get_address(const struct interface_type *itp, int index) +{ + if (0 <= index && index < itp->it_addrcnt) + return (itp->it_address[index]); + return (NULL); +} + +const struct intfaddr_type * +netstat_it_get_mcast_address(const struct interface_type *itp, int index) +{ + if (0 <= index && index < itp->it_mcast_addrcnt) + return (itp->it_maddress[index]); + return (NULL); +} + +#undef INTERFACE_ACC +#undef INTERFACE_ACCP + +#define FACE_ACC(returns, field) \ + ACCESSOR(returns, f, face, field) + +FACE_ACC(u_int64_t, packets); +FACE_ACC(u_int64_t, bytes); +FACE_ACC(u_int64_t, mcasts); +FACE_ACC(u_int64_t, errors); +FACE_ACC(u_int64_t, drops); + +#undef FACE_ACC + +#define INTFADDR_ACC(returns, field) \ + ACCESSOR(returns, ia, intfaddr, field) + +#define INTFADDR_ACCP(returns, field) \ + ACCESSORP(returns, ia, intfaddr, field) + +INTFADDR_ACC(int, family); +INTFADDR_ACC(enum intfaddr_layer, layer); +INTFADDR_ACC(u_int64_t, ipackets); +INTFADDR_ACC(u_int64_t, ibytes); +INTFADDR_ACC(u_int64_t, opackets); +INTFADDR_ACC(u_int64_t, obytes); +INTFADDR_ACC(u_int32_t, refcount); + +const char * +netstat_iat_get_address(const struct intfaddr_type *iatp, int numeric) +{ + if (numeric) + return (iatp->iat_ni_address); + return (iatp->iat_address); +} + +const char * +netstat_iat_get_network(const struct intfaddr_type *iatp, int numeric) +{ + if (numeric) + return (iatp->iat_ni_network); + return (iatp->iat_network); +} + +#undef INTFADDR_ACC +#undef INTFADDR_ACCP + +void +_netstat_bptl_empty(struct bpf_type_list *list) +{ + struct bpf_type *btp; + + while ((btp = LIST_FIRST(&list->bptl_list))) { + LIST_REMOVE(btp, bpt_list); + netstat_bpt_free(btp); + } + + list->bptl_length = 0; +} + +struct bpf_type * +_netstat_bpt_allocate(struct bpf_type_list *list, const char *ifname) +{ + struct bpf_type *btp; + + MALLOC_PTR(btp); + + bzero(btp, sizeof(*btp)); + strlcpy(btp->bpt_ifname, ifname, BPFTYPE_MAXNAME); + LIST_INSERT_HEAD(&list->bptl_list, btp, bpt_list); + list->bptl_length += 1; + return (btp); +} + +struct bpf_type_list * +netstat_bptl_alloc(void) +{ + struct bpf_type_list *btlp; + + MALLOC_PTR(btlp); + + LIST_INIT(&btlp->bptl_list); + btlp->bptl_error = NETSTAT_ERROR_UNDEFINED; + btlp->bptl_length = 0; + return (btlp); +} + +void +netstat_bptl_free(struct bpf_type_list *list) +{ + _netstat_bptl_empty(list); + free(list); +} + +int +netstat_bptl_geterror(const struct bpf_type_list *list) +{ + return (list->bptl_error); +} + +int +netstat_bptl_length(const struct bpf_type_list *list) +{ + return (list->bptl_length); +} + +int +netstat_bpti_alloc(struct bpf_type_list *list, + struct bpf_type_iterator **iterator) +{ + struct bpf_type_iterator *btp; + + MALLOC_ITR(btp); + + bzero(btp, sizeof(*btp)); + btp->bpti_list = list; + btp->bpti_first = LIST_FIRST(&list->bptl_list); + if (btp->bpti_first != NULL) + btp->bpti_next = LIST_NEXT(btp->bpti_first, bpt_list); + *iterator = btp; + return (0); +} + +const struct bpf_type * +netstat_bpti_first(struct bpf_type_iterator *btip) +{ + if (btip->bpti_first != NULL) + btip->bpti_next = LIST_NEXT(btip->bpti_first, bpt_list); + return (btip->bpti_first); +} + +const struct bpf_type * +netstat_bpti_next(struct bpf_type_iterator *btip) +{ + const struct bpf_type *btp; + + btp = btip->bpti_next; + if (btip->bpti_next != NULL) + btip->bpti_next = LIST_NEXT(btip->bpti_next, bpt_list); + + return (btp); +} + +void +netstat_bpti_free(struct bpf_type_iterator *btip) +{ + free(btip); +} + +void +netstat_bpt_free(struct bpf_type *btp) +{ + free(btp->bpt_pidname); + free(btp); +} + +#define BPF_ACC(returns, field) \ + ACCESSOR(returns, bp, bpf, field) + +BPF_ACC(int, flags); +BPF_ACC(enum bpf_dir, direction); +BPF_ACC(u_int32_t, pid); +BPF_ACC(const char *, ifname); +BPF_ACC(u_int64_t, recv); +BPF_ACC(u_int64_t, drop); +BPF_ACC(u_int64_t, match); +BPF_ACC(u_int64_t, slen); +BPF_ACC(u_int64_t, hlen); +BPF_ACC(const char *, pidname); + +#undef BPF_ACC + +struct stat_type * +netstat_stat_alloc(void) +{ + struct stat_type *sttp; + + MALLOC_PTR(sttp); + + bzero(sttp, sizeof(*sttp)); + return (sttp); +} + +void +netstat_stat_free(struct stat_type *sttp) +{ + if (sttp->stt_type == stat_IPcomp || + sttp->stt_type == stat_SCTP) + free(((struct ipcomp_stat *)sttp->stt_data)->s); + free(sttp->stt_data); + free(sttp); +} + +int +netstat_stat_geterror(const struct stat_type *sttp) +{ + return (sttp->stt_error); +} + + +#define STATS_ACCX(returns, stats, f1, f2) \ +returns \ +netstat_##stats##s_get_##f1(const struct stats##_stat *a) \ +{ \ + return (a->s.f2); \ +} + +#define STATS_ACCXP(returns, stats, f1, f2) \ +returns \ +netstat_##stats##s_get_##f1(const struct stats##_stat *a) \ +{ \ + return (a->s->f2); \ +} + +#define STATS_ACC(returns, stats, field) \ + STATS_ACCX(returns, stats, field, stats##s_##field) + +#define STATS_ACCP(returns, stats, field) \ + STATS_ACCXP(returns, stats, field, stats##s_##field) + +#define STATS_GET(S,I) \ +const struct S##_stat * \ +netstat_get_##S##stats(const struct stat_type *sttp) \ +{ \ + if (sttp->stt_type == stat_##I) \ + return ((const struct S##_stat *)sttp->stt_data); \ + return (NULL); \ +} + +#define STATS_ACCXA(returns, stats, f1, f2, limit) \ +returns \ +netstat_##stats##s_get_##f1(const struct stats##_stat *a, int i) \ +{ \ + if (0 <= i && i < (limit)) \ + return (a->s.f2[i]); \ + return (0); \ +} + +#define STATS_ACCXAP(returns, stats, f1, f2, limit) \ +returns \ +netstat_##stats##s_get_##f1(const struct stats##_stat *a, int i) \ +{ \ + if (0 <= i && i < (limit)) \ + return (a->s->f2[i]); \ + return (0); \ +} + +#define STATS_ACCXE(returns, stats, f1, f2, enty) \ +returns \ +netstat_##stats##s_get_##f1(const struct stats##_stat *a, enum enty i) \ +{ \ + return (a->s.f2[i]); \ +} + +#define STATS_ACCXEP(returns, stats, f1, f2, enty) \ +returns \ +netstat_##stats##s_get_##f1(const struct stats##_stat *a, enum enty i) \ +{ \ + return (a->s->f2[i]); \ +} + + +#define TCP_ACC(field) \ + STATS_ACC(u_int64_t,tcp,field) + +STATS_GET(tcp,TCP); +TCP_ACC(connattempt); +TCP_ACC(accepts); +TCP_ACC(connects); +TCP_ACC(drops); +TCP_ACC(conndrops); +TCP_ACC(minmssdrops); +TCP_ACC(closed); +TCP_ACC(segstimed); +TCP_ACC(rttupdated); +TCP_ACC(delack); +TCP_ACC(timeoutdrop); +TCP_ACC(rexmttimeo); +TCP_ACC(persisttimeo); +TCP_ACC(keeptimeo); +TCP_ACC(keepprobe); +TCP_ACC(keepdrops); +TCP_ACC(sndtotal); +TCP_ACC(sndpack); +TCP_ACC(sndbyte); +TCP_ACC(sndrexmitpack); +TCP_ACC(sndrexmitbyte); +TCP_ACC(sndrexmitbad); +TCP_ACC(sndacks); +TCP_ACC(sndprobe); +TCP_ACC(sndurg); +TCP_ACC(sndwinup); +TCP_ACC(sndctrl); +TCP_ACC(rcvtotal); +TCP_ACC(rcvpack); +TCP_ACC(rcvbyte); +TCP_ACC(rcvbadsum); +TCP_ACC(rcvbadoff); +TCP_ACC(rcvmemdrop); +TCP_ACC(rcvshort); +TCP_ACC(rcvduppack); +TCP_ACC(rcvdupbyte); +TCP_ACC(rcvpartduppack); +TCP_ACC(rcvpartdupbyte); +TCP_ACC(rcvoopack); +TCP_ACC(rcvoobyte); +TCP_ACC(rcvpackafterwin); +TCP_ACC(rcvbyteafterwin); +TCP_ACC(rcvafterclose); +TCP_ACC(rcvwinprobe); +TCP_ACC(rcvdupack); +TCP_ACC(rcvacktoomuch); +TCP_ACC(rcvackpack); +TCP_ACC(rcvackbyte); +TCP_ACC(rcvwinupd); +TCP_ACC(pawsdrop); +TCP_ACC(predack); +TCP_ACC(preddat); +TCP_ACC(pcbcachemiss); +TCP_ACC(cachedrtt); +TCP_ACC(cachedrttvar); +TCP_ACC(cachedssthresh); +TCP_ACC(usedrtt); +TCP_ACC(usedrttvar); +TCP_ACC(usedssthresh); +TCP_ACC(persistdrop); +TCP_ACC(badsyn); +TCP_ACC(mturesent); +TCP_ACC(listendrop); +TCP_ACC(badrst); +TCP_ACC(sc_added); +TCP_ACC(sc_retransmitted); +TCP_ACC(sc_dupsyn); +TCP_ACC(sc_dropped); +TCP_ACC(sc_completed); +TCP_ACC(sc_bucketoverflow); +TCP_ACC(sc_cacheoverflow); +TCP_ACC(sc_reset); +TCP_ACC(sc_stale); +TCP_ACC(sc_aborted); +TCP_ACC(sc_badack); +TCP_ACC(sc_unreach); +TCP_ACC(sc_zonefail); +TCP_ACC(sc_sendcookie); +TCP_ACC(sc_recvcookie); +TCP_ACC(hc_added); +TCP_ACC(hc_bucketoverflow); +TCP_ACC(finwait2_drops); +TCP_ACC(sack_recovery_episode); +TCP_ACC(sack_rexmits); +TCP_ACC(sack_rexmit_bytes); +TCP_ACC(sack_rcv_blocks); +TCP_ACC(sack_send_blocks); +TCP_ACC(sack_sboverflow); +TCP_ACC(ecn_ce); +TCP_ACC(ecn_ect0); +TCP_ACC(ecn_ect1); +TCP_ACC(ecn_shs); +TCP_ACC(ecn_rcwnd); +#undef TCP_ACC + + +#define UDP_ACC(field) \ + STATS_ACC(u_int64_t,udp,field) + +#define UDP_ACCX(f1,f2) \ + STATS_ACCX(u_int64_t,udp,f1,f2) + +STATS_GET(udp,UDP); +UDP_ACC(ipackets); +UDP_ACC(hdrops); +UDP_ACC(badsum); +UDP_ACC(nosum); +UDP_ACC(badlen); +UDP_ACC(noport); +UDP_ACC(noportbcast); +UDP_ACC(fullsock); +UDP_ACCX(pcbcachemiss,udpps_pcbcachemiss); +UDP_ACCX(pcbhashmiss,udpps_pcbhashmiss); +UDP_ACC(delivered); +UDP_ACC(opackets); +UDP_ACC(fastout); +UDP_ACC(noportmcast); +UDP_ACC(filtermcast); +#undef UDP_ACC +#undef UDP_ACCX + + +#define CARP_ACC(field) \ + STATS_ACC(u_int64_t,carp,field) + +STATS_GET(carp,CARP); +CARP_ACC(ipackets); +CARP_ACC(ipackets6); +CARP_ACC(badif); +CARP_ACC(badttl); +CARP_ACC(hdrops); +CARP_ACC(badsum); +CARP_ACC(badver); +CARP_ACC(badlen); +CARP_ACC(badauth); +CARP_ACC(badvhid); +CARP_ACC(badaddrs); +CARP_ACC(opackets); +CARP_ACC(opackets6); +CARP_ACC(onomem); +CARP_ACC(ostates); +CARP_ACC(preempt); +#undef CARP_ACC + + +#define IP_ACC(field) \ + STATS_ACC(u_int64_t,ip,field) + +STATS_GET(ip,IP); +IP_ACC(total); +IP_ACC(badsum); +IP_ACC(tooshort); +IP_ACC(toosmall); +IP_ACC(badhlen); +IP_ACC(badlen); +IP_ACC(fragments); +IP_ACC(fragdropped); +IP_ACC(fragtimeout); +IP_ACC(forward); +IP_ACC(fastforward); +IP_ACC(cantforward); +IP_ACC(redirectsent); +IP_ACC(noproto); +IP_ACC(delivered); +IP_ACC(localout); +IP_ACC(odropped); +IP_ACC(reassembled); +IP_ACC(fragmented); +IP_ACC(ofragments); +IP_ACC(cantfrag); +IP_ACC(badoptions); +IP_ACC(noroute); +IP_ACC(badvers); +IP_ACC(rawout); +IP_ACC(toolong); +IP_ACC(notmember); +IP_ACC(nogif); +IP_ACC(badaddr); +#undef IP_ACC + + +#define ICMP_ACC(field) \ + STATS_ACCX(u_int64_t,icmp,field,icps_##field) + +#define ICMP_ACCA(field) \ + STATS_ACCXA(u_int64_t,icmp,field,icps_##field,ICMP_MAXTYPE) + +STATS_GET(icmp,ICMP); +ICMP_ACCA(inhist); +ICMP_ACCA(outhist); +ICMP_ACC(error); +ICMP_ACC(oldshort); +ICMP_ACC(oldicmp); +ICMP_ACC(badcode); +ICMP_ACC(tooshort); +ICMP_ACC(checksum); +ICMP_ACC(badlen); +ICMP_ACC(reflect); +ICMP_ACC(bmcastecho); +ICMP_ACC(bmcasttstamp); +ICMP_ACC(badaddr); +ICMP_ACC(noroute); +#undef ICMP_ACC +#undef ICMP_ACCA + + +#define PIM_ACC(field) \ + STATS_ACC(u_int64_t,pim,field) + +STATS_GET(pim,PIM); +PIM_ACC(rcv_total_msgs); +PIM_ACC(rcv_total_bytes); +PIM_ACC(rcv_tooshort); +PIM_ACC(rcv_badsum); +PIM_ACC(rcv_badversion); +PIM_ACC(rcv_registers_msgs); +PIM_ACC(rcv_registers_bytes); +PIM_ACC(rcv_registers_wrongiif); +PIM_ACC(rcv_badregisters); +PIM_ACC(snd_registers_msgs); +PIM_ACC(snd_registers_bytes); +#undef PIM_ACC + + +#define IGMP_ACC(field) \ + STATS_ACCX(u_int64_t,igmp,field,igps_##field) + +STATS_GET(igmp,IGMP); +IGMP_ACC(rcv_total); +IGMP_ACC(rcv_tooshort); +IGMP_ACC(rcv_badttl); +IGMP_ACC(rcv_badsum); +IGMP_ACC(rcv_v1v2_queries); +IGMP_ACC(rcv_v3_queries); +IGMP_ACC(rcv_badqueries); +IGMP_ACC(rcv_gen_queries); +IGMP_ACC(rcv_group_queries); +IGMP_ACC(rcv_gsr_queries); +IGMP_ACC(drop_gsr_queries); +IGMP_ACC(rcv_reports); +IGMP_ACC(rcv_badreports); +IGMP_ACC(rcv_ourreports); +IGMP_ACC(rcv_nora); +IGMP_ACC(snd_reports); +#undef IGMP_ACC + +#define DDP_ACC(field) \ + STATS_ACC(u_int64_t,ddp,field) + +STATS_GET(ddp,DDP); +DDP_ACC(short); +DDP_ACC(long); +DDP_ACC(nosum); +DDP_ACC(badsum); +DDP_ACC(tooshort); +DDP_ACC(toosmall); +DDP_ACC(forward); +DDP_ACC(encap); +DDP_ACC(cantforward); +DDP_ACC(nosockspace); +#undef DDP_ACC + + +u_int32_t +netstat_ts_get_sec(const struct timestamp_type *tsp) +{ + return (tsp->ts_sec); +} + +u_int32_t +netstat_ts_get_usec(const struct timestamp_type *tsp) +{ + return (tsp->ts_usec); +} + + +#ifdef SCTP +#define SCTP_ACC(field) \ + STATS_ACC(u_int32_t,sctp,field) + +const struct timestamp_type * +netstat_sctps_get_discontinuitytime(const struct sctp_stat *a) +{ + return &a->s.sctps_discontinuitytime; +} + +STATS_GET(sctp,SCTP); +SCTP_ACC(currestab); +SCTP_ACC(activeestab); +SCTP_ACC(restartestab); +SCTP_ACC(collisionestab); +SCTP_ACC(passiveestab); +SCTP_ACC(aborted); +SCTP_ACC(shutdown); +SCTP_ACC(outoftheblue); +SCTP_ACC(checksumerrors); +SCTP_ACC(outcontrolchunks); +SCTP_ACC(outorderchunks); +SCTP_ACC(outunorderchunks); +SCTP_ACC(incontrolchunks); +SCTP_ACC(inorderchunks); +SCTP_ACC(inunorderchunks); +SCTP_ACC(fragusrmsgs); +SCTP_ACC(reasmusrmsgs); +SCTP_ACC(outpackets); +SCTP_ACC(inpackets); +SCTP_ACC(recvpackets); +SCTP_ACC(recvdatagrams); +SCTP_ACC(recvpktwithdata); +SCTP_ACC(recvsacks); +SCTP_ACC(recvdata); +SCTP_ACC(recvdupdata); +SCTP_ACC(recvheartbeat); +SCTP_ACC(recvheartbeatack); +SCTP_ACC(recvecne); +SCTP_ACC(recvauth); +SCTP_ACC(recvauthmissing); +SCTP_ACC(recvivalhmacid); +SCTP_ACC(recvivalkeyid); +SCTP_ACC(recvauthfailed); +SCTP_ACC(recvexpress); +SCTP_ACC(recvexpressm); +SCTP_ACC(recvnocrc); +SCTP_ACC(recvswcrc); +SCTP_ACC(recvhwcrc); +SCTP_ACC(sendpackets); +SCTP_ACC(sendsacks); +SCTP_ACC(senddata); +SCTP_ACC(sendretransdata); +SCTP_ACC(sendfastretrans); +SCTP_ACC(sendmultfastretrans); +SCTP_ACC(sendheartbeat); +SCTP_ACC(sendecne); +SCTP_ACC(sendauth); +SCTP_ACC(senderrors); +SCTP_ACC(sendnocrc); +SCTP_ACC(sendswcrc); +SCTP_ACC(sendhwcrc); +SCTP_ACC(pdrpfmbox); +SCTP_ACC(pdrpfehos); +SCTP_ACC(pdrpmbda); +SCTP_ACC(pdrpmbct); +SCTP_ACC(pdrpbwrpt); +SCTP_ACC(pdrpcrupt); +SCTP_ACC(pdrpnedat); +SCTP_ACC(pdrppdbrk); +SCTP_ACC(pdrptsnnf); +SCTP_ACC(pdrpdnfnd); +SCTP_ACC(pdrpdiwnp); +SCTP_ACC(pdrpdizrw); +SCTP_ACC(pdrpbadd); +SCTP_ACC(pdrpmark); +SCTP_ACC(timoiterator); +SCTP_ACC(timodata); +SCTP_ACC(timowindowprobe); +SCTP_ACC(timoinit); +SCTP_ACC(timosack); +SCTP_ACC(timoshutdown); +SCTP_ACC(timoheartbeat); +SCTP_ACC(timocookie); +SCTP_ACC(timosecret); +SCTP_ACC(timopathmtu); +SCTP_ACC(timoshutdownack); +SCTP_ACC(timoshutdownguard); +SCTP_ACC(timostrmrst); +SCTP_ACC(timoearlyfr); +SCTP_ACC(timoasconf); +SCTP_ACC(timodelprim); +SCTP_ACC(timoautoclose); +SCTP_ACC(timoassockill); +SCTP_ACC(timoinpkill); +SCTP_ACC(earlyfrstart); +SCTP_ACC(earlyfrstop); +SCTP_ACC(earlyfrmrkretrans); +SCTP_ACC(earlyfrstpout); +SCTP_ACC(earlyfrstpidsck1); +SCTP_ACC(earlyfrstpidsck2); +SCTP_ACC(earlyfrstpidsck3); +SCTP_ACC(earlyfrstpidsck4); +SCTP_ACC(earlyfrstrid); +SCTP_ACC(earlyfrstrout); +SCTP_ACC(earlyfrstrtmr); +SCTP_ACC(hdrops); +SCTP_ACC(badsum); +SCTP_ACC(noport); +SCTP_ACC(badvtag); +SCTP_ACC(badsid); +SCTP_ACC(nomem); +SCTP_ACC(fastretransinrtt); +SCTP_ACC(markedretrans); +SCTP_ACC(naglesent); +SCTP_ACC(naglequeued); +SCTP_ACC(maxburstqueued); +SCTP_ACC(ifnomemqueued); +SCTP_ACC(windowprobed); +SCTP_ACC(lowlevelerr); +SCTP_ACC(lowlevelerrusr); +SCTP_ACC(datadropchklmt); +SCTP_ACC(datadroprwnd); +SCTP_ACC(ecnereducedcwnd); +SCTP_ACC(vtagexpress); +SCTP_ACC(vtagbogus); +SCTP_ACC(primary_randry); +SCTP_ACC(cmt_randry); +SCTP_ACC(slowpath_sack); +SCTP_ACC(wu_sacks_sent); +SCTP_ACC(sends_with_flags); +SCTP_ACC(sends_with_unord); +SCTP_ACC(sends_with_eof); +SCTP_ACC(sends_with_abort); +SCTP_ACC(protocol_drain_calls); +SCTP_ACC(protocol_drains_done); +SCTP_ACC(read_peeks); +SCTP_ACC(cached_chk); +SCTP_ACC(cached_strmoq); +SCTP_ACC(left_abandon); +SCTP_ACC(send_burst_avoid); +SCTP_ACC(send_cwnd_avoid); +SCTP_ACC(fwdtsn_map_over); +#undef SCTP_ACC +#endif /* !SCTP */ + +#ifdef INET6 +#define IP6_ACC(field) \ + STATS_ACCX(u_int64_t,ip6,field,ip6s_##field) + +#define IP6_ACCA(field,size) \ + STATS_ACCXA(u_int64_t,ip6,field,ip6s_##field,size) + +STATS_GET(ip6,IP6); +IP6_ACC(total); +IP6_ACC(tooshort); +IP6_ACC(toosmall); +IP6_ACC(fragments); +IP6_ACC(fragdropped); +IP6_ACC(fragtimeout); +IP6_ACC(fragoverflow); +IP6_ACC(forward); +IP6_ACC(cantforward); +IP6_ACC(redirectsent); +IP6_ACC(delivered); +IP6_ACC(localout); +IP6_ACC(odropped); +IP6_ACC(reassembled); +IP6_ACC(fragmented); +IP6_ACC(ofragments); +IP6_ACC(cantfrag); +IP6_ACC(badoptions); +IP6_ACC(noroute); +IP6_ACC(badvers); +IP6_ACC(rawout); +IP6_ACC(badscope); +IP6_ACC(notmember); +IP6_ACCA(nxthist,NETSTAT_IP6_NHIST_MAX); +IP6_ACC(m1); +IP6_ACCA(m2m,NETSTAT_IP6_MBUF_MAX); +IP6_ACC(mext1); +IP6_ACC(mext2m); +IP6_ACC(exthdrtoolong); +IP6_ACC(nogif); +IP6_ACC(toomanyhdr); +IP6_ACC(sources_none); +IP6_ACCA(sources_sameif,NETSTAT_IP6_IF_MAX); +IP6_ACCA(sources_otherif,NETSTAT_IP6_IF_MAX); +IP6_ACCA(sources_samescope,NETSTAT_IP6_IF_MAX); +IP6_ACCA(sources_otherscope,NETSTAT_IP6_IF_MAX); +IP6_ACCA(sources_deprecated,NETSTAT_IP6_IF_MAX); +IP6_ACCA(sources_rule,NETSTAT_IP6_IF_MAX); +#undef IP6_ACC +#undef IP6_ACCA + +#define ICMP6_ACC(field) \ + STATS_ACCX(u_int64_t,icmp6,field,icp6s_##field) + +#define ICMP6_ACCA(field) \ + STATS_ACCXA(u_int64_t,icmp6,field,icp6s_##field,256) + +STATS_GET(icmp6,ICMP6); +ICMP6_ACC(error); +ICMP6_ACC(canterror); +ICMP6_ACC(toofreq); +ICMP6_ACCA(outhist); +ICMP6_ACC(badcode); +ICMP6_ACC(tooshort); +ICMP6_ACC(checksum); +ICMP6_ACC(badlen); +ICMP6_ACC(reflect); +ICMP6_ACCA(inhist); +ICMP6_ACC(nd_toomanyopt); +ICMP6_ACC(odst_unreach_noroute); +ICMP6_ACC(odst_unreach_admin); +ICMP6_ACC(odst_unreach_beyondscope); +ICMP6_ACC(odst_unreach_addr); +ICMP6_ACC(odst_unreach_noport); +ICMP6_ACC(opacket_too_big); +ICMP6_ACC(otime_exceed_transit); +ICMP6_ACC(otime_exceed_reassembly); +ICMP6_ACC(oparamprob_header); +ICMP6_ACC(oparamprob_nextheader); +ICMP6_ACC(oparamprob_option); +ICMP6_ACC(oredirect); +ICMP6_ACC(ounknown); +ICMP6_ACC(pmtuchg); +ICMP6_ACC(nd_badopt); +ICMP6_ACC(badns); +ICMP6_ACC(badna); +ICMP6_ACC(badrs); +ICMP6_ACC(badra); +ICMP6_ACC(badredirect); +#undef ICMP_ACC +#undef ICMP_ACCA + +#define PIM6_ACC(field) \ + STATS_ACCX(u_int64_t,pim6,field,pim6s_##field) + +STATS_GET(pim6,PIM6); +PIM6_ACC(rcv_total); +PIM6_ACC(rcv_tooshort); +PIM6_ACC(rcv_badsum); +PIM6_ACC(rcv_badversion); +PIM6_ACC(rcv_registers); +PIM6_ACC(rcv_badregisters); +PIM6_ACC(snd_registers); +#undef PIM6_ACC + +#define RIP6_ACC(field) \ + STATS_ACCX(u_int64_t,rip6,field,rip6s_##field) + +STATS_GET(rip6,RIP6); +RIP6_ACC(ipackets); +RIP6_ACC(isum); +RIP6_ACC(badsum); +RIP6_ACC(nosock); +RIP6_ACC(nosockmcast); +RIP6_ACC(fullsock); +RIP6_ACC(opackets); +RIP6_ACC(delivered); +#undef RIP6_ACC +#endif /* !INET6 */ + +#ifdef IPX +#define IPX_ACC(field) \ + STATS_ACCX(u_int64_t,ipx,field,ipxs_##field) + +STATS_GET(ipx,IPX); +IPX_ACC(total); +IPX_ACC(badsum); +IPX_ACC(tooshort); +IPX_ACC(toosmall); +IPX_ACC(forward); +IPX_ACC(cantforward); +IPX_ACC(delivered); +IPX_ACC(localout); +IPX_ACC(odropped); +IPX_ACC(noroute); +IPX_ACC(mtutoosmall); +#undef IPX_ACC + +#define SPX_ACC(field) \ + STATS_ACCX(u_int64_t,spx,field,newstats.spxs_##field) + +#define SPX_ACC1(field) \ + STATS_ACCX(u_int64_t,spx,field,field) + +STATS_GET(spx,SPX); +SPX_ACC(connattempt); +SPX_ACC(accepts); +SPX_ACC(connects); +SPX_ACC(drops); +SPX_ACC(conndrops); +SPX_ACC(closed); +SPX_ACC(segstimed); +SPX_ACC(rttupdated); +SPX_ACC(delack); +SPX_ACC(timeoutdrop); +SPX_ACC(rexmttimeo); +SPX_ACC(persisttimeo); +SPX_ACC(keeptimeo); +SPX_ACC(keepprobe); +SPX_ACC(keepdrops); +SPX_ACC(sndtotal); +SPX_ACC(sndpack); +SPX_ACC(sndbyte); +SPX_ACC(sndrexmitpack); +SPX_ACC(sndrexmitbyte); +SPX_ACC(sndacks); +SPX_ACC(sndprobe); +SPX_ACC(sndurg); +SPX_ACC(sndwinup); +SPX_ACC(sndctrl); +SPX_ACC(sndvoid); +SPX_ACC(rcvtotal); +SPX_ACC(rcvpack); +SPX_ACC(rcvbyte); +SPX_ACC(rcvbadsum); +SPX_ACC(rcvbadoff); +SPX_ACC(rcvshort); +SPX_ACC(rcvduppack); +SPX_ACC(rcvdupbyte); +SPX_ACC(rcvpartduppack); +SPX_ACC(rcvpartdupbyte); +SPX_ACC(rcvoopack); +SPX_ACC(rcvoobyte); +SPX_ACC(rcvpackafterwin); +SPX_ACC(rcvbyteafterwin); +SPX_ACC(rcvafterclose); +SPX_ACC(rcvwinprobe); +SPX_ACC(rcvdupack); +SPX_ACC(rcvacktoomuch); +SPX_ACC(rcvackpack); +SPX_ACC(rcvackbyte); +SPX_ACC(rcvwinupd); +SPX_ACC1(hdrops); +SPX_ACC1(badsum); +SPX_ACC1(badlen); +SPX_ACC1(slotim); +SPX_ACC1(fastim); +SPX_ACC1(nonucn); +SPX_ACC1(noconn); +SPX_ACC1(notme); +SPX_ACC1(wrncon); +SPX_ACC1(bdreas); +SPX_ACC1(gonawy); +SPX_ACC1(notyet); +SPX_ACC1(lstdup); +#undef SPX_ACC +#undef SPX_ACC1 +#endif /* !IPX */ + +#define PFSYNC_ACC(field) \ + STATS_ACCX(u_int64_t,pfsync,field,pfsyncs_##field) + +STATS_GET(pfsync,pfsync); +PFSYNC_ACC(ipackets); +PFSYNC_ACC(ipackets6); +PFSYNC_ACC(badif); +PFSYNC_ACC(badttl); +PFSYNC_ACC(hdrops); +PFSYNC_ACC(badver); +PFSYNC_ACC(badact); +PFSYNC_ACC(badlen); +PFSYNC_ACC(badauth); +PFSYNC_ACC(stale); +PFSYNC_ACC(badval); +PFSYNC_ACC(badstate); +PFSYNC_ACC(opackets); +PFSYNC_ACC(opackets6); +PFSYNC_ACC(onomem); +PFSYNC_ACC(oerrors); +#undef PFSYNC_ACC + +#ifdef IPSEC +#define PFKEY_ACC(field) \ + STATS_ACCX(u_int64_t,pfkey,field,field) + +#define PFKEY_ACCA(field,size) \ + STATS_ACCXA(u_int64_t,pfkey,field,field,size) + +#define PFKEY_ACCE(field,size) \ + STATS_ACCXE(u_int64_t,pfkey,field,field,pfkey_msgtarget) + +STATS_GET(pfkey,pfkey); +PFKEY_ACC(out_total); +PFKEY_ACC(out_bytes); +PFKEY_ACCA(out_msgtype,256); +PFKEY_ACC(out_invlen); +PFKEY_ACC(out_invver); +PFKEY_ACC(out_invmsgtype); +PFKEY_ACC(out_tooshort); +PFKEY_ACC(out_nomem); +PFKEY_ACC(out_dupext); +PFKEY_ACC(out_invexttype); +PFKEY_ACC(out_invsatype); +PFKEY_ACC(out_invaddr); +PFKEY_ACC(in_total); +PFKEY_ACC(in_bytes); +PFKEY_ACCA(in_msgtype,256); +PFKEY_ACCE(in_msgtarget,pfkey_msgtarget); +PFKEY_ACC(in_nomem); +PFKEY_ACC(sockerr); +#undef PFKEY_ACC +#undef PFKEY_ACCA + +#define ESP_ACC(field) \ + STATS_ACCX(u_int32_t,esp,field,esps_##field) + +#define ESP_ACC64(field) \ + STATS_ACCX(u_int64_t,esp,field,esps_##field) + +#define ESP_ACCA(field,size) \ + STATS_ACCXA(u_int32_t,esp,field,esps_##field,size) + +STATS_GET(esp,ESP); +ESP_ACC(hdrops); +ESP_ACC(nopf); +ESP_ACC(notdb); +ESP_ACC(badkcr); +ESP_ACC(qfull); +ESP_ACC(noxform); +ESP_ACC(badilen); +ESP_ACC(wrap); +ESP_ACC(badenc); +ESP_ACC(badauth); +ESP_ACC(replay); +ESP_ACC(input); +ESP_ACC(output); +ESP_ACC(invalid); +ESP_ACC64(ibytes); +ESP_ACC64(obytes); +ESP_ACC(toobig); +ESP_ACC(pdrops); +ESP_ACC(crypto); +ESP_ACC(tunnel); +ESP_ACCA(hist,ESP_ALG_MAX); +#undef ESP_ACC +#undef ESP_ACC64 +#undef ESP_ACCA + +#define AH_ACC(field) \ + STATS_ACCX(u_int32_t,ah,field,ahs_##field) + +#define AH_ACC64(field) \ + STATS_ACCX(u_int64_t,ah,field,ahs_##field) + +#define AH_ACCA(field,size) \ + STATS_ACCXA(u_int32_t,ah,field,ahs_##field,size) + +STATS_GET(ah,AH); +AH_ACC(hdrops); +AH_ACC(nopf); +AH_ACC(notdb); +AH_ACC(badkcr); +AH_ACC(badauth); +AH_ACC(noxform); +AH_ACC(qfull); +AH_ACC(wrap); +AH_ACC(replay); +AH_ACC(badauthl); +AH_ACC(input); +AH_ACC(output); +AH_ACC(invalid); +AH_ACC64(ibytes); +AH_ACC64(obytes); +AH_ACC(toobig); +AH_ACC(pdrops); +AH_ACC(crypto); +AH_ACC(tunnel); +AH_ACCA(hist,AH_ALG_MAX); +#undef AH_ACC +#undef AH_ACC64 +#undef AH_ACCA + +#define IPCOMP_ACC(field) \ + STATS_ACCXP(u_int32_t,ipcomp,field,ipcomps_##field) + +#define IPCOMP_ACC64(field) \ + STATS_ACCXP(u_int64_t,ipcomp,field,ipcomps_##field) + +#define IPCOMP_ACCA(field,size) \ + STATS_ACCXAP(u_int32_t,ipcomp,field,ipcomps_##field,size) + +STATS_GET(ipcomp,IPcomp); +IPCOMP_ACC(hdrops); +IPCOMP_ACC(nopf); +IPCOMP_ACC(notdb); +IPCOMP_ACC(badkcr); +IPCOMP_ACC(qfull); +IPCOMP_ACC(noxform); +IPCOMP_ACC(wrap); +IPCOMP_ACC(input); +IPCOMP_ACC(output); +IPCOMP_ACC(invalid); +IPCOMP_ACC64(ibytes); +IPCOMP_ACC64(obytes); +IPCOMP_ACC(toobig); +IPCOMP_ACC(pdrops); +IPCOMP_ACC(crypto); +IPCOMP_ACCA(hist,IPCOMP_ALG_MAX); +IPCOMP_ACC(threshold); +IPCOMP_ACC(uncompr); +#undef IPCOMP_ACC +#undef IPCOMP_ACC64 +#undef IPCOMP_ACCA + +u_int32_t +netstat_ipcomps_get_version(const struct ipcomp_stat *icsp) +{ + return(icsp->v); +} + +#define IPSEC_ACC(field) \ + STATS_ACCX(u_int64_t,ipsec,field,field) + +#define IPSEC_ACC32(field) \ + STATS_ACCX(u_int32_t,ipsec,field,field) + +#define IPSEC_ACCA(field,size) \ + STATS_ACCXA(u_int64_t,ipsec,field,field,size) + +STATS_GET(ipsec,IPsec); +IPSEC_ACC(in_success); +IPSEC_ACC(in_polvio); +IPSEC_ACC(in_nosa); +IPSEC_ACC(in_inval); +IPSEC_ACC(in_nomem); +IPSEC_ACC(in_badspi); +IPSEC_ACC(in_ahreplay); +IPSEC_ACC(in_espreplay); +IPSEC_ACC(in_ahauthsucc); +IPSEC_ACC(in_ahauthfail); +IPSEC_ACC(in_espauthsucc); +IPSEC_ACC(in_espauthfail); +IPSEC_ACCA(in_esphist,256); +IPSEC_ACCA(in_ahhist,256); +IPSEC_ACCA(in_comphist,256); +IPSEC_ACC(out_success); +IPSEC_ACC(out_polvio); +IPSEC_ACC(out_nosa); +IPSEC_ACC(out_inval); +IPSEC_ACC(out_nomem); +IPSEC_ACC(out_noroute); +IPSEC_ACCA(out_esphist,256); +IPSEC_ACCA(out_ahhist,256); +IPSEC_ACCA(out_comphist,256); +IPSEC_ACC(spdcachelookup); +IPSEC_ACC(spdcachemiss); +IPSEC_ACC32(ips_in_polvio); +IPSEC_ACC32(ips_out_polvio); +IPSEC_ACC32(ips_out_nosa); +IPSEC_ACC32(ips_out_nomem); +IPSEC_ACC32(ips_out_noroute); +IPSEC_ACC32(ips_out_inval); +IPSEC_ACC32(ips_out_bundlesa); +IPSEC_ACC32(ips_mbcoalesced); +IPSEC_ACC32(ips_clcoalesced); +IPSEC_ACC32(ips_clcopied); +IPSEC_ACC32(ips_mbinserted); +IPSEC_ACC32(ips_input_front); +IPSEC_ACC32(ips_input_middle); +IPSEC_ACC32(ips_input_end); +#undef IPSEC_ACC +#undef IPSEC_ACC32 +#undef IPSEC_ACCA +#endif /* !IPSEC */ + +#define RT_ACC(field) \ + STATS_ACCX(u_int64_t,route,field,rts_##field) + +STATS_GET(route,route); +RT_ACC(badredirect); +RT_ACC(dynamic); +RT_ACC(newgateway); +RT_ACC(unreach); +RT_ACC(wildcard); +RT_ACC(trash); +#undef RT_ACC + +#define MRT_ACC(field) \ + STATS_ACCX(u_int64_t,mroute,field,mrts_##field) + +STATS_GET(mroute,mroute); +MRT_ACC(mfc_lookups); +MRT_ACC(mfc_misses); +MRT_ACC(upcalls); +MRT_ACC(no_route); +MRT_ACC(bad_tunnel); +MRT_ACC(cant_tunnel); +MRT_ACC(wrong_if); +MRT_ACC(upq_ovflw); +MRT_ACC(cache_cleanups); +MRT_ACC(drop_sel); +MRT_ACC(q_overflow); +MRT_ACC(pkt2large); +MRT_ACC(upq_sockfull); +#undef MRT_ACC + +#ifdef INET6 +#define MRT6_ACC(field) \ + STATS_ACCX(u_int64_t,mroute6,field,mrt6s_##field) + +STATS_GET(mroute6,mroute6); +MRT6_ACC(mfc_lookups); +MRT6_ACC(mfc_misses); +MRT6_ACC(upcalls); +MRT6_ACC(no_route); +MRT6_ACC(bad_tunnel); +MRT6_ACC(cant_tunnel); +MRT6_ACC(wrong_if); +MRT6_ACC(upq_ovflw); +MRT6_ACC(cache_cleanups); +MRT6_ACC(drop_sel); +MRT6_ACC(q_overflow); +MRT6_ACC(pkt2large); +MRT6_ACC(upq_sockfull); +#undef MRT6_ACC +#endif + +void +_netstat_rtl_empty(struct route_type_list *list) +{ + struct route_type *rtp; + + while ((rtp = TAILQ_FIRST(&list->rtl_list)) ) { + TAILQ_REMOVE(&list->rtl_list, rtp, rt_list); + _netstat_rt_free(rtp); + } + + list->rtl_length = 0; +} + +void +_netstat_rt_free(struct route_type *rtp) +{ + int i; + _netstat_rat_free(rtp->rt_destination); + _netstat_rat_free(rtp->rt_gateway); + for (i = 0; i < rtp->rt_node.rnt_mkcnt; i++) + _netstat_rat_free(rtp->rt_node.rnt_mklist[i].rmt_netmask); + if (rtp->rt_node.rnt_mklist != NULL) + free(rtp->rt_node.rnt_mklist); + free(rtp->rt_interface); + free(rtp); +} + +void +_netstat_rat_free(struct routeaddr_type *ratp) +{ + if (ratp == NULL) + return; + free(ratp->rat_address); + free(ratp->rat_data); + free(ratp); +} + +struct route_type * +_netstat_rt_allocate(struct route_type_list *list) +{ + struct route_type *rtp; + + MALLOC_PTR(rtp); + + bzero(rtp, sizeof(*rtp)); + TAILQ_INSERT_TAIL(&list->rtl_list, rtp, rt_list); + list->rtl_length += 1; + return (rtp); +} + +struct routeaddr_type * +_netstat_rat_allocate(int family, void *address, size_t len) +{ + struct routeaddr_type *ratp; + + MALLOC_PTR(ratp); + + bzero(ratp, sizeof(*ratp)); + if (address != NULL && len > 0) { + ratp->rat_data = malloc(len); + if (ratp->rat_data == NULL) { + free(ratp); + ratp = NULL; + } else { + memcpy(ratp->rat_data, address, len); + ratp->rat_data_len = len; + } + } + ratp->rat_family = family; + return (ratp); +} + +struct route_type_list * +netstat_rtl_alloc(void) +{ + struct route_type_list *rtlp; + + MALLOC_PTR(rtlp); + + TAILQ_INIT(&rtlp->rtl_list); + rtlp->rtl_error = NETSTAT_ERROR_UNDEFINED; + rtlp->rtl_length = 0; + return (rtlp); +} + +void +netstat_rtl_free(struct route_type_list *list) +{ + _netstat_rtl_empty(list); + free(list); +} + +int +netstat_rtl_geterror(const struct route_type_list *list) +{ + return (list->rtl_error); +} + +int +netstat_rtl_length(const struct route_type_list *list) +{ + return (list->rtl_length); +} + +int +netstat_rti_alloc(struct route_type_list *list, + struct route_type_iterator **iterator) +{ + struct route_type_iterator *rtip; + + MALLOC_ITR(rtip); + + bzero(rtip, sizeof(*rtip)); + rtip->rti_list = list; + rtip->rti_first = TAILQ_FIRST(&list->rtl_list); + if (rtip->rti_first != NULL) + rtip->rti_next = TAILQ_NEXT(rtip->rti_first, rt_list); + *iterator = rtip; + return (0); +} + +const struct route_type * +netstat_rti_first(struct route_type_iterator *rtip) +{ + if (rtip->rti_first != NULL) + rtip->rti_next = TAILQ_NEXT(rtip->rti_first, rt_list); + return (rtip->rti_first); +} + +const struct route_type * +netstat_rti_next(struct route_type_iterator *rtip) +{ + const struct route_type *rtp; + + rtp = rtip->rti_next; + if (rtip->rti_next != NULL) + rtip->rti_next = TAILQ_NEXT(rtip->rti_next, rt_list); + + return (rtp); +} + +void +netstat_rti_free(struct route_type_iterator *rtip) +{ + free(rtip); +} + +#define ROUTE_ACC(returns, field) \ + ACCESSOR(returns, r, route, field) + +#define ROUTE_ACCP(returns, field) \ + ACCESSORP(returns, r, route, field) + +ROUTE_ACC (int, fib); +ROUTE_ACC (int, family); +ROUTE_ACC (const struct routeaddr_type *, destination); +ROUTE_ACC (const struct routeaddr_type *, gateway); +ROUTE_ACC (int, flags); +ROUTE_ACC (u_int64_t, refs); +ROUTE_ACC (u_int64_t, used); +ROUTE_ACC (const char *, interface); +ROUTE_ACC (u_int64_t, expire); +ROUTE_ACC (u_int32_t, mtu); +ROUTE_ACCP(const struct routenode_type *, node); + +#undef ROUTE_ACC +#undef ROUTE_ACCP + +#define ROUTENODE_ACC(returns, field) \ + ACCESSOR(returns, rn, routenode, field) + +ROUTENODE_ACC(int, bit); +ROUTENODE_ACC(int, flags); +ROUTENODE_ACC(u_int64_t, address); +ROUTENODE_ACC(u_int64_t, left); +ROUTENODE_ACC(u_int64_t, right); +ROUTENODE_ACC(const struct routeaddr_type *, netmask); +ROUTENODE_ACC(int, mkcnt); + +const struct routemask_type * +netstat_rnt_get_mask(const struct routenode_type *rntp, int i) +{ + if (0 <= i && i < rntp->rnt_mkcnt) + return (&rntp->rnt_mklist[i]); + return (NULL); +} + +#undef ROUTENODE_ACC + +#define ROUTEMASK_ACC(returns, field) \ + ACCESSOR(returns, rm, routemask, field) + +ROUTEMASK_ACC(int, flags); +ROUTEMASK_ACC(int, bit); +ROUTEMASK_ACC(u_int64_t, address); +ROUTEMASK_ACC(u_int64_t, refs); +ROUTEMASK_ACC(const struct routeaddr_type *, netmask); + +#undef ROUTEMASK_ACC + +#define ROUTEADDR_ACC(returns, field) \ + ACCESSOR(returns, ra, routeaddr, field) + +ROUTEADDR_ACC(int, family); + +const char * +netstat_rat_get_name(const struct routeaddr_type *ratp, int numeric) +{ + if (numeric) + return (ratp->rat_ni_address); + return (ratp->rat_address); +} + +size_t +netstat_rat_get_address(const struct routeaddr_type *ratp, void *addr, + size_t size) +{ + if ((ratp->rat_data != NULL) && (addr != NULL) && + (ratp->rat_data_len <= size)) { + memcpy(addr, ratp->rat_data, ratp->rat_data_len); + return (ratp->rat_data_len); + } + + return (0); +} + +#undef ROUTEADDR_ACC + +void +_netstat_mitl_empty(struct mcastif_type_list *list) +{ + struct mcastif_type *mitp; + + while ((mitp = TAILQ_FIRST(&list->mitl_list)) ) { + TAILQ_REMOVE(&list->mitl_list, mitp, mit_list); + _netstat_mit_free(mitp); + } + + list->mitl_length = 0; +} + +void +_netstat_mit_free(struct mcastif_type *mitp) +{ + _netstat_rat_free(mitp->mit_address); + if (mitp->mit_remote_address != NULL) + _netstat_rat_free(mitp->mit_remote_address); + free(mitp); +} + +struct mcastif_type * +_netstat_mit_allocate(struct mcastif_type_list *list) +{ + struct mcastif_type *mitp; + + MALLOC_PTR(mitp); + + bzero(mitp, sizeof(*mitp)); + TAILQ_INSERT_TAIL(&list->mitl_list, mitp, mit_list); + list->mitl_length += 1; + return (mitp); +} + +struct mcastif_type_list * +netstat_mitl_alloc(void) +{ + struct mcastif_type_list *mitlp; + + MALLOC_PTR(mitlp); + + TAILQ_INIT(&mitlp->mitl_list); + mitlp->mitl_error = NETSTAT_ERROR_UNDEFINED; + mitlp->mitl_length = 0; + return (mitlp); +} + +void +netstat_mitl_free(struct mcastif_type_list *mitlp) +{ + _netstat_mitl_empty(mitlp); + free(mitlp); +} + +int +netstat_mitl_geterror(const struct mcastif_type_list *mitlp) +{ + return (mitlp->mitl_error); +} + +int +netstat_mitl_length(const struct mcastif_type_list *mitlp) +{ + return (mitlp->mitl_length); +} + +int +netstat_miti_alloc(struct mcastif_type_list *list, + struct mcastif_type_iterator **iterator) +{ + struct mcastif_type_iterator *mitip; + + MALLOC_ITR(mitip); + + bzero(mitip, sizeof(*mitip)); + mitip->miti_list = list; + mitip->miti_first = TAILQ_FIRST(&list->mitl_list); + if (mitip->miti_first != NULL) + mitip->miti_next = TAILQ_NEXT(mitip->miti_first, mit_list); + *iterator = mitip; + return (0); +} + +const struct mcastif_type * +netstat_miti_first(struct mcastif_type_iterator *mitip) +{ + if (mitip->miti_first != NULL) + mitip->miti_next = TAILQ_NEXT(mitip->miti_first, mit_list); + return (mitip->miti_first); +} + +const struct mcastif_type * +netstat_miti_next(struct mcastif_type_iterator *mitip) +{ + const struct mcastif_type *mitp; + + mitp = mitip->miti_next; + if (mitip->miti_next != NULL) + mitip->miti_next = TAILQ_NEXT(mitip->miti_next, mit_list); + + return (mitp); +} + +void +netstat_miti_free(struct mcastif_type_iterator *mitip) +{ + free(mitip); +} + +#define MCASTIF_ACC(returns, field) \ + ACCESSOR(returns, mi, mcastif, field) + +MCASTIF_ACC(u_int32_t, index); +MCASTIF_ACC(int, flags); +MCASTIF_ACC(u_int32_t, limit); +MCASTIF_ACC(const struct routeaddr_type *, address); +MCASTIF_ACC(const struct routeaddr_type *, remote_address); +MCASTIF_ACC(u_int64_t, packets_in); +MCASTIF_ACC(u_int64_t, packets_out); +MCASTIF_ACC(u_int64_t, bytes_in); +MCASTIF_ACC(u_int64_t, bytes_out); +MCASTIF_ACC(const char *, ifname); + +#undef MCASTIF_ACC + +void +_netstat_mrtl_empty(struct mroute_type_list *list) +{ + struct mroute_type *mrtp; + + while ((mrtp = TAILQ_FIRST(&list->mrtl_list)) ) { + TAILQ_REMOVE(&list->mrtl_list, mrtp, mrt_list); + _netstat_mrt_free(mrtp); + } + + list->mrtl_length = 0; +} + +void +_netstat_mrt_free(struct mroute_type *mrtp) +{ + _netstat_rat_free(mrtp->mrt_origin); + _netstat_rat_free(mrtp->mrt_group); + free(mrtp); +} + +struct mroute_type * +_netstat_mrt_allocate(struct mroute_type_list *list) +{ + struct mroute_type *mrtp; + + MALLOC_PTR(mrtp); + + bzero(mrtp, sizeof(*mrtp)); + TAILQ_INSERT_TAIL(&list->mrtl_list, mrtp, mrt_list); + list->mrtl_length += 1; + return (mrtp); +} + +struct mroute_type_list * +netstat_mrtl_alloc(void) +{ + struct mroute_type_list *mrtlp; + + MALLOC_PTR(mrtlp); + + TAILQ_INIT(&mrtlp->mrtl_list); + mrtlp->mrtl_error = NETSTAT_ERROR_UNDEFINED; + mrtlp->mrtl_length = 0; + return (mrtlp); +} + +void +netstat_mrtl_free(struct mroute_type_list *mrtlp) +{ + _netstat_mrtl_empty(mrtlp); + free(mrtlp); +} + +int +netstat_mrtl_geterror(const struct mroute_type_list *mrtlp) +{ + return (mrtlp->mrtl_error); +} + +int +netstat_mrtl_length(const struct mroute_type_list *mrtlp) +{ + return (mrtlp->mrtl_length); +} + +int +netstat_mrti_alloc(struct mroute_type_list *list, + struct mroute_type_iterator **iterator) +{ + struct mroute_type_iterator *mrtip; + + MALLOC_ITR(mrtip); + + bzero(mrtip, sizeof(*mrtip)); + mrtip->mrti_list = list; + mrtip->mrti_first = TAILQ_FIRST(&list->mrtl_list); + if (mrtip->mrti_first != NULL) + mrtip->mrti_next = TAILQ_NEXT(mrtip->mrti_first, mrt_list); + *iterator = mrtip; + return (0); +} + +const struct mroute_type * +netstat_mrti_first(struct mroute_type_iterator *mrtip) +{ + if (mrtip->mrti_first != NULL) + mrtip->mrti_next = TAILQ_NEXT(mrtip->mrti_first, mrt_list); + return (mrtip->mrti_first); +} + +const struct mroute_type * +netstat_mrti_next(struct mroute_type_iterator *mrtip) +{ + const struct mroute_type *mrtp; + + mrtp = mrtip->mrti_next; + if (mrtip->mrti_next != NULL) + mrtip->mrti_next = TAILQ_NEXT(mrtip->mrti_next, mrt_list); + + return (mrtp); +} + +void +netstat_mrti_free(struct mroute_type_iterator *mrtip) +{ + free(mrtip); +} + +#define MROUTE_ACC(returns, field) \ + ACCESSOR(returns, mr, mroute, field) + +MROUTE_ACC(const struct routeaddr_type *, origin); +MROUTE_ACC(const struct routeaddr_type *, group); +MROUTE_ACC(u_int64_t, packets); +MROUTE_ACC(u_int64_t, bytes); +MROUTE_ACC(u_int64_t, waitings); +MROUTE_ACC(u_int32_t, parent); + +u_int8_t +netstat_mrt_get_ttl(const struct mroute_type *mrtp, int i) +{ + if (0 <= i && i < MRTTYPE_MAXVIFS) + return (mrtp->mrt_ttls[i]); + return (0); +} + +int +netstat_mrt_get_is_mif_set(const struct mroute_type *mrtp, u_int32_t mifi) +{ + return (IF_ISSET(mifi, &mrtp->mrt_ifset)); +} + +#undef MROUTE_ACC + + +static const char *icmpnames[ICMP_MAXTYPE + 1] = { + "echo reply", /* RFC 792 */ + "#1", + "#2", + "destination unreachable", /* RFC 792 */ + "source quench", /* RFC 792 */ + "routing redirect", /* RFC 792 */ + "#6", + "#7", + "echo", /* RFC 792 */ + "router advertisement", /* RFC 1256 */ + "router solicitation", /* RFC 1256 */ + "time exceeded", /* RFC 792 */ + "parameter problem", /* RFC 792 */ + "time stamp", /* RFC 792 */ + "time stamp reply", /* RFC 792 */ + "information request", /* RFC 792 */ + "information request reply", /* RFC 792 */ + "address mask request", /* RFC 950 */ + "address mask reply", /* RFC 950 */ + "#19", + "#20", + "#21", + "#22", + "#23", + "#24", + "#25", + "#26", + "#27", + "#28", + "#29", + "icmp traceroute", /* RFC 1393 */ + "datagram conversion error", /* RFC 1475 */ + "mobile host redirect", + "IPv6 where-are-you", + "IPv6 i-am-here", + "mobile registration req", + "mobile registration reply", + "domain name request", /* RFC 1788 */ + "domain name reply", /* RFC 1788 */ + "icmp SKIP", + "icmp photuris", /* RFC 2521 */ +}; + +static const char *icmp6names[] = { + "#0", + "unreach", + "packet too big", + "time exceed", + "parameter problem", + "#5", + "#6", + "#7", + "#8", + "#9", + "#10", + "#11", + "#12", + "#13", + "#14", + "#15", + "#16", + "#17", + "#18", + "#19", + "#20", + "#21", + "#22", + "#23", + "#24", + "#25", + "#26", + "#27", + "#28", + "#29", + "#30", + "#31", + "#32", + "#33", + "#34", + "#35", + "#36", + "#37", + "#38", + "#39", + "#40", + "#41", + "#42", + "#43", + "#44", + "#45", + "#46", + "#47", + "#48", + "#49", + "#50", + "#51", + "#52", + "#53", + "#54", + "#55", + "#56", + "#57", + "#58", + "#59", + "#60", + "#61", + "#62", + "#63", + "#64", + "#65", + "#66", + "#67", + "#68", + "#69", + "#70", + "#71", + "#72", + "#73", + "#74", + "#75", + "#76", + "#77", + "#78", + "#79", + "#80", + "#81", + "#82", + "#83", + "#84", + "#85", + "#86", + "#87", + "#88", + "#89", + "#80", + "#91", + "#92", + "#93", + "#94", + "#95", + "#96", + "#97", + "#98", + "#99", + "#100", + "#101", + "#102", + "#103", + "#104", + "#105", + "#106", + "#107", + "#108", + "#109", + "#110", + "#111", + "#112", + "#113", + "#114", + "#115", + "#116", + "#117", + "#118", + "#119", + "#120", + "#121", + "#122", + "#123", + "#124", + "#125", + "#126", + "#127", + "echo", + "echo reply", + "multicast listener query", + "MLDv1 listener report", + "MLDv1 listener done", + "router solicitation", + "router advertisement", + "neighbor solicitation", + "neighbor advertisement", + "redirect", + "router renumbering", + "node information request", + "node information reply", + "inverse neighbor solicitation", + "inverse neighbor advertisement", + "MLDv2 listener report", + "#144", + "#145", + "#146", + "#147", + "#148", + "#149", + "#150", + "#151", + "#152", + "#153", + "#154", + "#155", + "#156", + "#157", + "#158", + "#159", + "#160", + "#161", + "#162", + "#163", + "#164", + "#165", + "#166", + "#167", + "#168", + "#169", + "#170", + "#171", + "#172", + "#173", + "#174", + "#175", + "#176", + "#177", + "#178", + "#179", + "#180", + "#181", + "#182", + "#183", + "#184", + "#185", + "#186", + "#187", + "#188", + "#189", + "#180", + "#191", + "#192", + "#193", + "#194", + "#195", + "#196", + "#197", + "#198", + "#199", + "#200", + "#201", + "#202", + "#203", + "#204", + "#205", + "#206", + "#207", + "#208", + "#209", + "#210", + "#211", + "#212", + "#213", + "#214", + "#215", + "#216", + "#217", + "#218", + "#219", + "#220", + "#221", + "#222", + "#223", + "#224", + "#225", + "#226", + "#227", + "#228", + "#229", + "#230", + "#231", + "#232", + "#233", + "#234", + "#235", + "#236", + "#237", + "#238", + "#239", + "#240", + "#241", + "#242", + "#243", + "#244", + "#245", + "#246", + "#247", + "#248", + "#249", + "#250", + "#251", + "#252", + "#253", + "#254", + "#255", +}; + +const char * +netstat_icmpname(int type) +{ + if (0 <= type && type < ICMP_MAXTYPE) { + return (icmpnames[type]); + } + return (NULL); +} + +#define SizeOf(X) \ + ((int)(sizeof(X) / sizeof(X[0]))) + +const char * +netstat_icmp6name(int type) +{ + if (0 <= type && type < SizeOf(icmp6names)) { + return (icmp6names[type]); + } + return (NULL); +} + +static const char *pfkey_msgtypenames[] = { + "reserved", "getspi", "update", "add", "delete", + "get", "acquire", "register", "expire", "flush", + "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd", + "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush", + "x_spdsetidx", "x_spdexpire", "x_spddelete2" +}; + +const char * +netstat_pfkey_msgtype_name(int x) +{ + static char buf[20]; + + if (x < SizeOf(pfkey_msgtypenames) && pfkey_msgtypenames[x]) + return pfkey_msgtypenames[x]; + snprintf(buf, sizeof(buf), "#%d", x); + return buf; +} + +static struct val2str ipsec_espnames[] = { + { SADB_EALG_NONE, "none" }, + { SADB_EALG_DESCBC, "des-cbc" }, + { SADB_EALG_3DESCBC, "3des-cbc" }, + { SADB_EALG_NULL, "null" }, + { SADB_X_EALG_CAST128CBC, "cast128-cbc" }, + { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc" }, +#ifdef SADB_X_EALG_RIJNDAELCBC + { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc" }, +#endif +#ifdef SADB_X_EALG_AESCTR + { SADB_X_EALG_AESCTR, "aes-ctr" }, +#endif + { -1, NULL }, +}; + +static struct val2str ipsec_ahnames[] = { + { SADB_AALG_NONE, "none" }, + { SADB_AALG_MD5HMAC, "hmac-md5" }, + { SADB_AALG_SHA1HMAC, "hmac-sha1" }, + { SADB_X_AALG_MD5, "md5" }, + { SADB_X_AALG_SHA, "sha" }, + { SADB_X_AALG_NULL, "null" }, +#ifdef SADB_X_AALG_SHA2_256 + { SADB_X_AALG_SHA2_256, "hmac-sha2-256" }, +#endif +#ifdef SADB_X_AALG_SHA2_384 + { SADB_X_AALG_SHA2_512, "hmac-sha2-384" }, +#endif +#ifdef SADB_X_AALG_SHA2_512 + { SADB_X_AALG_SHA2_512, "hmac-sha2-512" }, +#endif +#ifdef SADB_X_AALG_RIPEMD160HMAC + { SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160" }, +#endif +#ifdef SADB_X_AALG_AES_XCBC_MAC + { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac" }, +#endif + { -1, NULL }, +}; + +static struct val2str ipsec_ipcompnames[] = { + { SADB_X_CALG_NONE, "none" }, + { SADB_X_CALG_OUI, "oui" }, + { SADB_X_CALG_DEFLATE, "deflate" }, + { SADB_X_CALG_LZS, "lzs" }, + { -1, NULL }, +}; + +const char * +resolve_val2str_name(int proto, const struct val2str *name) +{ + static char buf[20]; + const struct val2str *p; + + for (p = name; p && p->str; p++) { + if (p->val == proto) + break; + } + + if (p != NULL && p->str != NULL) + return (p->str); + + snprintf(buf, sizeof(buf), "#%lu", (unsigned long)proto); + return buf; +} + +const char * +netstat_ipsec_espname(int proto) +{ + return (resolve_val2str_name(proto, ipsec_espnames)); +} + +const char * +netstat_ipsec_ahname(int proto) +{ + return (resolve_val2str_name(proto, ipsec_ahnames)); +} + +const char * +netstat_ipsec_ipcompname(int proto) +{ + return (resolve_val2str_name(proto, ipsec_ipcompnames)); +} + +static const char *ip6nh[] = { + "hop by hop", + "ICMP", + "IGMP", + "#3", + "IP", + "#5", + "TCP", + "#7", + "#8", + "#9", + "#10", + "#11", + "#12", + "#13", + "#14", + "#15", + "#16", + "UDP", + "#18", + "#19", + "#20", + "#21", + "IDP", + "#23", + "#24", + "#25", + "#26", + "#27", + "#28", + "TP", + "#30", + "#31", + "#32", + "#33", + "#34", + "#35", + "#36", + "#37", + "#38", + "#39", + "#40", + "IP6", + "#42", + "routing", + "fragment", + "#45", + "#46", + "#47", + "#48", + "#49", + "ESP", + "AH", + "#52", + "#53", + "#54", + "#55", + "#56", + "#57", + "ICMP6", + "no next header", + "destination option", + "#61", + "mobility", + "#63", + "#64", + "#65", + "#66", + "#67", + "#68", + "#69", + "#70", + "#71", + "#72", + "#73", + "#74", + "#75", + "#76", + "#77", + "#78", + "#79", + "ISOIP", + "#81", + "#82", + "#83", + "#84", + "#85", + "#86", + "#87", + "#88", + "OSPF", + "#80", + "#91", + "#92", + "#93", + "#94", + "#95", + "#96", + "Ethernet", + "#98", + "#99", + "#100", + "#101", + "#102", + "PIM", + "#104", + "#105", + "#106", + "#107", + "#108", + "#109", + "#110", + "#111", + "#112", + "#113", + "#114", + "#115", + "#116", + "#117", + "#118", + "#119", + "#120", + "#121", + "#122", + "#123", + "#124", + "#125", + "#126", + "#127", + "#128", + "#129", + "#130", + "#131", + "#132", + "#133", + "#134", + "#135", + "#136", + "#137", + "#138", + "#139", + "#140", + "#141", + "#142", + "#143", + "#144", + "#145", + "#146", + "#147", + "#148", + "#149", + "#150", + "#151", + "#152", + "#153", + "#154", + "#155", + "#156", + "#157", + "#158", + "#159", + "#160", + "#161", + "#162", + "#163", + "#164", + "#165", + "#166", + "#167", + "#168", + "#169", + "#170", + "#171", + "#172", + "#173", + "#174", + "#175", + "#176", + "#177", + "#178", + "#179", + "#180", + "#181", + "#182", + "#183", + "#184", + "#185", + "#186", + "#187", + "#188", + "#189", + "#180", + "#191", + "#192", + "#193", + "#194", + "#195", + "#196", + "#197", + "#198", + "#199", + "#200", + "#201", + "#202", + "#203", + "#204", + "#205", + "#206", + "#207", + "#208", + "#209", + "#210", + "#211", + "#212", + "#213", + "#214", + "#215", + "#216", + "#217", + "#218", + "#219", + "#220", + "#221", + "#222", + "#223", + "#224", + "#225", + "#226", + "#227", + "#228", + "#229", + "#230", + "#231", + "#232", + "#233", + "#234", + "#235", + "#236", + "#237", + "#238", + "#239", + "#240", + "#241", + "#242", + "#243", + "#244", + "#245", + "#246", + "#247", + "#248", + "#249", + "#250", + "#251", + "#252", + "#253", + "#254", + "#255", +}; + +const char * +netstat_ip6_nhist_name(int i) +{ + if (0 <= i && i < SizeOf(ip6nh)) + return (ip6nh[i]); + return (NULL); +} + +static const char *srcrule[] = { + "first candidate", + "same address", + "appropriate scope", + "deprecated address", + "home address", + "outgoing interface", + "matching label", + "public/temporary address", + "alive interface", + "preferred interface", + "rule #10", + "rule #11", + "rule #12", + "rule #13", + "longest match", + "rule #15", +}; + + +const char * +netstat_ip6_srcrule_name(int i) +{ + if (0 <= i && i < SizeOf(srcrule)) + return (srcrule[i]); + return (NULL); +} + +const char * +routename(in_addr_t in, int numeric) +{ + char *cp; + static char line[MAXHOSTNAMELEN]; + struct hostent *hp; + + cp = NULL; + if (!numeric) { + hp = gethostbyaddr(&in, sizeof(struct in_addr), PF_INET); + if (hp != NULL) { + cp = hp->h_name; + trimdomain(cp, strlen(cp)); + } + } + if (cp != NULL) { + 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 numeric) +{ + int b, i; + + if (mask == 0 || (!numeric && 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); +} + +const char * +netname(in_addr_t in, u_long mask, int numeric) +{ + char *cp = NULL; + static char line[MAXHOSTNAMELEN]; + struct netent *np = NULL; + in_addr_t i; + + i = ntohl(in); + if (!numeric && i) { + np = getnetbyaddr(i >> NSHIFT(mask), PF_INET); + if (np != NULL) { + cp = np->n_name; + trimdomain(cp, strlen(cp)); + } + } + if (cp != NULL) + strlcpy(line, cp, sizeof(line)); + else + inet_ntop(PF_INET, &in, line, sizeof(line) - 1); + domask(line + strlen(line), i, mask, numeric); + return (line); +} + +#undef NSHIFT + +#ifdef INET6 +const char * +routename6(struct sockaddr_in6 *in6, int numeric) +{ + static char line[MAXHOSTNAMELEN]; + int flag = 0; + struct sockaddr_in6 in6_local; + + in6_local.sin6_family = PF_INET6; + in6_local.sin6_len = sizeof(in6_local); + in6_local.sin6_addr = in6->sin6_addr; + in6_local.sin6_scope_id = in6->sin6_scope_id; + + if (numeric) + flag |= NI_NUMERICHOST; + + getnameinfo((struct sockaddr *)&in6_local, in6_local.sin6_len, + line, sizeof(line), NULL, 0, flag); + + return (line); +} + +const char * +netname6(struct sockaddr_in6 *in6, struct in6_addr *mask, int numeric) +{ + static char line[MAXHOSTNAMELEN]; + u_char *p = (u_char *)mask; + u_char *lim; + int masklen, 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; + } + } + } + else + masklen = 128; + + if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr)) + return ("default"); + + if (numeric != 0) + flag |= NI_NUMERICHOST; + getnameinfo((struct sockaddr *)in6, in6->sin6_len, line, sizeof(line), + NULL, 0, flag); + + if (numeric != 0) + sprintf(&line[strlen(line)], "/%d", masklen); + + return (line); +} +#endif Index: lib/libnetstat/netstat_if.c =================================================================== --- lib/libnetstat/netstat_if.c (revision 0) +++ lib/libnetstat/netstat_if.c (revision 0) @@ -0,0 +1,331 @@ +/*- + * Copyright (c) 2009, 2010 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "netstat.h" +#include "netstat_internal.h" + +/* nlist(3) indices and symbols. */ +enum nlIF { + nlIF_ifnet = 0, + nlIF_MAX, +}; + +static const char *const if_symbol[] = { "_ifnet" }; + +static void extract_if_data(struct ifnet *ifp, struct interface_type *itp); +static struct intfaddr_type *extract_if_address(int type, void *ifaddr, + void *saddr, struct interface_type *itp); + +#define KREAD(off, dst) do { \ + if ((list->itl_error = (kread_data(session->sst_kvm, \ + (uintptr_t)(off), &(dst), sizeof(dst)))) != 0) { \ + result = -1; \ + goto end; \ + } \ +} while (0); + +int +netstat_interface(const struct session_type *session, const char *name, + int domain, struct interface_type_list *list, __unused int flags) +{ + int result; + struct nlist nls[nlIF_MAX + 1]; + + struct ifnethead ifnethead; + struct ifnet ifnet; + union { + struct ifaddr ifa; + struct in_ifaddr in; +#ifdef INET6 + struct in6_ifaddr in6; +#endif + struct ipx_ifaddr ipx; + } ifaddr; + union { + struct sockaddr sa; + struct sockaddr_dl dl; + struct sockaddr_in in; +#ifdef INET6 + struct sockaddr_in6 in6; +#endif + struct sockaddr_ipx ipx; + } sa; + struct ifmultiaddr ifmultiaddr; + struct interface_type *itp; + u_long ifn_addr; + u_long ifa_addr; + u_long ifma_addr; + + result = -1; + bzero(nls, sizeof(nls)); + + if (session->sst_flags & NETSTAT_SESSION_KVM) { + /* Using kvm(3). */ + nls[nlIF_ifnet].n_name = if_symbol[nlIF_ifnet]; + nls[nlIF_MAX].n_name = NULL; + + if (kvm_nlist(session->sst_kvm, nls) < 0) { + list->itl_error = NETSTAT_ERROR_KVM; + goto end; + } + + KREAD(nls[nlIF_ifnet].n_value, ifnethead); + + for (ifn_addr = (u_long)TAILQ_FIRST(&ifnethead); + ifn_addr != 0; + ifn_addr = (u_long)TAILQ_NEXT(&ifnet, if_link)) { + KREAD(ifn_addr, ifnet); + + if (name != NULL && strcmp(name, ifnet.if_xname) != 0) + continue; + + itp = _netstat_it_allocate(list, ifnet.if_type, + ifnet.if_physical, ifnet.if_xname); + extract_if_data(&ifnet, itp); + + /* Interface addresses. */ + for (ifa_addr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead); + ifa_addr != 0; + ifa_addr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link)) { + KREAD(ifa_addr, ifaddr); + KREAD(ifaddr.ifa.ifa_addr, sa); + ifaddr.ifa.ifa_addr = &sa.sa; + /* List addresses with the given protocol. */ + if (domain != PF_UNSPEC && + domain != ifaddr.ifa.ifa_addr->sa_family) + continue; + if (itp->it_addrcnt >= IFTYPE_MAXADDRCNT) + continue; + itp->it_address[itp->it_addrcnt++] = + extract_if_address(NETSTAT_IF_IFADDR, + &ifaddr.ifa, ifaddr.ifa.ifa_addr, itp); + } + + /* Multicast addresses. */ + for (ifma_addr = (u_long)TAILQ_FIRST(&ifnet.if_multiaddrs); + ifma_addr != 0; + ifma_addr = (u_long)TAILQ_NEXT(&ifmultiaddr, ifma_link)) { + KREAD(ifma_addr, ifmultiaddr); + KREAD(ifmultiaddr.ifma_addr, sa); + ifmultiaddr.ifma_addr = &sa.sa; + if (domain != PF_UNSPEC && + domain != ifmultiaddr.ifma_addr->sa_family) + continue; + if (itp->it_mcast_addrcnt >= IFTYPE_MAXADDRCNT) + continue; + itp->it_maddress[itp->it_mcast_addrcnt++] = + extract_if_address(NETSTAT_IF_IFMULTIADDR, + &ifmultiaddr, ifmultiaddr.ifma_addr, itp); + } + } + } else { + /* Using sysctl(8). */ + /* XXX: not implemented yet :) */ + goto end; + } + result = 0; +end: + return (result); +} + +#undef KREAD + +void +extract_if_data(struct ifnet *ifp, struct interface_type *itp) +{ + itp->it_mtu = ifp->if_mtu; + itp->it_in.ft_packets = ifp->if_ipackets; + itp->it_in.ft_bytes = ifp->if_ibytes; + itp->it_in.ft_mcasts = ifp->if_imcasts; + itp->it_in.ft_errors = ifp->if_ierrors; + itp->it_in.ft_drops = ifp->if_iqdrops; + itp->it_out.ft_packets = ifp->if_opackets; + itp->it_out.ft_bytes = ifp->if_obytes; + itp->it_out.ft_mcasts = ifp->if_omcasts; + itp->it_out.ft_errors = ifp->if_oerrors; + itp->it_out.ft_drops = 0; + itp->it_collisions = ifp->if_collisions; + itp->it_drops = ifp->if_snd.ifq_drops; + itp->it_flags = 0; + if (ifp->if_flags & IFF_UP) + itp->it_flags |= NETSTAT_IF_UP; +} + +struct intfaddr_type * +extract_if_address(int type, void *ifaddr, void *saddr, + struct interface_type *itp) +{ + struct sockaddr *sa; + struct sockaddr_in *sa_in; +#ifdef INET6 + struct sockaddr_in6 *sa_in6; +#endif + struct sockaddr_dl *sa_dl; + struct in_ifaddr *in; +#ifdef INET6 + struct in6_ifaddr *in6; +#endif + struct ipx_ifaddr *ipx; + + struct ifmultiaddr *ifma; + struct intfaddr_type *ifap; + + char *cp, *p; + int n; + + sa = (struct sockaddr *)saddr; + sa_in = (struct sockaddr_in *)sa; + sa_in6 = (struct sockaddr_in6 *)sa; + sa_dl = (struct sockaddr_dl *)sa; + + in = (struct in_ifaddr *)ifaddr; + in6 = (struct in6_ifaddr *)in; + ipx = (struct ipx_ifaddr *)in; + ifma = (struct ifmultiaddr *)ifaddr; + + ifap = _netstat_iat_allocate(sa->sa_family, type); + if (ifap == NULL) + return (NULL); + + switch (sa->sa_family) { + case PF_UNSPEC: + ifap->iat_address = strdup("none"); + ifap->iat_network = strdup("none"); + break; + case PF_INET: + ifap->iat_sockaddr_len = sizeof(struct sockaddr_in); + ifap->iat_sockaddr = malloc(ifap->iat_sockaddr_len); + if (ifap->iat_sockaddr != NULL) + memcpy(ifap->iat_sockaddr, sa_in, + ifap->iat_sockaddr_len); + ifap->iat_ifaddr_len = sizeof(struct in_ifaddr); + if (ifap->iat_ifaddr != NULL) + memcpy(ifap->iat_ifaddr, in, ifap->iat_ifaddr_len); + strlcpy(ifap->iat_ni_network, + netname(htonl(in->ia_subnet), in->ia_subnetmask, 1), + sizeof(ifap->iat_ni_network)); + ifap->iat_network = strdup(netname(htonl(in->ia_subnet), + in->ia_subnetmask, 0)); + inet_ntop(PF_INET, &sa_in->sin_addr, ifap->iat_ni_address, + sizeof(ifap->iat_ni_address)); + ifap->iat_address = strdup(routename(sa_in->sin_addr.s_addr, 0)); + ifap->iat_layer = layer_Network; + switch (type) { + case NETSTAT_IF_IFADDR: + ifap->iat_refcount = in->ia_ifa.ifa_refcnt; + break; + case NETSTAT_IF_IFMULTIADDR: + ifap->iat_refcount = ifma->ifma_refcount; + break; + } + ifap->iat_opackets = in->ia_ifa.if_opackets; + ifap->iat_ipackets = in->ia_ifa.if_ipackets; + ifap->iat_obytes = in->ia_ifa.if_obytes; + ifap->iat_ibytes = in->ia_ifa.if_ibytes; + break; +#ifdef INET6 + case PF_INET6: + ifap->iat_sockaddr_len = sizeof(struct sockaddr_in6); + ifap->iat_sockaddr = malloc(ifap->iat_sockaddr_len); + if (ifap->iat_sockaddr != NULL) + memcpy(ifap->iat_sockaddr, sa_in6, + ifap->iat_sockaddr_len); + ifap->iat_ifaddr_len = sizeof(struct in6_ifaddr); + if (ifap->iat_ifaddr != NULL) + memcpy(ifap->iat_ifaddr, in6, ifap->iat_ifaddr_len); + strlcpy(ifap->iat_ni_network, + netname6(&in6->ia_addr, &in6->ia_prefixmask.sin6_addr, 1), + sizeof(ifap->iat_ni_network)); + ifap->iat_network = + strdup(netname6(&in6->ia_addr, + &in6->ia_prefixmask.sin6_addr, 0)); + inet_ntop(PF_INET6, &sa_in6->sin6_addr, ifap->iat_ni_address, + sizeof(ifap->iat_ni_address)); + ifap->iat_address = strdup(routename6(sa_in6, 0)); + ifap->iat_layer = layer_Network; + switch (type) { + case NETSTAT_IF_IFADDR: + ifap->iat_refcount = in->ia_ifa.ifa_refcnt; + break; + case NETSTAT_IF_IFMULTIADDR: + ifap->iat_refcount = ifma->ifma_refcount; + break; + } + ifap->iat_opackets = in6->ia_ifa.if_opackets; + ifap->iat_ipackets = in6->ia_ifa.if_ipackets; + ifap->iat_obytes = in6->ia_ifa.if_obytes; + ifap->iat_ibytes = in6->ia_ifa.if_ibytes; + break; +#endif /* INET6 */ + case PF_IPX: + break; + case PF_APPLETALK: + break; + case PF_LINK: + ifap->iat_sockaddr_len = sizeof(struct sockaddr_dl); + ifap->iat_sockaddr = malloc(ifap->iat_sockaddr_len); + if (ifap->iat_sockaddr != NULL) + memcpy(ifap->iat_sockaddr, sa_dl, + ifap->iat_sockaddr_len); + sprintf(ifap->iat_ni_network, "", sa_dl->sdl_index); + ifap->iat_network = strdup(ifap->iat_ni_network); + cp = (char *)LLADDR(sa_dl); + n = sa_dl->sdl_alen; + p = ifap->iat_ni_address; + while (--n >= 0) { + sprintf(p, "%02x%s", *cp++ & 0xff, n > 0 ? ":" : ""); + p += 3; + } + ifap->iat_address = strdup(ifap->iat_ni_address); + ifap->iat_layer = layer_Link; + break; + default: + break; + } + + return (ifap); +} Index: lib/libnetstat/netstat_route.c =================================================================== --- lib/libnetstat/netstat_route.c (revision 0) +++ lib/libnetstat/netstat_route.c (revision 0) @@ -0,0 +1,564 @@ +/*- + * Copyright (c) 2009, 2010 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "netstat.h" +#include "netstat_internal.h" + +#define PTR2INT(i,p) bcopy(&(p), &(i), MIN(sizeof(p), sizeof(i))) + +/* nlist(3) indices and symbols */ +enum nlRT { + nlRT_rt_tables = 0, + nlRT_MAX, +}; + +static const char *const rt_symbol[] = + { "_rt_tables" }; + +static int read_kvm(kvm_t *, const char *, void *, size_t); +static int route_tree_kvm(struct route_type_list *, int, int, kvm_t *, int); +static int route_tree_sysctl(struct route_type_list *, int, int, int); +static void process_tree(kvm_t *, struct route_type_list *, + struct radix_node *, int, int); +static void extract_rtentry_data(struct rtentry *, struct route_type *); +static void extract_node(struct radix_node *, struct routenode_type *, int); + +int +netstat_route(const struct session_type *session, int fib, int domain, + struct route_type_list *list, int flags) +{ + if (session->sst_flags & NETSTAT_SESSION_KVM) + return (route_tree_kvm(list, fib, domain, session->sst_kvm, + flags)); + else + return (route_tree_sysctl(list, fib, domain, flags)); +} + +#define KREAD(off, dst) do { \ + if ((kread_data(kvm, (uintptr_t)(off), &(dst), sizeof(dst))) != 0) {\ + list->rtl_error = NETSTAT_ERROR_KVM; \ + goto out; \ + } \ +} while (0); + +struct rtline { + struct radix_node_head *tables[PF_MAX + 1]; +}; + +typedef union { + long dummy; + struct sockaddr u_sa; + u_short u_data[128]; +} sa_u; + +int +route_tree_kvm(struct route_type_list *list, int fib, int domain, kvm_t *kvm, + int flags) +{ + int result; + size_t intsize; + int i, fibnum, numfibs, treesize, allfibs; + int tmpfib; + + struct rtline *rt_tables; + struct radix_node_head *rnh; + struct radix_node_head head; + + result = -1; + intsize = sizeof(int); + allfibs = flags & NETSTAT_ROUTE_ALLFIBS; + + if (sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1) + fibnum = 0; + + if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) + numfibs = 1; + + if (!allfibs && (fib >= numfibs)) { + list->rtl_error = NETSTAT_ERROR_INVALID; + goto out; + } + + treesize = numfibs * sizeof(struct rtline); + rt_tables = malloc(treesize); + bzero(rt_tables, treesize); + + if (rt_tables == NULL) { + list->rtl_error = NETSTAT_ERROR_NOMEMORY; + goto out; + } + + if (read_kvm(kvm, rt_symbol[nlRT_rt_tables], rt_tables, treesize) < 0) { + list->rtl_error = NETSTAT_ERROR_KVM; + goto out; + } + + if (domain == PF_UNSPEC) + for (i = 0; i <= PF_MAX; i++) { + tmpfib = (i != PF_INET) ? 0 : fibnum; + rnh = rt_tables[tmpfib].tables[i]; + + if (rnh == NULL) + continue; + + KREAD(rnh, head); + process_tree(kvm, list, head.rnh_treetop, i, flags); + } + else { + tmpfib = (domain != PF_INET) ? 0 : fibnum; + rnh = rt_tables[tmpfib].tables[domain]; + if (rnh != NULL) { + KREAD(rnh, head); + process_tree(kvm, list, head.rnh_treetop, domain, + flags); + } + } + + result = 0; +out: + return (result); +} +#undef KREAD + +#define KREAD(off, dst) do { \ + if ((kread_data(kvm, (uintptr_t)(off), &(dst), sizeof(dst))) != 0) {\ + list->rtl_error = NETSTAT_ERROR_KVM; \ + return; \ + } \ +} while (0); + +void +process_tree(kvm_t *kvm, struct route_type_list *list, struct radix_node *rn, + int domain, int flags) +{ + struct rtentry rtentry; + struct radix_node *rnode, *rnp; + struct ifnet iface; + struct route_type *rtp; + struct radix_mask rm, *rmp, *next, **oldptr; + struct radix_node rmn; + sa_u sa, mk, sagw; + int cnt; + +again: + if (rn == NULL) + return; + + KREAD(rn, rtentry); + rnode = rtentry.rt_nodes; + + if (!(rnode->rn_flags & RNF_ACTIVE)) + return; + + if (rtentry.rt_ifp != NULL) { + KREAD(rtentry.rt_ifp, iface); + rtentry.rt_ifp = &iface; + } + + cnt = 0; + if ((flags & NETSTAT_ROUTE_ALL) && (rnode->rn_mklist != NULL)) { + rmp = rnode->rn_mklist; + oldptr = &rnode->rn_mklist; + while (rmp != NULL) { + KREAD(rmp, rm); + rmp = malloc(sizeof(rm)); + bcopy(&rm, rmp, sizeof(rm)); + KREAD(rmp->rm_leaf, rmn); + rmp->rm_leaf = malloc(sizeof(rmn)); + bcopy(&rmn, rmp->rm_leaf, sizeof(rmn)); + rnp = rmp->rm_leaf; + if (rmn.rn_mask != NULL) { + KREAD(rmn.rn_mask, rm); + rnp->rn_mask = malloc(sizeof(rm)); + bcopy(&rm, rnp->rn_mask, sizeof(rm)); + } + *oldptr = rmp; + oldptr = &rmp->rm_mklist; + rmp = rmp->rm_mklist; + cnt += 1; + } + } + + if (rnode->rn_bit < 0) { + if (rnode->rn_flags & RNF_ROOT) { + if (flags & NETSTAT_ROUTE_ALL) { + rtp = _netstat_rt_allocate(list); + rtp->rt_family = domain; + PTR2INT(rtp->rt_node.rnt_address, rn); + rtp->rt_node.rnt_flags |= NETSTAT_RTN_ROOT; + extract_node(rnode, &rtp->rt_node, cnt); + } + } else { + if (rnode->rn_key != NULL) { + KREAD(rnode->rn_key, sa); + rtentry.rt_nodes->rn_key = (caddr_t)&sa.u_sa; + } + + if (rnode->rn_mask != NULL) { + KREAD(rnode->rn_mask, mk); + rtentry.rt_nodes->rn_mask = (caddr_t)&mk.u_sa; + } + + if (rtentry.rt_gateway != NULL) { + KREAD(rtentry.rt_gateway, sagw); + rtentry.rt_gateway = &sagw.u_sa; + } + + rtp = _netstat_rt_allocate(list); + PTR2INT(rtp->rt_node.rnt_address, rn); + rtp->rt_node.rnt_netmask = + extract_address(rnode->rn_mask, NULL, 0); + extract_rtentry_data(&rtentry, rtp); + extract_node(rnode, &rtp->rt_node, cnt); + } + if ((rn = rnode->rn_dupedkey)) + goto again; + } else { + if (flags & NETSTAT_ROUTE_ALL) { + rtp = _netstat_rt_allocate(list); + rtp->rt_family = domain; + PTR2INT(rtp->rt_node.rnt_address, rn); + extract_node(rnode, &rtp->rt_node, cnt); + } + rn = rnode->rn_right; + process_tree(kvm, list, rnode->rn_left, domain, flags); + process_tree(kvm, list, rn, domain, flags); + } + + if (flags & NETSTAT_ROUTE_ALL) { + rmp = rnode->rn_mklist; + while (rmp != NULL) { + next = rmp->rm_mklist; + rnp = rmp->rm_leaf; + if (rnp != NULL && rnp->rn_mask != NULL) + free(rnp->rn_mask); + free(rmp->rm_leaf); + free(rmp); + rmp = next; + } + } +} +#undef KREAD + +int +read_kvm(kvm_t *k, const char *sym, void *addr, size_t len) +{ + struct nlist nls[2]; + char buf[32]; + + if (k == NULL) + return (-1); + + bzero(nls, sizeof(nls)); + strlcpy(buf, sym, sizeof(buf)); + nls[0].n_name = buf; + + if (kvm_nlist(k, nls) < 0) + return (-1); + + if (kread_data(k, (uintptr_t)nls[0].n_value, addr, len) != 0) + return (-1); + + return (0); +} + +int +route_tree_sysctl(struct route_type_list *list, __unused int fib, + __unused int domain, __unused int flags) +{ + /* XXX: unsupported */ + list->rtl_error = NETSTAT_ERROR_UNSUPPORTED; + return (-1); +} + +#define CNV_FLAG(X, Y) \ + if (rte->rt_flags & (X)) \ + rtp->rt_flags |= (Y) + +void +extract_rtentry_data(struct rtentry *rte, struct route_type *rtp) +{ + time_t expire_time; + struct timespec uptime; + struct sockaddr *sa, *mk; + + CNV_FLAG(RTF_UP, NETSTAT_RT_UP); + CNV_FLAG(RTF_GATEWAY, NETSTAT_RT_GATEWAY); + CNV_FLAG(RTF_HOST, NETSTAT_RT_HOST); + CNV_FLAG(RTF_REJECT, NETSTAT_RT_REJECT); + CNV_FLAG(RTF_DYNAMIC, NETSTAT_RT_DYNAMIC); + CNV_FLAG(RTF_MODIFIED, NETSTAT_RT_MODIFIED); + CNV_FLAG(RTF_DONE, NETSTAT_RT_DONE); + CNV_FLAG(RTF_XRESOLVE, NETSTAT_RT_XRESOLVE); + CNV_FLAG(RTF_LLINFO, NETSTAT_RT_LLINFO); + CNV_FLAG(RTF_STATIC, NETSTAT_RT_STATIC); + CNV_FLAG(RTF_PROTO1, NETSTAT_RT_PROTO1); + CNV_FLAG(RTF_PROTO2, NETSTAT_RT_PROTO2); + CNV_FLAG(RTF_PROTO3, NETSTAT_RT_PROTO3); + CNV_FLAG(RTF_BLACKHOLE, NETSTAT_RT_BLACKHOLE); + CNV_FLAG(RTF_BROADCAST, NETSTAT_RT_BROADCAST); + rtp->rt_fib = rte->rt_fibnum; + sa = (struct sockaddr *)rte->rt_nodes->rn_key; + mk = (struct sockaddr *)rte->rt_nodes->rn_mask; + rtp->rt_family = sa->sa_family; + rtp->rt_destination = extract_address(sa, mk, rte->rt_flags); + rtp->rt_gateway = extract_address(rte->rt_gateway, NULL, RTF_HOST); + rtp->rt_refs = rte->rt_refcnt; + rtp->rt_used = rte->rt_use; + if (rte->rt_ifp != NULL) + rtp->rt_interface = strdup(rte->rt_ifp->if_xname); + else + rtp->rt_interface = strdup("---"); + if (rte->rt_rmx.rmx_expire > 0) { + if (clock_gettime(CLOCK_UPTIME, &uptime) < 0) { + warn("netstat_route: clock_gettime() failed"); + } + expire_time = rte->rt_rmx.rmx_expire - uptime.tv_sec; + if (expire_time > 0) { + rtp->rt_flags |= NETSTAT_RT_EXPIRES; + rtp->rt_expire = expire_time; + } + } + rtp->rt_mtu = rte->rt_rmx.rmx_mtu; + rtp->rt_fib = rte->rt_fibnum; +} +#undef CNV_FLAG + +struct routeaddr_type * +extract_address(void *saddr, void *maddr, int flags) +{ + struct routeaddr_type *rap; + struct sockaddr *sa, *mask; + struct sockaddr_in *sa_in, *mk_in; +#ifdef INET6 + struct sockaddr_in6 *sa_in6, *mk_in6; + struct in6_addr *in6; +#endif + struct sockaddr_dl *sa_dl; + char *cp, *cq, *cqlim, *p; + int n; + char workbuf[128]; + u_char *s, *slim; + + if (saddr == NULL) + return (NULL); + + sa = (struct sockaddr *)saddr; + mask = (struct sockaddr *)maddr; + sa_in = (struct sockaddr_in *)sa; + mk_in = (struct sockaddr_in *)mask; +#ifdef INET6 + sa_in6 = (struct sockaddr_in6 *)sa; + in6 = &sa_in6->sin6_addr; + mk_in6 = (struct sockaddr_in6 *)mask; +#endif + sa_dl = (struct sockaddr_dl *)sa; + + rap = _netstat_rat_allocate(sa->sa_family, sa, sizeof(struct sockaddr)); + if (rap == NULL) + return (NULL); + + switch (sa->sa_family) { + case PF_INET: + if ((sa_in->sin_addr.s_addr == INADDR_ANY) && + (mask != NULL) && + (ntohl(mk_in->sin_addr.s_addr) == 0L)) { + rap->rat_address = strdup("default"); + strlcpy(rap->rat_ni_address, "default", + sizeof(rap->rat_ni_address)); + } else if (flags & RTF_HOST) { + inet_ntop(PF_INET, &sa_in->sin_addr, + rap->rat_ni_address, sizeof(rap->rat_ni_address)); + rap->rat_address = + strdup(routename(sa_in->sin_addr.s_addr, 0)); + } else if (mask != NULL) { + strlcpy(rap->rat_ni_address, + netname(sa_in->sin_addr.s_addr, + ntohl(mk_in->sin_addr.s_addr), 1), + sizeof(rap->rat_ni_address)); + rap->rat_address = + strdup(netname(sa_in->sin_addr.s_addr, + ntohl(mk_in->sin_addr.s_addr), 0)); + } else { + rap->rat_address = + strdup(netname(sa_in->sin_addr.s_addr, + 0L, 0)); + strlcpy(rap->rat_ni_address, rap->rat_address, + sizeof(rap->rat_ni_address)); + } + rap->rat_data = malloc(sizeof(struct sockaddr_in)); + if (rap->rat_data != NULL) { + rap->rat_data_len = sizeof(struct sockaddr_in); + memcpy(rap->rat_data, sa_in, rap->rat_data_len); + } + break; +#ifdef INET6 + case PF_INET6: + /* + * 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(in6) || + IN6_IS_ADDR_MC_LINKLOCAL(in6)) { + sa_in6->sin6_scope_id = + (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]); + *(u_short *)&in6->s6_addr[2] = 0; + } + if (flags & RTF_HOST) { + rap->rat_address = strdup(routename6(sa_in6, 0)); + strlcpy(rap->rat_ni_address, routename6(sa_in6, 1), + sizeof(rap->rat_ni_address)); + } + else if (mask != NULL) { + rap->rat_address = strdup(netname6(sa_in6, + &mk_in6->sin6_addr, 0)); + strlcpy(rap->rat_ni_address, + netname6(sa_in6, &mk_in6->sin6_addr, 1), + sizeof(rap->rat_ni_address)); + } else { + rap->rat_address = strdup(netname6(sa_in6, 0L, 0)); + strlcpy(rap->rat_ni_address, rap->rat_address, + sizeof(rap->rat_ni_address)); + } + rap->rat_data = malloc(sizeof(struct sockaddr_in6)); + if (rap->rat_data != NULL) { + rap->rat_data_len = sizeof(struct sockaddr_in6); + memcpy(rap->rat_data, sa_in6, rap->rat_data_len); + } + break; +#endif + case PF_IPX: + break; + case PF_APPLETALK: + break; + case PF_NETGRAPH: + break; + case PF_LINK: + if (sa_dl->sdl_nlen == 0 && sa_dl->sdl_alen == 0 && + sa_dl->sdl_slen == 0) { + sprintf(rap->rat_ni_address, "", + sa_dl->sdl_index); + } else { + cp = (char *)LLADDR(sa_dl); + n = sa_dl->sdl_alen; + p = rap->rat_address; + while (--n >= 0) { + sprintf(p, "%02x%s", *cp++ & 0xff, + n > 0 ? ":" : ""); + p += 3; + } + } + rap->rat_address = strdup(rap->rat_ni_address); + rap->rat_data = malloc(sizeof(struct sockaddr_dl)); + if (rap->rat_data != NULL) { + rap->rat_data_len = sizeof(struct sockaddr_dl); + memcpy(rap->rat_data, sa_dl, rap->rat_data_len); + } + break; + default: + s = (u_char *)sa->sa_data; + 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++); + } + rap->rat_address = strdup(workbuf); + strlcpy(rap->rat_ni_address, workbuf, + sizeof(rap->rat_ni_address)); + rap->rat_data = malloc(sizeof(struct sockaddr)); + if (rap->rat_data != NULL) { + rap->rat_data_len = sizeof(struct sockaddr); + memcpy(rap->rat_data, sa, rap->rat_data_len); + } + break; + } + + return (rap); +} + +void +extract_node(struct radix_node *rn, struct routenode_type *rnp, int mkcnt) +{ + struct radix_mask *rmp; + struct radix_node *rnode; + int i; + + rnp->rnt_bit = rn->rn_bit; + PTR2INT(rnp->rnt_left, rn->rn_left); + PTR2INT(rnp->rnt_right, rn->rn_right); + PTR2INT(rnp->rnt_key, rn->rn_key); + PTR2INT(rnp->rnt_dupedkey, rn->rn_dupedkey); + if (rn->rn_dupedkey != 0) + rnp->rnt_flags |= NETSTAT_RTN_DUPEDKEY; + rnp->rnt_mkcnt = mkcnt; + + if (rnp->rnt_mkcnt == 0) + return; + + rnp->rnt_mklist = malloc(sizeof(struct routemask_type) * rnp->rnt_mkcnt); + rmp = rn->rn_mklist; + i = 0; + + while (rmp != NULL) { + rnp->rnt_mklist[i].rmt_address = 0; + rnp->rnt_mklist[i].rmt_flags = 0; + if (rmp->rm_flags & RNF_NORMAL) + rnp->rnt_mklist[i].rmt_flags |= NETSTAT_RTM_NORMAL; + rnp->rnt_mklist[i].rmt_bit = rmp->rm_bit; + rnp->rnt_mklist[i].rmt_refs = rmp->rm_refs; + rnode = rmp->rm_leaf; + rnp->rnt_mklist[i].rmt_netmask = + (rmp->rm_flags & RNF_NORMAL && rnode->rn_mask != NULL) ? + extract_address(rnode->rn_mask, NULL, 0) : + extract_address(rmp->rm_mask, NULL, 0); + rmp = rmp->rm_mklist; + i += 1; + } +} Index: lib/libnetstat/netstat_internal.h =================================================================== --- lib/libnetstat/netstat_internal.h (revision 0) +++ lib/libnetstat/netstat_internal.h (revision 0) @@ -0,0 +1,612 @@ +/*- + * Copyright (c) 2009, 2010 Gabor Pali + * 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. + * + * 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$ + */ + +#ifndef _NETSTAT_INTERNAL_H_ +#define _NETSTAT_INTERNAL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SCTP +#include +#endif +#ifdef INET6 +#include +#include +#include +#include +#endif +#ifdef IPX +#include +#include +#endif +#include +#include +#ifdef IPSEC +#include +#include +#include +#include +#include +#endif +#include +#include +#ifdef INET6 +#define _KERNEL +#include +#include +#undef _KERNEL +#endif + +#include "netstat.h" + +struct session_type { + int sst_flags; + kvm_t *sst_kvm; +}; + +/* Address type: + * local, foreign, node (Netgraph), raw (domain) + */ +struct sockaddr_type { + /* XXX: this should be an enum? */ + int sat_type; + char sat_name[1024]; + int sat_flags; + struct socket_type * sat_parent; + /* numeric representation */ + char sat_numeric[32]; + char *sat_address; + int sat_address_len; + uint16_t sat_port; + char sat_portname[32]; +}; + +/* Socket buffer type */ +struct sockbuf_type { + u_int32_t sbt_cc; /* actual chars in the buffer */ + u_int32_t sbt_mcnt; + u_int32_t sbt_ccnt; + u_int32_t sbt_hiwat; + u_int32_t sbt_lowat; + u_int32_t sbt_mbcnt; + u_int32_t sbt_mbmax; +}; + +/* internal defines for sockaddr_type: */ +#define SOCKADDRTYPE_ANONPORT 0x01 +#define SOCKADDRTYPE_NAME_RESOLVED 0x02 +#define SOCKADDRTYPE_PORT_RESOLVED 0x04 + +#define NETSTAT_ADDRTYPE_LOCAL 0 +#define NETSTAT_ADDRTYPE_INET_LOCAL 1 +#define NETSTAT_ADDRTYPE_INET_FOREIGN 2 +#define NETSTAT_ADDRTYPE_INET46_LOCAL 3 +#define NETSTAT_ADDRTYPE_INET46_FOREIGN 4 +#define NETSTAT_ADDRTYPE_INET6_LOCAL 5 +#define NETSTAT_ADDRTYPE_INET6_FOREIGN 6 + +#define NETSTAT_IF_IFADDR 0 +#define NETSTAT_IF_IFMULTIADDR 1 + +#define NETSTAT_SESSION_KVM 0x01 + +/* Socket (PCB) type: a connection. */ +struct socket_type { + /* Static properties. */ + unsigned short st_family; + unsigned short st_protocol; + int st_flags; + char st_name[SOCKTYPE_MAXNAME]; + char st_extname[SOCKTYPE_MAXNAME]; + + /* address(es) */ + struct sockaddr_type *st_address[SOCKTYPE_MAXADDRCNT]; + int st_addrcnt; /* address count */ + + /* buffers */ + struct sockbuf_type st_snd; + struct sockbuf_type st_rcv; + + u_int16_t st_qlen; /* number of unaccepted connections */ + u_int16_t st_incqlen; /* number of unaccepted incomplete + connections */ + u_int16_t st_qlimit; /* max number queued connections */ + u_int64_t st_pcb; /* protocol control block */ + u_int64_t st_vnode; /* if associated with file */ + u_int64_t st_conn; /* control block of connected socket */ + u_int64_t st_refs; /* referencing socket linked list */ + u_int64_t st_reflink; /* link in references list */ + enum tcp_state st_tcps; + char st_tcpstate[16]; + + /* list of types */ + LIST_ENTRY(socket_type) st_list; +}; + +/* Internal flags for socket_type: */ +#define SOCKTYPE_VNODE 0x01 /* Associated with a file. */ +#define SOCKTYPE_CONN 0x02 /* Has a control block connected. */ +#define SOCKTYPE_REFS 0x04 /* Has socket references. */ +#define SOCKTYPE_TCP 0x08 /* A TCP socket, has states. */ + +struct socket_type_list { + LIST_HEAD(, socket_type) stl_list; + int stl_length; + int stl_error; +}; + +struct socket_type_iterator { + struct socket_type_list *sti_list; + struct socket_type *sti_first; + struct socket_type *sti_next; +}; + +struct buffer_type { + u_int64_t bt_count; + u_int64_t bt_bytes; + u_int64_t bt_free; + u_int64_t bt_failures; + u_int64_t bt_size; + u_int64_t bt_limit; +}; + +struct mbuf_type { + struct buffer_type mbt_mbuf; + struct buffer_type mbt_cluster; + struct buffer_type mbt_packet; + struct buffer_type mbt_tag; + struct buffer_type mbt_jumbop; + struct buffer_type mbt_jumbo9; + struct buffer_type mbt_jumbo16; + + u_int64_t mbt_bytes_inuse; + u_int64_t mbt_bytes_incache; + u_int64_t mbt_bytes_total; + + /* from mbstat */ + u_int64_t mbt_drain; /* times drained protocols for space */ + + /* Sendfile stats */ + u_int64_t mbt_sf_bufs; /* number of avail sf_bufs */ + u_int64_t mbt_sf_bufs_peak; /* peak usage */ + u_int64_t mbt_sf_bufs_inuse; /* in use */ + u_int64_t mbt_sf_iocnt; /* times sf had to do disk I/O */ + u_int64_t mbt_sf_allocfail; /* times sfbuf alloc failed */ + u_int64_t mbt_sf_allocwait; /* times sfbuf alloc waited */ + + int mbt_error; +}; + +/* General interface statistics. */ +struct face_type { + u_int64_t ft_packets; + u_int64_t ft_bytes; + u_int64_t ft_mcasts; + u_int64_t ft_errors; + u_int64_t ft_drops; +}; + +/* Interface address. */ +struct intfaddr_type { + int iat_family; /* protocol family */ + enum intfaddr_layer iat_layer; + int iat_type; /* ifa, ifma */ + char *iat_address; + char iat_ni_address[20]; /* numeric */ + char *iat_network; + char iat_ni_network[16]; /* numeric */ + void *iat_sockaddr; + void *iat_ifaddr; + int iat_sockaddr_len; + int iat_ifaddr_len; + u_int32_t iat_refcount; + /* for network-layer addresses: */ + u_int64_t iat_opackets; + u_int64_t iat_ipackets; + u_int64_t iat_obytes; + u_int64_t iat_ibytes; +}; + +/* Interface. */ +struct interface_type { + int it_type; /* ethernet, tokenring, etc. */ + int it_physical; /* AUI, Thinnet, 10base-T, etc. */ + char it_name[IFTYPE_MAXNAME]; + u_int64_t it_mtu; /* maximum transmission unit */ + int it_flags; + + struct face_type it_in; + struct face_type it_out; + + u_int64_t it_collisions; + u_int64_t it_drops; + + /* Addresses. */ + struct intfaddr_type *it_address[IFTYPE_MAXADDRCNT]; + int it_addrcnt; + + /* Multicast addresses. */ + struct intfaddr_type *it_maddress[IFTYPE_MAXADDRCNT]; + int it_mcast_addrcnt; + + TAILQ_ENTRY(interface_type) it_list; +}; + +struct interface_type_list { + TAILQ_HEAD(, interface_type) itl_list; + int itl_length; + int itl_error; +}; + +struct interface_type_iterator { + struct interface_type_list *iti_list; + struct interface_type *iti_first; + struct interface_type *iti_next; +}; + +/* Berkeley Packet Filter (descriptor). */ +struct bpf_type { + int bpt_flags; + u_int32_t bpt_slen; /* current length of store buffer */ + u_int32_t bpt_hlen; /* current length of hold buffer */ + u_int64_t bpt_recv; /* number of packets received */ + u_int64_t bpt_drop; /* number of packets dropped */ + u_int64_t bpt_match; /* number of packets which matched + filter */ + u_int32_t bpt_pid; /* PID which created descriptor */ + char *bpt_pidname; + enum bpf_dir bpt_direction; /* select packet direction */ + char bpt_ifname[BPFTYPE_MAXNAME]; /* interface name */ + + LIST_ENTRY(bpf_type) bpt_list; +}; + +struct bpf_type_list { + LIST_HEAD(, bpf_type) bptl_list; + int bptl_length; + int bptl_error; +}; + +struct bpf_type_iterator { + struct bpf_type_list *bpti_list; + struct bpf_type *bpti_first; + struct bpf_type *bpti_next; +}; + +/* General statistics type. */ +struct stat_type { + enum stat stt_type; + void *stt_data; + int stt_error; +}; + +struct tcp_stat { + struct tcpstat s; +}; + +struct udp_stat { + struct udpstat s; +}; + +struct carp_stat { + struct carpstats s; +}; + +struct ip_stat { + struct ipstat s; +}; + +struct icmp_stat { + struct icmpstat s; +}; + +struct pim_stat { + struct pimstat s; +}; + +struct igmp_stat { + struct igmpstat s; +}; + +struct ddp_stat { + struct ddpstat s; +}; + +#ifdef SCTP +struct sctp_stat { + struct sctpstat s; +}; +#endif + +#ifdef INET6 +struct ip6_stat { + struct ip6stat s; +}; + +struct icmp6_stat { + struct icmp6stat s; +}; + +struct pim6_stat { + struct pim6stat s; +}; + +struct rip6_stat { + struct rip6stat s; +}; +#endif + +#ifdef IPX +struct ipx_stat { + struct ipxstat s; +}; + +struct spx_stat { + struct spx_istat s; +}; +#endif + +struct pfsync_stat { + struct pfsyncstats s; +}; + +#ifdef IPSEC +struct pfkey_stat { + struct pfkeystat s; +}; + +struct esp_stat { + struct espstat s; +}; + +struct ah_stat { + struct ahstat s; +}; + +struct ipcomp_stat { + u_int32_t v; + struct ipcompstat *s; +}; + +struct ipsec_stat { + struct ipsecstat s; +}; +#endif + +struct route_stat { + struct rtstat s; +}; + +struct mroute_stat { + struct mrtstat s; +}; + +#ifdef INET6 +struct mroute6_stat { + struct mrt6stat s; +}; +#endif + +struct val2str { + int val; + const char *str; +}; + +/* Route type. */ +struct routeaddr_type { + int rat_family; /* protocol family */ + /* for printing purposes: */ + char *rat_address; /* resolved hostname */ + char rat_ni_address[20]; /* numeric */ + /* for other: */ + void *rat_data; /* raw socket information */ + size_t rat_data_len; +}; + +struct routemask_type { + int rmt_flags; + int rmt_bit; + u_int64_t rmt_address; + u_int64_t rmt_refs; + struct routeaddr_type *rmt_netmask; +}; + +struct routenode_type { + int rnt_flags; + int rnt_bit; + u_int64_t rnt_address; + u_int64_t rnt_left; + u_int64_t rnt_right; + u_int64_t rnt_key; + u_int64_t rnt_dupedkey; + struct routeaddr_type *rnt_netmask; + int rnt_mkcnt; + struct routemask_type *rnt_mklist; +}; + +struct route_type { + int rt_fib; /* FIB instance */ + int rt_family; /* protocol family */ + struct routeaddr_type *rt_destination; /* destination: subnet */ + struct routeaddr_type *rt_gateway; /* gateway: node */ + int rt_flags; + u_int64_t rt_refs; /* # references */ + u_int64_t rt_used; /* # raw packets forwarded */ + char *rt_interface; /* routing interface name */ + u_int64_t rt_expire; /* sec */ + u_int32_t rt_mtu; /* bytes */ + struct routenode_type rt_node; + + TAILQ_ENTRY(route_type) rt_list; +}; + +struct route_type_list { + TAILQ_HEAD(, route_type) rtl_list; + int rtl_length; + int rtl_error; +}; + +struct route_type_iterator { + struct route_type_list *rti_list; + struct route_type *rti_first; + struct route_type *rti_next; +}; + + +/* Multicast interface type. */ +struct mcastif_type { + u_int32_t mit_index; + int mit_flags; + u_int32_t mit_limit; /* threshold/rate limit */ + struct routeaddr_type *mit_address; + struct routeaddr_type *mit_remote_address; + u_int64_t mit_packets_in; + u_int64_t mit_packets_out; + u_int64_t mit_bytes_in; + u_int64_t mit_bytes_out; + char mit_ifname[MIFTYPE_MAXNAME]; + + TAILQ_ENTRY(mcastif_type) mit_list; +}; + +struct mcastif_type_list { + TAILQ_HEAD(, mcastif_type) mitl_list; + int mitl_length; + int mitl_error; +}; + +struct mcastif_type_iterator { + struct mcastif_type_list *miti_list; + struct mcastif_type *miti_first; + struct mcastif_type *miti_next; +}; + + +/* Multicast route type. */ +struct mroute_type { + struct routeaddr_type *mrt_origin; + struct routeaddr_type *mrt_group; + u_int64_t mrt_packets; + u_int64_t mrt_bytes; + u_int64_t mrt_waitings; + u_int32_t mrt_parent; + u_int8_t mrt_ttls[MRTTYPE_MAXVIFS]; + struct if_set mrt_ifset; + + TAILQ_ENTRY(mroute_type) mrt_list; +}; + +struct mroute_type_list { + TAILQ_HEAD(, mroute_type) mrtl_list; + int mrtl_length; + int mrtl_error; +}; + +struct mroute_type_iterator { + struct mroute_type_list *mrti_list; + struct mroute_type *mrti_first; + struct mroute_type *mrti_next; +}; + + +int kread_data(kvm_t *kvm, u_long kvm_pointer, void *address, size_t size); +int kread_string(kvm_t *kvm, u_long kvm_pointer, char *buffer, int buflen); + +void _netstat_stl_empty(struct socket_type_list *list); +struct socket_type *_netstat_st_allocate(struct socket_type_list *list, + unsigned short family, unsigned short protocol, + const char *name); +void _netstat_st_reset_stats(struct socket_type *list); +struct sockaddr_type *_netstat_sat_allocate(struct socket_type *parent, + int type, const char *name, char *address, + int addr_len); +void _netstat_sat_resolve_name(struct sockaddr_type *addr); +void _netstat_sat_resolve_portname(struct sockaddr_type *addr); + +int sotoxsocket(kvm_t * kvm, struct socket *so, struct xsocket *xso); + +void _netstat_itl_empty(struct interface_type_list *list); +struct interface_type *_netstat_it_allocate(struct interface_type_list *list, + int type, int physical, const char *name); +struct intfaddr_type *_netstat_iat_allocate(int family, int type); + +void _netstat_bptl_empty(struct bpf_type_list *list); +struct bpf_type *_netstat_bpt_allocate(struct bpf_type_list *list, + const char *ifname); + +void _netstat_rtl_empty(struct route_type_list *); +void _netstat_rt_free(struct route_type *); +void _netstat_rat_free(struct routeaddr_type *); +struct route_type *_netstat_rt_allocate(struct route_type_list *); +struct routeaddr_type *_netstat_rat_allocate(int, void *, size_t); + +void _netstat_mitl_empty(struct mcastif_type_list *); +void _netstat_mit_free(struct mcastif_type *); +struct mcastif_type *_netstat_mit_allocate(struct mcastif_type_list *); + +void _netstat_mrtl_empty(struct mroute_type_list *); +void _netstat_mrt_free(struct mroute_type *); +struct mroute_type *_netstat_mrt_allocate(struct mroute_type_list *); +#ifdef INET6 +int _mrt6_get_nstall_kvm(kvm_t *, struct mf6c *); +#endif /* !INET6 */ + +struct routeaddr_type *extract_address(void *, void *, int); +const char *resolve_val2str_name(int, const struct val2str *); +/* XXX: merge these into a common address resolution routine. */ +const char *routename(in_addr_t in, int numeric); +const char *netname(in_addr_t in, u_long mask, int numeric); +#ifdef INET6 +const char *routename6(struct sockaddr_in6 *in6, int numeric); +const char *netname6(struct sockaddr_in6 *in6, struct in6_addr *mask, + int numeric); +#endif + +#endif /* !_NETSTAT_INTERNAL_H_ */ Index: lib/libnetstat/netstat.h =================================================================== --- lib/libnetstat/netstat.h (revision 0) +++ lib/libnetstat/netstat.h (revision 0) @@ -0,0 +1,1344 @@ +/*- + * Copyright (c) 2009, 2010 Gabor Pali + * 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. + * + * 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$ + */ + +#ifndef _NETSTAT_H_ +#define _NETSTAT_H_ + +#include +#include + +#ifdef IPSEC +#include +#include +#include +#include +#endif + +#define NETSTAT_MAXCALLER 16 + +#define SOCKTYPE_MAXNAME 32 +#define SOCKTYPE_MAXADDR SOCK_MAXADDRLEN +#define SOCKTYPE_MAXADDRCNT 2 + +#define IFTYPE_MAXNAME 32 +#define IFTYPE_MAXADDRCNT 8 + +#define BPFTYPE_MAXNAME IFNAMSIZ +#define MIFTYPE_MAXNAME IFNAMSIZ +#define MRTTYPE_MAXVIFS MAXVIFS + +#define NETSTAT_ERROR_UNDEFINED 0 +#define NETSTAT_ERROR_NOMEMORY 1 +#define NETSTAT_ERROR_VERSION 2 +#define NETSTAT_ERROR_KVM 3 +#define NETSTAT_ERROR_KVM_NOSYMBOL 4 +#define NETSTAT_ERROR_KVM_SHORTREAD 5 +#define NETSTAT_ERROR_UNSUPPORTED 6 +#define NETSTAT_ERROR_INVALID 7 + +/* Flags for netstat_socket(): */ +#define NETSTAT_SOCKET_ALL 0x01 /* Return all connections. */ + +/* netstat_interface(): */ +#define NETSTAT_INTERFACE_ALL 0x01 + +/* Testing flags for interface_type: */ +#define NETSTAT_IF_UP 0x01 /* interface is up */ + +/* Flags for bpf_type: */ +#define NETSTAT_BPF_PROMISC 0x01 /* if listening prmoiscuously */ +#define NETSTAT_BPF_IMMEDIATE 0x02 /* return on packet arrival */ +#define NETSTAT_BPF_HDRCMPLT 0x04 /* fill in src lladdr automatically */ +#define NETSTAT_BPF_FEEDBACK 0x08 /* feed back sent packets */ +#define NETSTAT_BPF_ASYNC 0x10 /* packet reception should generate signal */ +#define NETSTAT_BPF_LOCKED 0x20 /* descriptor is locked */ + +/* pfkey: */ +#define NETSTAT_PFKEY_IN_MSGTYPE_MAX 256 +#define NETSTAT_PFKEY_OUT_MSGTYPE_MAX 256 + +/* IPsec: */ +#define NETSTAT_ESP_HIST_MAX ESP_ALG_MAX +#define NETSTAT_AH_HIST_MAX AH_ALG_MAX +#define NETSTAT_IPCOMP_HIST_MAX IPCOMP_ALG_MAX +#define NETSTAT_IPSEC_ESP_HIST_MAX 256 +#define NETSTAT_IPSEC_AH_HIST_MAX 256 +#define NETSTAT_IPSEC_IPCOMP_HIST_MAX 256 + +/* IP6: */ +#define NETSTAT_IP6_NHIST_MAX 256 +#define NETSTAT_IP6_MBUF_MAX 32 +#define NETSTAT_IP6_IF_MAX 16 + +/* Flags for netstat_route(): */ +#define NETSTAT_ROUTE_ALL 0x01 /* Return all routes. */ +#define NETSTAT_ROUTE_ALLFIBS 0x02 /* Return routes for all FIBs. */ + +/* Testing flags for route_type: */ +#define NETSTAT_RT_UP 0x00001 +#define NETSTAT_RT_GATEWAY 0x00002 +#define NETSTAT_RT_HOST 0x00004 +#define NETSTAT_RT_REJECT 0x00008 +#define NETSTAT_RT_DYNAMIC 0x00010 +#define NETSTAT_RT_MODIFIED 0x00020 +#define NETSTAT_RT_DONE 0x00040 +#define NETSTAT_RT_XRESOLVE 0x00080 +#define NETSTAT_RT_STATIC 0x00100 +#define NETSTAT_RT_PROTO1 0x00200 +#define NETSTAT_RT_PROTO2 0x00400 +#define NETSTAT_RT_PROTO3 0x00800 +#define NETSTAT_RT_PRCLONING 0x01000 +#define NETSTAT_RT_BLACKHOLE 0x02000 +#define NETSTAT_RT_BROADCAST 0x04000 +#define NETSTAT_RT_LLINFO 0x08000 +#define NETSTAT_RT_WASCLONED 0x10000 +#define NETSTAT_RT_CLONING 0x20000 +#define NETSTAT_RT_EXPIRES 0x40000 /* has expire time */ + +/* Testing flags for routenode_type: */ +#define NETSTAT_RTN_ROOT 0x01 +#define NETSTAT_RTN_DUPEDKEY 0x02 + +/* Testing flags for routemask_type: */ +#define NETSTAT_RTM_NORMAL 0x01 + +/* Testing flags for mcastif_type: */ +#define NETSTAT_MIF_TUNNEL 0x01 +#define NETSTAT_MIF_SRCRT 0x02 +#define NETSTAT_MIF_REGISTER 0x04 + +#define NETSTAT_MROUTE_INCOMPLETE_PARENT MF6C_INCOMPLETE_PARENT + +/* Enum for TCP states: */ +enum tcp_state { + tcps_Closed, + tcps_Listen, + tcps_SynSent, + tcps_SynReceived, + tcps_Established, + tcps_CloseWait, + tcps_FinWait1, + tcps_FinWait2, + tcps_Closing, + tcps_LastAck, + tcps_TimeWait, + tcps_Hidden, + tcps_Invalid, + tcps_MAX, +}; + +enum intfaddr_layer { + layer_None, + layer_Link, + layer_Network, + layer_MAX, +}; + +enum bpf_dir { + bpfdir_Invalid, + bpfdir_In, + bpfdir_Out, + bpfdir_InOut, + bpfdir_MAX, +}; + +#ifdef IPSEC +enum pfkey_msgtarget { + pfkey_Sendup_One = KEY_SENDUP_ONE, + pfkey_Sendup_All = KEY_SENDUP_ALL, + pfkey_Sendup_Registered = KEY_SENDUP_REGISTERED, +}; +#endif /* !IPSEC */ + +enum stat { + stat_TCP = 0, + stat_UDP, + stat_CARP, + stat_IP, + stat_ICMP, + stat_PIM, + stat_IGMP, + stat_DDP, +#ifdef SCTP + stat_SCTP, +#endif +#ifdef INET6 + stat_IP6, + stat_ICMP6, + stat_PIM6, + stat_RIP6, +#endif +#ifdef IPX + stat_IPX, + stat_SPX, +#endif + stat_pfsync, +#ifdef IPSEC + stat_pfkey, + stat_ESP, + stat_AH, + stat_IPcomp, + stat_IPsec, +#endif + stat_route, + stat_mroute, +#ifdef INET6 + stat_mroute6, +#endif + stat_MAX, + stat_Invalid, +}; + +struct session_type; + +struct socket_type; +struct sockaddr_type; +struct sockbuf_type; + +struct socket_type_list; +struct socket_type_iterator; + +struct mbuf_type; + +struct interface_type; +struct intfaddr_type; +struct face_type; + +struct interface_type_list; +struct interface_type_iterator; + +struct bpf_type; +struct bpf_type_list; +struct bpf_type_iterator; + +struct timestamp_type; + +struct stat_type; +struct tcp_stat; +struct udp_stat; +struct carp_stat; +struct ip_stat; +struct icmp_stat; +struct pim_stat; +struct igmp_stat; +struct ddp_stat; +#ifdef SCTP +struct sctp_stat; +#endif +#ifdef INET6 +struct ip6_stat; +struct icmp6_stat; +struct pim6_stat; +struct rip6_stat; +#endif +#ifdef IPX +struct ipx_stat; +struct spx_stat; +#endif +struct pfsync_stat; +#ifdef IPSEC +struct pfkey_stat; +struct esp_stat; +struct ah_stat; +struct ipcomp_stat; +#endif +struct route_stat; +struct mroute_stat; +#ifdef INET6 +struct mroute6_stat; +#endif + +struct route_type; +struct route_type_list; +struct route_type_iterator; + +struct mcastif_type; +struct mcastif_type_list; +struct mcastif_type_iterator; + +struct mroute_type; +struct mroute_type_list; +struct mroute_type_iterator; + +__BEGIN_DECLS + +const char *netstat_strerror(int); +const char *netstat_kvmerror(const struct session_type *); + +const char *netstat_family_name(int); + +/* "Session" */ +struct session_type *netstat_session_new(void* kvm_handle); +void netstat_session_free(struct session_type *); + + +/* "Socket" */ + +/* Socket list: */ +struct socket_type_list *netstat_stl_alloc(void); +struct socket_type *netstat_stl_find(struct socket_type_list *list, + unsigned short family, const char *name); +void netstat_stl_iterate(struct socket_type_list *list, + void (*func)(struct socket_type *)); +void netstat_stl_free(struct socket_type_list *list); +int netstat_stl_geterror(struct socket_type_list *list); +int netstat_stl_refresh(struct socket_type_list *list); +int netstat_stl_length(struct socket_type_list *list); + +/* Socket iterator: */ +int netstat_sti_alloc(struct socket_type_list *list, + struct socket_type_iterator **iterator); +const struct socket_type *netstat_sti_first(struct socket_type_iterator *); +const struct socket_type *netstat_sti_next(struct socket_type_iterator *); +void netstat_sti_free(struct socket_type_iterator *iterator); + +void netstat_st_free(struct socket_type *stp); +void netstat_sat_free(struct sockaddr_type *satp); + +int netstat_socket(const struct session_type *, int domain, int type, + int protocol, struct socket_type_list *, int flags); + +/* Accessor functions: */ +int netstat_st_get_family(const struct socket_type *stp); +int netstat_st_get_protocol(const struct socket_type *stp); +const char *netstat_st_get_name(const struct socket_type *stp); +const char *netstat_st_get_extname(const struct socket_type *stp); +const struct sockbuf_type *netstat_st_get_snd(const struct socket_type *stp); +const struct sockbuf_type *netstat_st_get_rcv(const struct socket_type *stp); +u_int16_t netstat_st_get_qlen(const struct socket_type *stp); +u_int16_t netstat_st_get_incqlen(const struct socket_type *stp); +u_int16_t netstat_st_get_qlimit(const struct socket_type *stp); +u_int64_t netstat_st_get_pcb(const struct socket_type *stp); +u_int64_t netstat_st_get_vnode(const struct socket_type *stp); +u_int64_t netstat_st_get_conn(const struct socket_type *stp); +u_int64_t netstat_st_get_refs(const struct socket_type *stp); +u_int64_t netstat_st_get_reflink(const struct socket_type *stp); +const char *netstat_st_get_tcpstate(const struct socket_type *stp); +enum tcp_state netstat_st_get_tcps(const struct socket_type *stp); +/* Socket addresses: */ +int netstat_st_get_addrcnt(const struct socket_type *stp); +struct sockaddr_type *netstat_st_get_address(const struct socket_type *stp, + int index); + +const char *netstat_sat_get_name(struct sockaddr_type *satp); +const char *netstat_sat_get_numeric(const struct sockaddr_type *satp); +int netstat_sat_get_address(const struct sockaddr_type *satp, + char *addr, int addr_len); +u_int16_t netstat_sat_get_port(const struct sockaddr_type *satp); +const char *netstat_sat_get_portname(struct sockaddr_type *satp); +/* Socket buffers: */ +u_int32_t netstat_sbt_get_cc(const struct sockbuf_type *sbtp); +u_int32_t netstat_sbt_get_hiwat(const struct sockbuf_type *sbtp); +u_int32_t netstat_sbt_get_lowat(const struct sockbuf_type *sbtp); +u_int32_t netstat_sbt_get_mbcnt(const struct sockbuf_type *sbtp); +u_int32_t netstat_sbt_get_mcnt(const struct sockbuf_type *sbtp); +u_int32_t netstat_sbt_get_ccnt(const struct sockbuf_type *sbtp); +u_int32_t netstat_sbt_get_mbmax(const struct sockbuf_type *sbtp); + +/* "Memory buffers" */ +struct mbuf_type *netstat_mbt_alloc(void); +void netstat_mbt_free(struct mbuf_type *); +int netstat_mbt_get_error(const struct mbuf_type *); + +int netstat_mbuf(const struct session_type *, struct mbuf_type *stats, + int flags); + +const struct buffer_type *netstat_mbt_get_mbuf(const struct mbuf_type *); +const struct buffer_type *netstat_mbt_get_cluster(const struct mbuf_type *); +const struct buffer_type *netstat_mbt_get_packet(const struct mbuf_type *); +const struct buffer_type *netstat_mbt_get_tag(const struct mbuf_type *); +const struct buffer_type *netstat_mbt_get_jumbop(const struct mbuf_type *); +const struct buffer_type *netstat_mbt_get_jumbo9(const struct mbuf_type *); +const struct buffer_type *netstat_mbt_get_jumbo16(const struct mbuf_type *); +u_int64_t netstat_mbt_get_bytes_inuse(const struct mbuf_type *); +u_int64_t netstat_mbt_get_bytes_incache(const struct mbuf_type *); +u_int64_t netstat_mbt_get_bytes_total(const struct mbuf_type *); +u_int64_t netstat_mbt_get_drain(const struct mbuf_type *); +u_int64_t netstat_mbt_get_sf_bufs(const struct mbuf_type *); +u_int64_t netstat_mbt_get_sf_bufs_peak(const struct mbuf_type *); +u_int64_t netstat_mbt_get_sf_bufs_inuse(const struct mbuf_type *); +u_int64_t netstat_mbt_get_sf_iocnt(const struct mbuf_type *); +u_int64_t netstat_mbt_get_sf_allocfail(const struct mbuf_type *); +u_int64_t netstat_mbt_get_sf_allocwait(const struct mbuf_type *); + +u_int64_t netstat_bt_get_count(const struct buffer_type *); +u_int64_t netstat_bt_get_bytes(const struct buffer_type *); +u_int64_t netstat_bt_get_free(const struct buffer_type *); +u_int64_t netstat_bt_get_failures(const struct buffer_type *); +u_int64_t netstat_bt_get_size(const struct buffer_type *); +u_int64_t netstat_bt_get_limit(const struct buffer_type *); + +/* Interfaces: */ +struct interface_type_list *netstat_itl_alloc(void); +void netstat_itl_free(struct interface_type_list *); +int netstat_itl_geterror(const struct interface_type_list *); +int netstat_itl_length(const struct interface_type_list *); + +int netstat_iti_alloc(struct interface_type_list *list, + struct interface_type_iterator **iterator); +const struct interface_type *netstat_iti_first(struct interface_type_iterator *); +const struct interface_type *netstat_iti_next(struct interface_type_iterator *); +void netstat_iti_free(struct interface_type_iterator *iterator); + +void netstat_it_free(struct interface_type *); +void netstat_iat_free(struct intfaddr_type *); + +int netstat_interface(const struct session_type *, const char *name, + int domain, struct interface_type_list *list, int flags); + +const char *netstat_it_get_name(const struct interface_type *); +u_int64_t netstat_it_get_mtu(const struct interface_type *); +int netstat_it_get_flags(const struct interface_type *); +u_int64_t netstat_it_get_collisions(const struct interface_type *); +u_int64_t netstat_it_get_drops(const struct interface_type *); +const struct face_type *netstat_it_get_in(const struct interface_type *); +const struct face_type *netstat_it_get_out(const struct interface_type *); + +int netstat_it_get_addrcnt(const struct interface_type *); +const struct intfaddr_type * +netstat_it_get_address(const struct interface_type *, int index); + +int netstat_it_get_mcast_addrcnt(const struct interface_type *); +const struct intfaddr_type * +netstat_it_get_mcast_address(const struct interface_type *, int index); + +u_int64_t netstat_ft_get_packets(const struct face_type *); +u_int64_t netstat_ft_get_bytes(const struct face_type *); +u_int64_t netstat_ft_get_mcasts(const struct face_type *); +u_int64_t netstat_ft_get_errors(const struct face_type *); +u_int64_t netstat_ft_get_drops(const struct face_type *); + +/* Interface addresses: */ +int netstat_iat_get_family(const struct intfaddr_type *); +const char *netstat_iat_get_address(const struct intfaddr_type *, int numeric); +const char *netstat_iat_get_network(const struct intfaddr_type *, int numeric); +enum intfaddr_layer netstat_iat_get_layer(const struct intfaddr_type *); +u_int64_t netstat_iat_get_ipackets(const struct intfaddr_type *); +u_int64_t netstat_iat_get_ibytes(const struct intfaddr_type *); +u_int64_t netstat_iat_get_opackets(const struct intfaddr_type *); +u_int64_t netstat_iat_get_obytes(const struct intfaddr_type *); +u_int32_t netstat_iat_get_refcount(const struct intfaddr_type *); + +/* BPF peers: */ +struct bpf_type_list *netstat_bptl_alloc(void); +void netstat_bptl_free(struct bpf_type_list *); +int netstat_bptl_geterror(const struct bpf_type_list *); +int netstat_bptl_length(const struct bpf_type_list *); + +int netstat_bpti_alloc(struct bpf_type_list *list, + struct bpf_type_iterator **iterator); +const struct bpf_type *netstat_bpti_first(struct bpf_type_iterator *); +const struct bpf_type *netstat_bpti_next(struct bpf_type_iterator *); +void netstat_bpti_free(struct bpf_type_iterator *); +void netstat_bpt_free(struct bpf_type *); + +int netstat_bpf(const struct session_type *, const char *name, + struct bpf_type_list *list, int flags); + +int netstat_bpt_get_flags(const struct bpf_type *); +enum bpf_dir netstat_bpt_get_direction(const struct bpf_type *); +u_int32_t netstat_bpt_get_pid(const struct bpf_type *); +const char *netstat_bpt_get_ifname(const struct bpf_type *); +u_int64_t netstat_bpt_get_recv(const struct bpf_type *); +u_int64_t netstat_bpt_get_drop(const struct bpf_type *); +u_int64_t netstat_bpt_get_match(const struct bpf_type *); +u_int64_t netstat_bpt_get_slen(const struct bpf_type *); +u_int64_t netstat_bpt_get_hlen(const struct bpf_type *); +const char *netstat_bpt_get_pidname(const struct bpf_type *); + +/* Timestamp: */ +u_int32_t netstat_ts_get_sec(const struct timestamp_type *); +u_int32_t netstat_ts_get_usec(const struct timestamp_type *); + +/* Protocol-dependent statistics: */ +struct stat_type *netstat_stat_alloc(void); +void netstat_stat_free(struct stat_type *); +int netstat_stat_geterror(const struct stat_type *); + +int netstat_stat(const struct session_type *, enum stat, struct stat_type *, + int flags); +int netstat_zerostat(const struct session_type *, enum stat); + +const struct tcp_stat *netstat_get_tcpstats(const struct stat_type *); + +u_int64_t netstat_tcps_get_connattempt(const struct tcp_stat *); +u_int64_t netstat_tcps_get_accepts(const struct tcp_stat *); +u_int64_t netstat_tcps_get_connects(const struct tcp_stat *); +u_int64_t netstat_tcps_get_drops(const struct tcp_stat *); +u_int64_t netstat_tcps_get_conndrops(const struct tcp_stat *); +u_int64_t netstat_tcps_get_minmssdrops(const struct tcp_stat *); +u_int64_t netstat_tcps_get_closed(const struct tcp_stat *); +u_int64_t netstat_tcps_get_segstimed(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rttupdated(const struct tcp_stat *); +u_int64_t netstat_tcps_get_delack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_timeoutdrop(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rexmttimeo(const struct tcp_stat *); +u_int64_t netstat_tcps_get_persisttimeo(const struct tcp_stat *); +u_int64_t netstat_tcps_get_keeptimeo(const struct tcp_stat *); +u_int64_t netstat_tcps_get_keepprobe(const struct tcp_stat *); +u_int64_t netstat_tcps_get_keepdrops(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndtotal(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndpack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndbyte(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndrexmitpack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndrexmitbyte(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndrexmitbad(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndacks(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndprobe(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndurg(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndwinup(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sndctrl(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvtotal(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvpack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvbyte(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvbadsum(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvbadoff(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvmemdrop(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvshort(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvduppack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvdupbyte(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvpartduppack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvpartdupbyte(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvoopack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvoobyte(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvpackafterwin(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvbyteafterwin(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvafterclose(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvwinprobe(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvdupack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvacktoomuch(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvackpack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvackbyte(const struct tcp_stat *); +u_int64_t netstat_tcps_get_rcvwinupd(const struct tcp_stat *); +u_int64_t netstat_tcps_get_pawsdrop(const struct tcp_stat *); +u_int64_t netstat_tcps_get_predack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_preddat(const struct tcp_stat *); +u_int64_t netstat_tcps_get_pcbcachemiss(const struct tcp_stat *); +u_int64_t netstat_tcps_get_cachedrtt(const struct tcp_stat *); +u_int64_t netstat_tcps_get_cachedrttvar(const struct tcp_stat *); +u_int64_t netstat_tcps_get_cachedssthresh(const struct tcp_stat *); +u_int64_t netstat_tcps_get_usedrtt(const struct tcp_stat *); +u_int64_t netstat_tcps_get_usedrttvar(const struct tcp_stat *); +u_int64_t netstat_tcps_get_usedssthresh(const struct tcp_stat *); +u_int64_t netstat_tcps_get_persistdrop(const struct tcp_stat *); +u_int64_t netstat_tcps_get_badsyn(const struct tcp_stat *); +u_int64_t netstat_tcps_get_mturesent(const struct tcp_stat *); +u_int64_t netstat_tcps_get_listendrop(const struct tcp_stat *); +u_int64_t netstat_tcps_get_badrst(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_added(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_retransmitted(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_dupsyn(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_dropped(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_completed(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_bucketoverflow(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_cacheoverflow(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_reset(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_stale(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_aborted(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_badack(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_unreach(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_zonefail(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_sendcookie(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sc_recvcookie(const struct tcp_stat *); +u_int64_t netstat_tcps_get_hc_added(const struct tcp_stat *); +u_int64_t netstat_tcps_get_hc_bucketoverflow(const struct tcp_stat *); +u_int64_t netstat_tcps_get_finwait2_drops(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sack_recovery_episode(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sack_rexmits(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sack_rexmit_bytes(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sack_rcv_blocks(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sack_send_blocks(const struct tcp_stat *); +u_int64_t netstat_tcps_get_sack_sboverflow(const struct tcp_stat *); +u_int64_t netstat_tcps_get_ecn_ce(const struct tcp_stat *); +u_int64_t netstat_tcps_get_ecn_ect0(const struct tcp_stat *); +u_int64_t netstat_tcps_get_ecn_ect1(const struct tcp_stat *); +u_int64_t netstat_tcps_get_ecn_shs(const struct tcp_stat *); +u_int64_t netstat_tcps_get_ecn_rcwnd(const struct tcp_stat *); + +const struct udp_stat *netstat_get_udpstats(const struct stat_type *); + +u_int64_t netstat_udps_get_ipackets(const struct udp_stat *); +u_int64_t netstat_udps_get_hdrops(const struct udp_stat *); +u_int64_t netstat_udps_get_badsum(const struct udp_stat *); +u_int64_t netstat_udps_get_nosum(const struct udp_stat *); +u_int64_t netstat_udps_get_badlen(const struct udp_stat *); +u_int64_t netstat_udps_get_noport(const struct udp_stat *); +u_int64_t netstat_udps_get_noportbcast(const struct udp_stat *); +u_int64_t netstat_udps_get_fullsock(const struct udp_stat *); +u_int64_t netstat_udps_get_pcbcachemiss(const struct udp_stat *); +u_int64_t netstat_udps_get_pcbhashmiss(const struct udp_stat *); +u_int64_t netstat_udps_get_delivered(const struct udp_stat *); +u_int64_t netstat_udps_get_opackets(const struct udp_stat *); +u_int64_t netstat_udps_get_fastout(const struct udp_stat *); +u_int64_t netstat_udps_get_noportmcast(const struct udp_stat *); +u_int64_t netstat_udps_get_filtermcast(const struct udp_stat *); + +const struct carp_stat *netstat_get_carpstats(const struct stat_type *); + +u_int64_t netstat_carps_get_ipackets(const struct carp_stat *); +u_int64_t netstat_carps_get_ipackets6(const struct carp_stat *); +u_int64_t netstat_carps_get_badif(const struct carp_stat *); +u_int64_t netstat_carps_get_badttl(const struct carp_stat *); +u_int64_t netstat_carps_get_hdrops(const struct carp_stat *); +u_int64_t netstat_carps_get_badsum(const struct carp_stat *); +u_int64_t netstat_carps_get_badver(const struct carp_stat *); +u_int64_t netstat_carps_get_badlen(const struct carp_stat *); +u_int64_t netstat_carps_get_badauth(const struct carp_stat *); +u_int64_t netstat_carps_get_badvhid(const struct carp_stat *); +u_int64_t netstat_carps_get_badaddrs(const struct carp_stat *); +u_int64_t netstat_carps_get_opackets(const struct carp_stat *); +u_int64_t netstat_carps_get_opackets6(const struct carp_stat *); +u_int64_t netstat_carps_get_onomem(const struct carp_stat *); +u_int64_t netstat_carps_get_ostates(const struct carp_stat *); +u_int64_t netstat_carps_get_preempt(const struct carp_stat *); + +const struct ip_stat *netstat_get_ipstats(const struct stat_type *); + +u_int64_t netstat_ips_get_total(const struct ip_stat *); +u_int64_t netstat_ips_get_badsum(const struct ip_stat *); +u_int64_t netstat_ips_get_tooshort(const struct ip_stat *); +u_int64_t netstat_ips_get_toosmall(const struct ip_stat *); +u_int64_t netstat_ips_get_badhlen(const struct ip_stat *); +u_int64_t netstat_ips_get_badlen(const struct ip_stat *); +u_int64_t netstat_ips_get_fragments(const struct ip_stat *); +u_int64_t netstat_ips_get_fragdropped(const struct ip_stat *); +u_int64_t netstat_ips_get_fragtimeout(const struct ip_stat *); +u_int64_t netstat_ips_get_forward(const struct ip_stat *); +u_int64_t netstat_ips_get_fastforward(const struct ip_stat *); +u_int64_t netstat_ips_get_cantforward(const struct ip_stat *); +u_int64_t netstat_ips_get_redirectsent(const struct ip_stat *); +u_int64_t netstat_ips_get_noproto(const struct ip_stat *); +u_int64_t netstat_ips_get_delivered(const struct ip_stat *); +u_int64_t netstat_ips_get_localout(const struct ip_stat *); +u_int64_t netstat_ips_get_odropped(const struct ip_stat *); +u_int64_t netstat_ips_get_reassembled(const struct ip_stat *); +u_int64_t netstat_ips_get_fragmented(const struct ip_stat *); +u_int64_t netstat_ips_get_ofragments(const struct ip_stat *); +u_int64_t netstat_ips_get_cantfrag(const struct ip_stat *); +u_int64_t netstat_ips_get_badoptions(const struct ip_stat *); +u_int64_t netstat_ips_get_noroute(const struct ip_stat *); +u_int64_t netstat_ips_get_badvers(const struct ip_stat *); +u_int64_t netstat_ips_get_rawout(const struct ip_stat *); +u_int64_t netstat_ips_get_toolong(const struct ip_stat *); +u_int64_t netstat_ips_get_notmember(const struct ip_stat *); +u_int64_t netstat_ips_get_nogif(const struct ip_stat *); +u_int64_t netstat_ips_get_badaddr(const struct ip_stat *); + +const struct icmp_stat *netstat_get_icmpstats(const struct stat_type *); + +u_int64_t netstat_icmps_get_error(const struct icmp_stat *); +u_int64_t netstat_icmps_get_oldshort(const struct icmp_stat *); +u_int64_t netstat_icmps_get_oldicmp(const struct icmp_stat *); +u_int64_t netstat_icmps_get_outhist(const struct icmp_stat *, int); +u_int64_t netstat_icmps_get_badcode(const struct icmp_stat *); +u_int64_t netstat_icmps_get_tooshort(const struct icmp_stat *); +u_int64_t netstat_icmps_get_checksum(const struct icmp_stat *); +u_int64_t netstat_icmps_get_badlen(const struct icmp_stat *); +u_int64_t netstat_icmps_get_reflect(const struct icmp_stat *); +u_int64_t netstat_icmps_get_inhist(const struct icmp_stat *, int); +u_int64_t netstat_icmps_get_bmcastecho(const struct icmp_stat *); +u_int64_t netstat_icmps_get_bmcasttstamp(const struct icmp_stat *); +u_int64_t netstat_icmps_get_badaddr(const struct icmp_stat *); +u_int64_t netstat_icmps_get_noroute(const struct icmp_stat *); +const char *netstat_icmpname(int); +#ifdef INET6 +const char *netstat_icmp6name(int); +#endif +int netstat_icmp_get_maskrepl(const struct session_type *); + +const struct pim_stat *netstat_get_pimstats(const struct stat_type *); + +u_int64_t netstat_pims_get_rcv_total_msgs(const struct pim_stat *); +u_int64_t netstat_pims_get_rcv_total_bytes(const struct pim_stat *); +u_int64_t netstat_pims_get_rcv_tooshort(const struct pim_stat *); +u_int64_t netstat_pims_get_rcv_badsum(const struct pim_stat *); +u_int64_t netstat_pims_get_rcv_badversion(const struct pim_stat *); +u_int64_t netstat_pims_get_rcv_registers_msgs(const struct pim_stat *); +u_int64_t netstat_pims_get_rcv_registers_bytes(const struct pim_stat *); +u_int64_t netstat_pims_get_rcv_registers_wrongiif(const struct pim_stat *); +u_int64_t netstat_pims_get_rcv_badregisters(const struct pim_stat *); +u_int64_t netstat_pims_get_snd_registers_msgs(const struct pim_stat *); +u_int64_t netstat_pims_get_snd_registers_bytes(const struct pim_stat *); + +const struct igmp_stat *netstat_get_igmpstats(const struct stat_type *); + +u_int64_t netstat_igmps_get_rcv_total(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_tooshort(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_badttl(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_badsum(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_v1v2_queries(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_v3_queries(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_badqueries(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_gen_queries(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_group_queries(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_gsr_queries(const struct igmp_stat *); +u_int64_t netstat_igmps_get_drop_gsr_queries(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_reports(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_badreports(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_ourreports(const struct igmp_stat *); +u_int64_t netstat_igmps_get_rcv_nora(const struct igmp_stat *); +u_int64_t netstat_igmps_get_snd_reports(const struct igmp_stat *); + +const struct ddp_stat *netstat_get_ddpstats(const struct stat_type *); + +u_int64_t netstat_ddps_get_short(const struct ddp_stat *); +u_int64_t netstat_ddps_get_long(const struct ddp_stat *); +u_int64_t netstat_ddps_get_nosum(const struct ddp_stat *); +u_int64_t netstat_ddps_get_badsum(const struct ddp_stat *); +u_int64_t netstat_ddps_get_tooshort(const struct ddp_stat *); +u_int64_t netstat_ddps_get_toosmall(const struct ddp_stat *); +u_int64_t netstat_ddps_get_forward(const struct ddp_stat *); +u_int64_t netstat_ddps_get_encap(const struct ddp_stat *); +u_int64_t netstat_ddps_get_cantforward(const struct ddp_stat *); +u_int64_t netstat_ddps_get_nosockspace(const struct ddp_stat *); + +#ifdef SCTP +const struct sctp_stat *netstat_get_sctpstats(const struct stat_type *); + +const struct timestamp_type *netstat_sctps_get_discontinuitytime(const struct sctp_stat *); +u_int32_t netstat_sctps_get_currestab(const struct sctp_stat *); +u_int32_t netstat_sctps_get_activeestab(const struct sctp_stat *); +u_int32_t netstat_sctps_get_restartestab(const struct sctp_stat *); +u_int32_t netstat_sctps_get_collisionestab(const struct sctp_stat *); +u_int32_t netstat_sctps_get_passiveestab(const struct sctp_stat *); +u_int32_t netstat_sctps_get_aborted(const struct sctp_stat *); +u_int32_t netstat_sctps_get_shutdown(const struct sctp_stat *); +u_int32_t netstat_sctps_get_outoftheblue(const struct sctp_stat *); +u_int32_t netstat_sctps_get_checksumerrors(const struct sctp_stat *); +u_int32_t netstat_sctps_get_outcontrolchunks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_outorderchunks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_outunorderchunks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_incontrolchunks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_inorderchunks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_inunorderchunks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_fragusrmsgs(const struct sctp_stat *); +u_int32_t netstat_sctps_get_reasmusrmsgs(const struct sctp_stat *); +u_int32_t netstat_sctps_get_outpackets(const struct sctp_stat *); +u_int32_t netstat_sctps_get_inpackets(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvpackets(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvdatagrams(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvpktwithdata(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvsacks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvdata(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvdupdata(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvheartbeat(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvheartbeatack(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvecne(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvauth(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvauthmissing(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvivalhmacid(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvivalkeyid(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvauthfailed(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvexpress(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvexpressm(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvnocrc(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvswcrc(const struct sctp_stat *); +u_int32_t netstat_sctps_get_recvhwcrc(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendpackets(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendsacks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_senddata(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendretransdata(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendfastretrans(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendmultfastretrans(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendheartbeat(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendecne(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendauth(const struct sctp_stat *); +u_int32_t netstat_sctps_get_senderrors(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendnocrc(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendswcrc(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sendhwcrc(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpfmbox(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpfehos(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpmbda(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpmbct(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpbwrpt(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpcrupt(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpnedat(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrppdbrk(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrptsnnf(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpdnfnd(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpdiwnp(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpdizrw(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpbadd(const struct sctp_stat *); +u_int32_t netstat_sctps_get_pdrpmark(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoiterator(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timodata(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timowindowprobe(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoinit(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timosack(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoshutdown(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoheartbeat(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timocookie(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timosecret(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timopathmtu(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoshutdownack(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoshutdownguard(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timostrmrst(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoearlyfr(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoasconf(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timodelprim(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoautoclose(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoassockill(const struct sctp_stat *); +u_int32_t netstat_sctps_get_timoinpkill(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstart(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstop(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrmrkretrans(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstpout(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstpidsck1(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstpidsck2(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstpidsck3(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstpidsck4(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstrid(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstrout(const struct sctp_stat *); +u_int32_t netstat_sctps_get_earlyfrstrtmr(const struct sctp_stat *); +u_int32_t netstat_sctps_get_hdrops(const struct sctp_stat *); +u_int32_t netstat_sctps_get_badsum(const struct sctp_stat *); +u_int32_t netstat_sctps_get_noport(const struct sctp_stat *); +u_int32_t netstat_sctps_get_badvtag(const struct sctp_stat *); +u_int32_t netstat_sctps_get_badsid(const struct sctp_stat *); +u_int32_t netstat_sctps_get_nomem(const struct sctp_stat *); +u_int32_t netstat_sctps_get_fastretransinrtt(const struct sctp_stat *); +u_int32_t netstat_sctps_get_markedretrans(const struct sctp_stat *); +u_int32_t netstat_sctps_get_naglesent(const struct sctp_stat *); +u_int32_t netstat_sctps_get_naglequeued(const struct sctp_stat *); +u_int32_t netstat_sctps_get_maxburstqueued(const struct sctp_stat *); +u_int32_t netstat_sctps_get_ifnomemqueued(const struct sctp_stat *); +u_int32_t netstat_sctps_get_windowprobed(const struct sctp_stat *); +u_int32_t netstat_sctps_get_lowlevelerr(const struct sctp_stat *); +u_int32_t netstat_sctps_get_lowlevelerrusr(const struct sctp_stat *); +u_int32_t netstat_sctps_get_datadropchklmt(const struct sctp_stat *); +u_int32_t netstat_sctps_get_datadroprwnd(const struct sctp_stat *); +u_int32_t netstat_sctps_get_ecnereducedcwnd(const struct sctp_stat *); +u_int32_t netstat_sctps_get_vtagexpress(const struct sctp_stat *); +u_int32_t netstat_sctps_get_vtagbogus(const struct sctp_stat *); +u_int32_t netstat_sctps_get_primary_randry(const struct sctp_stat *); +u_int32_t netstat_sctps_get_cmt_randry(const struct sctp_stat *); +u_int32_t netstat_sctps_get_slowpath_sack(const struct sctp_stat *); +u_int32_t netstat_sctps_get_wu_sacks_sent(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sends_with_flags(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sends_with_unord(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sends_with_eof(const struct sctp_stat *); +u_int32_t netstat_sctps_get_sends_with_abort(const struct sctp_stat *); +u_int32_t netstat_sctps_get_protocol_drain_calls(const struct sctp_stat *); +u_int32_t netstat_sctps_get_protocol_drains_done(const struct sctp_stat *); +u_int32_t netstat_sctps_get_read_peeks(const struct sctp_stat *); +u_int32_t netstat_sctps_get_cached_chk(const struct sctp_stat *); +u_int32_t netstat_sctps_get_cached_strmoq(const struct sctp_stat *); +u_int32_t netstat_sctps_get_left_abandon(const struct sctp_stat *); +u_int32_t netstat_sctps_get_send_burst_avoid(const struct sctp_stat *); +u_int32_t netstat_sctps_get_send_cwnd_avoid(const struct sctp_stat *); +u_int32_t netstat_sctps_get_fwdtsn_map_over(const struct sctp_stat *); +#endif /* !SCTP */ + +#ifdef INET6 +const struct ip6_stat *netstat_get_ip6stats(const struct stat_type *); +const char *netstat_ip6_nhist_name(int); +const char *netstat_ip6_srcrule_name(int); + +u_int64_t netstat_ip6s_get_total(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_tooshort(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_toosmall(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_fragments(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_fragdropped(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_fragtimeout(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_fragoverflow(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_forward(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_cantforward(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_redirectsent(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_delivered(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_localout(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_odropped(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_reassembled(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_fragmented(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_ofragments(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_cantfrag(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_badoptions(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_noroute(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_badvers(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_rawout(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_badscope(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_notmember(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_nxthist(const struct ip6_stat *, int); +u_int64_t netstat_ip6s_get_m1(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_m2m(const struct ip6_stat *, int); +u_int64_t netstat_ip6s_get_mext1(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_mext2m(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_exthdrtoolong(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_nogif(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_toomanyhdr(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_sources_none(const struct ip6_stat *); +u_int64_t netstat_ip6s_get_sources_sameif(const struct ip6_stat *, int); +u_int64_t netstat_ip6s_get_sources_otherif(const struct ip6_stat *, int); +u_int64_t netstat_ip6s_get_sources_samescope(const struct ip6_stat *, int); +u_int64_t netstat_ip6s_get_sources_otherscope(const struct ip6_stat *, int); +u_int64_t netstat_ip6s_get_sources_deprecated(const struct ip6_stat *, int); +u_int64_t netstat_ip6s_get_sources_rule(const struct ip6_stat *, int); + +const struct icmp6_stat *netstat_get_icmp6stats(const struct stat_type *); + +u_int64_t netstat_icmp6s_get_error(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_canterror(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_toofreq(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_outhist(const struct icmp6_stat *, int); +u_int64_t netstat_icmp6s_get_badcode(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_tooshort(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_checksum(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_badlen(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_reflect(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_inhist(const struct icmp6_stat *, int); +u_int64_t netstat_icmp6s_get_nd_toomanyopt(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_odst_unreach_noroute(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_odst_unreach_admin(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_odst_unreach_beyondscope(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_odst_unreach_addr(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_odst_unreach_noport(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_opacket_too_big(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_otime_exceed_transit(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_otime_exceed_reassembly(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_oparamprob_header(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_oparamprob_nextheader(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_oparamprob_option(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_oredirect(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_ounknown(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_pmtuchg(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_nd_badopt(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_badns(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_badna(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_badrs(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_badra(const struct icmp6_stat *); +u_int64_t netstat_icmp6s_get_badredirect(const struct icmp6_stat *); + +const struct pim6_stat *netstat_get_pim6stats(const struct stat_type *); + +u_int64_t netstat_pim6s_get_rcv_total(const struct pim6_stat *); +u_int64_t netstat_pim6s_get_rcv_tooshort(const struct pim6_stat *); +u_int64_t netstat_pim6s_get_rcv_badsum(const struct pim6_stat *); +u_int64_t netstat_pim6s_get_rcv_badversion(const struct pim6_stat *); +u_int64_t netstat_pim6s_get_rcv_registers(const struct pim6_stat *); +u_int64_t netstat_pim6s_get_rcv_badregisters(const struct pim6_stat *); +u_int64_t netstat_pim6s_get_snd_registers(const struct pim6_stat *); + +const struct rip6_stat *netstat_get_rip6stats(const struct stat_type *); + +u_int64_t netstat_rip6s_get_ipackets(const struct rip6_stat *); +u_int64_t netstat_rip6s_get_isum(const struct rip6_stat *); +u_int64_t netstat_rip6s_get_badsum(const struct rip6_stat *); +u_int64_t netstat_rip6s_get_nosock(const struct rip6_stat *); +u_int64_t netstat_rip6s_get_nosockmcast(const struct rip6_stat *); +u_int64_t netstat_rip6s_get_fullsock(const struct rip6_stat *); +u_int64_t netstat_rip6s_get_opackets(const struct rip6_stat *); +u_int64_t netstat_rip6s_get_delivered(const struct rip6_stat *); +#endif /* !INET6 */ + +#ifdef IPX +const struct ipx_stat *netstat_get_ipxstats(const struct stat_type *); + +u_int64_t netstat_ipxs_get_total(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_badsum(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_tooshort(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_toosmall(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_forward(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_cantforward(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_delivered(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_localout(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_odropped(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_noroute(const struct ipx_stat *); +u_int64_t netstat_ipxs_get_mtutoosmall(const struct ipx_stat *); + +const struct spx_stat *netstat_get_spxstats(const struct stat_type *); + +u_int64_t netstat_spxs_get_connattempt(const struct spx_stat *); +u_int64_t netstat_spxs_get_accepts(const struct spx_stat *); +u_int64_t netstat_spxs_get_connects(const struct spx_stat *); +u_int64_t netstat_spxs_get_drops(const struct spx_stat *); +u_int64_t netstat_spxs_get_conndrops(const struct spx_stat *); +u_int64_t netstat_spxs_get_closed(const struct spx_stat *); +u_int64_t netstat_spxs_get_segstimed(const struct spx_stat *); +u_int64_t netstat_spxs_get_rttupdated(const struct spx_stat *); +u_int64_t netstat_spxs_get_delack(const struct spx_stat *); +u_int64_t netstat_spxs_get_timeoutdrop(const struct spx_stat *); +u_int64_t netstat_spxs_get_rexmttimeo(const struct spx_stat *); +u_int64_t netstat_spxs_get_persisttimeo(const struct spx_stat *); +u_int64_t netstat_spxs_get_keeptimeo(const struct spx_stat *); +u_int64_t netstat_spxs_get_keepprobe(const struct spx_stat *); +u_int64_t netstat_spxs_get_keepdrops(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndtotal(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndpack(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndbyte(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndrexmitpack(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndrexmitbyte(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndacks(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndprobe(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndurg(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndwinup(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndctrl(const struct spx_stat *); +u_int64_t netstat_spxs_get_sndvoid(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvtotal(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvpack(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvbyte(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvbadsum(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvbadoff(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvshort(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvduppack(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvdupbyte(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvpartduppack(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvpartdupbyte(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvoopack(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvoobyte(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvpackafterwin(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvbyteafterwin(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvafterclose(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvwinprobe(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvdupack(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvacktoomuch(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvackpack(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvackbyte(const struct spx_stat *); +u_int64_t netstat_spxs_get_rcvwinupd(const struct spx_stat *); +u_int64_t netstat_spxs_get_hdrops(const struct spx_stat *); +u_int64_t netstat_spxs_get_badsum(const struct spx_stat *); +u_int64_t netstat_spxs_get_badlen(const struct spx_stat *); +u_int64_t netstat_spxs_get_slotim(const struct spx_stat *); +u_int64_t netstat_spxs_get_fastim(const struct spx_stat *); +u_int64_t netstat_spxs_get_nonucn(const struct spx_stat *); +u_int64_t netstat_spxs_get_noconn(const struct spx_stat *); +u_int64_t netstat_spxs_get_notme(const struct spx_stat *); +u_int64_t netstat_spxs_get_wrncon(const struct spx_stat *); +u_int64_t netstat_spxs_get_bdreas(const struct spx_stat *); +u_int64_t netstat_spxs_get_gonawy(const struct spx_stat *); +u_int64_t netstat_spxs_get_notyet(const struct spx_stat *); +u_int64_t netstat_spxs_get_lstdup(const struct spx_stat *); +#endif /* !IPX */ + +const struct pfsync_stat *netstat_get_pfsyncstats(const struct stat_type *); + +u_int64_t netstat_pfsyncs_get_ipackets(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_ipackets6(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_badif(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_badttl(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_hdrops(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_badver(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_badact(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_badlen(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_badauth(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_stale(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_badval(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_badstate(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_opackets(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_opackets6(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_onomem(const struct pfsync_stat *); +u_int64_t netstat_pfsyncs_get_oerrors(const struct pfsync_stat *); + +#ifdef IPSEC +const struct pfkey_stat *netstat_get_pfkeystats(const struct stat_type *); +const char *netstat_pfkey_msgtype_name(int); + +u_int64_t netstat_pfkeys_get_out_total(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_bytes(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_msgtype(const struct pfkey_stat *, int); +u_int64_t netstat_pfkeys_get_out_invlen(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_invver(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_invmsgtype(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_tooshort(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_nomem(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_dupext(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_invexttype(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_invsatype(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_out_invaddr(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_in_total(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_in_bytes(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_in_msgtype(const struct pfkey_stat *, int); +u_int64_t netstat_pfkeys_get_in_msgtarget(const struct pfkey_stat *, + enum pfkey_msgtarget); +u_int64_t netstat_pfkeys_get_in_nomem(const struct pfkey_stat *); +u_int64_t netstat_pfkeys_get_sockerr(const struct pfkey_stat *); + +const struct esp_stat *netstat_get_espstats(const struct stat_type *); +const char *netstat_ipsec_espname(int); + +u_int32_t netstat_esps_get_hdrops(const struct esp_stat *); +u_int32_t netstat_esps_get_nopf(const struct esp_stat *); +u_int32_t netstat_esps_get_notdb(const struct esp_stat *); +u_int32_t netstat_esps_get_badkcr(const struct esp_stat *); +u_int32_t netstat_esps_get_qfull(const struct esp_stat *); +u_int32_t netstat_esps_get_noxform(const struct esp_stat *); +u_int32_t netstat_esps_get_badilen(const struct esp_stat *); +u_int32_t netstat_esps_get_wrap(const struct esp_stat *); +u_int32_t netstat_esps_get_badenc(const struct esp_stat *); +u_int32_t netstat_esps_get_badauth(const struct esp_stat *); +u_int32_t netstat_esps_get_replay(const struct esp_stat *); +u_int32_t netstat_esps_get_input(const struct esp_stat *); +u_int32_t netstat_esps_get_output(const struct esp_stat *); +u_int32_t netstat_esps_get_invalid(const struct esp_stat *); +u_int64_t netstat_esps_get_ibytes(const struct esp_stat *); +u_int64_t netstat_esps_get_obytes(const struct esp_stat *); +u_int32_t netstat_esps_get_toobig(const struct esp_stat *); +u_int32_t netstat_esps_get_pdrops(const struct esp_stat *); +u_int32_t netstat_esps_get_crypto(const struct esp_stat *); +u_int32_t netstat_esps_get_tunnel(const struct esp_stat *); +u_int32_t netstat_esps_get_hist(const struct esp_stat *, int); + +const struct ah_stat *netstat_get_ahstats(const struct stat_type *); +const char *netstat_ipsec_ahname(int); + +u_int32_t netstat_ahs_get_hdrops(const struct ah_stat *); +u_int32_t netstat_ahs_get_nopf(const struct ah_stat *); +u_int32_t netstat_ahs_get_notdb(const struct ah_stat *); +u_int32_t netstat_ahs_get_badkcr(const struct ah_stat *); +u_int32_t netstat_ahs_get_badauth(const struct ah_stat *); +u_int32_t netstat_ahs_get_noxform(const struct ah_stat *); +u_int32_t netstat_ahs_get_qfull(const struct ah_stat *); +u_int32_t netstat_ahs_get_wrap(const struct ah_stat *); +u_int32_t netstat_ahs_get_replay(const struct ah_stat *); +u_int32_t netstat_ahs_get_badauthl(const struct ah_stat *); +u_int32_t netstat_ahs_get_input(const struct ah_stat *); +u_int32_t netstat_ahs_get_output(const struct ah_stat *); +u_int32_t netstat_ahs_get_invalid(const struct ah_stat *); +u_int64_t netstat_ahs_get_ibytes(const struct ah_stat *); +u_int64_t netstat_ahs_get_obytes(const struct ah_stat *); +u_int32_t netstat_ahs_get_toobig(const struct ah_stat *); +u_int32_t netstat_ahs_get_pdrops(const struct ah_stat *); +u_int32_t netstat_ahs_get_crypto(const struct ah_stat *); +u_int32_t netstat_ahs_get_tunnel(const struct ah_stat *); +u_int32_t netstat_ahs_get_hist(const struct ah_stat *, int); + +const struct ipcomp_stat *netstat_get_ipcompstats(const struct stat_type *); +const char *netstat_ipsec_ipcompname(int); + +u_int32_t netstat_ipcomps_get_version(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_hdrops(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_nopf(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_notdb(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_badkcr(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_qfull(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_noxform(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_wrap(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_input(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_output(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_invalid(const struct ipcomp_stat *); +u_int64_t netstat_ipcomps_get_ibytes(const struct ipcomp_stat *); +u_int64_t netstat_ipcomps_get_obytes(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_toobig(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_pdrops(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_crypto(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_hist(const struct ipcomp_stat *, int); +u_int32_t netstat_ipcomps_get_threshold(const struct ipcomp_stat *); +u_int32_t netstat_ipcomps_get_uncompr(const struct ipcomp_stat *); + +const struct ipsec_stat *netstat_get_ipsecstats(const struct stat_type *); + +u_int64_t netstat_ipsecs_get_in_success(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_polvio(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_nosa(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_inval(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_nomem(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_badspi(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_ahreplay(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_espreplay(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_ahauthsucc(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_ahauthfail(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_espauthsucc(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_espauthfail(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_in_esphist(const struct ipsec_stat *, int); +u_int64_t netstat_ipsecs_get_in_ahhist(const struct ipsec_stat *, int); +u_int64_t netstat_ipsecs_get_in_comphist(const struct ipsec_stat *, int); +u_int64_t netstat_ipsecs_get_out_success(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_out_polvio(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_out_nosa(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_out_inval(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_out_nomem(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_out_noroute(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_out_esphist(const struct ipsec_stat *, int); +u_int64_t netstat_ipsecs_get_out_ahhist(const struct ipsec_stat *, int); +u_int64_t netstat_ipsecs_get_out_comphist(const struct ipsec_stat *, int); +u_int64_t netstat_ipsecs_get_spdcachelookup(const struct ipsec_stat *); +u_int64_t netstat_ipsecs_get_spdcachemiss(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_in_polvio(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_out_polvio(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_out_nosa(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_out_nomem(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_out_noroute(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_out_inval(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_out_bundlesa(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_mbcoalesced(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_clcoalesced(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_clcopied(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_mbinserted(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_input_front(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_input_middle(const struct ipsec_stat *); +u_int32_t netstat_ipsecs_get_ips_input_end(const struct ipsec_stat *); +#endif /* !IPSEC */ + +const struct route_stat *netstat_get_routestats(const struct stat_type *); + +u_int64_t netstat_routes_get_badredirect(const struct route_stat *); +u_int64_t netstat_routes_get_dynamic(const struct route_stat *); +u_int64_t netstat_routes_get_newgateway(const struct route_stat *); +u_int64_t netstat_routes_get_unreach(const struct route_stat *); +u_int64_t netstat_routes_get_wildcard(const struct route_stat *); +u_int64_t netstat_routes_get_trash(const struct route_stat *); + +const struct mroute_stat *netstat_get_mroutestats(const struct stat_type *); + +u_int64_t netstat_mroutes_get_mfc_lookups(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_mfc_misses(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_upcalls(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_no_route(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_bad_tunnel(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_cant_tunnel(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_wrong_if(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_upq_ovflw(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_cache_cleanups(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_drop_sel(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_q_overflow(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_pkt2large(const struct mroute_stat *); +u_int64_t netstat_mroutes_get_upq_sockfull(const struct mroute_stat *); + +#ifdef INET6 +const struct mroute6_stat *netstat_get_mroute6stats(const struct stat_type *); + +u_int64_t netstat_mroute6s_get_mfc_lookups(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_mfc_misses(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_upcalls(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_no_route(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_bad_tunnel(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_cant_tunnel(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_wrong_if(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_upq_ovflw(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_cache_cleanups(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_drop_sel(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_q_overflow(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_pkt2large(const struct mroute6_stat *); +u_int64_t netstat_mroute6s_get_upq_sockfull(const struct mroute6_stat *); +#endif + +/* Routing: */ +struct route_type_list *netstat_rtl_alloc(void); +void netstat_rtl_free(struct route_type_list *); +int netstat_rtl_geterror(const struct route_type_list *); +int netstat_rtl_length(const struct route_type_list *); + +int netstat_rti_alloc(struct route_type_list *list, + struct route_type_iterator **iterator); +const struct route_type *netstat_rti_first(struct route_type_iterator *); +const struct route_type *netstat_rti_next(struct route_type_iterator *); +void netstat_rti_free(struct route_type_iterator *); + +int netstat_route(const struct session_type *, int fib, int domain, + struct route_type_list *list, int flags); + +int netstat_rt_get_fib(const struct route_type *); +int netstat_rt_get_family(const struct route_type *); +const struct routeaddr_type *netstat_rt_get_destination(const struct route_type *); +const struct routeaddr_type *netstat_rt_get_gateway(const struct route_type *); +int netstat_rt_get_flags(const struct route_type *); +u_int64_t netstat_rt_get_refs(const struct route_type *); +u_int64_t netstat_rt_get_used(const struct route_type *); +const char *netstat_rt_get_interface(const struct route_type *); +u_int64_t netstat_rt_get_expire(const struct route_type *); +u_int32_t netstat_rt_get_mtu(const struct route_type *); +const struct routenode_type *netstat_rt_get_node(const struct route_type *); + +/* Routing nodes: */ +int netstat_rnt_get_bit(const struct routenode_type *); +int netstat_rnt_get_flags(const struct routenode_type *); +u_int64_t netstat_rnt_get_address(const struct routenode_type *); +u_int64_t netstat_rnt_get_left(const struct routenode_type *); +u_int64_t netstat_rnt_get_right(const struct routenode_type *); +const struct routeaddr_type * + netstat_rnt_get_netmask(const struct routenode_type *); +int netstat_rnt_get_mkcnt(const struct routenode_type *); +const struct routemask_type * + netstat_rnt_get_mask(const struct routenode_type *, int); + +/* Routing masks: */ +int netstat_rmt_get_flags(const struct routemask_type *); +int netstat_rmt_get_bit(const struct routemask_type *); +u_int64_t netstat_rmt_get_address(const struct routemask_type *); +u_int64_t netstat_rmt_get_refs(const struct routemask_type *); +const struct routeaddr_type * + netstat_rmt_get_netmask(const struct routemask_type *); + +/* Routing addresses: */ +const char *netstat_rat_get_name(const struct routeaddr_type *, int); +size_t netstat_rat_get_address(const struct routeaddr_type *, void *, size_t); +int netstat_rat_get_family(const struct routeaddr_type *); + +/* Multicast interfaces: */ +struct mcastif_type_list *netstat_mitl_alloc(void); +void netstat_mitl_free(struct mcastif_type_list *); +int netstat_mitl_geterror(const struct mcastif_type_list *); +int netstat_mitl_length(const struct mcastif_type_list *); + +int netstat_miti_alloc(struct mcastif_type_list *list, + struct mcastif_type_iterator **iterator); +const struct mcastif_type *netstat_miti_first(struct mcastif_type_iterator *); +const struct mcastif_type *netstat_miti_next(struct mcastif_type_iterator *); +void netstat_miti_free(struct mcastif_type_iterator *); + +int netstat_mif(const struct session_type *, int domain, + struct mcastif_type_list *list, int flags); + +u_int32_t netstat_mit_get_index(const struct mcastif_type *); +int netstat_mit_get_flags(const struct mcastif_type *); +u_int32_t netstat_mit_get_limit(const struct mcastif_type *); +const struct routeaddr_type *netstat_mit_get_address(const struct mcastif_type *); +const struct routeaddr_type *netstat_mit_get_remote_address(const struct mcastif_type *); +u_int64_t netstat_mit_get_packets_in(const struct mcastif_type *); +u_int64_t netstat_mit_get_packets_out(const struct mcastif_type *); +u_int64_t netstat_mit_get_bytes_in(const struct mcastif_type *); +u_int64_t netstat_mit_get_bytes_out(const struct mcastif_type *); +const char *netstat_mit_get_ifname(const struct mcastif_type *); + + +/* Multicast routing: */ +struct mroute_type_list *netstat_mrtl_alloc(void); +void netstat_mrtl_free(struct mroute_type_list *); +int netstat_mrtl_geterror(const struct mroute_type_list *); +int netstat_mrtl_length(const struct mroute_type_list *); + +int netstat_mrti_alloc(struct mroute_type_list *list, + struct mroute_type_iterator **iterator); +const struct mroute_type *netstat_mrti_first(struct mroute_type_iterator *); +const struct mroute_type *netstat_mrti_next(struct mroute_type_iterator *); +void netstat_mrti_free(struct mroute_type_iterator *); + +int netstat_mroute(const struct session_type *, int domain, + struct mroute_type_list *list, int flags); + +const struct routeaddr_type *netstat_mrt_get_origin(const struct mroute_type *); +const struct routeaddr_type *netstat_mrt_get_group(const struct mroute_type *); +u_int64_t netstat_mrt_get_packets(const struct mroute_type *); +u_int64_t netstat_mrt_get_bytes(const struct mroute_type *); +u_int64_t netstat_mrt_get_waitings(const struct mroute_type *); +u_int32_t netstat_mrt_get_parent(const struct mroute_type *); +u_int8_t netstat_mrt_get_ttl(const struct mroute_type *, int); +int netstat_mrt_get_is_mif_set(const struct mroute_type *, u_int32_t); + +__END_DECLS + +#endif /* !_NETSTAT_H_ */ Index: lib/libnetstat/netstat_bpf.c =================================================================== --- lib/libnetstat/netstat_bpf.c (revision 0) +++ lib/libnetstat/netstat_bpf.c (revision 0) @@ -0,0 +1,333 @@ +/*- + * Copyright (c) 2005 Christian S.J. Peron + * Copyright (c) 2009 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#define _KERNEL +#include +#undef _KERNEL +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "netstat.h" +#include "netstat_internal.h" + +/* nlist(3) indices and symbols. */ +enum nlBPF { + nlBPF_iflist = 0, + nlBPF_allproc, + nlBPF_MAX +}; + +static const char *const bpf_symbol[] = + { "_bpf_iflist", "_allproc" }; + +static int bpf_iflist_kvm(struct bpf_type_list *list, const char *ifname, + kvm_t *kvm); +static int bpf_iflist_sysctl(struct bpf_type_list *list, const char *ifname); +static void extract_bpfd_data(struct bpfd_data *bdp, struct bpf_type *btp, + const char *pidname); +static void extract_bpf_data(struct bpf_d *d, struct bpf_type *btp, + const char *pidname); +static const char *get_procname_kvm(kvm_t *kvm, pid_t pid, u_long ap); + +int +netstat_bpf(const struct session_type *session, const char *name, + struct bpf_type_list *list, __unused int flags) +{ + int result; + + result = -1; + if (session->sst_flags & NETSTAT_SESSION_KVM) { + result = bpf_iflist_kvm(list, name, session->sst_kvm); + } else + result = bpf_iflist_sysctl(list, name); + return (result); +} + +#define KREAD(off, dst) do { \ + if ((list->bptl_error = (kread_data(kvm, (uintptr_t)(off), &(dst), \ + sizeof(dst)))) != 0) { \ + goto out; \ + } \ +} while (0); + +int +bpf_iflist_kvm(struct bpf_type_list *list, const char *ifname, kvm_t *kvm) +{ + int result; + struct nlist nls[nlBPF_MAX + 1]; + + LIST_HEAD(bpf_if_head, bpf_if) head; + struct bpf_if *bp; + struct bpf_d *bd; + struct bpf_if bpf_if; + struct bpf_d bpf_d; + struct ifnet bif_ifp; + + struct bpf_type *btp; + + result = -1; + bzero(nls, sizeof(nls)); + nls[nlBPF_iflist].n_name = bpf_symbol[nlBPF_iflist]; + nls[nlBPF_allproc].n_name = bpf_symbol[nlBPF_allproc]; + nls[nlBPF_MAX].n_name = NULL; + + if (kvm_nlist(kvm, nls) < 0) { + list->bptl_error = NETSTAT_ERROR_KVM; + goto out; + } + + KREAD(nls[nlBPF_iflist].n_value, head); + LIST_FOREACH(bp, &head, bif_next) { + KREAD(bp, bpf_if); + bp = &bpf_if; + KREAD(bp->bif_ifp, bif_ifp); + bp->bif_ifp = &bif_ifp; + if (bp->bif_dlist.lh_first == NULL) + continue; + if (ifname != NULL && strcmp(ifname, bp->bif_ifp->if_xname) != 0) + continue; + LIST_FOREACH(bd, &bp->bif_dlist, bd_next) { + KREAD(bd, bpf_d); + bd = &bpf_d; + btp = _netstat_bpt_allocate(list, + bp->bif_ifp->if_xname); + extract_bpf_data(bd, btp, + get_procname_kvm(kvm, bd->bd_pid, + nls[nlBPF_allproc].n_value)); + } + } + + result = 0; +out: + return (result); +} + +#undef KREAD + +#define KREAD(off, dst) do { \ + if ((kread_data(kvm, (uintptr_t)(off), &(dst), sizeof(dst))) != 0) { \ + goto out; \ + } \ +} while (0); + +const char * +get_procname_kvm(kvm_t *kvm, pid_t pid, u_long ap) +{ + LIST_HEAD(proclist, proc) proclist; + struct proc *p = NULL; + struct proc proc; + const char *result; + + KREAD(ap, proclist); + LIST_FOREACH(p, &proclist, p_list) { + KREAD(p, proc); + p = &proc; + if (p->p_pid == pid) { + if (p->p_state == PRS_NEW) { + p = NULL; + break; + } + break; + } + } +out: + result = (p != NULL) ? p->p_comm : "???"; + return (result); +} + +#undef KREAD + +int +bpf_iflist_sysctl(struct bpf_type_list *list, const char *ifname) +{ + struct kinfo_proc newkp; + int error, mib[4]; + int i, count, result; + size_t size; + char *mibvar = "net.bpf.sstats"; + char *buf, *p; + + struct bpfd_stream *bsp; + struct bpfd_data *bdp; + struct bpf_type *btp; + + result = 0; + size = 0; + if (sysctlbyname(mibvar, 0, &size, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + return (-1); + } + if ((buf = malloc(size)) == 0) { + warnx("malloc %lu bytes", (u_long)size); + return (-2); + } + if (sysctlbyname(mibvar, buf, &size, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + result = -2; + goto out; + } + if (size < sizeof(*bsp)) { + list->bptl_error = NETSTAT_ERROR_VERSION; + result = -2; + goto out; + } + + p = buf; + bsp = (struct bpfd_stream *)p; + p += sizeof(*bsp); + + if (bsp->bps_version != BPFD_STREAM_VERSION) { + list->bptl_error = NETSTAT_ERROR_VERSION; + result = -1; + goto out; + } + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + + count = bsp->bps_count; + + for (i = 0; i < count; i++) { + bdp = (struct bpfd_data *)p; + p += sizeof(*bdp); + if (ifname != NULL && strcmp(bdp->bpd_ifname, ifname) != 0) + continue; + /* Resolve process name. */ + mib[3] = bdp->bpd_pid; + size = sizeof(newkp); + error = sysctl(mib, 4, &newkp, &size, NULL, 0); + if (error < 0) { + warn("kern.proc.pid failed"); + result = -1; + goto out; + } + btp = _netstat_bpt_allocate(list, bdp->bpd_ifname); + extract_bpfd_data(bdp, btp, newkp.ki_comm); + } +out: + free(buf); + return (result); +} + +void +extract_bpfd_data(struct bpfd_data *bpd, struct bpf_type *btp, + const char *pidname) +{ + btp->bpt_flags = 0; + if (bpd->bpd_promisc) + btp->bpt_flags |= NETSTAT_BPF_PROMISC; + if (bpd->bpd_immediate) + btp->bpt_flags |= NETSTAT_BPF_IMMEDIATE; + if (bpd->bpd_hdrcmplt) + btp->bpt_flags |= NETSTAT_BPF_HDRCMPLT; + if (bpd->bpd_feedback) + btp->bpt_flags |= NETSTAT_BPF_FEEDBACK; + if (bpd->bpd_async) + btp->bpt_flags |= NETSTAT_BPF_ASYNC; + if (bpd->bpd_locked) + btp->bpt_flags |= NETSTAT_BPF_LOCKED; + btp->bpt_slen = bpd->bpd_slen; + btp->bpt_hlen = bpd->bpd_hlen; + btp->bpt_recv = bpd->bpd_rcount; + btp->bpt_drop = bpd->bpd_dcount; + btp->bpt_match = bpd->bpd_fcount; + btp->bpt_pid = bpd->bpd_pid; + btp->bpt_pidname = strdup(pidname); + switch (bpd->bpd_direction) { + case BPF_D_IN: + btp->bpt_direction = bpfdir_In; + break; + case BPF_D_OUT: + btp->bpt_direction = bpfdir_Out; + break; + case BPF_D_INOUT: + btp->bpt_direction = bpfdir_InOut; + default: + btp->bpt_direction = bpfdir_Invalid; + break; + } +} + +void +extract_bpf_data(struct bpf_d *d, struct bpf_type *btp, const char *pidname) +{ + btp->bpt_flags = 0; + if (d->bd_promisc) + btp->bpt_flags |= NETSTAT_BPF_PROMISC; + if (d->bd_immediate) + btp->bpt_flags |= NETSTAT_BPF_IMMEDIATE; + if (d->bd_hdrcmplt) + btp->bpt_flags |= NETSTAT_BPF_HDRCMPLT; + if (d->bd_feedback) + btp->bpt_flags |= NETSTAT_BPF_FEEDBACK; + if (d->bd_async) + btp->bpt_flags |= NETSTAT_BPF_ASYNC; + if (d->bd_locked) + btp->bpt_flags |= NETSTAT_BPF_LOCKED; + btp->bpt_slen = d->bd_slen; + btp->bpt_hlen = d->bd_hlen; + btp->bpt_recv = d->bd_rcount; + btp->bpt_drop = d->bd_dcount; + btp->bpt_match = d->bd_fcount; + btp->bpt_pid = d->bd_pid; + btp->bpt_pidname = strdup(pidname); + switch (d->bd_direction) { + case BPF_D_IN: + btp->bpt_direction = bpfdir_In; + break; + case BPF_D_OUT: + btp->bpt_direction = bpfdir_Out; + break; + case BPF_D_INOUT: + btp->bpt_direction = bpfdir_InOut; + default: + btp->bpt_direction = bpfdir_Invalid; + break; + } +} Index: lib/libnetstat/netstat_socket.c =================================================================== --- lib/libnetstat/netstat_socket.c (revision 0) +++ lib/libnetstat/netstat_socket.c (revision 0) @@ -0,0 +1,1056 @@ +/*- + * Copyright (c) 2009 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define TCPSTATES +#include +#include +#include +#include +#include +#include +#include + +#include "netstat.h" +#include "netstat_internal.h" + +/* nlist(3) indices and symbols. */ +enum nlUNP { + nlUNP_count = 0, + nlUNP_gencnt, + nlUNP_dhead, + nlUNP_shead, + nlUNP_MAX +}; + +static const char *const unp_symbol[] = + { "_unp_count", "_unp_gencnt", "_unp_dhead", "_unp_shead" }; + +enum nlINP { + nlINP_tcbinfo = 0, + nlINP_udbinfo, + nlINP_divcbinfo, + nlINP_ripcbinfo, + nlINP_MAX +}; + +static const char *const inp_symbol[] = + { "_tcbinfo", "_udbinfo", "_divcbinfo", "_ripcbinfo" }; + +static const enum tcp_state tcp_states[] = + { tcps_Closed, tcps_Listen, tcps_SynSent, tcps_SynReceived, + tcps_Established, tcps_CloseWait, tcps_FinWait1, tcps_Closing, + tcps_LastAck, tcps_FinWait2, tcps_TimeWait }; + +static void extract_xunpcb_data(struct xunpcb *, struct socket_type *); +static void extract_unpcb_data(struct unpcb_data *, struct socket_type *); +static void extract_inet_data(struct tcpcb *, struct inpcb *, + struct xsocket *, struct socket_type *); +static void extract_inpcb_data(struct inpcb_data *, struct socket_type *); + +static char ntop_buf[INET_ADDRSTRLEN]; +static char ntop_buf6[INET6_ADDRSTRLEN]; + +static struct sockaddr_type *extract_inet_address(struct socket_type *parent, + int type, struct in_addr *in, u_short port, int anonport); +static struct sockaddr_type *extract_inet6_address(struct socket_type *parent, + int type, struct in6_addr *in, u_short port); + +static int netstat_local_sockets(int, struct socket_type_list *, kvm_t *, + struct nlist *, int, int); +static int netstat_inet_sockets(int, int, struct socket_type_list *, + kvm_t *, struct nlist *, int, int); + +/* type names */ +static const char *const socktype[] = + { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" }; + +static int +net_local_pcblist_sysctl(int family, int type, struct socket_type_list *list, + __unused int flags) +{ + char *buf, *p; + size_t len; + char mibvar[64]; + + int count, i; + unp_gen_t gencnt; + + struct unpcb_stream *usp; + struct unpcb_data *udp; + struct socket_type *stp; + + /* XXX: Should "spcblist" be renamed to "pcblist"? */ + sprintf(mibvar, "net.local.%s.spcblist", socktype[type]); + + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); + return (-1); + } + if ((buf = malloc(len)) == 0) { + warnx("malloc %lu bytes", (u_long)len); + return (-2); + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + free(buf); + return (-2); + } + if (len < sizeof(*usp)) { + list->stl_error = NETSTAT_ERROR_VERSION; + free(buf); + return (-2); + } + + p = buf; + usp = (struct unpcb_stream *)p; + p += sizeof(*usp); + + if (usp->us_version != UNPCB_STREAM_VERSION) { + list->stl_error = NETSTAT_ERROR_VERSION; + free(buf); + return (-1); + } + + count = usp->us_count; + gencnt = usp->us_gencnt; + + for (i = 0; i < count; i++) { + udp = (struct unpcb_data *)p; + p += sizeof(*udp); + /* Keep active PCBs only. */ + if (udp->ud_gencnt <= usp->us_gencnt) { + stp = _netstat_st_allocate(list, family, type, + socktype[type]); + extract_unpcb_data(udp, stp); + } + } + + free(buf); + return (0); +} + +static const char * +ipproto(int protocol) +{ + const char * result; + + switch (protocol) { + case IPPROTO_TCP: + result = "tcp"; + break; + case IPPROTO_UDP: + result = "udp"; + break; + case IPPROTO_DIVERT: + result = "divert"; + break; + default: + case IPPROTO_RAW: + result = "raw"; + break; + } + + return (result); +} + +static int +net_inet_pcblist_sysctl(int family, int protocol, + struct socket_type_list *list, int flags) +{ + char *buf, *p; + size_t len; + char mibvar[64]; + + u_int i; + + struct inpcb_stream *isp; + struct inpcb_data *idp; + struct socket_type *stp; + + sprintf(mibvar, "net.inet.%s.spcblist", ipproto(protocol)); + + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); + return (-1); + } + if ((buf = malloc(len)) == 0) { + warnx("malloc %lu bytes", (u_long)len); + return (-2); + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + free(buf); + return (-2); + } + if (len < sizeof(*isp)) { + list->stl_error = NETSTAT_ERROR_VERSION; + free(buf); + return (-2); + } + + p = buf; + isp = (struct inpcb_stream *)p; + p += sizeof(*isp); + + if (isp->is_version != INPCB_STREAM_VERSION) { + list->stl_error = NETSTAT_ERROR_VERSION; + free(buf); + return (-1); + } + + for (i = 0; i < isp->is_count; i++) { + idp = (struct inpcb_data *)p; + p += sizeof(*idp); + + if (idp->id_protocol != protocol) + continue; + + /* Keep active PCBs only. */ + if (idp->id_gencnt > isp->is_gencnt) + continue; + + /* Not a valid IPv4/IPv6 connection. */ + if (((idp->id_vflag & INP_IPV4) == 0) +#ifdef INET6 + && ((idp->id_vflag & INP_IPV6) == 0) +#endif + ) + continue; + +#ifdef INET6 + if ((family == PF_INET && ((idp->id_vflag & INP_IPV4) == 0)) || + (family == PF_INET6 && ((idp->id_vflag & INP_IPV6) == 0))) + continue; +#endif + + if ((flags & NETSTAT_SOCKET_ALL) == 0 && + ( + (protocol == IPPROTO_TCP && idp->id_state == TCPS_LISTEN) + || ((idp->id_vflag & INP_IPV4) != 0 && + inet_lnaof(*((struct in_addr *)&idp->id_laddr)) + == INADDR_ANY) +#ifdef INET6 + || ((idp->id_vflag & INP_IPV6) != 0 && + IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)&idp->id_laddr)) +#endif + )) + continue; + + stp = _netstat_st_allocate(list, family, protocol, + ipproto(protocol)); + extract_inpcb_data(idp, stp); + } + + free(buf); + return (0); +} + +#define KREAD(off, buf, len) do { \ + if (kread_data(kvm, (uintptr_t)(off), (buf), (len)) != 0) { \ + return (-1); \ + } \ +} while (0); + +static int +net_local_pcblist_kvm(int family, int type, struct socket_type_list *list, + kvm_t *kvm, struct nlist *nlistp, __unused int flags) +{ + struct unp_head head; + struct unpcb *unp, unp_conn; + u_char sun_len; + struct socket so; + struct xunpcb xu; + unp_gen_t unp_gencnt; + u_int unp_count; + struct socket_type *stp; + u_long count_off, gencnt_off, head_off; + + count_off = nlistp[nlUNP_count].n_value; + gencnt_off = nlistp[nlUNP_gencnt].n_value; + + if (count_off == 0 || gencnt_off == 0) { + list->stl_error = NETSTAT_ERROR_UNDEFINED; + return (-1); + } + switch (type) { + case SOCK_STREAM: + head_off = nlistp[nlUNP_shead].n_value; + break; + case SOCK_DGRAM: + head_off = nlistp[nlUNP_dhead].n_value; + break; + default: + list->stl_error = NETSTAT_ERROR_UNDEFINED; + return (-1); + } + + KREAD(count_off, &unp_count, sizeof(unp_count)); + KREAD(gencnt_off, &unp_gencnt, sizeof(unp_gencnt)); + KREAD(head_off, &head, sizeof(head)); + LIST_FOREACH(unp, &head, unp_link) { + xu.xu_len = sizeof xu; + xu.xu_unpp = unp; + KREAD(unp, &xu.xu_unp, sizeof (*unp)); + unp = &xu.xu_unp; + + /* Keep active PCBs only. */ + if (unp->unp_gencnt > unp_gencnt) + continue; + if (unp->unp_addr != NULL) { + KREAD(unp->unp_addr, &sun_len, sizeof(sun_len)); + KREAD(unp->unp_addr, &xu.xu_addr, sun_len); + } + if (unp->unp_conn != NULL) { + KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn)); + if (unp_conn.unp_addr != NULL) { + KREAD(unp_conn.unp_addr, &sun_len, + sizeof(sun_len)); + KREAD(unp_conn.unp_addr, &xu.xu_caddr, + sun_len); + } + } + KREAD(unp->unp_socket, &so, sizeof(so)); + if (sotoxsocket(kvm, &so, &xu.xu_socket) != 0) { + list->stl_error = NETSTAT_ERROR_UNDEFINED; + return (-1); + } + stp = _netstat_st_allocate(list, family, type, + socktype[type]); + extract_xunpcb_data(&xu, stp); + } + + return (0); +} + +static int +net_inet_pcblist_kvm(int family, int protocol, struct socket_type_list *list, + kvm_t *kvm, struct nlist *nlistp, __unused int flags) +{ + struct inpcbinfo pcbinfo; + struct inpcbhead listhead; + struct inpcb *inp; + struct xinpcb xi; + struct xtcpcb xt; + struct tcpcb *tcb = NULL; + struct socket so; + struct xsocket xso; + u_long off; + + struct socket_type *stp; + + switch (protocol) { + case IPPROTO_TCP: + off = nlistp[nlINP_tcbinfo].n_value; + break; + case IPPROTO_UDP: + off = nlistp[nlINP_udbinfo].n_value; + break; + case IPPROTO_DIVERT: + off = nlistp[nlINP_divcbinfo].n_value; + break; + case IPPROTO_RAW: + case IPPROTO_ICMP: + case IPPROTO_IGMP: + case IPPROTO_PIM: + off = nlistp[nlINP_ripcbinfo].n_value; + break; + default: + list->stl_error = NETSTAT_ERROR_UNDEFINED; + return (-1); + } + + KREAD(off, &pcbinfo, sizeof(pcbinfo)); + KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead)); + LIST_FOREACH(inp, &listhead, inp_list) { + if (protocol == IPPROTO_TCP) { + KREAD(inp, &xt.xt_inp, sizeof(*inp)); + inp = &xt.xt_inp; + } else { + KREAD(inp, &xi.xi_inp, sizeof(*inp)); + inp = &xi.xi_inp; + } + + /* Keep active PCBs only. */ + if (inp->inp_gencnt > pcbinfo.ipi_gencnt) + continue; + + if (((inp->inp_vflag & INP_IPV4) == 0) +#ifdef INET6 + && ((inp->inp_vflag & INP_IPV6) == 0) +#endif + ) + continue; + +#ifdef INET6 + if ((family == PF_INET && ((inp->inp_vflag & INP_IPV4) == 0)) || + (family == PF_INET6 && ((inp->inp_vflag & INP_IPV6) == 0))) + continue; +#endif + + if ((flags & NETSTAT_SOCKET_ALL) == 0 && + ( + (protocol == IPPROTO_TCP && + inp->inp_ppcb != NULL && + ((struct tcpcb *)inp->inp_ppcb)->t_state == TCPS_LISTEN) + || ((inp->inp_vflag & INP_IPV4) != 0 && + inet_lnaof(inp->inp_laddr) == INADDR_ANY) +#ifdef INET6 + || ((inp->inp_vflag & INP_IPV6) != 0 && + IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) +#endif + )) + continue; + + if (protocol == IPPROTO_TCP) { + if (inp->inp_ppcb == NULL) + bzero(&xt.xt_tp, sizeof(xt.xt_tp)); + else if (inp->inp_flags & INP_TIMEWAIT) { + bzero(&xt.xt_tp, sizeof(xt.xt_tp)); + xt.xt_tp.t_state = TCPS_TIME_WAIT; + } else + KREAD(inp->inp_ppcb, &xt.xt_tp, + sizeof(xt.xt_tp)); + } + if (inp->inp_socket) { + KREAD(inp->inp_socket, &so, sizeof(so)); + if (sotoxsocket(kvm, &so, &xso) != 0) { + list->stl_error = NETSTAT_ERROR_UNDEFINED; + return (-1); + } + } else { + bzero(&xso, sizeof(xso)); + if (protocol == IPPROTO_TCP) + xso.xso_protocol = protocol; + } + stp = _netstat_st_allocate(list, family, protocol, + ipproto(protocol)); + extract_inet_data(tcb, inp, &xso, stp); + } + + return (0); +} + +#undef KREAD + + +#define NPCB_KVM(proc, family, type, list, kvm, nl, flags) do { \ + if (net_##proc##_pcblist_kvm((family), (type), (list), (kvm), (nl), \ + (flags)) != 0) { \ + return (-1); \ + } \ +} while (0) + +#define NPCB_SCT(proc, family, type, list, flags) do { \ + if (net_##proc##_pcblist_sysctl((family), (type), (list), \ + (flags)) != 0) { \ + return (-1); \ + } \ +} while (0) + +int +netstat_local_sockets(int type, struct socket_type_list *list, kvm_t *kvm, + struct nlist *nlp, int flags, int use_kvm) +{ + switch (type) { + case SOCK_STREAM: + case SOCK_DGRAM: + if (use_kvm) + NPCB_KVM(local, PF_LOCAL, type, list, kvm, nlp, + flags); + else + /* Use sysctl (or something else). */ + NPCB_SCT(local, PF_LOCAL, type, list, flags); + break; + /* All PF_LOCAL */ + case 0: + if (use_kvm) { + NPCB_KVM(local, PF_LOCAL, SOCK_STREAM, list, kvm, + nlp, flags); + NPCB_KVM(local, PF_LOCAL, SOCK_DGRAM, list, kvm, + nlp, flags); + } else { + NPCB_SCT(local, PF_LOCAL, SOCK_STREAM, list, + flags); + NPCB_SCT(local, PF_LOCAL, SOCK_DGRAM, list, + flags); + } + break; + default: + list->stl_error = NETSTAT_ERROR_UNSUPPORTED; + return (-1); + } + return (0); +} + +int +netstat_inet_sockets(int domain, int protocol, struct socket_type_list *list, + kvm_t *kvm, struct nlist *nlp, int flags, int use_kvm) +{ + switch (protocol) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_DIVERT: + case IPPROTO_RAW: + case IPPROTO_ICMP: + case IPPROTO_IGMP: + case IPPROTO_PIM: + case IPPROTO_ICMPV6: + if (use_kvm) + NPCB_KVM(inet, domain, protocol, list, kvm, nlp, + flags); + else + NPCB_SCT(inet, domain, protocol, list, flags); + break; + /* All PF_INET, PF_INET6 */ + case 0: + /* Errors do not count here. */ + if (use_kvm) { + net_inet_pcblist_kvm(domain, IPPROTO_TCP, list, kvm, + nlp, flags); + net_inet_pcblist_kvm(domain, IPPROTO_UDP, list, kvm, + nlp, flags); + net_inet_pcblist_kvm(domain, IPPROTO_DIVERT, list, + kvm, nlp, flags); + net_inet_pcblist_kvm(domain, IPPROTO_RAW, list, kvm, + nlp, flags); + } else { + net_inet_pcblist_sysctl(domain, IPPROTO_TCP, list, + flags); + net_inet_pcblist_sysctl(domain, IPPROTO_UDP, list, + flags); + net_inet_pcblist_sysctl(domain, IPPROTO_DIVERT, list, + flags); + net_inet_pcblist_sysctl(domain, IPPROTO_RAW, list, + flags); + } + break; + default: + list->stl_error = NETSTAT_ERROR_UNSUPPORTED; + return (-1); + } + return (0); +} + +#undef NPCB_KVM +#undef NPCB_SCT + + +int +netstat_socket(const struct session_type *session, int domain, int type, + int protocol, struct socket_type_list *list, int flags) +{ + int use_kvm = session->sst_flags & NETSTAT_SESSION_KVM; + int result, i; + struct nlist nls[nlUNP_MAX + 1 + nlINP_MAX + 1]; + + bzero(nls, sizeof(nls)); + if (use_kvm) { + /* Use KVM to retrieve data. */ + switch (domain) { + case PF_UNSPEC: + for (i = 0; i < nlUNP_MAX; i++) + nls[i].n_name = unp_symbol[i]; + nls[nlUNP_MAX].n_name = NULL; + for (i = nlUNP_MAX + 1; + i < (nlUNP_MAX + 1 + nlINP_MAX + 1); i++) + nls[i].n_name = inp_symbol[i - (nlUNP_MAX + 1)]; + nls[nlUNP_MAX + 1 + nlINP_MAX].n_name = NULL; + break; + case PF_LOCAL: + for (i = 0; i < nlUNP_MAX; i++) + nls[i].n_name = unp_symbol[i]; + nls[nlUNP_MAX].n_name = NULL; + break; + case PF_INET: + case PF_INET6: + for (i = 0; i < nlINP_MAX; i++) + nls[i].n_name = inp_symbol[i]; + nls[nlINP_MAX].n_name = NULL; + break; + default: + break; + } + if (kvm_nlist(session->sst_kvm, nls) < 0) { + list->stl_error = NETSTAT_ERROR_KVM; + result = -1; + goto end; + } + } + switch (domain) { + case PF_UNSPEC: + /* "Everything" */ + result = netstat_local_sockets(0, list, session->sst_kvm, nls, + flags, use_kvm); + if (result < 0) + goto end; + result = netstat_inet_sockets(PF_INET, 0, list, + session->sst_kvm, &nls[nlUNP_MAX + 1], flags, use_kvm); + if (result < 0) + goto end; + result = netstat_inet_sockets(PF_INET6, 0, list, + session->sst_kvm, &nls[nlUNP_MAX + 1], flags, use_kvm); + if (result < 0) + goto end; + break; + case PF_LOCAL: + result = (netstat_local_sockets(type, list, session->sst_kvm, + nls, flags, use_kvm)); + goto end; + break; + case PF_INET: + case PF_INET6: + result = (netstat_inet_sockets(domain, protocol, list, + session->sst_kvm, nls, flags, use_kvm)); + goto end; + break; + default: + list->stl_error = NETSTAT_ERROR_UNSUPPORTED; + result = -1; + goto end; + } + +end: + return (result); +} + +void +extract_xunpcb_data(struct xunpcb *xpcb, struct socket_type *stp) +{ + struct sockaddr_un *sa; + char address[1024]; + + strlcpy(stp->st_extname, stp->st_name, SOCKTYPE_MAXNAME); + stp->st_qlen = xpcb->xu_socket.so_qlen; + stp->st_incqlen = xpcb->xu_socket.so_incqlen; + stp->st_qlimit = xpcb->xu_socket.so_qlimit; + stp->st_snd.sbt_cc = xpcb->xu_socket.so_snd.sb_cc; + stp->st_snd.sbt_mcnt = xpcb->xu_socket.so_snd.sb_mcnt; + stp->st_snd.sbt_ccnt = xpcb->xu_socket.so_snd.sb_ccnt; + stp->st_snd.sbt_hiwat = xpcb->xu_socket.so_snd.sb_hiwat; + stp->st_snd.sbt_lowat = xpcb->xu_socket.so_snd.sb_lowat; + stp->st_snd.sbt_mbcnt = xpcb->xu_socket.so_snd.sb_mbcnt; + stp->st_snd.sbt_mbmax = xpcb->xu_socket.so_snd.sb_mbmax; + stp->st_rcv.sbt_cc = xpcb->xu_socket.so_rcv.sb_cc; + stp->st_rcv.sbt_mcnt = xpcb->xu_socket.so_rcv.sb_mcnt; + stp->st_rcv.sbt_ccnt = xpcb->xu_socket.so_rcv.sb_ccnt; + stp->st_rcv.sbt_hiwat = xpcb->xu_socket.so_rcv.sb_hiwat; + stp->st_rcv.sbt_lowat = xpcb->xu_socket.so_rcv.sb_lowat; + stp->st_rcv.sbt_mbcnt = xpcb->xu_socket.so_rcv.sb_mbcnt; + stp->st_rcv.sbt_mbmax = xpcb->xu_socket.so_rcv.sb_mbmax; + stp->st_pcb = (u_long)xpcb->xu_socket.so_pcb; + stp->st_vnode = (u_long)xpcb->xu_unp.unp_vnode; + stp->st_conn = (u_long)xpcb->xu_unp.unp_conn; + stp->st_refs = (u_long)LIST_FIRST(&xpcb->xu_unp.unp_refs); + stp->st_reflink = (u_long)LIST_NEXT(&xpcb->xu_unp, unp_reflink); + stp->st_flags = SOCKTYPE_VNODE | SOCKTYPE_CONN | SOCKTYPE_REFS; + stp->st_addrcnt = 0; + if (xpcb->xu_unp.unp_addr) { + sa = (struct sockaddr_un *)&xpcb->xu_addr; + sprintf(address, "%.*s", + (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)), + sa->sun_path); + stp->st_address[stp->st_addrcnt] = + _netstat_sat_allocate(stp, NETSTAT_ADDRTYPE_LOCAL, address, + NULL, 0); + stp->st_address[stp->st_addrcnt]->sat_port = 0; + strcpy(stp->st_address[stp->st_addrcnt]->sat_portname, "*"); + stp->st_address[stp->st_addrcnt]->sat_numeric[0] = '\0'; + stp->st_addrcnt += 1; + } + stp->st_tcpstate[0] = '\0'; + stp->st_tcps = tcps_Invalid; +} + +void +extract_unpcb_data(struct unpcb_data *udp, struct socket_type *stp) +{ + strlcpy(stp->st_extname, stp->st_name, SOCKTYPE_MAXNAME); + stp->st_qlen = udp->ud_qlen; + stp->st_incqlen = udp->ud_incqlen; + stp->st_qlimit = udp->ud_qlimit; + stp->st_snd.sbt_cc = udp->ud_snd_cc; + stp->st_snd.sbt_mcnt = udp->ud_snd_mcnt; + stp->st_snd.sbt_ccnt = udp->ud_snd_ccnt; + stp->st_snd.sbt_hiwat = udp->ud_snd_hiwat; + stp->st_snd.sbt_lowat = udp->ud_snd_lowat; + stp->st_snd.sbt_mbcnt = udp->ud_snd_mbcnt; + stp->st_snd.sbt_mbmax = udp->ud_snd_mbmax; + stp->st_rcv.sbt_cc = udp->ud_rcv_cc; + stp->st_rcv.sbt_mcnt = udp->ud_rcv_mcnt; + stp->st_rcv.sbt_ccnt = udp->ud_rcv_ccnt; + stp->st_rcv.sbt_hiwat = udp->ud_rcv_hiwat; + stp->st_rcv.sbt_lowat = udp->ud_rcv_lowat; + stp->st_rcv.sbt_mbcnt = udp->ud_rcv_mbcnt; + stp->st_rcv.sbt_mbmax = udp->ud_rcv_mbmax; + stp->st_pcb = udp->ud_pcb; + stp->st_vnode = udp->ud_vnode; + stp->st_conn = udp->ud_conn; + stp->st_refs = udp->ud_refs; + stp->st_reflink = udp->ud_reflink; + stp->st_flags = SOCKTYPE_VNODE | SOCKTYPE_CONN | SOCKTYPE_REFS; + stp->st_addrcnt = 0; + if (udp->ud_address_len > 0) { + stp->st_address[stp->st_addrcnt] = + _netstat_sat_allocate(stp, NETSTAT_ADDRTYPE_LOCAL, + udp->ud_address, NULL, 0); + stp->st_address[stp->st_addrcnt]->sat_port = 0; + strcpy(stp->st_address[stp->st_addrcnt]->sat_portname, "*"); + stp->st_address[stp->st_addrcnt]->sat_numeric[0] = '\0'; + stp->st_addrcnt += 1; + } + stp->st_tcpstate[0] = '\0'; + stp->st_tcps = tcps_Invalid; +} + +void +extract_inet_data(struct tcpcb *tp, struct inpcb *inp, struct xsocket *so, + struct socket_type *stp) +{ + const char *vchar; + + stp->st_qlen = so->so_qlen; + stp->st_incqlen = so->so_incqlen; + stp->st_qlimit = so->so_qlimit; + stp->st_snd.sbt_cc = so->so_snd.sb_cc; + stp->st_snd.sbt_mcnt = so->so_snd.sb_mcnt; + stp->st_snd.sbt_ccnt = so->so_snd.sb_ccnt; + stp->st_snd.sbt_hiwat = so->so_snd.sb_hiwat; + stp->st_snd.sbt_lowat = so->so_snd.sb_lowat; + stp->st_snd.sbt_mbcnt = so->so_snd.sb_mbcnt; + stp->st_snd.sbt_mbmax = so->so_snd.sb_mbmax; + stp->st_rcv.sbt_cc = so->so_rcv.sb_cc; + stp->st_rcv.sbt_mcnt = so->so_rcv.sb_mcnt; + stp->st_rcv.sbt_ccnt = so->so_rcv.sb_ccnt; + stp->st_rcv.sbt_hiwat = so->so_rcv.sb_hiwat; + stp->st_rcv.sbt_lowat = so->so_rcv.sb_lowat; + stp->st_rcv.sbt_mbcnt = so->so_rcv.sb_mbcnt; + stp->st_rcv.sbt_mbmax = so->so_rcv.sb_mbmax; + stp->st_pcb = (tp == NULL) ? (u_long)inp->inp_ppcb : + (u_long)so->so_pcb; + stp->st_vnode = 0; + stp->st_conn = 0; + stp->st_refs = 0; + stp->st_reflink = 0; + stp->st_flags = 0; + stp->st_addrcnt = 0; + if (tp != NULL) { + if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) { + sprintf(stp->st_tcpstate, "%d", tp->t_state); + stp->st_tcps = tcps_Invalid; + } else { + sprintf(stp->st_tcpstate, "%s", tcpstates[tp->t_state]); + stp->st_tcps = tcp_states[tp->t_state]; +#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) + /* T/TCP `hidden state' */ + if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) { + stp->st_tcpstate[0] = '*'; + stp->st_tcpstate[1] = '\0'; + stp->st_tcps = tcps_Hidden; + } +#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ + } + stp->st_flags |= SOCKTYPE_TCP; + } else { + /* Has no TCP state. */ + stp->st_tcpstate[0] = '\0'; + stp->st_tcps = tcps_Invalid; + } +#ifdef INET6 + if ((inp->inp_vflag & INP_IPV6) != 0) + vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? + "46" : "6 "; + else +#endif + vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? + "4 " : " "; + sprintf(stp->st_extname, "%-3.3s%-2.2s", stp->st_name, vchar); + /* local address */ + if (inp->inp_vflag & INP_IPV4) { + stp->st_address[stp->st_addrcnt] = + extract_inet_address(stp, NETSTAT_ADDRTYPE_INET_LOCAL, + &inp->inp_laddr, inp->inp_lport, + inp->inp_vflag & INP_ANONPORT); + stp->st_addrcnt += 1; + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + stp->st_address[stp->st_addrcnt] = + extract_inet6_address(stp, NETSTAT_ADDRTYPE_INET6_LOCAL, + &inp->in6p_laddr, inp->inp_lport); + stp->st_addrcnt += 1; + } +#endif + /* foreign address */ + if (inp->inp_vflag & INP_IPV4) { + stp->st_address[stp->st_addrcnt] = + extract_inet_address(stp, NETSTAT_ADDRTYPE_INET_FOREIGN, + &inp->inp_faddr, inp->inp_fport, + inp->inp_vflag & INP_ANONPORT); + stp->st_addrcnt += 1; + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + stp->st_address[stp->st_addrcnt] = + extract_inet6_address(stp, NETSTAT_ADDRTYPE_INET6_FOREIGN, + &inp->in6p_faddr, inp->inp_fport); + stp->st_addrcnt += 1; + } +#endif +} + +void +extract_inpcb_data(struct inpcb_data *idp, struct socket_type *stp) +{ + const char *vchar; + + stp->st_qlen = idp->id_qlen; + stp->st_incqlen = idp->id_incqlen; + stp->st_qlimit = idp->id_qlimit; + stp->st_snd.sbt_cc = idp->id_snd_cc; + stp->st_snd.sbt_mcnt = idp->id_snd_mcnt; + stp->st_snd.sbt_ccnt = idp->id_snd_ccnt; + stp->st_snd.sbt_hiwat = idp->id_snd_hiwat; + stp->st_snd.sbt_lowat = idp->id_snd_lowat; + stp->st_snd.sbt_mbcnt = idp->id_snd_mbcnt; + stp->st_snd.sbt_mbmax = idp->id_snd_mbmax; + stp->st_rcv.sbt_cc = idp->id_rcv_cc; + stp->st_rcv.sbt_mcnt = idp->id_rcv_mcnt; + stp->st_rcv.sbt_ccnt = idp->id_rcv_ccnt; + stp->st_rcv.sbt_hiwat = idp->id_rcv_hiwat; + stp->st_rcv.sbt_lowat = idp->id_rcv_lowat; + stp->st_rcv.sbt_mbcnt = idp->id_rcv_mbcnt; + stp->st_rcv.sbt_mbmax = idp->id_rcv_mbmax; + stp->st_pcb = idp->id_pcb; + if (idp->id_protocol == IPPROTO_TCP) { + if (idp->id_state >= TCP_NSTATES) { + sprintf(stp->st_tcpstate, "%d", idp->id_state); + stp->st_tcps = tcps_Invalid; + } else { + sprintf(stp->st_tcpstate, "%s", + tcpstates[idp->id_state]); + stp->st_tcps = tcp_states[idp->id_state]; +#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) + /* T/TCP `hidden state` */ + if (idp->id_flags & (TF_NEEDSYN | TF_NEEDFIN)) { + strcpy(stp->st_tcpstate, "*"); + stp->st_tcps = tcps_Hidden; + } +#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ + } + stp->st_flags |= SOCKTYPE_TCP; + } +#ifdef INET6 + if ((idp->id_vflag & INP_IPV6) != 0) + vchar = ((idp->id_vflag & INP_IPV4) != 0) ? "46" : "6"; + else +#endif + vchar = ((idp->id_vflag & INP_IPV4) != 0) ? "4 " : " "; + sprintf(stp->st_extname, "%-3.3s%-2.2s", stp->st_name, vchar); + /* Local address. */ + if (idp->id_vflag & INP_IPV4) { + stp->st_address[stp->st_addrcnt] = + extract_inet_address(stp, NETSTAT_ADDRTYPE_INET_LOCAL, + (struct in_addr *)&idp->id_laddr, idp->id_lport, + idp->id_vflag & INP_ANONPORT); + stp->st_addrcnt += 1; + } +#ifdef INET6 + else if (idp->id_vflag & INP_IPV6) { + stp->st_address[stp->st_addrcnt] = + extract_inet6_address(stp, NETSTAT_ADDRTYPE_INET6_LOCAL, + (struct in6_addr *)&idp->id_laddr, idp->id_lport); + stp->st_addrcnt += 1; + } +#endif + /* Foreign address. */ + if (idp->id_vflag & INP_IPV4) { + stp->st_address[stp->st_addrcnt] = + extract_inet_address(stp, NETSTAT_ADDRTYPE_INET_FOREIGN, + (struct in_addr *)&idp->id_faddr, idp->id_fport, + idp->id_vflag & INP_ANONPORT); + stp->st_addrcnt += 1; + } +#ifdef INET6 + else if (idp->id_vflag & INP_IPV6) { + stp->st_address[stp->st_addrcnt] = + extract_inet6_address(stp, NETSTAT_ADDRTYPE_INET6_FOREIGN, + (struct in6_addr *)&idp->id_faddr, idp->id_fport); + stp->st_addrcnt += 1; + } +#endif +} + +struct sockaddr_type * +extract_inet_address(struct socket_type *parent, int type, struct in_addr *in, + u_short port, int anonport) +{ + struct sockaddr_type *result; + char numeric[32]; + + result = _netstat_sat_allocate(parent, type, "*", (char *)in, + sizeof(*in)); + if (result == NULL) + return (result); + if (in->s_addr == INADDR_ANY) { + strcpy(numeric, "*"); + result->sat_flags |= SOCKADDRTYPE_NAME_RESOLVED; + } else { + sprintf(numeric, "%s", inet_ntop(AF_INET, (void *)in, ntop_buf, + sizeof(ntop_buf))); + } + strlcpy(result->sat_numeric, numeric, sizeof(result->sat_numeric)); + result->sat_port = ntohs(port); + if (anonport) + result->sat_flags |= SOCKADDRTYPE_ANONPORT; + + return (result); +} + +struct sockaddr_type * +extract_inet6_address(struct socket_type *parent, int type, + struct in6_addr *in, u_short port) +{ + struct sockaddr_type *result; + char numeric[32]; + + result = _netstat_sat_allocate(parent, type, "*", (char *)in, + sizeof(*in)); + if (result == NULL) + return (result); + if (IN6_IS_ADDR_UNSPECIFIED(in)) { + strcpy(numeric, "*"); + result->sat_flags |= SOCKADDRTYPE_NAME_RESOLVED; + } else + sprintf(numeric, "%s", inet_ntop(AF_INET6, (void *)in, + ntop_buf6, sizeof(ntop_buf6))); + strlcpy(result->sat_numeric, numeric, sizeof(result->sat_numeric)); + result->sat_port = ntohs(port); + + return (result); +} + +void +_netstat_sat_resolve_name(struct sockaddr_type *addr) +{ + struct hostent *hp; + struct netent *np; + int net, lna; + struct in_addr *in; + struct in6_addr *in6; + char *cp = NULL; + char domain[MAXHOSTNAMELEN]; + + switch (addr->sat_parent->st_family) { + case PF_INET: + in = (struct in_addr *)addr->sat_address; + net = inet_netof(*in); + lna = inet_lnaof(*in); + if (lna == INADDR_ANY) { + np = getnetbyaddr(net, AF_INET); + if (np != NULL) + cp = np->n_name; + } + if (cp == NULL) { + hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET); + if (hp != NULL) { + cp = hp->h_name; + trimdomain(cp, strlen(cp)); + } + } + if (cp != NULL) + strlcpy(addr->sat_name, cp, sizeof(addr->sat_name)); + else + strlcpy(addr->sat_name, addr->sat_numeric, + sizeof(addr->sat_name)); + addr->sat_flags |= SOCKADDRTYPE_NAME_RESOLVED; + break; + case PF_INET6: + in6 = (struct in6_addr *)addr->sat_address; + if (gethostname(domain, MAXHOSTNAMELEN) == 0 && + (cp = index(domain, '.'))) + strcpy(domain, cp + 1); + else + domain[0] = '\0'; + cp = NULL; + if (!IN6_IS_ADDR_UNSPECIFIED(in6)) { + hp = gethostbyaddr((char *)in6, sizeof(*in6), AF_INET6); + if (hp != NULL) { + if ((cp = index(hp->h_name, '.')) && + !strcmp(cp + 1, domain)) + *cp = '\0'; + cp = hp->h_name; + } + } + if (cp != NULL) + strlcpy(addr->sat_name, cp, sizeof(addr->sat_name)); + else + strlcpy(addr->sat_name, addr->sat_numeric, + sizeof(addr->sat_name)); + addr->sat_flags |= SOCKADDRTYPE_NAME_RESOLVED; + break; + } +} + +void +_netstat_sat_resolve_portname(struct sockaddr_type *addr) +{ + struct servent *sp = NULL; + + if ((addr->sat_port == 0) || + ((addr->sat_flags & SOCKADDRTYPE_ANONPORT) != 0)) { + sprintf(addr->sat_portname, "%.15s", "*"); + } else { + sp = getservbyport((int)htons(addr->sat_port), + addr->sat_parent->st_name); + if (sp != NULL) + sprintf(addr->sat_portname, "%.15s", sp->s_name); + else + sprintf(addr->sat_portname, "%d", addr->sat_port); + } + addr->sat_flags |= SOCKADDRTYPE_PORT_RESOLVED; +} Index: lib/libnetstat/netstat_mbuf.c =================================================================== --- lib/libnetstat/netstat_mbuf.c (revision 0) +++ lib/libnetstat/netstat_mbuf.c (revision 0) @@ -0,0 +1,271 @@ +/*- + * Copyright (c) 2005 Robert N. M. Watson + * Copyright (c) 2009 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netstat.h" +#include "netstat_internal.h" + +/* nlist(3) indices and symbols. */ +enum nlMBF { + nlMBF_mbstat = 0, + nlMBF_nsfbufs, + nlMBF_nsfbufs_peak, + nlMBF_nsfbufs_used, + nlMBF_MAX +}; + +static const char *const mbstat_symbol[] = + { "_mbstat", "_nsfbufs", "_nsfbufspeak", "_nsfbufsused", + "_mbtypes", "_nmbclusters", "_nmbufs", "_mbuf_hiwm", + "_clust_hiwm", "_smp_cpus", "_pagesize", "_mb_statpcpu", + "_mbuf_lowm", "_clust_lowm" }; + +static int fill_bt(struct memory_type_list *mtlp, struct buffer_type *btp, + int allocator, const char *name); + +int netstat_mbuf(const struct session_type *session, struct mbuf_type *stats, + __unused int flags) +{ + struct memory_type_list *mtlp; + struct nlist nls[nlMBF_MAX + 1]; + struct sfbuf_data sfbd; + struct mbstat_data mbsd; + struct mbstat mbstat; + + int error, result, i, bucket; + size_t len; + + const char *sfstats_mib = "kern.ipc.sfbstats"; + const char *mbstats_mib = "kern.ipc.mbstats"; + + result = -1; + mtlp = memstat_mtl_alloc(); + if (mtlp == NULL) { + warn("netstat_mbuf: memstat_mtl_alloc"); + return (result); + } + + bzero(&sfbd, sizeof(struct sfbuf_data)); + bzero(&mbsd, sizeof(struct mbstat_data)); + bzero(nls, sizeof(nls)); + + if (session->sst_flags & NETSTAT_SESSION_KVM) { + /* kvm(3)-based monitoring */ + if (memstat_kvm_all(mtlp, session->sst_kvm) < 0) { + error = memstat_mtl_geterror(mtlp); + if (error == MEMSTAT_ERROR_KVM) + warnx("netstat_mbuf: memstat_kvm_all: %s", + kvm_geterr(session->sst_kvm)); + else + warnx("netstat_mbuf: memstat_kvm_all: %s", + memstat_strerror(error)); + stats->mbt_error = NETSTAT_ERROR_KVM; + goto out; + } + + for (i = 0; i < nlMBF_MAX; i++) + nls[i].n_name = mbstat_symbol[i]; + nls[nlMBF_MAX].n_name = NULL; + + if (kvm_nlist(session->sst_kvm, nls) < 0) { + stats->mbt_error = NETSTAT_ERROR_KVM; + goto out; + } + +#define KREAD(idx, dst) do { \ + if (kread_data(session->sst_kvm, nls[idx].n_value, &(dst), \ + sizeof(dst)) != 0) { \ + stats->mbt_error = NETSTAT_ERROR_KVM; \ + goto out; \ + } \ +} while (0); + + KREAD(nlMBF_mbstat, mbstat); + stats->mbt_drain = mbstat.m_drain; + stats->mbt_sf_iocnt = mbstat.sf_iocnt; + stats->mbt_sf_allocfail = mbstat.sf_allocfail; + stats->mbt_sf_allocwait = mbstat.sf_allocwait; + + KREAD(nlMBF_nsfbufs, bucket); + stats->mbt_sf_bufs = bucket; + + KREAD(nlMBF_nsfbufs_peak, bucket); + stats->mbt_sf_bufs_peak = bucket; + + KREAD(nlMBF_nsfbufs_used, bucket); + stats->mbt_sf_bufs_inuse = bucket; +#undef KREAD + } else { + /* sysctl(8)-based monitoring */ + if (memstat_sysctl_all(mtlp, 0) < 0) { + warnx("netstat_mbuf: memstat_sysctl_all: %s", + memstat_strerror(memstat_mtl_geterror(mtlp))); + goto out; + } + len = sizeof(struct sfbuf_data); + if (sysctlbyname(sfstats_mib, &sfbd, &len, 0, 0) < 0) { + warn("sysctl: %s", sfstats_mib); + goto out; + } + if (sfbd.sfd_version != SFBUF_DATA_VERSION) { + stats->mbt_error = NETSTAT_ERROR_VERSION; + goto out; + } + + stats->mbt_sf_bufs = sfbd.sfd_nbufs; + stats->mbt_sf_bufs_peak = sfbd.sfd_nbufs_peak; + stats->mbt_sf_bufs_inuse = sfbd.sfd_nbufs_used; + stats->mbt_sf_iocnt = sfbd.sfd_iocnt; + stats->mbt_sf_allocfail = sfbd.sfd_allocfail; + stats->mbt_sf_allocwait = sfbd.sfd_allocwait; + + len = sizeof(struct mbstat_data); + if (sysctlbyname(mbstats_mib, &mbsd, &len, 0, 0) < 0) { + warn("sysctl: %s", mbstats_mib); + goto out; + } + if (mbsd.mbd_version != MBSTAT_DATA_VERSION) { + stats->mbt_error = NETSTAT_ERROR_VERSION; + goto out; + } + stats->mbt_drain = mbsd.mbd_drain; + } + + if (fill_bt(mtlp, &stats->mbt_mbuf, ALLOCATOR_UMA, MBUF_MEM_NAME) < 0) + goto out; + + if (fill_bt(mtlp, &stats->mbt_cluster, ALLOCATOR_UMA, + MBUF_CLUSTER_MEM_NAME) < 0) + goto out; + + if (fill_bt(mtlp, &stats->mbt_packet, ALLOCATOR_UMA, + MBUF_PACKET_MEM_NAME) < 0) + goto out; + + if (fill_bt(mtlp, &stats->mbt_tag, ALLOCATOR_MALLOC, + MBUF_TAG_MEM_NAME) < 0) + goto out; + + if (fill_bt(mtlp, &stats->mbt_jumbop, ALLOCATOR_UMA, + MBUF_JUMBOP_MEM_NAME) < 0) + goto out; + + if (fill_bt(mtlp, &stats->mbt_jumbo9, ALLOCATOR_UMA, + MBUF_JUMBO9_MEM_NAME) < 0) + goto out; + + if (fill_bt(mtlp, &stats->mbt_jumbo16, ALLOCATOR_UMA, + MBUF_JUMBO16_MEM_NAME) < 0) + goto out; + + /*- + * 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. + */ + stats->mbt_bytes_inuse = + stats->mbt_mbuf.bt_bytes + + stats->mbt_packet.bt_bytes + + (stats->mbt_packet.bt_count * stats->mbt_cluster.bt_size) + + ((stats->mbt_cluster.bt_count - stats->mbt_packet.bt_count - + stats->mbt_packet.bt_free) * stats->mbt_cluster.bt_size) + + stats->mbt_tag.bt_bytes + + (stats->mbt_jumbop.bt_count * stats->mbt_jumbop.bt_size) + + (stats->mbt_jumbo9.bt_count * stats->mbt_jumbo9.bt_size) + + (stats->mbt_jumbo16.bt_count * stats->mbt_jumbo16.bt_size); + + /*- + * Calculate in-cache bytes as: + * - cached straight mbufs + * - cached packet mbufs + * - cached packet clusters + * - cached straight clusters + * This currently excludes sf_buf space. + */ + stats->mbt_bytes_incache = + (stats->mbt_mbuf.bt_free * stats->mbt_mbuf.bt_size) + + (stats->mbt_packet.bt_free * stats->mbt_packet.bt_size) + + (stats->mbt_packet.bt_free * stats->mbt_cluster.bt_size) + + (stats->mbt_cluster.bt_free * stats->mbt_cluster.bt_size) + + (stats->mbt_jumbop.bt_free * stats->mbt_jumbop.bt_size) + + (stats->mbt_jumbo9.bt_free * stats->mbt_jumbo9.bt_size) + + (stats->mbt_jumbo16.bt_free * stats->mbt_jumbo16.bt_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. + */ + stats->mbt_bytes_total = stats->mbt_bytes_inuse + + stats->mbt_bytes_incache; + + result = 0; +out: + memstat_mtl_free(mtlp); + return (result); +} + +int +fill_bt(struct memory_type_list *mtlp, struct buffer_type *btp, int allocator, + const char *name) +{ + struct memory_type *mtp; + + mtp = memstat_mtl_find(mtlp, allocator, name); + if (mtp == NULL) { + warnx("netstat_mbuf: memstat_mtl_find: zone %s not found", + name); + return (-1); + } + + btp->bt_count = memstat_get_count(mtp); + btp->bt_bytes = memstat_get_bytes(mtp); + btp->bt_free = memstat_get_free(mtp); + btp->bt_failures = memstat_get_free(mtp); + btp->bt_size = memstat_get_size(mtp); + btp->bt_limit = memstat_get_countlimit(mtp); + + return (0); +} Index: lib/libnetstat/Makefile =================================================================== --- lib/libnetstat/Makefile (revision 0) +++ lib/libnetstat/Makefile (revision 0) @@ -0,0 +1,29 @@ +# $FreeBSD$ + +#.include + +WARNS?= 3 +LIB= netstat +SHLIB_MAJOR= 1 +DPADD= ${LIBKVM} ${LIBMEMSTAT} ${LIBUTIL} +LDADD= -lkvm -lmemstat -lutil + +CFLAGS+=-DSCTP +CFLAGS+=-DIPSEC + +#.if ${MK_INET6_SUPPORT} != "no" +CFLAGS+= -DINET6 +#.endif + +#.if ${MK_IPX_SUPPORT} != "no" +CFLAGS+= -DIPX +#.endif + +SRCS= netstat_socket.c netstat_mbuf.c netstat_if.c netstat_bpf.c \ + netstat_stat.c netstat_route.c netstat_mroute.c netstat_util.c + +INCS= netstat.h + +WITHOUT_MAN= yes + +.include Index: lib/libnetstat/netstat_mroute.c =================================================================== --- lib/libnetstat/netstat_mroute.c (revision 0) +++ lib/libnetstat/netstat_mroute.c (revision 0) @@ -0,0 +1,834 @@ +/*- + * Copyright (c) 2009, 2010 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define _KERNEL +#include +#ifdef INET6 +#include +#endif /* !INET6 */ +#undef _KERNEL + +#include +#include +#include +#include +#include +#include + +#include "netstat.h" +#include "netstat_internal.h" + +/* nlist(3) indices and symbols */ +enum nlMIF { + nlMIF_viftable = 0, + nlMIF_MAX, +}; + +static const char *const mif_symbol[] = + { "_viftable" }; + +enum nlMRT { + nlMRT_mfchashtbl = 0, + nlMRT_mfctablesize, + nlMRT_MAX, +}; + +static const char *const mrt_symbol[] = + { "_mfchashtbl", "_mfctablesize" }; + +#ifdef INET6 +enum nlMIF6 { + nlMIF6_mif6table = 0, + nlMIF6_MAX, +}; + +static const char *const mif6_symbol[] = + { "_mif6table" }; + +enum nlMRT6 { + nlMRT6_mf6ctable = 0, + nlMRT6_MAX, +}; + +static const char *const mrt6_symbol[] = + { "_mf6ctable" }; +#endif /* !INET6 */ + +static int mif_kvm(struct mcastif_type_list *, kvm_t *, struct nlist *); +static int mif_sysctl(struct mcastif_type_list *); +static int mrt_kvm(struct mroute_type_list *, kvm_t *, struct nlist *); +static int mrt_sysctl(struct mroute_type_list *); +#ifdef INET6 +static int mif6_kvm(struct mcastif_type_list *, kvm_t *, struct nlist *); +static int mif6_sysctl(struct mcastif_type_list *); +static int mrt6_kvm(struct mroute_type_list *, kvm_t *, struct nlist *); +static int mrt6_sysctl(struct mroute_type_list *); +#endif /* !INET6 */ + +static void extract_vif_data(int, struct vif *, struct mcastif_type *); +static void extract_svif_data(int, struct vif_data *, struct mcastif_type *); +static void extract_mfc_data(struct mfc *, struct mroute_type *); +static void extract_smfc_data(struct mfc_data *, struct mroute_type *); +#ifdef INET6 +static void extract_mif6_data(int, struct mif6 *, struct mcastif_type *); +static void extract_smif6_data(int, struct mif6_data *, struct mcastif_type *); +static void extract_mf6c_data(int, struct mf6c *, struct mroute_type *); +static void extract_smf6c_data(struct mf6c_data *, struct mroute_type *); +#endif /* !INET6 */ + +#ifdef INET6 +#define nls_size (nlMIF_MAX + nlMIF6_MAX + 1) +#else +#define nls_size (nlMIF_MAX + 1) +#endif /* !INET6 */ + +int +netstat_mif(const struct session_type *session, int domain, + struct mcastif_type_list *list, __unused int flags) +{ + int result, use_kvm, i; + struct nlist nls[nls_size]; + + result = -1; + use_kvm = session->sst_flags & NETSTAT_SESSION_KVM; + bzero(nls, sizeof(nls)); + + if (use_kvm) { + switch (domain) { + case PF_UNSPEC: + for (i = 0; i < nlMIF_MAX; i++) + nls[i].n_name = mif_symbol[i]; + for (i = nlMIF_MAX; i < nls_size; i++) + nls[i].n_name = mif6_symbol[i - nlMIF_MAX]; + break; + case PF_INET: + for (i = 0; i < nlMIF_MAX; i++) + nls[i].n_name = mif_symbol[i]; + break; +#ifdef INET6 + case PF_INET6: + for (i = 0; i < nlMIF6_MAX; i++) + nls[i].n_name = mif6_symbol[i]; + break; +#endif /* !INET6 */ + default: + break; + } + if (kvm_nlist(session->sst_kvm, nls) < 0) { + list->mitl_error = NETSTAT_ERROR_KVM; + goto end; + } + } + + switch (domain) { + case PF_UNSPEC: + result = use_kvm ? + mif_kvm(list, session->sst_kvm, nls) : + mif_sysctl(list); + if (result < 0) + goto end; + result = use_kvm ? + mif6_kvm(list, session->sst_kvm, &nls[nlMIF_MAX]) : + mif6_sysctl(list); + break; + case PF_INET: + result = use_kvm ? + mif_kvm(list, session->sst_kvm, nls) : + mif_sysctl(list); + break; +#ifdef INET6 + case PF_INET6: + result = use_kvm ? + mif6_kvm(list, session->sst_kvm, nls) : + mif6_sysctl(list); + break; +#endif /* !INET6 */ + default: + list->mitl_error = NETSTAT_ERROR_UNSUPPORTED; + break; + } + +end: + return (result); +} +#undef nls_size + +int +mif_kvm(struct mcastif_type_list *list, kvm_t *kvm, struct nlist *nlp) +{ + struct vif viftable[MAXVIFS]; + struct vif *v; + struct mcastif_type *mitp; + struct ifnet ifnet; + int vifi; + + if (kread_data(kvm, (uintptr_t)nlp[nlMIF_viftable].n_value, viftable, + sizeof(viftable)) != 0) { + list->mitl_error = NETSTAT_ERROR_KVM; + return (-1); + } + + for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) { + if (v->v_lcl_addr.s_addr == 0) + continue; + if (kread_data(kvm, (uintptr_t)v->v_ifp, &ifnet, + sizeof(struct ifnet)) != 0) + v->v_ifp = &ifnet; + else + v->v_ifp = NULL; + mitp = _netstat_mit_allocate(list); + extract_vif_data(vifi, v, mitp); + } + + return (0); +} + +int +mif_sysctl(struct mcastif_type_list *list) +{ + const char *mibvar = "net.inet.ip.sviftable"; + + struct vif_stream *vsp; + struct vif_data *vdp; + struct mcastif_type *mitp; + char *buf, *p; + size_t len; + int result; + u_int32_t vifi; + + result = -1; + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); + goto out2; + } + if ((buf = malloc(len)) == 0) { + warnx("malloc %lu bytes", (u_long)len); + goto out2; + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + goto out1; + } + if (len < sizeof(*vsp)) { + list->mitl_error = NETSTAT_ERROR_VERSION; + goto out1; + } + + p = buf; + vsp = (struct vif_stream *)p; + p+= sizeof(*vsp); + + if (vsp->vs_version != VIF_STREAM_VERSION) { + list->mitl_error = NETSTAT_ERROR_VERSION; + goto out1; + } + + for (vifi = 0; vifi < vsp->vs_count; vifi++) { + vdp = (struct vif_data *)p; + p += sizeof(*vdp); + + if (vdp->vd_lcl_addr == 0) + continue; + + mitp = _netstat_mit_allocate(list); + extract_svif_data(vifi, vdp, mitp); + } + + result = 0; + +out1: free(buf); +out2: return (result); +} + +#ifdef INET6 +int +mif6_kvm(struct mcastif_type_list *list, kvm_t *kvm, struct nlist *nlp) +{ + struct mif6 mif6table[MAXMIFS]; + struct mif6 *m; + struct ifnet ifnet; + struct mcastif_type *mitp; + int mifi; + + if (kread_data(kvm, (uintptr_t)nlp[nlMIF6_mif6table].n_value, mif6table, + sizeof(mif6table)) != 0) { + list->mitl_error = NETSTAT_ERROR_KVM; + return (-1); + } + + for (mifi = 0, m = mif6table; mifi < MAXMIFS; ++mifi, ++m) { + if (m->m6_ifp == NULL) + continue; + + if (kread_data(kvm, (uintptr_t)m->m6_ifp, &ifnet, + sizeof(struct ifnet)) != 0) + m->m6_ifp = &ifnet; + else + continue; + + mitp = _netstat_mit_allocate(list); + extract_mif6_data(mifi, m, mitp); + } + + return (0); +} + +int +mif6_sysctl(struct mcastif_type_list *list) +{ + const char *mibvar = "net.inet6.ip6.smif6table"; + + struct mif6_stream *msp; + struct mif6_data *mdp; + struct mcastif_type *mitp; + char *buf, *p; + size_t len; + int result; + u_int32_t mifi; + + result = -1; + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); + goto out2; + } + if ((buf = malloc(len)) == 0) { + warnx("malloc %lu bytes", (u_long)len); + goto out2; + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + goto out1; + } + if (len < sizeof(*msp)) { + list->mitl_error = NETSTAT_ERROR_VERSION; + goto out1; + } + + p = buf; + msp = (struct mif6_stream *)p; + p+= sizeof(*msp); + + if (msp->ms_version != MIF6_STREAM_VERSION) { + list->mitl_error = NETSTAT_ERROR_VERSION; + goto out1; + } + + for (mifi = 0; mifi < msp->ms_count; mifi++) { + mdp = (struct mif6_data *)p; + p += sizeof(*mdp); + + mitp = _netstat_mit_allocate(list); + extract_smif6_data(mifi, mdp, mitp); + } + + result = 0; + +out1: free(buf); +out2: return (result); + +} +#endif /* !INET6 */ + +#define CNV_FLAG(X, Y) \ + if (v->v_flags & (X)) \ + mitp->mit_flags |= (Y) + +void +extract_vif_data(int index, struct vif *v, struct mcastif_type *mitp) +{ + struct sockaddr_in sa_in; + + bzero(&sa_in, sizeof(struct sockaddr_in)); + sa_in.sin_len = sizeof(struct sockaddr_in); + sa_in.sin_family = PF_INET; + sa_in.sin_addr = v->v_lcl_addr; + + mitp->mit_index = index; + CNV_FLAG(VIFF_TUNNEL, NETSTAT_MIF_TUNNEL); + CNV_FLAG(VIFF_SRCRT, NETSTAT_MIF_SRCRT); + CNV_FLAG(VIFF_REGISTER, NETSTAT_MIF_REGISTER); + mitp->mit_limit = v->v_threshold; + mitp->mit_address = extract_address(&sa_in, NULL, 0); + if (v->v_flags & VIFF_TUNNEL) { + sa_in.sin_addr = v->v_rmt_addr; + mitp->mit_remote_address = extract_address(&sa_in, NULL, 0); + } + mitp->mit_packets_in = v->v_pkt_in; + mitp->mit_packets_out = v->v_pkt_out; + mitp->mit_bytes_in = v->v_bytes_in; + mitp->mit_bytes_out = v->v_bytes_out; + if (v->v_flags & VIFF_REGISTER) + strlcpy(mitp->mit_ifname, "reg0", sizeof(mitp->mit_ifname)); + else if (v->v_ifp != NULL) + if_indextoname(v->v_ifp->if_index, mitp->mit_ifname); +} + +#undef CNV_FLAG + +#define CNV_FLAG(X, Y) \ + if (v->vd_flags & (X)) \ + mitp->mit_flags |= (Y) + +void +extract_svif_data(int index, struct vif_data *v, struct mcastif_type *mitp) +{ + struct sockaddr_in sa_in; + + bzero(&sa_in, sizeof(struct sockaddr_in)); + sa_in.sin_len = sizeof(struct sockaddr_in); + sa_in.sin_family = PF_INET; + sa_in.sin_addr.s_addr = v->vd_lcl_addr; + + mitp->mit_index = index; + CNV_FLAG(VIFF_TUNNEL, NETSTAT_MIF_TUNNEL); + CNV_FLAG(VIFF_SRCRT, NETSTAT_MIF_SRCRT); + CNV_FLAG(VIFF_REGISTER, NETSTAT_MIF_REGISTER); + mitp->mit_limit = v->vd_threshold; + mitp->mit_address = extract_address(&sa_in, NULL, 0); + if (v->vd_flags & VIFF_TUNNEL) { + sa_in.sin_addr.s_addr = v->vd_rmt_addr; + mitp->mit_remote_address = extract_address(&sa_in, NULL, 0); + } + mitp->mit_packets_in = v->vd_pkt_in; + mitp->mit_packets_out = v->vd_pkt_out; + mitp->mit_bytes_in = v->vd_bytes_in; + mitp->mit_bytes_out = v->vd_bytes_out; + if (v->vd_flags & VIFF_REGISTER) + strlcpy(mitp->mit_ifname, "reg0", sizeof(mitp->mit_ifname)); + else + if_indextoname(v->vd_if_index, mitp->mit_ifname); +} + +#undef CNV_FLAG + +#ifdef INET6 +#define CNV_FLAG(X, Y) \ + if (m->m6_flags & (X)) \ + mitp->mit_flags |= (Y) + +void +extract_mif6_data(int index, struct mif6 *m, struct mcastif_type *mitp) +{ + struct sockaddr_in6 sa_in6; + + bzero(&sa_in6, sizeof(struct sockaddr_in6)); + sa_in6.sin6_len = sizeof(struct sockaddr_in6); + sa_in6.sin6_family = PF_INET6; + sa_in6.sin6_addr = m->m6_lcl_addr; + + mitp->mit_index = index; + CNV_FLAG(MIFF_REGISTER, NETSTAT_MIF_REGISTER); + mitp->mit_limit = m->m6_rate_limit; + mitp->mit_address = extract_address(&sa_in6, NULL, 0); + mitp->mit_packets_in = m->m6_pkt_in; + mitp->mit_packets_out = m->m6_pkt_out; + if (m->m6_flags & MIFF_REGISTER) + strlcpy(mitp->mit_ifname, "reg0", sizeof(mitp->mit_ifname)); + else if (m->m6_ifp != NULL) + if_indextoname(m->m6_ifp->if_index, mitp->mit_ifname); +} + +#undef CNV_FLAG + +#define CNV_FLAG(X, Y) \ + if (m->md_flags & (X)) \ + mitp->mit_flags |= (Y) + +void +extract_smif6_data(int index, struct mif6_data *m, struct mcastif_type *mitp) +{ + struct sockaddr_in6 sa_in6; + + bzero(&sa_in6, sizeof(struct sockaddr_in6)); + sa_in6.sin6_len = sizeof(struct sockaddr_in6); + sa_in6.sin6_family = PF_INET6; + sa_in6.sin6_addr = *((struct in6_addr *)m->md_lcl_addr); + + mitp->mit_index = index; + CNV_FLAG(MIFF_REGISTER, NETSTAT_MIF_REGISTER); + mitp->mit_limit = m->md_rate_limit; + mitp->mit_address = extract_address(&sa_in6, NULL, 0); + mitp->mit_packets_in = m->md_pkt_in; + mitp->mit_packets_out = m->md_pkt_out; + if (m->md_flags & MIFF_REGISTER) + strlcpy(mitp->mit_ifname, "reg0", sizeof(mitp->mit_ifname)); + else + if_indextoname(m->md_if_index, mitp->mit_ifname); +} + +#undef CNV_FLAG +#endif /* !INET6 */ + + +#ifdef INET6 +#define nls_size (nlMRT_MAX + nlMRT6_MAX + 1) +#else +#define nls_size (nlMRT_MAX + 1) +#endif /* !INET6 */ + +int +netstat_mroute(const struct session_type *session, int domain, + struct mroute_type_list *list, __unused int flags) +{ + int result, use_kvm, i; + struct nlist nls[nls_size]; + + result = -1; + use_kvm = session->sst_flags & NETSTAT_SESSION_KVM; + bzero(nls, sizeof(nls)); + + if (use_kvm) { + switch (domain) { + case PF_UNSPEC: + for (i = 0; i < nlMRT_MAX; i++) + nls[i].n_name = mrt_symbol[i]; + for (i = nlMRT_MAX; i < nls_size; i++) + nls[i].n_name = mrt6_symbol[i - nlMRT_MAX]; + break; + case PF_INET: + for (i = 0; i < nlMRT_MAX; i++) + nls[i].n_name = mrt_symbol[i]; + break; +#ifdef INET6 + case PF_INET6: + for (i = 0; i < nlMRT6_MAX; i++) + nls[i].n_name = mrt6_symbol[i]; + break; +#endif /* !INET6 */ + default: + break; + } + if (kvm_nlist(session->sst_kvm, nls) < 0) { + list->mrtl_error = NETSTAT_ERROR_KVM; + goto end; + } + } + + switch (domain) { + case PF_UNSPEC: + result = use_kvm ? + mrt_kvm(list, session->sst_kvm, nls) : + mrt_sysctl(list); + if (result < 0) + goto end; + result = use_kvm ? + mrt6_kvm(list, session->sst_kvm, &nls[nlMRT_MAX]) : + mrt6_sysctl(list); + break; + case PF_INET: + result = use_kvm ? + mrt_kvm(list, session->sst_kvm, nls) : + mrt_sysctl(list); + break; +#ifdef INET6 + case PF_INET6: + result = use_kvm ? + mrt6_kvm(list, session->sst_kvm, nls) : + mrt6_sysctl(list); + break; +#endif /* !INET6 */ + default: + list->mrtl_error = NETSTAT_ERROR_UNSUPPORTED; + break; + } + +end: + return (result); +} +#undef nls_size + +int +mrt_kvm(struct mroute_type_list *list, kvm_t *kvm, struct nlist *nlp) +{ + u_long mfctablesize, i; + LIST_HEAD(, mfc) *mfchashtbl; + struct mfc mfc, *m; + struct mroute_type *mrtp; + size_t len; + + if (kread_data(kvm, (uintptr_t)nlp[nlMRT_mfctablesize].n_value, + &mfctablesize, sizeof(mfctablesize)) != 0) { + list->mrtl_error = NETSTAT_ERROR_KVM; + return (-1); + } + + len = sizeof(*mfchashtbl) * mfctablesize; + mfchashtbl = malloc(len); + if (mfchashtbl == NULL) { + list->mrtl_error = NETSTAT_ERROR_NOMEMORY; + return (-1); + } + + if (kread_data(kvm, (uintptr_t)nlp[nlMRT_mfchashtbl].n_value, + mfchashtbl, len) != 0) { + list->mrtl_error = NETSTAT_ERROR_KVM; + return (-1); + } + + for (i = 0; i < mfctablesize; i++) { + LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) { + if (kread_data(kvm, (uintptr_t)m, &mfc, + sizeof(mfc)) != 0) + continue; + mrtp = _netstat_mrt_allocate(list); + extract_mfc_data(&mfc, mrtp); + } + } + + free(mfchashtbl); + return (0); +} + +int +mrt_sysctl(struct mroute_type_list *list) +{ + const char *mibvar = "net.inet.ip.smfctable"; + + struct mfc_stream *msp; + struct mfc_data *mdp; + struct mroute_type *mrtp; + char *buf, *p; + size_t len; + int result; + u_int32_t i; + + result = -1; + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); + goto out2; + } + if ((buf = malloc(len)) == 0) { + warnx("malloc %lu bytes", (u_long)len); + goto out2; + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + goto out1; + } + if (len < sizeof(*msp)) { + list->mrtl_error = NETSTAT_ERROR_VERSION; + goto out1; + } + + p = buf; + msp = (struct mfc_stream *)p; + p+= sizeof(*msp); + + if (msp->ms_version != MFC_STREAM_VERSION) { + list->mrtl_error = NETSTAT_ERROR_VERSION; + goto out1; + } + + for (i = 0; i < msp->ms_count; i++) { + mdp = (struct mfc_data *)p; + p += sizeof(*mdp); + mrtp = _netstat_mrt_allocate(list); + extract_smfc_data(mdp, mrtp); + } + + result = 0; + +out1: free(buf); +out2: return (result); +} + +#ifdef INET6 +int +mrt6_kvm(struct mroute_type_list *list, kvm_t *kvm, struct nlist *nlp) +{ + struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp; + struct mf6c mfc; + struct mroute_type *mrtp; + int i; + + if (kread_data(kvm, (uintptr_t)nlp[nlMRT6_mf6ctable].n_value, + mf6ctable, sizeof(mf6ctable)) != 0) { + list->mrtl_error = NETSTAT_ERROR_KVM; + return (-1); + } + + for (i = 0; i < MF6CTBLSIZ; ++i) { + for (mfcp = mf6ctable[i]; mfcp != NULL; mfcp = mfc.mf6c_next) { + kread_data(kvm, (uintptr_t)mfcp, &mfc, sizeof(mfc)); + mrtp = _netstat_mrt_allocate(list); + extract_mf6c_data(_mrt6_get_nstall_kvm(kvm, &mfc), + &mfc, mrtp); + } + } + + return (0); +} + +int +mrt6_sysctl(struct mroute_type_list *list) +{ + const char *mibvar = "net.inet6.ip6.smf6ctable"; + + struct mf6c_stream *msp; + struct mf6c_data *mdp; + struct mroute_type *mrtp; + char *buf, *p; + size_t len; + int result; + u_int32_t i; + + result = -1; + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); + goto out2; + } + if ((buf = malloc(len)) == 0) { + warnx("malloc %lu bytes", (u_long)len); + goto out2; + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + goto out1; + } + if (len < sizeof(*msp)) { + list->mrtl_error = NETSTAT_ERROR_VERSION; + goto out1; + } + + p = buf; + msp = (struct mf6c_stream *)p; + p+= sizeof(*msp); + + if (msp->ms_version != MF6C_STREAM_VERSION) { + list->mrtl_error = NETSTAT_ERROR_VERSION; + goto out1; + } + + for (i = 0; i < msp->ms_count; i++) { + mdp = (struct mf6c_data *)p; + p += sizeof(*mdp); + mrtp = _netstat_mrt_allocate(list); + extract_smf6c_data(mdp, mrtp); + } + + result = 0; + +out1: free(buf); +out2: return (result); +} +#endif /* !INET6 */ + +void +extract_mfc_data(struct mfc *m, struct mroute_type *mrtp) +{ + int i; + struct sockaddr_in sa_in; + + bzero(&sa_in, sizeof(struct sockaddr_in)); + sa_in.sin_len = sizeof(struct sockaddr_in); + sa_in.sin_family = PF_INET; + sa_in.sin_addr = m->mfc_origin; + + mrtp->mrt_origin = extract_address(&sa_in, NULL, 0); + sa_in.sin_addr = m->mfc_mcastgrp; + mrtp->mrt_group = extract_address(&sa_in, NULL, 0); + mrtp->mrt_packets = m->mfc_pkt_cnt; + mrtp->mrt_bytes = m->mfc_byte_cnt; + mrtp->mrt_waitings = m->mfc_nstall; + mrtp->mrt_parent = m->mfc_parent; + for (i = 0; i < MAXVIFS; i++) + mrtp->mrt_ttls[i] = m->mfc_ttls[i]; +} + +void +extract_smfc_data(struct mfc_data *md, struct mroute_type *mrtp) +{ + struct sockaddr_in sa_in; + + bzero(&sa_in, sizeof(struct sockaddr_in)); + sa_in.sin_len = sizeof(struct sockaddr_in); + sa_in.sin_family = PF_INET; + sa_in.sin_addr.s_addr = md->md_origin; + + mrtp->mrt_origin = extract_address(&sa_in, NULL, 0); + sa_in.sin_addr.s_addr = md->md_mcastgrp; + mrtp->mrt_group = extract_address(&sa_in, NULL, 0); + mrtp->mrt_packets = md->md_pkt_cnt; + mrtp->mrt_bytes = md->md_byte_cnt; + mrtp->mrt_waitings = md->md_nstall; + mrtp->mrt_parent = md->md_parent; + bcopy(md->md_ttls, mrtp->mrt_ttls, sizeof(md->md_ttls)); +} + +#ifdef INET6 +void +extract_mf6c_data(int nstall, struct mf6c *m, struct mroute_type *mrtp) +{ + mrtp->mrt_origin = extract_address(&m->mf6c_origin, NULL, 0); + mrtp->mrt_group = extract_address(&m->mf6c_mcastgrp, NULL, 0); + mrtp->mrt_packets = m->mf6c_pkt_cnt; + mrtp->mrt_bytes = m->mf6c_byte_cnt; + mrtp->mrt_waitings = nstall; + mrtp->mrt_parent = m->mf6c_parent; + mrtp->mrt_ifset = m->mf6c_ifset; +} + +void +extract_smf6c_data(struct mf6c_data *md, struct mroute_type *mrtp) +{ + struct sockaddr_in6 sa_in6; + + bzero(&sa_in6, sizeof(struct sockaddr_in6)); + sa_in6.sin6_len = sizeof(struct sockaddr_in6); + sa_in6.sin6_family = PF_INET6; + sa_in6.sin6_addr = *((struct in6_addr *)md->md_origin); + + mrtp->mrt_origin = extract_address(&sa_in6, NULL, 0); + sa_in6.sin6_addr = *((struct in6_addr *)md->md_mcastgrp); + mrtp->mrt_group = extract_address(&sa_in6, NULL, 0); + mrtp->mrt_packets = md->md_pkt_cnt; + mrtp->mrt_bytes = md->md_byte_cnt; + mrtp->mrt_waitings = md->md_nstall; + mrtp->mrt_parent = md->md_parent; + bcopy(&md->md_ifs_bits, &mrtp->mrt_ifset, sizeof(md->md_ifs_bits)); +} +#endif /* !INET6 */ Index: lib/libnetstat/netstat_stat.c =================================================================== --- lib/libnetstat/netstat_stat.c (revision 0) +++ lib/libnetstat/netstat_stat.c (revision 0) @@ -0,0 +1,300 @@ +/*- + * Copyright (c) 2009, 2010 Gabor Pali + * 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. + * + * 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$ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef INET6 +#include +#include +#endif +#ifdef IPX +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "netstat.h" +#include "netstat_internal.h" + +static int read_sysctl(const char *mib_symbol, void *addr, size_t len); +static int read_kvm(void *, const char *kvm_symbol, void *addr, size_t len); + +static struct stat_info { + u_int32_t version; + const char *mib; + const char *kvm; +} stat_info [] = { + { TCPSTAT_VERSION, "net.inet.tcp.stats", "_tcpstat" }, + { UDPSTAT_VERSION, "net.inet.udp.stats", "_udpstat" }, + { CARPSTAT_VERSION, "net.inet.carp.stats", "_carpstats" }, + { IPSTAT_VERSION, "net.inet.ip.stats", "_ipstat" }, + { ICMPSTAT_VERSION, "net.inet.icmp.stats", "_icmpstat" }, + { PIMSTAT_VERSION, "net.inet.pim.stats", "_pimstat" }, + { IGMPSTAT_VERSION, "net.inet.igmp.stats", "_igmpstat" }, + { DDPSTAT_VERSION, "net.ddp.stats", "_ddpstat" }, +#ifdef SCTP + { SCTPSTAT_VERSION, "net.inet.sctp.stats", "_sctpstat" }, +#endif +#ifdef INET6 + { IP6STAT_VERSION, "net.inet6.ip6.stats", "_ip6stat" }, + { ICMP6STAT_VERSION, "net.inet6.icmp6.stats", "_icmp6stat" }, + { PIM6STAT_VERSION, "net.inet6.pim.stats", "_pim6stat" }, + { RIP6STAT_VERSION, "net.inet6.ip6.rip6stats", "_rip6stat" }, +#endif +#ifdef IPX + { IPXSTAT_VERSION, "net.ipx.ipx.stats", "_ipxstat" }, + { SPXSTAT_VERSION, "net.ipx.spx.stats", "_spx_istat" }, +#endif + { PFSYNCSTAT_VERSION, "net.inet.pfsync.stats", "_pfsyncstats" }, +#ifdef IPSEC + { PFKEYSTAT_VERSION, "net.key.stats", "_pfkeystat" }, + { ESPSTAT_VERSION, "net.inet.esp.stats", "_espstat" }, + { AHSTAT_VERSION, "net.inet.ah.stats", "_ahstat" }, + { IPCOMPSTAT_VERSION, "net.inet.ipcomp.stats", "_ipcompstat" }, + { IPSECSTAT_VERSION, "net.inet.ipsec.ipsecstats", "_ipsec4stat" }, +#endif + { RTSTAT_VERSION, "net.inet.ip.rtstat", "_rtstat" }, + { MRTSTAT_VERSION, "net.inet.ip.mrtstat", "_mrtstat" }, +#ifdef INET6 + { MRT6STAT_VERSION, "net.inet6.ip6.mrt6stat", "_mrt6stat" }, +#endif +}; + +int +netstat_stat(const struct session_type *session, enum stat type, + struct stat_type *sttp, __unused int flags) +{ + char *buffer; + char symbuf[64]; + + struct stat_header head; + struct udpstat *u; +#ifdef INET6 + struct rip6stat *r; +#endif + int res; + + if (type >= stat_MAX) { + sttp->stt_error = NETSTAT_ERROR_INVALID; + return (-1); + } + + sttp->stt_type = type; + bzero(&head, sizeof(head)); + + if (session->sst_flags & NETSTAT_SESSION_KVM) { + sprintf(symbuf, "%s_header", stat_info[sttp->stt_type].kvm); + res = read_kvm(session->sst_kvm, symbuf, &head, sizeof(head)); + if (res != 0) { + sttp->stt_error = NETSTAT_ERROR_KVM; + return (-1); + } + if (head.sth_version != stat_info[sttp->stt_type].version) { + sttp->stt_error = NETSTAT_ERROR_VERSION; + return (-1); + } + buffer = malloc(head.sth_len); + if (buffer == NULL) { + sttp->stt_error = NETSTAT_ERROR_NOMEMORY; + return (-1); + } + res = read_kvm(session->sst_kvm, stat_info[sttp->stt_type].kvm, + buffer, head.sth_len); + if (res != 0) { + sttp->stt_error = NETSTAT_ERROR_KVM; + return (-1); + } + } else { + sprintf(symbuf, "%s_header", stat_info[sttp->stt_type].mib); + res = read_sysctl(symbuf, &head, sizeof(head)); + if (res != 0) + return (res); + if (head.sth_version != stat_info[sttp->stt_type].version) { + sttp->stt_error = NETSTAT_ERROR_VERSION; + return (-1); + } + buffer = malloc(head.sth_len); + if (buffer == NULL) { + sttp->stt_error = NETSTAT_ERROR_NOMEMORY; + return (-1); + } + res = read_sysctl(stat_info[sttp->stt_type].mib, buffer, + head.sth_len); + if (res != 0) + return (res); + } + + /* + * XXX : This is a temporary hack that we use to handle cases + * where statistics structures have a version field or not. + * Once all statistics structures have a version field, + * This switch-case block shall be removed. + */ + + switch (sttp->stt_type) { + case stat_UDP: + sttp->stt_data = buffer; + u = (struct udpstat *)sttp->stt_data; + u->udps_delivered = + u->udps_ipackets - u->udps_hdrops - u->udps_badlen - + u->udps_badsum - u->udps_noport - u->udps_noportbcast - + u->udps_fullsock; + break; +#ifdef INET6 + case stat_RIP6: + sttp->stt_data = buffer; + r = (struct rip6stat *)sttp->stt_data; + r->rip6s_delivered = + r->rip6s_ipackets - r->rip6s_badsum - r->rip6s_nosock - + r->rip6s_nosockmcast - r->rip6s_fullsock; + break; +#endif /* !INET6 */ + +#ifdef IPSEC + case stat_IPcomp: + sttp->stt_data = malloc(sizeof(struct ipcomp_stat)); + if (sttp->stt_data == NULL) { + sttp->stt_error = NETSTAT_ERROR_NOMEMORY; + free(buffer); + return(-1); + } + ((struct ipcomp_stat *)sttp->stt_data)->v = head.sth_version; + ((struct ipcomp_stat *)sttp->stt_data)->s = (struct ipcompstat *)buffer; + break; +#endif /* !IPSEC */ + + default: + sttp->stt_data = buffer; + } + + return (0); +} + +int +netstat_icmp_get_maskrepl(const struct session_type *session) +{ + int res; + + res = 0; + + if (session->sst_flags & NETSTAT_SESSION_KVM) { + if (read_kvm(session->sst_kvm, "_icmpmaskrepl", &res, + sizeof(res)) < 0) { + warn("netstat_icmp_get_maskrepl"); + return (res); + } + } else { + if (read_sysctl("net.inet.icmp.maskrepl", &res, + sizeof(res)) < 0) { + warn("netstat_icmp_get_maskrepl"); + return (res); + } + } + + return (res); +} + +int +read_sysctl(const char *mib_symbol, void *addr, size_t len) +{ + if (sysctlbyname(mib_symbol, addr, &len, 0, 0) < 0) { + warnx("sysctl: %s", mib_symbol); + return (-1); + } + + return (0); +} + +int +read_kvm(void *kvm_handle, const char *kvm_symbol, void *addr, size_t len) { + kvm_t *kvm; + struct nlist nls[2]; + char buf[32]; + + if (kvm_handle == NULL) { + return (-1); + } + + kvm = (kvm_t *)kvm_handle; + bzero(nls, sizeof(nls)); + strlcpy(buf, kvm_symbol, sizeof(buf)); + nls[0].n_name = buf; + + if (kvm_nlist(kvm, nls) < 0) { + return (-1); + } + + if (kread_data(kvm, (uintptr_t)nls[0].n_value, addr, len) != 0) { + return (-1); + } + + return (0); +} + +int +netstat_zerostat(const struct session_type *session, enum stat type) +{ + char symbuf[64]; + char buffer[1024]; + struct stat_header head; + + if (session->sst_flags & NETSTAT_SESSION_KVM) + return (-1); /* unsupported */ + + if (type >= stat_MAX) { + return (-1); + } + + sprintf(symbuf, "%s_header", stat_info[type].mib); + read_sysctl(symbuf, &head, sizeof(head)); + bzero(buffer, sizeof(buffer)); + + if (sysctlbyname(stat_info[type].mib, NULL, NULL, buffer, + head.sth_len) < 0) { + warn("netstat_zerostat"); + return (-1); + } + + return (0); +} Index: Makefile.inc1 =================================================================== --- Makefile.inc1 (revision 209358) +++ Makefile.inc1 (working copy) @@ -1132,7 +1132,7 @@ lib/libradius lib/libsbuf lib/libtacplus \ lib/libutil ${_lib_libypclnt} lib/libz lib/msun \ ${_secure_lib_libcrypto} ${_secure_lib_libssh} \ - ${_secure_lib_libssl} + ${_secure_lib_libssl} lib/libmemstat .if ${MK_LIBTHR} != "no" _lib_libthr= lib/libthr Index: sys/kern/uipc_syscalls.c =================================================================== --- sys/kern/uipc_syscalls.c (revision 209358) +++ sys/kern/uipc_syscalls.c (working copy) @@ -117,6 +117,30 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0, "Number of sendfile(2) sf_bufs in use"); +static int +sfbuf_stats(SYSCTL_HANDLER_ARGS) +{ + struct sfbuf_data sfd; + int error; + + error = 0; + bzero(&sfd, sizeof(sfd)); + + sfd.sfd_version = SFBUF_DATA_VERSION; + sfd.sfd_nbufs = nsfbufs; + sfd.sfd_nbufs_peak = nsfbufspeak; + sfd.sfd_nbufs_used = nsfbufsused; + sfd.sfd_iocnt = mbstat.sf_iocnt; + sfd.sfd_allocfail = mbstat.sf_allocfail; + sfd.sfd_allocwait = mbstat.sf_allocwait; + + error = SYSCTL_OUT(req, &sfd, sizeof(sfd)); + return (error); +} + +SYSCTL_PROC(_kern_ipc, OID_AUTO, sfbstats, CTLFLAG_RD|CTLTYPE_STRUCT, 0, 0, + sfbuf_stats, "s,struct sfbuf_data", "Statistics on sendfile(2) buffers"); + /* * Convert a user file descriptor to a kernel file entry. A reference on the * file entry is held upon returning. This is lighter weight than Index: sys/kern/uipc_usrreq.c =================================================================== --- sys/kern/uipc_usrreq.c (revision 209358) +++ sys/kern/uipc_usrreq.c (working copy) @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -1586,6 +1588,129 @@ (caddr_t)(long)SOCK_SEQPACKET, 0, unp_pcblist, "S,xunpcb", "List of active local seqpacket sockets"); +static int +unp_spcblist(SYSCTL_HANDLER_ARGS) +{ + struct unpcb_stream us; + struct unpcb_data ud; + struct sbuf sbuf; + int error, i, buflen; + int freeunp; + char *buffer; + + struct unpcb *unp, **unp_list; + struct unp_head *head; + struct socket *sock; + struct sockaddr_un *sa; + + error = 0; + head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead); + + bzero(&us, sizeof(us)); + us.us_version = UNPCB_STREAM_VERSION; + + UNP_LIST_LOCK(); + us.us_gencnt = unp_gencnt; + us.us_count = unp_count; + UNP_LIST_UNLOCK(); + + unp_list = malloc(us.us_count * sizeof(*unp_list), M_TEMP, M_WAITOK); + if (unp_list == NULL) + return (ENOMEM); + + UNP_LIST_LOCK(); + for (unp = LIST_FIRST(head), i = 0; (unp != NULL) && (i < us.us_count); + unp = LIST_NEXT(unp, unp_link)) { + UNP_PCB_LOCK(unp); + if (unp->unp_gencnt <= us.us_gencnt && + cr_cansee(req->td->td_ucred, + unp->unp_socket->so_cred) == 0) { + unp_list[i++] = unp; + unp->unp_refcount++; + } + UNP_PCB_UNLOCK(unp); + } + UNP_LIST_UNLOCK(); + us.us_count = i; + + buflen = sizeof(us) + us.us_count * sizeof(ud) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &us, sizeof(us)) < 0) { + error = ENOMEM; + goto out; + } + + for (i = 0; i < us.us_count; i++) { + unp = unp_list[i]; + UNP_PCB_LOCK(unp); + unp->unp_refcount--; + if (unp->unp_refcount != 0 && unp->unp_gencnt <= us.us_gencnt) { + bzero(&ud, sizeof(ud)); + ud.ud_gencnt = unp->unp_gencnt; + sock = unp->unp_socket; + if (sock != NULL) { + ud.ud_qlen = sock->so_qlen; + ud.ud_incqlen = sock->so_incqlen; + ud.ud_qlimit = sock->so_qlimit; + ud.ud_snd_cc = sock->so_snd.sb_cc; + ud.ud_snd_mcnt = sock->so_snd.sb_mcnt; + ud.ud_snd_ccnt = sock->so_snd.sb_ccnt; + ud.ud_snd_hiwat = sock->so_snd.sb_hiwat; + ud.ud_snd_lowat = sock->so_snd.sb_lowat; + ud.ud_snd_mbcnt = sock->so_snd.sb_mbcnt; + ud.ud_snd_mbmax = sock->so_snd.sb_mbmax; + ud.ud_rcv_cc = sock->so_rcv.sb_cc; + ud.ud_rcv_mcnt = sock->so_rcv.sb_mcnt; + ud.ud_rcv_ccnt = sock->so_rcv.sb_ccnt; + ud.ud_rcv_hiwat = sock->so_rcv.sb_hiwat; + ud.ud_rcv_lowat = sock->so_rcv.sb_lowat; + ud.ud_rcv_mbcnt = sock->so_rcv.sb_mbcnt; + ud.ud_rcv_mbmax = sock->so_rcv.sb_mbmax; + } + ud.ud_pcb = (u_long)sock->so_pcb; + ud.ud_vnode = (u_long)unp->unp_vnode; + ud.ud_conn = (u_long)unp->unp_conn; + ud.ud_refs = (u_long)LIST_FIRST(&unp->unp_refs); + ud.ud_reflink = (u_long)LIST_NEXT(unp, unp_reflink); + if (unp->unp_addr != NULL) { + sa = unp->unp_addr; + ud.ud_address_len = sa->sun_len + - offsetof(struct sockaddr_un, sun_path); + bcopy(sa->sun_path, ud.ud_address, + ud.ud_address_len); + } + UNP_PCB_UNLOCK(unp); + if (sbuf_bcat(&sbuf, &ud, sizeof(ud)) < 0) { + error = ENOMEM; + goto out; + } + } else { + freeunp = (unp->unp_refcount == 0); + UNP_PCB_UNLOCK(unp); + if (freeunp) { + UNP_PCB_LOCK_DESTROY(unp); + uma_zfree(unp_zone, unp); + } + } + } + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(unp_list, M_TEMP); + free(buffer, M_TEMP); + return (error); +} + +SYSCTL_PROC(_net_local_dgram, OID_AUTO, spcblist, CTLFLAG_RD|CTLTYPE_STRUCT, + (caddr_t)(long)SOCK_DGRAM, 0, unp_spcblist, "s,struct unpcb_data", + "List of active local datagram sockets (stream)"); + +SYSCTL_PROC(_net_local_stream, OID_AUTO, spcblist, CTLFLAG_RD|CTLTYPE_STRUCT, + (caddr_t)(long)SOCK_STREAM, 0, unp_spcblist, "s,struct unpcb_data", + "List of active local stream sockets (stream)"); + static void unp_shutdown(struct unpcb *unp) { Index: sys/kern/kern_mbuf.c =================================================================== --- sys/kern/kern_mbuf.c (revision 209358) +++ sys/kern/kern_mbuf.c (working copy) @@ -208,6 +208,25 @@ SYSCTL_STRUCT(_kern_ipc, OID_AUTO, mbstat, CTLFLAG_RD, &mbstat, mbstat, "Mbuf general information and statistics"); +static int +mbuf_stats(SYSCTL_HANDLER_ARGS) +{ + struct mbstat_data mbsd; + int error; + + error = 0; + bzero(&mbsd, sizeof(mbsd)); + + mbsd.mbd_version = MBSTAT_DATA_VERSION; + mbsd.mbd_drain = mbstat.m_drain; + + error = SYSCTL_OUT(req, &mbsd, sizeof(mbsd)); + return (error); +} + +SYSCTL_PROC(_kern_ipc, OID_AUTO, mbstats, CTLFLAG_RD|CTLTYPE_STRUCT, 0, 0, + mbuf_stats, "s,struct mbstat_data", "Statistics on mbuf"); + /* * Zones from which we allocate. */ Index: sys/netatalk/ddp_var.h =================================================================== --- sys/netatalk/ddp_var.h (revision 209358) +++ sys/netatalk/ddp_var.h (working copy) @@ -40,17 +40,19 @@ #define sotoddpcb(so) ((struct ddpcb *)(so)->so_pcb) +#define DDPSTAT_VERSION 0x00000001 + struct ddpstat { - long ddps_short; /* short header packets received */ - long ddps_long; /* long header packets received */ - long ddps_nosum; /* no checksum */ - long ddps_badsum; /* bad checksum */ - long ddps_tooshort; /* packet too short */ - long ddps_toosmall; /* not enough data */ - long ddps_forward; /* packets forwarded */ - long ddps_encap; /* packets encapsulated */ - long ddps_cantforward; /* packets rcvd for unreachable dest */ - long ddps_nosockspace; /* no space in sockbuf for packet */ + u_int64_t ddps_short; /* short header packets received */ + u_int64_t ddps_long; /* long header packets received */ + u_int64_t ddps_nosum; /* no checksum */ + u_int64_t ddps_badsum; /* bad checksum */ + u_int64_t ddps_tooshort; /* packet too short */ + u_int64_t ddps_toosmall; /* not enough data */ + u_int64_t ddps_forward; /* packets forwarded */ + u_int64_t ddps_encap; /* packets encapsulated */ + u_int64_t ddps_cantforward; /* packets rcvd for unreachable dest */ + u_int64_t ddps_nosockspace; /* no space in sockbuf for packet */ }; #ifdef _KERNEL Index: sys/netatalk/ddp_input.c =================================================================== --- sys/netatalk/ddp_input.c (revision 209358) +++ sys/netatalk/ddp_input.c (working copy) @@ -58,8 +58,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -72,8 +74,19 @@ static volatile int ddp_forward = 1; static volatile int ddp_firewall = 0; + +static struct stat_header ddpstat_header = { + .sth_version = DDPSTAT_VERSION, + .sth_len = sizeof(struct ddpstat) +}; static struct ddpstat ddpstat; +SYSCTL_NODE(_net, OID_AUTO, ddp, CTLFLAG_RW, 0, "DDP"); +SYSCTL_STRUCT(_net_ddp, OID_AUTO, stats, CTLFLAG_RW, &ddpstat, ddpstat, + "DDP Statistics (struct ddpstat, netatalk/ddp_var.h)"); +SYSCTL_STRUCT(_net_ddp, OID_AUTO, stats_header, CTLFLAG_RD, &ddpstat_header, + stat_header, "DDP Statistics header"); + static struct route forwro; static void ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int); Index: sys/netinet/udp_var.h =================================================================== --- sys/netinet/udp_var.h (revision 209358) +++ sys/netinet/udp_var.h (working copy) @@ -69,25 +69,28 @@ /* .. per draft-ietf-ipsec-nat-t-ike-0[01], * and draft-ietf-ipsec-udp-encaps-(00/)01.txt */ #define UF_ESPINUDP 0x00000002 /* w/ non-ESP marker. */ +#define UDPSTAT_VERSION 0x00000001 struct udpstat { /* input statistics: */ - u_long udps_ipackets; /* total input packets */ - u_long udps_hdrops; /* packet shorter than header */ - u_long udps_badsum; /* checksum error */ - u_long udps_nosum; /* no checksum */ - u_long udps_badlen; /* data length larger than packet */ - u_long udps_noport; /* no socket on port */ - u_long udps_noportbcast; /* of above, arrived as broadcast */ - u_long udps_fullsock; /* not delivered, input socket full */ - u_long udpps_pcbcachemiss; /* input packets missing pcb cache */ - u_long udpps_pcbhashmiss; /* input packets not for hashed pcb */ + u_int64_t udps_ipackets; /* total input packets */ + u_int64_t udps_hdrops; /* packet shorter than header */ + u_int64_t udps_badsum; /* checksum error */ + u_int64_t udps_nosum; /* no checksum */ + u_int64_t udps_badlen; /* data length larger than packet */ + u_int64_t udps_noport; /* no socket on port */ + u_int64_t udps_noportbcast; /* of above, arrived as broadcast */ + u_int64_t udps_fullsock; /* not delivered, input socket full */ + u_int64_t udpps_pcbcachemiss; /* input packets missing pcb cache */ + u_int64_t udpps_pcbhashmiss; /* input packets not for hashed pcb */ + u_int64_t udps_delivered; + /* output statistics: */ - u_long udps_opackets; /* total output packets */ - u_long udps_fastout; /* output packets on fast path */ + u_int64_t udps_opackets; /* total output packets */ + u_int64_t udps_fastout; /* output packets on fast path */ /* of no socket on port, arrived as multicast */ - u_long udps_noportmcast; - u_long udps_filtermcast; /* blocked by multicast filter */ + u_int64_t udps_noportmcast; + u_int64_t udps_filtermcast; /* blocked by multicast filter */ }; #ifdef _KERNEL Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c (revision 209358) +++ sys/netinet/tcp_input.c (working copy) @@ -58,6 +58,7 @@ #include #include #include +#include #define TCPSTATES /* for logging */ @@ -99,10 +100,18 @@ static const int tcprexmtthresh = 3; VNET_DEFINE(struct tcpstat, tcpstat); +VNET_DEFINE(struct stat_header, tcpstat_header) = { + .sth_version = TCPSTAT_VERSION, + .sth_len = sizeof(struct tcpstat) +}; + SYSCTL_VNET_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, CTLFLAG_RW, &VNET_NAME(tcpstat), tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)"); +SYSCTL_VNET_STRUCT(_net_inet_tcp, OID_AUTO, stats_header, CTLFLAG_RD, + &VNET_NAME(tcpstat_header), stat_header, "TCP statistics header"); + int tcp_log_in_vain = 0; SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW, &tcp_log_in_vain, 0, Index: sys/netinet/ip_carp.c =================================================================== --- sys/netinet/ip_carp.c (revision 209358) +++ sys/netinet/ip_carp.c (working copy) @@ -86,6 +86,7 @@ #include #include +#include #define CARP_IFNAME "carp" static MALLOC_DEFINE(M_CARP, "CARP", "CARP interfaces"); @@ -147,11 +148,19 @@ SYSCTL_INT(_net_inet_carp, OID_AUTO, suppress_preempt, CTLFLAG_RD, &carp_suppress_preempt, 0, "Preemption is suppressed"); +struct stat_header carpstats_header = { + .sth_version = CARPSTAT_VERSION, + .sth_len = sizeof(struct carpstats), +}; struct carpstats carpstats; SYSCTL_STRUCT(_net_inet_carp, CARPCTL_STATS, stats, CTLFLAG_RW, &carpstats, carpstats, "CARP statistics (struct carpstats, netinet/ip_carp.h)"); +SYSCTL_STRUCT(_net_inet_carp, OID_AUTO, stats_header, CTLFLAG_RD, + &carpstats_header, stat_header, + "CARP statistics header"); + struct carp_if { TAILQ_HEAD(, carp_softc) vhif_vrs; int vhif_nvrs; Index: sys/netinet/raw_ip.c =================================================================== --- sys/netinet/raw_ip.c (revision 209358) +++ sys/netinet/raw_ip.c (working copy) @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -1083,6 +1084,118 @@ SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, 0, 0, rip_pcblist, "S,xinpcb", "List of active raw IP sockets"); +static int +rip_spcblist(SYSCTL_HANDLER_ARGS) +{ + struct inpcb_stream is; + struct inpcb_data id; + struct sbuf sbuf; + int error, i, buflen; + char *buffer; + + struct inpcb *inp, **inp_list; + struct socket *sock; + + bzero(&is, sizeof(is)); + is.is_version = INPCB_STREAM_VERSION; + + INP_INFO_RLOCK(&V_ripcbinfo); + is.is_gencnt = V_ripcbinfo.ipi_gencnt; + is.is_count = V_ripcbinfo.ipi_count; + INP_INFO_RUNLOCK(&V_ripcbinfo); + + inp_list = malloc(is.is_count * sizeof(*inp_list), M_TEMP, M_WAITOK); + if (inp_list == NULL) + return (ENOMEM); + + INP_INFO_RLOCK(&V_ripcbinfo); + for (inp = LIST_FIRST(V_ripcbinfo.ipi_listhead), i = 0; + inp != NULL && i < is.is_count; inp = LIST_NEXT(inp, inp_list)) { + INP_RLOCK(inp); + if (inp->inp_gencnt <= is.is_gencnt && + cr_canseeinpcb(req->td->td_ucred, inp) == 0) { + inp_list[i++] = inp; + } + INP_RUNLOCK(inp); + } + INP_INFO_RUNLOCK(&V_ripcbinfo); + is.is_count = i; + + error = 0; + buflen = sizeof(is) + is.is_count * sizeof(id) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &is, sizeof(is)) < 0) { + error = ENOMEM; + goto out; + } + + for (i = 0; i < is.is_count; i++) { + inp = inp_list[i]; + INP_RLOCK(inp); + if (inp->inp_gencnt <= is.is_gencnt) { + bzero(&id, sizeof(id)); + id.id_gencnt = inp->inp_gencnt; + sock = inp->inp_socket; + if (sock != NULL) { + id.id_qlen = sock->so_qlen; + id.id_qlimit = sock->so_qlimit; + id.id_snd_cc = sock->so_snd.sb_cc; + id.id_snd_mcnt = sock->so_snd.sb_mcnt; + id.id_snd_ccnt = sock->so_snd.sb_ccnt; + id.id_snd_hiwat = sock->so_snd.sb_hiwat; + id.id_snd_lowat = sock->so_snd.sb_lowat; + id.id_snd_mbcnt = sock->so_snd.sb_mbcnt; + id.id_snd_mbmax = sock->so_snd.sb_mbmax; + id.id_rcv_cc = sock->so_rcv.sb_cc; + id.id_rcv_mcnt = sock->so_rcv.sb_mcnt; + id.id_rcv_ccnt = sock->so_rcv.sb_ccnt; + id.id_rcv_hiwat = sock->so_rcv.sb_hiwat; + id.id_rcv_lowat = sock->so_rcv.sb_lowat; + id.id_rcv_mbcnt = sock->so_rcv.sb_mbcnt; + id.id_rcv_mbmax = sock->so_rcv.sb_mbmax; + id.id_pcb = (u_long)sock->so_pcb; + id.id_protocol = sock->so_proto->pr_protocol; + } + id.id_flags = inp->inp_flags; + id.id_vflag = inp->inp_vflag; + id.id_lport = inp->inp_lport; + id.id_fport = inp->inp_fport; + if (inp->inp_vflag & INP_IPV4) { + bcopy(&inp->inp_laddr, &id.id_laddr, + sizeof(inp->inp_laddr)); + bcopy(&inp->inp_faddr, &id.id_faddr, + sizeof(inp->inp_faddr)); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + bcopy(&inp->in6p_laddr, &id.id_laddr, + sizeof(inp->in6p_laddr)); + bcopy(&inp->in6p_faddr, &id.id_faddr, + sizeof(inp->in6p_faddr)); + } +#endif + if (sbuf_bcat(&sbuf, &id, sizeof(id)) < 0) { + INP_RUNLOCK(inp); + error = ENOMEM; + goto out; + } + } + INP_RUNLOCK(inp); + } + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(inp_list, M_TEMP); + free(buffer, M_TEMP); + return (error); +} + +SYSCTL_PROC(_net_inet_raw, OID_AUTO, spcblist, CTLFLAG_RD|CTLTYPE_STRUCT, + 0, 0, rip_spcblist, "s,struct inpcb_data", + "List of active raw IP sockets (stream)"); + struct pr_usrreqs rip_usrreqs = { .pru_abort = rip_abort, .pru_attach = rip_attach, Index: sys/netinet/tcp_subr.c =================================================================== --- sys/netinet/tcp_subr.c (revision 209358) +++ sys/netinet/tcp_subr.c (working copy) @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef INET6 #include #endif @@ -1156,6 +1157,137 @@ tcp_pcblist, "S,xtcpcb", "List of active TCP connections"); static int +tcp_spcblist(SYSCTL_HANDLER_ARGS) +{ + struct inpcb_stream is; + struct inpcb_data id; + struct sbuf sbuf; + int error, i, buflen; + char *buffer; + + struct inpcb *inp, **inp_list; + struct socket *sock; + struct tcpcb *pcb; + + bzero(&is, sizeof(is)); + is.is_version = INPCB_STREAM_VERSION; + + INP_INFO_RLOCK(&V_tcbinfo); + is.is_gencnt = V_tcbinfo.ipi_gencnt; + is.is_count = V_tcbinfo.ipi_count; + INP_INFO_RUNLOCK(&V_tcbinfo); + + inp_list = malloc(is.is_count * sizeof(*inp_list), M_TEMP, M_WAITOK); + if (inp_list == NULL) + return (ENOMEM); + + INP_INFO_RLOCK(&V_tcbinfo); + for (inp = LIST_FIRST(V_tcbinfo.ipi_listhead), i = 0; + inp != NULL && i < is.is_count; inp = LIST_NEXT(inp, inp_list)) { + INP_RLOCK(inp); + if (inp->inp_gencnt <= is.is_gencnt) { + if (inp->inp_flags & INP_TIMEWAIT) { + if (intotw(inp) != NULL) + error = cr_cansee(req->td->td_ucred, + intotw(inp)->tw_cred); + else + error = EINVAL; + } else + error = cr_canseeinpcb(req->td->td_ucred, inp); + if (error == 0) + inp_list[i++] = inp; + } + INP_RUNLOCK(inp); + } + INP_INFO_RUNLOCK(&V_tcbinfo); + is.is_count = i; + + error = 0; + buflen = sizeof(is) + is.is_count * sizeof(id) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &is, sizeof(is)) < 0) { + error = ENOMEM; + goto out; + } + + for (i = 0; i < is.is_count; i++) { + inp = inp_list[i]; + INP_RLOCK(inp); + if (inp->inp_gencnt <= is.is_gencnt) { + bzero(&id, sizeof(id)); + id.id_gencnt = inp->inp_gencnt; + sock = inp->inp_socket; + if (sock != NULL) { + id.id_qlen = sock->so_qlen; + id.id_incqlen = sock->so_incqlen; + id.id_qlimit = sock->so_qlimit; + id.id_snd_cc = sock->so_snd.sb_cc; + id.id_snd_mcnt = sock->so_snd.sb_mcnt; + id.id_snd_ccnt = sock->so_snd.sb_ccnt; + id.id_snd_hiwat = sock->so_snd.sb_hiwat; + id.id_snd_lowat = sock->so_snd.sb_lowat; + id.id_snd_mbcnt = sock->so_snd.sb_mbcnt; + id.id_snd_mbmax = sock->so_snd.sb_mbmax; + id.id_rcv_cc = sock->so_rcv.sb_cc; + id.id_rcv_mcnt = sock->so_rcv.sb_mcnt; + id.id_rcv_ccnt = sock->so_rcv.sb_ccnt; + id.id_rcv_hiwat = sock->so_rcv.sb_hiwat; + id.id_rcv_lowat = sock->so_rcv.sb_lowat; + id.id_rcv_mbcnt = sock->so_rcv.sb_mbcnt; + id.id_rcv_mbmax = sock->so_rcv.sb_mbmax; + id.id_pcb = (u_long)sock->so_pcb; + id.id_protocol = sock->so_proto->pr_protocol; + } else { + id.id_protocol = IPPROTO_TCP; + } + pcb = (struct tcpcb *)inp->inp_ppcb; + if (pcb != NULL) { + if (inp->inp_flags & INP_TIMEWAIT) + id.id_state = TCPS_TIME_WAIT; + else + id.id_state = pcb->t_state; + } + id.id_flags = inp->inp_flags; + id.id_vflag = inp->inp_vflag; + id.id_lport = inp->inp_lport; + id.id_fport = inp->inp_fport; + if (inp->inp_vflag & INP_IPV4) { + bcopy(&inp->inp_laddr, &id.id_laddr, + sizeof(inp->inp_laddr)); + bcopy(&inp->inp_faddr, &id.id_faddr, + sizeof(inp->inp_faddr)); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + bcopy(&inp->in6p_laddr, &id.id_laddr, + sizeof(inp->in6p_laddr)); + bcopy(&inp->in6p_faddr, &id.id_faddr, + sizeof(inp->in6p_faddr)); + } +#endif + if (sbuf_bcat(&sbuf, &id, sizeof(id)) < 0) { + INP_RUNLOCK(inp); + error = ENOMEM; + goto out; + } + } + INP_RUNLOCK(inp); + } + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(inp_list, M_TEMP); + free(buffer, M_TEMP); + return (error); +} + +SYSCTL_PROC(_net_inet_tcp, OID_AUTO, spcblist, CTLFLAG_RD|CTLTYPE_STRUCT, + 0, 0, tcp_spcblist, "s,struct inpcb_data", + "List of active TCP connections (stream)"); + +static int tcp_getcred(SYSCTL_HANDLER_ARGS) { struct xucred xuc; Index: sys/netinet/ip_carp.h =================================================================== --- sys/netinet/ip_carp.h (revision 209358) +++ sys/netinet/ip_carp.h (working copy) @@ -96,6 +96,8 @@ /* * Statistics. */ +#define CARPSTAT_VERSION 0x00000001 + struct carpstats { uint64_t carps_ipackets; /* total input packets, IPv4 */ uint64_t carps_ipackets6; /* total input packets, IPv6 */ Index: sys/netinet/ip_divert.c =================================================================== --- sys/netinet/ip_divert.c (revision 209358) +++ sys/netinet/ip_divert.c (working copy) @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -684,10 +685,121 @@ return error; } +static int +div_spcblist(SYSCTL_HANDLER_ARGS) +{ + struct inpcb_stream is; + struct inpcb_data id; + struct sbuf sbuf; + int error, i, buflen; + char *buffer; + + struct inpcb *inp, **inp_list; + struct socket *sock; + + bzero(&is, sizeof(is)); + is.is_version = INPCB_STREAM_VERSION; + + INP_INFO_RLOCK(&V_divcbinfo); + is.is_gencnt = V_divcbinfo.ipi_gencnt; + is.is_count = V_divcbinfo.ipi_count; + INP_INFO_RUNLOCK(&V_divcbinfo); + + inp_list = malloc(is.is_count * sizeof(*inp_list), M_TEMP, M_WAITOK); + if (inp_list == NULL) + return (ENOMEM); + + INP_INFO_RLOCK(&V_divcbinfo); + for (inp = LIST_FIRST(V_divcbinfo.ipi_listhead), i = 0; + inp != NULL && i < is.is_count; inp = LIST_NEXT(inp, inp_list)) { + INP_RLOCK(inp); + if (inp->inp_gencnt <= is.is_gencnt && + cr_canseeinpcb(req->td->td_ucred, inp) == 0) + inp_list[i++] = inp; + INP_RUNLOCK(inp); + } + INP_INFO_RUNLOCK(&V_divcbinfo); + is.is_count = i; + + error = 0; + buflen = sizeof(is) + is.is_count * sizeof(id) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &is, sizeof(is)) < 0) { + error = ENOMEM; + goto out; + } + + for (i = 0; i < is.is_count; i++) { + inp = inp_list[i]; + INP_RLOCK(inp); + if (inp->inp_gencnt <= is.is_gencnt) { + bzero(&id, sizeof(id)); + id.id_gencnt = inp->inp_gencnt; + sock = inp->inp_socket; + if (sock != NULL) { + id.id_qlen = sock->so_qlen; + id.id_incqlen = sock->so_incqlen; + id.id_qlimit = sock->so_qlimit; + id.id_snd_cc = sock->so_snd.sb_cc; + id.id_snd_mcnt = sock->so_snd.sb_mcnt; + id.id_snd_ccnt = sock->so_snd.sb_ccnt; + id.id_snd_hiwat = sock->so_snd.sb_hiwat; + id.id_snd_lowat = sock->so_snd.sb_lowat; + id.id_snd_mbcnt = sock->so_snd.sb_mbcnt; + id.id_snd_mbmax = sock->so_snd.sb_mbmax; + id.id_rcv_cc = sock->so_rcv.sb_cc; + id.id_rcv_mcnt = sock->so_rcv.sb_mcnt; + id.id_rcv_ccnt = sock->so_rcv.sb_ccnt; + id.id_rcv_hiwat = sock->so_rcv.sb_hiwat; + id.id_rcv_lowat = sock->so_rcv.sb_lowat; + id.id_rcv_mbcnt = sock->so_rcv.sb_mbcnt; + id.id_rcv_mbmax = sock->so_rcv.sb_mbmax; + id.id_pcb = (u_long)sock->so_pcb; + id.id_protocol = sock->so_proto->pr_protocol; + } + id.id_flags = inp->inp_flags; + id.id_vflag = inp->inp_vflag; + id.id_lport = inp->inp_lport; + id.id_fport = inp->inp_fport; + if (inp->inp_vflag & INP_IPV4) { + bcopy(&inp->inp_laddr, &id.id_laddr, + sizeof(inp->inp_laddr)); + bcopy(&inp->inp_faddr, &id.id_faddr, + sizeof(inp->inp_faddr)); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + bcopy(&inp->in6p_laddr, &id.id_laddr, + sizeof(inp->in6p_laddr)); + bcopy(&inp->in6p_faddr, &id.id_faddr, + sizeof(inp->in6p_faddr)); + } +#endif + if (sbuf_bcat(&sbuf, &id, sizeof(id)) < 0) { + INP_RUNLOCK(inp); + error = ENOMEM; + goto out; + } + } + INP_RUNLOCK(inp); + } + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(inp_list, M_TEMP); + free(buffer, M_TEMP); + return (error); +} + #ifdef SYSCTL_NODE SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, divert, CTLFLAG_RW, 0, "IPDIVERT"); SYSCTL_PROC(_net_inet_divert, OID_AUTO, pcblist, CTLFLAG_RD, 0, 0, div_pcblist, "S,xinpcb", "List of active divert sockets"); +SYSCTL_PROC(_net_inet_divert, OID_AUTO, spcblist, CTLFLAG_RD|CTLTYPE_STRUCT, + 0, 0, div_spcblist, "s,struct inpcb_data", + "List of active divert sockets (stream)"); #endif struct pr_usrreqs div_usrreqs = { Index: sys/netinet/sctp_uio.h =================================================================== --- sys/netinet/sctp_uio.h (revision 209358) +++ sys/netinet/sctp_uio.h (working copy) @@ -41,6 +41,7 @@ #endif #include #include +#include #include typedef uint32_t sctp_assoc_t; @@ -759,13 +760,10 @@ struct sctp_cwnd_log log[]; }; -struct sctp_timeval { - uint32_t tv_sec; - uint32_t tv_usec; -}; +#define SCTPSTAT_VERSION 0x00000001 struct sctpstat { - struct sctp_timeval sctps_discontinuitytime; /* sctpStats 18 + struct timestamp_type sctps_discontinuitytime; /* sctpStats 18 * (TimeStamp) */ /* MIB according to RFC 3873 */ uint32_t sctps_currestab; /* sctpStats 1 (Gauge32) */ @@ -1020,8 +1018,8 @@ uint32_t refcnt; uint16_t local_port; /* sctpAssocEntry 3 */ uint16_t remote_port; /* sctpAssocEntry 4 */ - struct sctp_timeval start_time; /* sctpAssocEntry 16 */ - struct sctp_timeval discontinuity_time; /* sctpAssocEntry 17 */ + struct timestamp_type start_time; /* sctpAssocEntry 16 */ + struct timestamp_type discontinuity_time; /* sctpAssocEntry 17 */ uint32_t peers_rwnd; sctp_assoc_t assoc_id; /* sctpAssocEntry 1 */ uint32_t extra_padding[32]; /* future */ @@ -1030,7 +1028,7 @@ struct xsctp_laddr { union sctp_sockstore address; /* sctpAssocLocalAddrEntry 1/2 */ uint32_t last; - struct sctp_timeval start_time; /* sctpAssocLocalAddrEntry 3 */ + struct timestamp_type start_time; /* sctpAssocLocalAddrEntry 3 */ uint32_t extra_padding[32]; /* future */ }; @@ -1047,7 +1045,7 @@ uint8_t active; /* sctpAssocLocalRemEntry 3 */ uint8_t confirmed; /* */ uint8_t heartbeat_enabled; /* sctpAssocLocalRemEntry 4 */ - struct sctp_timeval start_time; /* sctpAssocLocalRemEntry 8 */ + struct timestamp_type start_time; /* sctpAssocLocalRemEntry 8 */ uint32_t rtt; uint32_t extra_padding[32]; /* future */ }; Index: sys/netinet/in_pcb.h =================================================================== --- sys/netinet/in_pcb.h (revision 209358) +++ sys/netinet/in_pcb.h (working copy) @@ -254,6 +254,50 @@ }; #endif /* _SYS_SOCKETVAR_H_ */ +/* + * Statistics structures for user space monitoring tools. + */ + +#define INPCB_STREAM_VERSION 0x00000001 + +struct inpcb_stream { + u_int32_t is_version; + u_int32_t is_count; + u_int64_t is_gencnt; +}; + +struct inpcb_data { + u_int64_t id_gencnt; + u_int16_t id_qlen; + u_int16_t id_incqlen; + u_int16_t id_qlimit; + u_int32_t id_snd_cc; + u_int32_t id_snd_mcnt; + u_int32_t id_snd_ccnt; + u_int32_t id_snd_hiwat; + u_int32_t id_snd_lowat; + u_int32_t id_snd_mbcnt; + u_int32_t id_snd_mbmax; + u_int32_t id_rcv_cc; + u_int32_t id_rcv_mcnt; + u_int32_t id_rcv_ccnt; + u_int32_t id_rcv_hiwat; + u_int32_t id_rcv_lowat; + u_int32_t id_rcv_mbcnt; + u_int32_t id_rcv_mbmax; + u_int64_t id_pcb; + u_int16_t id_protocol; + u_int8_t id_state; + u_int16_t id_flags; + u_int8_t id_vflag; + u_int16_t id_lport; + u_int16_t id_fport; + u_int8_t id_laddr[16]; + u_int8_t id_faddr[16]; + u_int8_t _id_pad[2]; +}; + + struct inpcbport { LIST_ENTRY(inpcbport) phd_hash; struct inpcbhead phd_pcblist; Index: sys/netinet/pim_var.h =================================================================== --- sys/netinet/pim_var.h (revision 209358) +++ sys/netinet/pim_var.h (working copy) @@ -45,18 +45,21 @@ /* * PIM statistics kept in the kernel */ + +#define PIMSTAT_VERSION 0x00000001 + struct pimstat { - u_quad_t pims_rcv_total_msgs; /* total PIM messages received */ - u_quad_t pims_rcv_total_bytes; /* total PIM bytes received */ - u_quad_t pims_rcv_tooshort; /* rcvd with too few bytes */ - u_quad_t pims_rcv_badsum; /* rcvd with bad checksum */ - u_quad_t pims_rcv_badversion; /* rcvd bad PIM version */ - u_quad_t pims_rcv_registers_msgs; /* rcvd regs. msgs (data only) */ - u_quad_t pims_rcv_registers_bytes; /* rcvd regs. bytes (data only) */ - u_quad_t pims_rcv_registers_wrongiif; /* rcvd regs. on wrong iif */ - u_quad_t pims_rcv_badregisters; /* rcvd invalid registers */ - u_quad_t pims_snd_registers_msgs; /* sent regs. msgs (data only) */ - u_quad_t pims_snd_registers_bytes; /* sent regs. bytes (data only) */ + u_int64_t pims_rcv_total_msgs; /* total PIM messages received */ + u_int64_t pims_rcv_total_bytes; /* total PIM bytes received */ + u_int64_t pims_rcv_tooshort; /* rcvd with too few bytes */ + u_int64_t pims_rcv_badsum; /* rcvd with bad checksum */ + u_int64_t pims_rcv_badversion; /* rcvd bad PIM version */ + u_int64_t pims_rcv_registers_msgs; /* rcvd regs. msgs (data only) */ + u_int64_t pims_rcv_registers_bytes; /* rcvd regs. bytes (data only) */ + u_int64_t pims_rcv_registers_wrongiif; /* rcvd regs. on wrong iif */ + u_int64_t pims_rcv_badregisters; /* rcvd invalid registers */ + u_int64_t pims_snd_registers_msgs; /* sent regs. msgs (data only) */ + u_int64_t pims_snd_registers_bytes; /* sent regs. bytes (data only) */ }; #ifdef _KERNEL Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h (revision 209358) +++ sys/netinet/tcp_var.h (working copy) @@ -366,111 +366,113 @@ * Many of these should be kept per connection, * but that's inconvenient at the moment. */ -struct tcpstat { - u_long tcps_connattempt; /* connections initiated */ - u_long tcps_accepts; /* connections accepted */ - u_long tcps_connects; /* connections established */ - u_long tcps_drops; /* connections dropped */ - u_long tcps_conndrops; /* embryonic connections dropped */ - u_long tcps_minmssdrops; /* average minmss too low drops */ - u_long tcps_closed; /* conn. closed (includes drops) */ - u_long tcps_segstimed; /* segs where we tried to get rtt */ - u_long tcps_rttupdated; /* times we succeeded */ - u_long tcps_delack; /* delayed acks sent */ - u_long tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ - u_long tcps_rexmttimeo; /* retransmit timeouts */ - u_long tcps_persisttimeo; /* persist timeouts */ - u_long tcps_keeptimeo; /* keepalive timeouts */ - u_long tcps_keepprobe; /* keepalive probes sent */ - u_long tcps_keepdrops; /* connections dropped in keepalive */ - u_long tcps_sndtotal; /* total packets sent */ - u_long tcps_sndpack; /* data packets sent */ - u_long tcps_sndbyte; /* data bytes sent */ - u_long tcps_sndrexmitpack; /* data packets retransmitted */ - u_long tcps_sndrexmitbyte; /* data bytes retransmitted */ - u_long tcps_sndrexmitbad; /* unnecessary packet retransmissions */ - u_long tcps_sndacks; /* ack-only packets sent */ - u_long tcps_sndprobe; /* window probes sent */ - u_long tcps_sndurg; /* packets sent with URG only */ - u_long tcps_sndwinup; /* window update-only packets sent */ - u_long tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ +#define TCPSTAT_VERSION 0x00000001 - u_long tcps_rcvtotal; /* total packets received */ - u_long tcps_rcvpack; /* packets received in sequence */ - u_long tcps_rcvbyte; /* bytes received in sequence */ - u_long tcps_rcvbadsum; /* packets received with ccksum errs */ - u_long tcps_rcvbadoff; /* packets received with bad offset */ - u_long tcps_rcvmemdrop; /* packets dropped for lack of memory */ - u_long tcps_rcvshort; /* packets received too short */ - u_long tcps_rcvduppack; /* duplicate-only packets received */ - u_long tcps_rcvdupbyte; /* duplicate-only bytes received */ - u_long tcps_rcvpartduppack; /* packets with some duplicate data */ - u_long tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ - u_long tcps_rcvoopack; /* out-of-order packets received */ - u_long tcps_rcvoobyte; /* out-of-order bytes received */ - u_long tcps_rcvpackafterwin; /* packets with data after window */ - u_long tcps_rcvbyteafterwin; /* bytes rcvd after window */ - u_long tcps_rcvafterclose; /* packets rcvd after "close" */ - u_long tcps_rcvwinprobe; /* rcvd window probe packets */ - u_long tcps_rcvdupack; /* rcvd duplicate acks */ - u_long tcps_rcvacktoomuch; /* rcvd acks for unsent data */ - u_long tcps_rcvackpack; /* rcvd ack packets */ - u_long tcps_rcvackbyte; /* bytes acked by rcvd acks */ - u_long tcps_rcvwinupd; /* rcvd window update packets */ - u_long tcps_pawsdrop; /* segments dropped due to PAWS */ - u_long tcps_predack; /* times hdr predict ok for acks */ - u_long tcps_preddat; /* times hdr predict ok for data pkts */ - u_long tcps_pcbcachemiss; - u_long tcps_cachedrtt; /* times cached RTT in route updated */ - u_long tcps_cachedrttvar; /* times cached rttvar updated */ - u_long tcps_cachedssthresh; /* times cached ssthresh updated */ - u_long tcps_usedrtt; /* times RTT initialized from route */ - u_long tcps_usedrttvar; /* times RTTVAR initialized from rt */ - u_long tcps_usedssthresh; /* times ssthresh initialized from rt*/ - u_long tcps_persistdrop; /* timeout in persist state */ - u_long tcps_badsyn; /* bogus SYN, e.g. premature ACK */ - u_long tcps_mturesent; /* resends due to MTU discovery */ - u_long tcps_listendrop; /* listen queue overflows */ - u_long tcps_badrst; /* ignored RSTs in the window */ +struct tcpstat { + u_int64_t tcps_connattempt; /* connections initiated */ + u_int64_t tcps_accepts; /* connections accepted */ + u_int64_t tcps_connects; /* connections established */ + u_int64_t tcps_drops; /* connections dropped */ + u_int64_t tcps_conndrops; /* embryonic connections dropped */ + u_int64_t tcps_minmssdrops; /* average minmss too low drops */ + u_int64_t tcps_closed; /* conn. closed (includes drops) */ + u_int64_t tcps_segstimed; /* segs where we tried to get rtt */ + u_int64_t tcps_rttupdated; /* times we succeeded */ + u_int64_t tcps_delack; /* delayed acks sent */ + u_int64_t tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ + u_int64_t tcps_rexmttimeo; /* retransmit timeouts */ + u_int64_t tcps_persisttimeo; /* persist timeouts */ + u_int64_t tcps_keeptimeo; /* keepalive timeouts */ + u_int64_t tcps_keepprobe; /* keepalive probes sent */ + u_int64_t tcps_keepdrops; /* connections dropped in keepalive */ - u_long tcps_sc_added; /* entry added to syncache */ - u_long tcps_sc_retransmitted; /* syncache entry was retransmitted */ - u_long tcps_sc_dupsyn; /* duplicate SYN packet */ - u_long tcps_sc_dropped; /* could not reply to packet */ - u_long tcps_sc_completed; /* successful extraction of entry */ - u_long tcps_sc_bucketoverflow; /* syncache per-bucket limit hit */ - u_long tcps_sc_cacheoverflow; /* syncache cache limit hit */ - u_long tcps_sc_reset; /* RST removed entry from syncache */ - u_long tcps_sc_stale; /* timed out or listen socket gone */ - u_long tcps_sc_aborted; /* syncache entry aborted */ - u_long tcps_sc_badack; /* removed due to bad ACK */ - u_long tcps_sc_unreach; /* ICMP unreachable received */ - u_long tcps_sc_zonefail; /* zalloc() failed */ - u_long tcps_sc_sendcookie; /* SYN cookie sent */ - u_long tcps_sc_recvcookie; /* SYN cookie received */ + u_int64_t tcps_sndtotal; /* total packets sent */ + u_int64_t tcps_sndpack; /* data packets sent */ + u_int64_t tcps_sndbyte; /* data bytes sent */ + u_int64_t tcps_sndrexmitpack; /* data packets retransmitted */ + u_int64_t tcps_sndrexmitbyte; /* data bytes retransmitted */ + u_int64_t tcps_sndrexmitbad; /* unnecessary packet retransmissions */ + u_int64_t tcps_sndacks; /* ack-only packets sent */ + u_int64_t tcps_sndprobe; /* window probes sent */ + u_int64_t tcps_sndurg; /* packets sent with URG only */ + u_int64_t tcps_sndwinup; /* window update-only packets sent */ + u_int64_t tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ - u_long tcps_hc_added; /* entry added to hostcache */ - u_long tcps_hc_bucketoverflow; /* hostcache per bucket limit hit */ + u_int64_t tcps_rcvtotal; /* total packets received */ + u_int64_t tcps_rcvpack; /* packets received in sequence */ + u_int64_t tcps_rcvbyte; /* bytes received in sequence */ + u_int64_t tcps_rcvbadsum; /* packets received with ccksum errs */ + u_int64_t tcps_rcvbadoff; /* packets received with bad offset */ + u_int64_t tcps_rcvmemdrop; /* packets dropped for lack of memory */ + u_int64_t tcps_rcvshort; /* packets received too short */ + u_int64_t tcps_rcvduppack; /* duplicate-only packets received */ + u_int64_t tcps_rcvdupbyte; /* duplicate-only bytes received */ + u_int64_t tcps_rcvpartduppack; /* packets with some duplicate data */ + u_int64_t tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ + u_int64_t tcps_rcvoopack; /* out-of-order packets received */ + u_int64_t tcps_rcvoobyte; /* out-of-order bytes received */ + u_int64_t tcps_rcvpackafterwin; /* packets with data after window */ + u_int64_t tcps_rcvbyteafterwin; /* bytes rcvd after window */ + u_int64_t tcps_rcvafterclose; /* packets rcvd after "close" */ + u_int64_t tcps_rcvwinprobe; /* rcvd window probe packets */ + u_int64_t tcps_rcvdupack; /* rcvd duplicate acks */ + u_int64_t tcps_rcvacktoomuch; /* rcvd acks for unsent data */ + u_int64_t tcps_rcvackpack; /* rcvd ack packets */ + u_int64_t tcps_rcvackbyte; /* bytes acked by rcvd acks */ + u_int64_t tcps_rcvwinupd; /* rcvd window update packets */ + u_int64_t tcps_pawsdrop; /* segments dropped due to PAWS */ + u_int64_t tcps_predack; /* times hdr predict ok for acks */ + u_int64_t tcps_preddat; /* times hdr predict ok for data pkts */ + u_int64_t tcps_pcbcachemiss; + u_int64_t tcps_cachedrtt; /* times cached RTT in route updated */ + u_int64_t tcps_cachedrttvar; /* times cached rttvar updated */ + u_int64_t tcps_cachedssthresh; /* times cached ssthresh updated */ + u_int64_t tcps_usedrtt; /* times RTT initialized from route */ + u_int64_t tcps_usedrttvar; /* times RTTVAR initialized from rt */ + u_int64_t tcps_usedssthresh; /* times ssthresh initialized from rt*/ + u_int64_t tcps_persistdrop; /* timeout in persist state */ + u_int64_t tcps_badsyn; /* bogus SYN, e.g. premature ACK */ + u_int64_t tcps_mturesent; /* resends due to MTU discovery */ + u_int64_t tcps_listendrop; /* listen queue overflows */ + u_int64_t tcps_badrst; /* ignored RSTs in the window */ - u_long tcps_finwait2_drops; /* Drop FIN_WAIT_2 connection after time limit */ + u_int64_t tcps_sc_added; /* entry added to syncache */ + u_int64_t tcps_sc_retransmitted; /* syncache entry was retransmitted */ + u_int64_t tcps_sc_dupsyn; /* duplicate SYN packet */ + u_int64_t tcps_sc_dropped; /* could not reply to packet */ + u_int64_t tcps_sc_completed; /* successful extraction of entry */ + u_int64_t tcps_sc_bucketoverflow; /* syncache per-bucket limit hit */ + u_int64_t tcps_sc_cacheoverflow; /* syncache cache limit hit */ + u_int64_t tcps_sc_reset; /* RST removed entry from syncache */ + u_int64_t tcps_sc_stale; /* timed out or listen socket gone */ + u_int64_t tcps_sc_aborted; /* syncache entry aborted */ + u_int64_t tcps_sc_badack; /* removed due to bad ACK */ + u_int64_t tcps_sc_unreach; /* ICMP unreachable received */ + u_int64_t tcps_sc_zonefail; /* zalloc() failed */ + u_int64_t tcps_sc_sendcookie; /* SYN cookie sent */ + u_int64_t tcps_sc_recvcookie; /* SYN cookie received */ + u_int64_t tcps_hc_added; /* entry added to hostcache */ + u_int64_t tcps_hc_bucketoverflow; /* hostcache per bucket limit hit */ + + u_int64_t tcps_finwait2_drops; /* Drop FIN_WAIT_2 connection after time limit */ + /* SACK related stats */ - u_long tcps_sack_recovery_episode; /* SACK recovery episodes */ - u_long tcps_sack_rexmits; /* SACK rexmit segments */ - u_long tcps_sack_rexmit_bytes; /* SACK rexmit bytes */ - u_long tcps_sack_rcv_blocks; /* SACK blocks (options) received */ - u_long tcps_sack_send_blocks; /* SACK blocks (options) sent */ - u_long tcps_sack_sboverflow; /* times scoreboard overflowed */ + u_int64_t tcps_sack_recovery_episode; /* SACK recovery episodes */ + u_int64_t tcps_sack_rexmits; /* SACK rexmit segments */ + u_int64_t tcps_sack_rexmit_bytes; /* SACK rexmit bytes */ + u_int64_t tcps_sack_rcv_blocks; /* SACK blocks (options) received */ + u_int64_t tcps_sack_send_blocks; /* SACK blocks (options) sent */ + u_int64_t tcps_sack_sboverflow; /* times scoreboard overflowed */ /* ECN related stats */ - u_long tcps_ecn_ce; /* ECN Congestion Experienced */ - u_long tcps_ecn_ect0; /* ECN Capable Transport */ - u_long tcps_ecn_ect1; /* ECN Capable Transport */ - u_long tcps_ecn_shs; /* ECN successful handshakes */ - u_long tcps_ecn_rcwnd; /* # times ECN reduced the cwnd */ - - u_long _pad[12]; /* 6 UTO, 6 TBD */ + u_int64_t tcps_ecn_ce; /* ECN Congestion Experienced */ + u_int64_t tcps_ecn_ect0; /* ECN Capable Transport */ + u_int64_t tcps_ecn_ect1; /* ECN Capable Transport */ + u_int64_t tcps_ecn_shs; /* ECN successful handshakes */ + u_int64_t tcps_ecn_rcwnd; /* # times ECN reduced the cwnd */ + u_int64_t _pad[12]; /* 6 UTO, 6 TBD */ }; #ifdef _KERNEL Index: sys/netinet/icmp6.h =================================================================== --- sys/netinet/icmp6.h (revision 209358) +++ sys/netinet/icmp6.h (working copy) @@ -537,40 +537,43 @@ * Variables related to this implementation * of the internet control message protocol version 6. */ + +#define ICMP6STAT_VERSION 0x00000001 + struct icmp6errstat { - u_quad_t icp6errs_dst_unreach_noroute; - u_quad_t icp6errs_dst_unreach_admin; - u_quad_t icp6errs_dst_unreach_beyondscope; - u_quad_t icp6errs_dst_unreach_addr; - u_quad_t icp6errs_dst_unreach_noport; - u_quad_t icp6errs_packet_too_big; - u_quad_t icp6errs_time_exceed_transit; - u_quad_t icp6errs_time_exceed_reassembly; - u_quad_t icp6errs_paramprob_header; - u_quad_t icp6errs_paramprob_nextheader; - u_quad_t icp6errs_paramprob_option; - u_quad_t icp6errs_redirect; /* we regard redirect as an error here */ - u_quad_t icp6errs_unknown; + u_int64_t icp6errs_dst_unreach_noroute; + u_int64_t icp6errs_dst_unreach_admin; + u_int64_t icp6errs_dst_unreach_beyondscope; + u_int64_t icp6errs_dst_unreach_addr; + u_int64_t icp6errs_dst_unreach_noport; + u_int64_t icp6errs_packet_too_big; + u_int64_t icp6errs_time_exceed_transit; + u_int64_t icp6errs_time_exceed_reassembly; + u_int64_t icp6errs_paramprob_header; + u_int64_t icp6errs_paramprob_nextheader; + u_int64_t icp6errs_paramprob_option; + u_int64_t icp6errs_redirect; /* we regard redirect as an error here */ + u_int64_t icp6errs_unknown; }; struct icmp6stat { /* statistics related to icmp6 packets generated */ - u_quad_t icp6s_error; /* # of calls to icmp6_error */ - u_quad_t icp6s_canterror; /* no error 'cuz old was icmp */ - u_quad_t icp6s_toofreq; /* no error 'cuz rate limitation */ - u_quad_t icp6s_outhist[256]; + u_int64_t icp6s_error; /* # of calls to icmp6_error */ + u_int64_t icp6s_canterror; /* no error 'cuz old was icmp */ + u_int64_t icp6s_toofreq; /* no error 'cuz rate limitation */ + u_int64_t icp6s_outhist[256]; /* statistics related to input message processed */ - u_quad_t icp6s_badcode; /* icmp6_code out of range */ - u_quad_t icp6s_tooshort; /* packet < sizeof(struct icmp6_hdr) */ - u_quad_t icp6s_checksum; /* bad checksum */ - u_quad_t icp6s_badlen; /* calculated bound mismatch */ + u_int64_t icp6s_badcode; /* icmp6_code out of range */ + u_int64_t icp6s_tooshort; /* packet < sizeof(struct icmp6_hdr) */ + u_int64_t icp6s_checksum; /* bad checksum */ + u_int64_t icp6s_badlen; /* calculated bound mismatch */ /* * number of responses: this member is inherited from netinet code, but * for netinet6 code, it is already available in icp6s_outhist[]. */ - u_quad_t icp6s_reflect; - u_quad_t icp6s_inhist[256]; - u_quad_t icp6s_nd_toomanyopt; /* too many ND options */ + u_int64_t icp6s_reflect; + u_int64_t icp6s_inhist[256]; + u_int64_t icp6s_nd_toomanyopt; /* too many ND options */ struct icmp6errstat icp6s_outerrhist; #define icp6s_odst_unreach_noroute \ icp6s_outerrhist.icp6errs_dst_unreach_noroute @@ -590,13 +593,13 @@ #define icp6s_oparamprob_option icp6s_outerrhist.icp6errs_paramprob_option #define icp6s_oredirect icp6s_outerrhist.icp6errs_redirect #define icp6s_ounknown icp6s_outerrhist.icp6errs_unknown - u_quad_t icp6s_pmtuchg; /* path MTU changes */ - u_quad_t icp6s_nd_badopt; /* bad ND options */ - u_quad_t icp6s_badns; /* bad neighbor solicitation */ - u_quad_t icp6s_badna; /* bad neighbor advertisement */ - u_quad_t icp6s_badrs; /* bad router advertisement */ - u_quad_t icp6s_badra; /* bad router advertisement */ - u_quad_t icp6s_badredirect; /* bad redirect message */ + u_int64_t icp6s_pmtuchg; /* path MTU changes */ + u_int64_t icp6s_nd_badopt; /* bad ND options */ + u_int64_t icp6s_badns; /* bad neighbor solicitation */ + u_int64_t icp6s_badna; /* bad neighbor advertisement */ + u_int64_t icp6s_badrs; /* bad router advertisement */ + u_int64_t icp6s_badra; /* bad router advertisement */ + u_int64_t icp6s_badredirect; /* bad redirect message */ }; #ifdef _KERNEL Index: sys/netinet/ip_input.c =================================================================== --- sys/netinet/ip_input.c (revision 209358) +++ sys/netinet/ip_input.c (working copy) @@ -63,6 +63,7 @@ #include #include #include +#include #include #include @@ -94,6 +95,11 @@ VNET_DEFINE(int, rsvp_on); +VNET_DEFINE(struct stat_header, ipstat_header) = { + .sth_version = IPSTAT_VERSION, + .sth_len = sizeof(struct ipstat) +}; + VNET_DEFINE(int, ipforwarding); SYSCTL_VNET_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW, &VNET_NAME(ipforwarding), 0, @@ -174,6 +180,9 @@ #define V_ipq_zone VNET(ipq_zone) #define V_ipq VNET(ipq) +SYSCTL_VNET_STRUCT(_net_inet_ip, OID_AUTO, stats_header, CTLFLAG_RD, + &VNET_NAME(ipstat_header), stat_header, "IP statistics header"); + #define IPQ_LOCK() mtx_lock(&ipqlock) #define IPQ_UNLOCK() mtx_unlock(&ipqlock) #define IPQ_LOCK_INIT() mtx_init(&ipqlock, "ipqlock", NULL, MTX_DEF) Index: sys/netinet/ip_mroute.c =================================================================== --- sys/netinet/ip_mroute.c (revision 209358) +++ sys/netinet/ip_mroute.c (working copy) @@ -84,6 +84,7 @@ #include #include #include +#include #include #include #include @@ -98,6 +99,7 @@ #include #include #include +#include #include #include @@ -145,6 +147,12 @@ static int ip_mrouter_cnt; /* # of vnets with active mrouters */ static int ip_mrouter_unloading; /* Allow no more V_ip_mrouter sockets */ +static struct stat_header mrtstat_header = { + .sth_version = MRTSTAT_VERSION, + .sth_len = sizeof(struct mrtstat) +}; + + static VNET_DEFINE(struct mrtstat, mrtstat); #define V_mrtstat VNET(mrtstat) SYSCTL_VNET_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW, @@ -154,7 +162,12 @@ static VNET_DEFINE(u_long, mfchash); #define V_mfchash VNET(mfchash) -#define MFCHASH(a, g) \ + +SYSCTL_STRUCT(_net_inet_ip, OID_AUTO, mrtstat_header, CTLFLAG_RD, + &mrtstat_header, stat_header, + "IPv4 Multicast Forwarding Statistics header"); + +#define MFCHASH(a, g) \ ((((a).s_addr >> 20) ^ ((a).s_addr >> 10) ^ (a).s_addr ^ \ ((g).s_addr >> 20) ^ ((g).s_addr >> 10) ^ (g).s_addr) & V_mfchash) #define MFCHASHSIZE 256 @@ -181,6 +194,7 @@ &VNET_NAME(viftable), sizeof(V_viftable), "S,vif[MAXVIFS]", "IPv4 Multicast Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)"); + static struct mtx vif_mtx; #define VIF_LOCK() mtx_lock(&vif_mtx) #define VIF_UNLOCK() mtx_unlock(&vif_mtx) @@ -228,11 +242,20 @@ static VNET_DEFINE(struct pimstat, pimstat); #define V_pimstat VNET(pimstat) +static struct stat_header pimstat_header = { + .sth_version = PIMSTAT_VERSION, + .sth_len = sizeof(struct pimstat) +}; + SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); -SYSCTL_VNET_STRUCT(_net_inet_pim, PIMCTL_STATS, stats, CTLFLAG_RD, +SYSCTL_VNET_STRUCT(_net_inet_pim, PIMCTL_STATS, stats, CTLFLAG_RW, &VNET_NAME(pimstat), pimstat, "PIM Statistics (struct pimstat, netinet/pim_var.h)"); +SYSCTL_STRUCT(_net_inet_pim, OID_AUTO, stats_header, CTLFLAG_RD, + &pimstat_header, stat_header, + "PIM Statistics header"); + static u_long pim_squelch_wholepkt = 0; SYSCTL_ULONG(_net_inet_pim, OID_AUTO, squelch_wholepkt, CTLFLAG_RW, &pim_squelch_wholepkt, 0, @@ -782,6 +805,154 @@ return 0; } +static int +sysctl_export_viftable(SYSCTL_HANDLER_ARGS) +{ + struct vif_stream vs; + struct vif_data vd; + struct sbuf sbuf; + int error, buflen; + char *buffer; + struct vif *v; + vifi_t vifi; + + error = 0; + bzero(&vs, sizeof(vs)); + vs.vs_version = VIF_STREAM_VERSION; + + VIF_LOCK(); + + vs.vs_count = numvifs; + + VIF_UNLOCK(); + + buflen = sizeof(vs) + vs.vs_count * sizeof(vd) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + + VIF_LOCK(); + + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &vs, sizeof(vs)) < 0) { + VIF_UNLOCK(); + error = ENOMEM; + goto out; + } + + for (vifi = 0; vifi < min(vs.vs_count, numvifs); vifi++) { + v = &viftable[vifi]; + + bzero(&vd, sizeof(vd)); + vd.vd_flags = v->v_flags; + vd.vd_threshold = v->v_threshold; + vd.vd_lcl_addr = v->v_lcl_addr.s_addr; + vd.vd_rmt_addr = v->v_rmt_addr.s_addr; + vd.vd_if_index = v->v_ifp->if_index; + vd.vd_pkt_in = v->v_pkt_in; + vd.vd_pkt_out = v->v_pkt_out; + vd.vd_bytes_in = v->v_bytes_in; + vd.vd_bytes_out = v->v_bytes_out; + + if (sbuf_bcat(&sbuf, &vd, sizeof(vd)) < 0) { + VIF_UNLOCK(); + error = ENOMEM; + goto out; + } + } + + VIF_UNLOCK(); + + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(buffer, M_TEMP); + return (error); +} + +SYSCTL_PROC(_net_inet_ip, OID_AUTO, sviftable, CTLFLAG_RD|CTLTYPE_STRUCT, + 0, 0, sysctl_export_viftable, "s,struct vif_data", + "IPv4 Multicast Interfaces (streamed)"); + +static int +sysctl_export_mfctable(SYSCTL_HANDLER_ARGS) +{ + struct mfc_stream ms; + struct mfc_data md; + struct sbuf sbuf; + int error, buflen; + char *buffer; + struct mfc *m; + u_int32_t i, j; + + error = 0; + bzero(&ms, sizeof(ms)); + ms.ms_version = MFC_STREAM_VERSION; + + MFC_LOCK(); + + /* Count entries. */ + ms.ms_count = 0; + + if (mfchashtbl != NULL) + for (i = 0; i < mfchashsize; i++) { + LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) + ms.ms_count++; + } + + MFC_UNLOCK(); + + buflen = sizeof(ms) + ms.ms_count * sizeof(md) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + + MFC_LOCK(); + + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &ms, sizeof(ms)) < 0) { + MFC_UNLOCK(); + error = ENOMEM; + goto out; + } + + j = 0; + if (mfchashtbl != NULL) + for (i = 0; i < mfchashsize; i++) { + LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) { + bzero(&md, sizeof(md)); + md.md_origin = m->mfc_origin.s_addr; + md.md_mcastgrp = m->mfc_mcastgrp.s_addr; + md.md_pkt_cnt = m->mfc_pkt_cnt; + md.md_byte_cnt = m->mfc_byte_cnt; + md.md_nstall = m->mfc_nstall; + md.md_parent = m->mfc_parent; + bcopy(m->mfc_ttls, md.md_ttls, sizeof(md.md_ttls)); + + if (sbuf_bcat(&sbuf, &md, sizeof(md)) < 0) { + MFC_UNLOCK(); + error = ENOMEM; + goto out; + } + + if (j < ms.ms_count) + j++; + else + break; + } + } + + MFC_UNLOCK(); + + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(buffer, M_TEMP); + return (error); +} + +SYSCTL_PROC(_net_inet_ip, OID_AUTO, smfctable, CTLFLAG_RD|CTLTYPE_STRUCT, + 0, 0, sysctl_export_mfctable, "s,struct mfc_data", + "IPv4 Multicast Forwarding Table (streamed)"); + /* * Set PIM assert processing global */ Index: sys/netinet/icmp_var.h =================================================================== --- sys/netinet/icmp_var.h (revision 209358) +++ sys/netinet/icmp_var.h (working copy) @@ -38,23 +38,26 @@ * Variables related to this implementation * of the internet control message protocol. */ + +#define ICMPSTAT_VERSION 0x00000001 + struct icmpstat { /* statistics related to icmp packets generated */ - u_long icps_error; /* # of calls to icmp_error */ - u_long icps_oldshort; /* no error 'cuz old ip too short */ - u_long icps_oldicmp; /* no error 'cuz old was icmp */ - u_long icps_outhist[ICMP_MAXTYPE + 1]; + u_int64_t icps_error; /* # of calls to icmp_error */ + u_int64_t icps_oldshort; /* no error 'cuz old ip too short */ + u_int64_t icps_oldicmp; /* no error 'cuz old was icmp */ + u_int64_t icps_outhist[ICMP_MAXTYPE + 1]; /* statistics related to input messages processed */ - u_long icps_badcode; /* icmp_code out of range */ - u_long icps_tooshort; /* packet < ICMP_MINLEN */ - u_long icps_checksum; /* bad checksum */ - u_long icps_badlen; /* calculated bound mismatch */ - u_long icps_reflect; /* number of responses */ - u_long icps_inhist[ICMP_MAXTYPE + 1]; - u_long icps_bmcastecho; /* b/mcast echo requests dropped */ - u_long icps_bmcasttstamp; /* b/mcast tstamp requests dropped */ - u_long icps_badaddr; /* bad return address */ - u_long icps_noroute; /* no route back */ + u_int64_t icps_badcode; /* icmp_code out of range */ + u_int64_t icps_tooshort; /* packet < ICMP_MINLEN */ + u_int64_t icps_checksum; /* bad checksum */ + u_int64_t icps_badlen; /* calculated bound mismatch */ + u_int64_t icps_reflect; /* number of responses */ + u_int64_t icps_inhist[ICMP_MAXTYPE + 1]; + u_int64_t icps_bmcastecho; /* b/mcast echo requests dropped */ + u_int64_t icps_bmcasttstamp; /* b/mcast tstamp requests dropped */ + u_int64_t icps_badaddr; /* bad return address */ + u_int64_t icps_noroute; /* no route back */ }; #ifdef _KERNEL Index: sys/netinet/ip_mroute.h =================================================================== --- sys/netinet/ip_mroute.h (revision 209358) +++ sys/netinet/ip_mroute.h (working copy) @@ -205,20 +205,22 @@ /* * The kernel's multicast routing statistics. */ +#define MRTSTAT_VERSION 0x00000001 + struct mrtstat { - u_long mrts_mfc_lookups; /* # forw. cache hash table hits */ - u_long mrts_mfc_misses; /* # forw. cache hash table misses */ - u_long mrts_upcalls; /* # calls to multicast routing daemon */ - u_long mrts_no_route; /* no route for packet's origin */ - u_long mrts_bad_tunnel; /* malformed tunnel options */ - u_long mrts_cant_tunnel; /* no room for tunnel options */ - u_long mrts_wrong_if; /* arrived on wrong interface */ - u_long mrts_upq_ovflw; /* upcall Q overflow */ - u_long mrts_cache_cleanups; /* # entries with no upcalls */ - u_long mrts_drop_sel; /* pkts dropped selectively */ - u_long mrts_q_overflow; /* pkts dropped - Q overflow */ - u_long mrts_pkt2large; /* pkts dropped - size > BKT SIZE */ - u_long mrts_upq_sockfull; /* upcalls dropped - socket full */ + u_int64_t mrts_mfc_lookups; /* # forw. cache hash table hits */ + u_int64_t mrts_mfc_misses; /* # forw. cache hash table misses */ + u_int64_t mrts_upcalls; /* # calls to multicast routing daemon */ + u_int64_t mrts_no_route; /* no route for packet's origin */ + u_int64_t mrts_bad_tunnel; /* malformed tunnel options */ + u_int64_t mrts_cant_tunnel; /* no room for tunnel options */ + u_int64_t mrts_wrong_if; /* arrived on wrong interface */ + u_int64_t mrts_upq_ovflw; /* upcall Q overflow */ + u_int64_t mrts_cache_cleanups; /* # entries with no upcalls */ + u_int64_t mrts_drop_sel; /* pkts dropped selectively */ + u_int64_t mrts_q_overflow; /* pkts dropped - Q overflow */ + u_int64_t mrts_pkt2large; /* pkts dropped - size > BKT SIZE */ + u_int64_t mrts_upq_sockfull; /* upcalls dropped - socket full */ }; #ifdef _KERNEL @@ -265,6 +267,29 @@ struct route v_route; /* cached route */ }; +/* + * Statistics structures to be used by user space monitoring tools. + */ +#define VIF_STREAM_VERSION 0x00000001 + +struct vif_stream { + u_int32_t vs_version; + u_int32_t vs_count; +}; + +struct vif_data { + u_int8_t vd_flags; + u_int8_t vd_threshold; + u_int32_t vd_lcl_addr; + u_int32_t vd_rmt_addr; + u_int16_t vd_if_index; + u_int64_t vd_pkt_in; + u_int64_t vd_pkt_out; + u_int64_t vd_bytes_in; + u_int64_t vd_bytes_out; + u_int8_t _vd_pad[22]; +}; + #ifdef _KERNEL /* * The kernel's multicast forwarding cache entry structure @@ -288,6 +313,24 @@ }; #endif /* _KERNEL */ +#define MFC_STREAM_VERSION 0x00000001 + +struct mfc_stream { + u_int32_t ms_version; + u_int32_t ms_count; +}; + +struct mfc_data { + u_int32_t md_origin; + u_int32_t md_mcastgrp; + u_int64_t md_pkt_cnt; + u_int64_t md_byte_cnt; + u_int64_t md_nstall; + u_int32_t md_parent; + u_int8_t md_ttls[32]; + u_int8_t _md_pad[60]; +}; + /* * Struct used to communicate from kernel to multicast router * note the convenient similarity to an IP packet Index: sys/netinet/igmp_var.h =================================================================== --- sys/netinet/igmp_var.h (revision 209358) +++ sys/netinet/igmp_var.h (working copy) @@ -67,6 +67,7 @@ /* * IGMPv3 protocol statistics. */ +#define IGMPSTAT_VERSION 0x00000001 struct igmpstat { /* * Structure header (to insulate ABI changes). Index: sys/netinet/sctp_constants.h =================================================================== --- sys/netinet/sctp_constants.h (revision 209358) +++ sys/netinet/sctp_constants.h (working copy) @@ -997,8 +997,8 @@ #endif /*#if defined(__FreeBSD__) || defined(__APPLE__)*/ /*#define SCTP_GETTIME_TIMEVAL(x) { \*/ -/* (x)->tv_sec = ticks / 1000; \*/ -/* (x)->tv_usec = (ticks % 1000) * 1000; \*/ +/* (x)->ts_sec = ticks / 1000; \*/ +/* (x)->ts_usec = (ticks % 1000) * 1000; \*/ /*}*/ /*#else*/ Index: sys/netinet/sctp_sysctl.c =================================================================== --- sys/netinet/sctp_sysctl.c (revision 209358) +++ sys/netinet/sctp_sysctl.c (working copy) @@ -39,6 +39,7 @@ #include #include #include +#include /* * sysctl tunable variables @@ -285,8 +286,8 @@ continue; memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr)); memcpy((void *)&xladdr.address, (const void *)&laddr->ifa->address, sizeof(union sctp_sockstore)); - xladdr.start_time.tv_sec = (uint32_t) laddr->start_time.tv_sec; - xladdr.start_time.tv_usec = (uint32_t) laddr->start_time.tv_usec; + xladdr.start_time.ts_sec = (u_int32_t) laddr->start_time.tv_sec; + xladdr.start_time.ts_usec = (u_int32_t) laddr->start_time.tv_usec; SCTP_INP_RUNLOCK(inp); SCTP_INP_INFO_RUNLOCK(); error = SYSCTL_OUT(req, &xladdr, sizeof(struct xsctp_laddr)); @@ -428,10 +429,10 @@ xstcb.T1_expireries = stcb->asoc.timoinit + stcb->asoc.timocookie; xstcb.T2_expireries = stcb->asoc.timoshutdown + stcb->asoc.timoshutdownack; xstcb.retransmitted_tsns = stcb->asoc.marked_retrans; - xstcb.start_time.tv_sec = (uint32_t) stcb->asoc.start_time.tv_sec; - xstcb.start_time.tv_usec = (uint32_t) stcb->asoc.start_time.tv_usec; - xstcb.discontinuity_time.tv_sec = (uint32_t) stcb->asoc.discontinuity_time.tv_sec; - xstcb.discontinuity_time.tv_usec = (uint32_t) stcb->asoc.discontinuity_time.tv_usec; + xstcb.start_time.ts_sec = (u_int32_t) stcb->asoc.start_time.tv_sec; + xstcb.start_time.ts_usec = (u_int32_t) stcb->asoc.start_time.tv_usec; + xstcb.discontinuity_time.ts_sec = (u_int32_t) stcb->asoc.discontinuity_time.tv_sec; + xstcb.discontinuity_time.ts_usec = (u_int32_t) stcb->asoc.discontinuity_time.tv_usec; xstcb.total_sends = stcb->total_sends; xstcb.total_recvs = stcb->total_recvs; xstcb.local_tag = stcb->asoc.my_vtag; @@ -472,8 +473,8 @@ xraddr.flight_size = net->flight_size; xraddr.mtu = net->mtu; xraddr.rtt = net->rtt; - xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec; - xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec; + xraddr.start_time.ts_sec = (u_int32_t) net->start_time.tv_sec; + xraddr.start_time.ts_usec = (u_int32_t) net->start_time.tv_usec; SCTP_INP_RUNLOCK(inp); SCTP_INP_INFO_RUNLOCK(); error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr)); @@ -645,9 +646,9 @@ memset(&sb, 0, sizeof(sb)); for (cpu = 0; cpu < mp_ncpus; cpu++) { sarry = &SCTP_BASE_STATS[cpu]; - if (sarry->sctps_discontinuitytime.tv_sec > sb.sctps_discontinuitytime.tv_sec) { - sb.sctps_discontinuitytime.tv_sec = sarry->sctps_discontinuitytime.tv_sec; - sb.sctps_discontinuitytime.tv_usec = sarry->sctps_discontinuitytime.tv_usec; + if (sarry->sctps_discontinuitytime.ts_sec > sb.sctps_discontinuitytime.ts_sec) { + sb.sctps_discontinuitytime.ts_sec = sarry->sctps_discontinuitytime.ts_sec; + sb.sctps_discontinuitytime.ts_usec = sarry->sctps_discontinuitytime.ts_usec; } sb.sctps_currestab += sarry->sctps_currestab; sb.sctps_activeestab += sarry->sctps_activeestab; @@ -1086,6 +1087,15 @@ "SCTP statistics (struct sctp_stat)"); #endif +struct stat_header sctpstat_header = { + .sth_version = SCTPSTAT_VERSION, + .sth_len = sizeof(SCTP_BASE_STATS) +}; + +SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats_header, CTLFLAG_RD, + &sctpstat_header, stat_header, + "SCTP statistics header"); + SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD, 0, 0, sctp_assoclist, "S,xassoc", "List of active SCTP associations"); Index: sys/netinet/ip_icmp.c =================================================================== --- sys/netinet/ip_icmp.c (revision 209358) +++ sys/netinet/ip_icmp.c (working copy) @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -76,9 +77,29 @@ * host table maintenance routines. */ VNET_DEFINE(struct icmpstat, icmpstat); + +VNET_DEFINE(struct stat_header, icmpstat_header) = { + .sth_version = ICMPSTAT_VERSION, + .sth_len = sizeof(struct icmpstat) +}; + +#define V_icmpmaskrepl VNET(icmpmaskrepl) +#define V_icmpmaskfake VNET(icmpmaskfake) +#define V_drop_redirect VNET(drop_redirect) +#define V_log_redirect VNET(log_redirect) +#define V_icmplim VNET(icmplim) +#define V_icmplim_output VNET(icmplim_output) +#define V_reply_src VNET(reply_src) +#define V_icmp_rfi VNET(icmp_rfi) +#define V_icmp_quotelen VNET(icmp_quotelen) +#define V_icmpbmcastecho VNET(icmpbmcastecho) + SYSCTL_VNET_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RW, - &VNET_NAME(icmpstat), icmpstat, ""); + &VNET_NAME(icmpstat), icmpstat, "ICMP statistics"); +SYSCTL_VNET_STRUCT(_net_inet_icmp, OID_AUTO, stats_header, CTLFLAG_RW, + &VNET_NAME(icmpstat_header), stat_header, "ICMP statistics header"); + static VNET_DEFINE(int, icmpmaskrepl) = 0; #define V_icmpmaskrepl VNET(icmpmaskrepl) SYSCTL_VNET_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW, Index: sys/netinet/ip_var.h =================================================================== --- sys/netinet/ip_var.h (revision 209358) +++ sys/netinet/ip_var.h (working copy) @@ -95,36 +95,38 @@ struct in_mfilter *imo_mfilters; /* source filters */ }; +#define IPSTAT_VERSION 0x00000001 + struct ipstat { - u_long ips_total; /* total packets received */ - u_long ips_badsum; /* checksum bad */ - u_long ips_tooshort; /* packet too short */ - u_long ips_toosmall; /* not enough data */ - u_long ips_badhlen; /* ip header length < data size */ - u_long ips_badlen; /* ip length < ip header length */ - u_long ips_fragments; /* fragments received */ - u_long ips_fragdropped; /* frags dropped (dups, out of space) */ - u_long ips_fragtimeout; /* fragments timed out */ - u_long ips_forward; /* packets forwarded */ - u_long ips_fastforward; /* packets fast forwarded */ - u_long ips_cantforward; /* packets rcvd for unreachable dest */ - u_long ips_redirectsent; /* packets forwarded on same net */ - u_long ips_noproto; /* unknown or unsupported protocol */ - u_long ips_delivered; /* datagrams delivered to upper level*/ - u_long ips_localout; /* total ip packets generated here */ - u_long ips_odropped; /* lost packets due to nobufs, etc. */ - u_long ips_reassembled; /* total packets reassembled ok */ - u_long ips_fragmented; /* datagrams successfully fragmented */ - u_long ips_ofragments; /* output fragments created */ - u_long ips_cantfrag; /* don't fragment flag was set, etc. */ - u_long ips_badoptions; /* error in option processing */ - u_long ips_noroute; /* packets discarded due to no route */ - u_long ips_badvers; /* ip version != 4 */ - u_long ips_rawout; /* total raw ip packets generated */ - u_long ips_toolong; /* ip length > max ip packet size */ - u_long ips_notmember; /* multicasts for unregistered grps */ - u_long ips_nogif; /* no match gif found */ - u_long ips_badaddr; /* invalid address on header */ + u_int64_t ips_total; /* total packets received */ + u_int64_t ips_badsum; /* checksum bad */ + u_int64_t ips_tooshort; /* packet too short */ + u_int64_t ips_toosmall; /* not enough data */ + u_int64_t ips_badhlen; /* ip header length < data size */ + u_int64_t ips_badlen; /* ip length < ip header length */ + u_int64_t ips_fragments; /* fragments received */ + u_int64_t ips_fragdropped; /* frags dropped (dups, out of space) */ + u_int64_t ips_fragtimeout; /* fragments timed out */ + u_int64_t ips_forward; /* packets forwarded */ + u_int64_t ips_fastforward; /* packets fast forwarded */ + u_int64_t ips_cantforward; /* packets rcvd for unreachable dest */ + u_int64_t ips_redirectsent; /* packets forwarded on same net */ + u_int64_t ips_noproto; /* unknown or unsupported protocol */ + u_int64_t ips_delivered; /* datagrams delivered to upper level*/ + u_int64_t ips_localout; /* total ip packets generated here */ + u_int64_t ips_odropped; /* lost packets due to nobufs, etc. */ + u_int64_t ips_reassembled; /* total packets reassembled ok */ + u_int64_t ips_fragmented; /* datagrams successfully fragmented */ + u_int64_t ips_ofragments; /* output fragments created */ + u_int64_t ips_cantfrag; /* don't fragment flag was set, etc. */ + u_int64_t ips_badoptions; /* error in option processing */ + u_int64_t ips_noroute; /* packets discarded due to no route */ + u_int64_t ips_badvers; /* ip version != 4 */ + u_int64_t ips_rawout; /* total raw ip packets generated */ + u_int64_t ips_toolong; /* ip length > max ip packet size */ + u_int64_t ips_notmember; /* multicasts for unregistered grps */ + u_int64_t ips_nogif; /* no match gif found */ + u_int64_t ips_badaddr; /* invalid address on header */ }; #ifdef _KERNEL Index: sys/netinet/udp_usrreq.c =================================================================== --- sys/netinet/udp_usrreq.c (revision 209358) +++ sys/netinet/udp_usrreq.c (working copy) @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ #include #include +#include #include #include @@ -79,6 +81,7 @@ #endif #include #include +#include #ifdef IPSEC #include @@ -134,6 +137,11 @@ static VNET_DEFINE(uma_zone_t, udpcb_zone); #define V_udpcb_zone VNET(udpcb_zone) +VNET_DEFINE(struct stat_header, udpstat_header) = { + .sth_version = UDPSTAT_VERSION, + .sth_len = sizeof(struct udpstat) +}; + #ifndef UDBHASHSIZE #define UDBHASHSIZE 128 #endif @@ -143,6 +151,9 @@ &VNET_NAME(udpstat), udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)"); +SYSCTL_VNET_STRUCT(_net_inet_udp, OID_AUTO, stats_header, CTLFLAG_RD, + &VNET_NAME(udpstat_header), stat_header, "UDP statistics header"); + static void udp_detach(struct socket *so); static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); @@ -804,6 +815,118 @@ udp_pcblist, "S,xinpcb", "List of active UDP sockets"); static int +udp_spcblist(SYSCTL_HANDLER_ARGS) +{ + struct inpcb_stream is; + struct inpcb_data id; + struct sbuf sbuf; + int error, i, buflen; + char *buffer; + + struct inpcb *inp, **inp_list; + struct socket *sock; + + bzero(&is, sizeof(is)); + is.is_version = INPCB_STREAM_VERSION; + + INP_INFO_RLOCK(&V_udbinfo); + is.is_gencnt = V_udbinfo.ipi_gencnt; + is.is_count = V_udbinfo.ipi_count; + INP_INFO_RUNLOCK(&V_udbinfo); + + inp_list = malloc(is.is_count * sizeof(*inp_list), M_TEMP, M_WAITOK); + if (inp_list == NULL) + return (ENOMEM); + + INP_INFO_RLOCK(&V_udbinfo); + for (inp = LIST_FIRST(V_udbinfo.ipi_listhead), i = 0; + inp != NULL && i < is.is_count; inp = LIST_NEXT(inp, inp_list)) { + INP_RLOCK(inp); + if (inp->inp_gencnt <= is.is_gencnt && + cr_canseeinpcb(req->td->td_ucred, inp) == 0) + inp_list[i++] = inp; + INP_RUNLOCK(inp); + } + INP_INFO_RUNLOCK(&V_udbinfo); + is.is_count = i; + + error = 0; + buflen = sizeof(is) + is.is_count * sizeof(id) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &is, sizeof(is)) < 0) { + error = ENOMEM; + goto out; + } + + for (i = 0; i < is.is_count; i++) { + inp = inp_list[i]; + INP_RLOCK(inp); + if (inp->inp_gencnt <= is.is_gencnt) { + bzero(&id, sizeof(id)); + id.id_gencnt = inp->inp_gencnt; + sock = inp->inp_socket; + if (sock != NULL) { + id.id_qlen = sock->so_qlen; + id.id_incqlen = sock->so_incqlen; + id.id_qlimit = sock->so_qlimit; + id.id_snd_cc = sock->so_snd.sb_cc; + id.id_snd_mcnt = sock->so_snd.sb_mcnt; + id.id_snd_ccnt = sock->so_snd.sb_ccnt; + id.id_snd_hiwat = sock->so_snd.sb_hiwat; + id.id_snd_lowat = sock->so_snd.sb_lowat; + id.id_snd_mbcnt = sock->so_snd.sb_mbcnt; + id.id_snd_mbmax = sock->so_snd.sb_mbmax; + id.id_rcv_cc = sock->so_rcv.sb_cc; + id.id_rcv_mcnt = sock->so_rcv.sb_mcnt; + id.id_rcv_ccnt = sock->so_rcv.sb_ccnt; + id.id_rcv_hiwat = sock->so_rcv.sb_hiwat; + id.id_rcv_lowat = sock->so_rcv.sb_lowat; + id.id_rcv_mbcnt = sock->so_rcv.sb_mbcnt; + id.id_rcv_mbmax = sock->so_rcv.sb_mbmax; + id.id_pcb = (u_long)sock->so_pcb; + id.id_protocol = sock->so_proto->pr_protocol; + } + id.id_flags = inp->inp_flags; + id.id_vflag = inp->inp_vflag; + id.id_lport = inp->inp_lport; + id.id_fport = inp->inp_fport; + if (inp->inp_vflag & INP_IPV4) { + bcopy(&inp->inp_laddr, &id.id_laddr, + sizeof(inp->inp_laddr)); + bcopy(&inp->inp_faddr, &id.id_faddr, + sizeof(inp->inp_faddr)); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + bcopy(&inp->in6p_laddr, &id.id_laddr, + sizeof(inp->in6p_laddr)); + bcopy(&inp->in6p_faddr, &id.id_faddr, + sizeof(inp->in6p_faddr)); + } +#endif + if (sbuf_bcat(&sbuf, &id, sizeof(id)) < 0) { + INP_RUNLOCK(inp); + error = ENOMEM; + goto out; + } + } + INP_RUNLOCK(inp); + } + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(inp_list, M_TEMP); + free(buffer, M_TEMP); + return (error); +} + +SYSCTL_PROC(_net_inet_udp, OID_AUTO, spcblist, CTLFLAG_RD|CTLTYPE_STRUCT, + 0, 0, udp_spcblist, "s,struct inpcb_data", + "List of active UDP sockets (stream)"); + +static int udp_getcred(SYSCTL_HANDLER_ARGS) { struct xucred xuc; Index: sys/netinet/igmp.c =================================================================== --- sys/netinet/igmp.c (revision 209358) +++ sys/netinet/igmp.c (working copy) @@ -65,6 +65,7 @@ #include #include #include +#include #include #include @@ -223,6 +224,12 @@ .igps_version = IGPS_VERSION_3, .igps_len = sizeof(struct igmpstat), }; + +VNET_DEFINE(struct stat_header, igmpstat_header) = { + .sth_version = IGMPSTAT_VERSION, + .sth_len = sizeof(struct igmpstat) +}; + static VNET_DEFINE(struct timeval, igmp_gsrdelay) = {10, 0}; #define V_igi_head VNET(igi_head) @@ -250,6 +257,8 @@ */ SYSCTL_VNET_STRUCT(_net_inet_igmp, IGMPCTL_STATS, stats, CTLFLAG_RW, &VNET_NAME(igmpstat), igmpstat, ""); +SYSCTL_VNET_STRUCT(_net_inet_igmp, OID_AUTO, stats_header, CTLFLAG_RD, + &VNET_NAME(igmpstat_header), stat_header, "IGMP statistics header"); SYSCTL_VNET_INT(_net_inet_igmp, OID_AUTO, recvifkludge, CTLFLAG_RW, &VNET_NAME(igmp_recvifkludge), 0, "Rewrite IGMPv1/v2 reports from 0.0.0.0 to contain subnet address"); Index: sys/netinet/sctp_pcb.c =================================================================== --- sys/netinet/sctp_pcb.c (revision 209358) +++ sys/netinet/sctp_pcb.c (working copy) @@ -5449,11 +5449,11 @@ #endif (void)SCTP_GETTIME_TIMEVAL(&tv); #if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) - SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_sec = (uint32_t) tv.tv_sec; - SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_usec = (uint32_t) tv.tv_usec; + SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.ts_sec = (u_int32_t) tv.tv_sec; + SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.ts_usec = (u_int32_t) tv.tv_usec; #else - SCTP_BASE_STAT(sctps_discontinuitytime).tv_sec = (uint32_t) tv.tv_sec; - SCTP_BASE_STAT(sctps_discontinuitytime).tv_usec = (uint32_t) tv.tv_usec; + SCTP_BASE_STAT(sctps_discontinuitytime).ts_sec = (u_int32_t) tv.tv_sec; + SCTP_BASE_STAT(sctps_discontinuitytime).ts_usec = (u_int32_t) tv.tv_usec; #endif /* init the empty list of (All) Endpoints */ LIST_INIT(&SCTP_BASE_INFO(listhead)); Index: sys/netipx/spx_usrreq.c =================================================================== --- sys/netipx/spx_usrreq.c (revision 209358) +++ sys/netipx/spx_usrreq.c (working copy) @@ -65,6 +65,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include @@ -77,8 +78,13 @@ #include #include #include +#include +#include +#include #include +#include + #include #include @@ -99,8 +105,17 @@ u_short spx_newchecks[50]; static int spx_hardnosed; static int traceallspxs = 0; +struct stat_header spx_istat_header = { + .sth_version = SPXSTAT_VERSION, + .sth_len = sizeof(struct spx_istat) +}; struct spx_istat spx_istat; +SYSCTL_STRUCT(_net_ipx_spx, OID_AUTO, stats, CTLFLAG_RW, &spx_istat, + spx_istat, "SPX Statistics (struct spx_istat, netipx/spx_var.h)"); +SYSCTL_STRUCT(_net_ipx_spx, OID_AUTO, stats_header, CTLFLAG_RD, + &spx_istat_header, stat_header, "SPX Statistics header"); + #define SPX_LOCK_INIT() mtx_init(&spx_mtx, "spx_mtx", NULL, MTX_DEF) #define SPX_LOCK() mtx_lock(&spx_mtx) #define SPX_UNLOCK() mtx_unlock(&spx_mtx) Index: sys/netipx/ipx_var.h =================================================================== --- sys/netipx/ipx_var.h (revision 209358) +++ sys/netipx/ipx_var.h (working copy) @@ -67,18 +67,20 @@ /* * IPX Kernel Structures and Variables */ +#define IPXSTAT_VERSION 0x00000001 + struct ipxstat { - u_long ipxs_total; /* total packets received */ - u_long ipxs_badsum; /* checksum bad */ - u_long ipxs_tooshort; /* packet too short */ - u_long ipxs_toosmall; /* not enough data */ - u_long ipxs_forward; /* packets forwarded */ - u_long ipxs_cantforward; /* packets rcvd for unreachable dest */ - u_long ipxs_delivered; /* datagrams delivered to upper level*/ - u_long ipxs_localout; /* total ipx packets generated here */ - u_long ipxs_odropped; /* lost packets due to nobufs, etc. */ - u_long ipxs_noroute; /* packets discarded due to no route */ - u_long ipxs_mtutoosmall; /* the interface mtu is too small */ + u_int64_t ipxs_total; /* total packets received */ + u_int64_t ipxs_badsum; /* checksum bad */ + u_int64_t ipxs_tooshort; /* packet too short */ + u_int64_t ipxs_toosmall; /* not enough data */ + u_int64_t ipxs_forward; /* packets forwarded */ + u_int64_t ipxs_cantforward; /* packets rcvd for unreachable dest */ + u_int64_t ipxs_delivered; /* datagrams delivered to upper level*/ + u_int64_t ipxs_localout; /* total ipx packets generated here */ + u_int64_t ipxs_odropped; /* lost packets due to nobufs, etc. */ + u_int64_t ipxs_noroute; /* packets discarded due to no route */ + u_int64_t ipxs_mtutoosmall; /* the interface mtu is too small */ }; #ifdef _KERNEL Index: sys/netipx/ipx_input.c =================================================================== --- sys/netipx/ipx_input.c (revision 209358) +++ sys/netipx/ipx_input.c (working copy) @@ -75,10 +75,12 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -115,7 +117,17 @@ .s_host[1] = 0xffff, .s_host[2] = 0xffff }; +struct stat_header ipxstat_header = { + .sth_version = IPXSTAT_VERSION, + .sth_len = sizeof(struct ipxstat) +}; struct ipxstat ipxstat; + +SYSCTL_STRUCT(_net_ipx_ipx, OID_AUTO, stats, CTLFLAG_RW, &ipxstat, ipxstat, + "IPX Statistics (struct ipxstat, netipx/ipx_var.h)"); +SYSCTL_STRUCT(_net_ipx_ipx, OID_AUTO, stats_header, CTLFLAG_RD, + &ipxstat_header, stat_header, "IPX Statistics header"); + struct sockaddr_ipx ipx_netmask, ipx_hostmask; /* Index: sys/netipx/spx_var.h =================================================================== --- sys/netipx/spx_var.h (revision 209358) +++ sys/netipx/spx_var.h (working copy) @@ -64,71 +64,73 @@ #ifndef _NETIPX_SPX_VAR_H_ #define _NETIPX_SPX_VAR_H_ +#define SPXSTAT_VERSION 0x00000001 + struct spxstat { - long spxs_connattempt; /* connections initiated */ - long spxs_accepts; /* connections accepted */ - long spxs_connects; /* connections established */ - long spxs_drops; /* connections dropped */ - long spxs_conndrops; /* embryonic connections dropped */ - long spxs_closed; /* conn. closed (includes drops) */ - long spxs_segstimed; /* segs where we tried to get rtt */ - long spxs_rttupdated; /* times we succeeded */ - long spxs_delack; /* delayed acks sent */ - long spxs_timeoutdrop; /* conn. dropped in rxmt timeout */ - long spxs_rexmttimeo; /* retransmit timeouts */ - long spxs_persisttimeo; /* persist timeouts */ - long spxs_keeptimeo; /* keepalive timeouts */ - long spxs_keepprobe; /* keepalive probes sent */ - long spxs_keepdrops; /* connections dropped in keepalive */ + u_int64_t spxs_connattempt; /* connections initiated */ + u_int64_t spxs_accepts; /* connections accepted */ + u_int64_t spxs_connects; /* connections established */ + u_int64_t spxs_drops; /* connections dropped */ + u_int64_t spxs_conndrops; /* embryonic connections dropped */ + u_int64_t spxs_closed; /* conn. closed (includes drops) */ + u_int64_t spxs_segstimed; /* segs where we tried to get rtt */ + u_int64_t spxs_rttupdated; /* times we succeeded */ + u_int64_t spxs_delack; /* delayed acks sent */ + u_int64_t spxs_timeoutdrop; /* conn. dropped in rxmt timeout */ + u_int64_t spxs_rexmttimeo; /* retransmit timeouts */ + u_int64_t spxs_persisttimeo; /* persist timeouts */ + u_int64_t spxs_keeptimeo; /* keepalive timeouts */ + u_int64_t spxs_keepprobe; /* keepalive probes sent */ + u_int64_t spxs_keepdrops; /* connections dropped in keepalive */ - long spxs_sndtotal; /* total packets sent */ - long spxs_sndpack; /* data packets sent */ - long spxs_sndbyte; /* data bytes sent */ - long spxs_sndrexmitpack; /* data packets retransmitted */ - long spxs_sndrexmitbyte; /* data bytes retransmitted */ - long spxs_sndacks; /* ack-only packets sent */ - long spxs_sndprobe; /* window probes sent */ - long spxs_sndurg; /* packets sent with URG only */ - long spxs_sndwinup; /* window update-only packets sent */ - long spxs_sndctrl; /* control (SYN|FIN|RST) packets sent */ - long spxs_sndvoid; /* couldn't find requested packet*/ + u_int64_t spxs_sndtotal; /* total packets sent */ + u_int64_t spxs_sndpack; /* data packets sent */ + u_int64_t spxs_sndbyte; /* data bytes sent */ + u_int64_t spxs_sndrexmitpack; /* data packets retransmitted */ + u_int64_t spxs_sndrexmitbyte; /* data bytes retransmitted */ + u_int64_t spxs_sndacks; /* ack-only packets sent */ + u_int64_t spxs_sndprobe; /* window probes sent */ + u_int64_t spxs_sndurg; /* packets sent with URG only */ + u_int64_t spxs_sndwinup; /* window update-only packets sent */ + u_int64_t spxs_sndctrl; /* control (SYN|FIN|RST) packets sent */ + u_int64_t spxs_sndvoid; /* couldn't find requested packet*/ - long spxs_rcvtotal; /* total packets received */ - long spxs_rcvpack; /* packets received in sequence */ - long spxs_rcvbyte; /* bytes received in sequence */ - long spxs_rcvbadsum; /* packets received with ccksum errs */ - long spxs_rcvbadoff; /* packets received with bad offset */ - long spxs_rcvshort; /* packets received too short */ - long spxs_rcvduppack; /* duplicate-only packets received */ - long spxs_rcvdupbyte; /* duplicate-only bytes received */ - long spxs_rcvpartduppack; /* packets with some duplicate data */ - long spxs_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ - long spxs_rcvoopack; /* out-of-order packets received */ - long spxs_rcvoobyte; /* out-of-order bytes received */ - long spxs_rcvpackafterwin; /* packets with data after window */ - long spxs_rcvbyteafterwin; /* bytes rcvd after window */ - long spxs_rcvafterclose; /* packets rcvd after "close" */ - long spxs_rcvwinprobe; /* rcvd window probe packets */ - long spxs_rcvdupack; /* rcvd duplicate acks */ - long spxs_rcvacktoomuch; /* rcvd acks for unsent data */ - long spxs_rcvackpack; /* rcvd ack packets */ - long spxs_rcvackbyte; /* bytes acked by rcvd acks */ - long spxs_rcvwinupd; /* rcvd window update packets */ + u_int64_t spxs_rcvtotal; /* total packets received */ + u_int64_t spxs_rcvpack; /* packets received in sequence */ + u_int64_t spxs_rcvbyte; /* bytes received in sequence */ + u_int64_t spxs_rcvbadsum; /* packets received with ccksum errs */ + u_int64_t spxs_rcvbadoff; /* packets received with bad offset */ + u_int64_t spxs_rcvshort; /* packets received too short */ + u_int64_t spxs_rcvduppack; /* duplicate-only packets received */ + u_int64_t spxs_rcvdupbyte; /* duplicate-only bytes received */ + u_int64_t spxs_rcvpartduppack; /* packets with some duplicate data */ + u_int64_t spxs_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ + u_int64_t spxs_rcvoopack; /* out-of-order packets received */ + u_int64_t spxs_rcvoobyte; /* out-of-order bytes received */ + u_int64_t spxs_rcvpackafterwin; /* packets with data after window */ + u_int64_t spxs_rcvbyteafterwin; /* bytes rcvd after window */ + u_int64_t spxs_rcvafterclose; /* packets rcvd after "close" */ + u_int64_t spxs_rcvwinprobe; /* rcvd window probe packets */ + u_int64_t spxs_rcvdupack; /* rcvd duplicate acks */ + u_int64_t spxs_rcvacktoomuch; /* rcvd acks for unsent data */ + u_int64_t spxs_rcvackpack; /* rcvd ack packets */ + u_int64_t spxs_rcvackbyte; /* bytes acked by rcvd acks */ + u_int64_t spxs_rcvwinupd; /* rcvd window update packets */ }; struct spx_istat { - short hdrops; - short badsum; - short badlen; - short slotim; - short fastim; - short nonucn; - short noconn; - short notme; - short wrncon; - short bdreas; - short gonawy; - short notyet; - short lstdup; + u_int64_t hdrops; + u_int64_t badsum; + u_int64_t badlen; + u_int64_t slotim; + u_int64_t fastim; + u_int64_t nonucn; + u_int64_t noconn; + u_int64_t notme; + u_int64_t wrncon; + u_int64_t bdreas; + u_int64_t gonawy; + u_int64_t notyet; + u_int64_t lstdup; struct spxstat newstats; }; @@ -144,6 +146,11 @@ #define SSEQ_GEQ(a,b) (((short)((a)-(b))) >= 0) #ifdef _KERNEL + +#ifdef SYSCTL_DECL +SYSCTL_DECL(_net_ipx_spx); +#endif + /* Following was struct spxstat spxstat; */ #ifndef spxstat #define spxstat spx_istat.newstats Index: sys/net/bpf.c =================================================================== --- sys/net/bpf.c (revision 209358) +++ sys/net/bpf.c (working copy) @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -162,6 +163,7 @@ static int filt_bpfread(struct knote *, long); static void bpf_drvinit(void *); static int bpf_stats_sysctl(SYSCTL_HANDLER_ARGS); +static int bpf_sstats_sysctl(SYSCTL_HANDLER_ARGS); SYSCTL_NODE(_net, OID_AUTO, bpf, CTLFLAG_RW, 0, "bpf sysctl"); int bpf_maxinsns = BPF_MAXINSNS; @@ -172,6 +174,9 @@ &bpf_zerocopy_enable, 0, "Enable new zero-copy BPF buffer sessions"); SYSCTL_NODE(_net_bpf, OID_AUTO, stats, CTLFLAG_MPSAFE | CTLFLAG_RW, bpf_stats_sysctl, "bpf statistics portal"); +SYSCTL_PROC(_net_bpf, OID_AUTO, sstats, CTLFLAG_RD | CTLTYPE_STRUCT, + 0, 0, bpf_sstats_sysctl, "s,struct bpfd_data", + "bpf statistics portal (streamed)"); static d_open_t bpfopen; static d_read_t bpfread; @@ -2486,6 +2491,87 @@ return (error); } +static int +bpf_sstats_sysctl(SYSCTL_HANDLER_ARGS) +{ + int error, i, buflen; + char *buffer; + struct bpf_if *bp; + struct bpf_d *bd, **bd_list; + + struct bpfd_stream bps; + struct bpfd_data bpd; + struct sbuf sbuf; + + error = priv_check(req->td, PRIV_NET_BPF); + if (error != 0) + return (error); + + bzero(&bps, sizeof(bps)); + bps.bps_version = BPFD_STREAM_VERSION; + bps.bps_count = bpf_bpfd_cnt; + + bd_list = malloc(bps.bps_count * sizeof(*bd_list), M_TEMP, M_WAITOK); + if (bd_list == NULL) + return (ENOMEM); + + i = 0; + mtx_lock(&bpf_mtx); + LIST_FOREACH(bp, &bpf_iflist, bif_next) { + BPFIF_LOCK(bp); + LIST_FOREACH(bd, &bp->bif_dlist, bd_next) { + BPFD_LOCK(bd); + bd_list[i++] = bd; + BPFD_UNLOCK(bd); + } + BPFIF_UNLOCK(bp); + } + mtx_unlock(&bpf_mtx); + bps.bps_count = i; + + buflen = sizeof(bps) + bps.bps_count * sizeof(bpd) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &bps, sizeof(bps)) < 0) { + error = ENOMEM; + goto out; + } + + for (i = 0; i < bps.bps_count; i++) { + bd = bd_list[i]; + bzero(&bpd, sizeof(bpd)); + BPFD_LOCK(bd); + bpd.bpd_promisc = bd->bd_promisc; + bpd.bpd_immediate = bd->bd_immediate; + bpd.bpd_hdrcmplt = bd->bd_hdrcmplt; + bpd.bpd_direction = bd->bd_direction; + bpd.bpd_feedback = bd->bd_feedback; + bpd.bpd_async = bd->bd_async; + bpd.bpd_locked = bd->bd_locked; + bpd.bpd_slen = bd->bd_slen; + bpd.bpd_hlen = bd->bd_hlen; + bpd.bpd_rcount = bd->bd_rcount; + bpd.bpd_dcount = bd->bd_dcount; + bpd.bpd_fcount = bd->bd_fcount; + bpd.bpd_pid = bd->bd_pid; + bcopy(bd->bd_bif->bif_ifp->if_xname, bpd.bpd_ifname, + sizeof(bpd.bpd_ifname)); + BPFD_UNLOCK(bd); + if (sbuf_bcat(&sbuf, &bpd, sizeof(bpd)) < 0) { + error = ENOMEM; + goto out; + } + } + + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(bd_list, M_TEMP); + free(buffer, M_TEMP); + return (error); +} + SYSINIT(bpfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,bpf_drvinit,NULL); #else /* !DEV_BPF && !NETGRAPH_BPF */ Index: sys/net/bpfdesc.h =================================================================== --- sys/net/bpfdesc.h (revision 209358) +++ sys/net/bpfdesc.h (working copy) @@ -147,4 +147,34 @@ #define BPFIF_LOCK(bif) mtx_lock(&(bif)->bif_mtx) #define BPFIF_UNLOCK(bif) mtx_unlock(&(bif)->bif_mtx) +/* + * Structures for exporting BPF statistics for user-space monitoring tools. + */ + +#define BPFD_STREAM_VERSION 0x00000001 + +struct bpfd_stream { + u_int32_t bps_version; + u_int64_t bps_count; + u_int8_t _bps_pad[4]; +}; + +struct bpfd_data { + u_int8_t bpd_promisc; + u_int8_t bpd_immediate; + u_int8_t bpd_hdrcmplt; + u_int8_t bpd_direction; + u_int8_t bpd_feedback; + u_int8_t bpd_async; + u_int8_t bpd_locked; + u_int32_t bpd_slen; + u_int32_t bpd_hlen; + u_int64_t bpd_rcount; + u_int64_t bpd_dcount; + u_int64_t bpd_fcount; + u_int32_t bpd_pid; + char bpd_ifname[16]; /* IFNAMSIZ */ + u_int8_t _bpd_pad[5]; +}; + #endif Index: sys/net/route.c =================================================================== --- sys/net/route.c (revision 209358) +++ sys/net/route.c (working copy) @@ -63,7 +63,9 @@ #endif #include +#include #include +#include #include @@ -88,6 +90,11 @@ &rt_add_addr_allfibs, 0, ""); TUNABLE_INT("net.add_addr_allfibs", &rt_add_addr_allfibs); +VNET_DEFINE(struct stat_header, rtstat_header) = { + .sth_version = RTSTAT_VERSION, + .sth_len = sizeof(struct rtstat) +}; + VNET_DEFINE(struct rtstat, rtstat); #define V_rtstat VNET(rtstat) @@ -97,7 +104,15 @@ VNET_DEFINE(int, rttrash); /* routes not in table but not freed */ #define V_rttrash VNET(rttrash) +SYSCTL_VNET_STRUCT(_net_inet_ip, OID_AUTO, rtstat, CTLFLAG_RW, + &VNET_NAME(rtstat), rtstat, + "IPv4 Forwarding Statistics (struct rtstat, net/route.h)"); +SYSCTL_VNET_STRUCT(_net_inet_ip, OID_AUTO, rtstat_header, CTLFLAG_RD, + &VNET_NAME(rtstat_header), stat_header, + "IPv4 Forwarding Statistics header"); + + /* compare two sockaddr structures */ #define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0) @@ -506,7 +521,7 @@ { struct rtentry *rt, *rt0 = NULL; int error = 0; - short *stat = NULL; + u_int64_t *stat = NULL; struct rt_addrinfo info; struct ifaddr *ifa; struct radix_node_head *rnh; Index: sys/net/route.h =================================================================== --- sys/net/route.h (revision 209358) +++ sys/net/route.h (working copy) @@ -210,12 +210,15 @@ /* * Routing statistics. */ +#define RTSTAT_VERSION 0x00000001 + struct rtstat { - short rts_badredirect; /* bogus redirect calls */ - short rts_dynamic; /* routes created by redirects */ - short rts_newgateway; /* routes modified by redirects */ - short rts_unreach; /* lookups which failed */ - short rts_wildcard; /* lookups satisfied by a wildcard */ + u_int64_t rts_badredirect; /* bogus redirect calls */ + u_int64_t rts_dynamic; /* routes created by redirects */ + u_int64_t rts_newgateway; /* routes modified by redirects */ + u_int64_t rts_unreach; /* lookups which failed */ + u_int64_t rts_wildcard; /* lookups satisfied by a wildcard */ + u_int64_t rts_trash; /* routes not in table but not freed */ }; /* * Structures for routing messages. Index: sys/net/stat.h =================================================================== --- sys/net/stat.h (revision 0) +++ sys/net/stat.h (revision 0) @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2010 Gabor Pali + * 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. + * + * 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$ + */ + +#ifndef _NET_STAT_H_ +#define _NET_STAT_H_ + +struct stat_header { + const u_int32_t sth_version; + const u_int32_t sth_len; +}; + +/* Timestamp type. */ +struct timestamp_type { + u_int32_t ts_sec; + u_int32_t ts_usec; +}; + +#endif /* !_NET_STAT_H_ */ Index: sys/netinet6/ip6_mroute.h =================================================================== --- sys/netinet6/ip6_mroute.h (revision 209358) +++ sys/netinet6/ip6_mroute.h (working copy) @@ -120,20 +120,22 @@ /* * The kernel's multicast routing statistics. */ +#define MRT6STAT_VERSION 0x00000001 + struct mrt6stat { - u_quad_t mrt6s_mfc_lookups; /* # forw. cache hash table hits */ - u_quad_t mrt6s_mfc_misses; /* # forw. cache hash table misses */ - u_quad_t mrt6s_upcalls; /* # calls to multicast routing daemon */ - u_quad_t mrt6s_no_route; /* no route for packet's origin */ - u_quad_t mrt6s_bad_tunnel; /* malformed tunnel options */ - u_quad_t mrt6s_cant_tunnel; /* no room for tunnel options */ - u_quad_t mrt6s_wrong_if; /* arrived on wrong interface */ - u_quad_t mrt6s_upq_ovflw; /* upcall Q overflow */ - u_quad_t mrt6s_cache_cleanups; /* # entries with no upcalls */ - u_quad_t mrt6s_drop_sel; /* pkts dropped selectively */ - u_quad_t mrt6s_q_overflow; /* pkts dropped - Q overflow */ - u_quad_t mrt6s_pkt2large; /* pkts dropped - size > BKT SIZE */ - u_quad_t mrt6s_upq_sockfull; /* upcalls dropped - socket full */ + u_int64_t mrt6s_mfc_lookups; /* # forw. cache hash table hits */ + u_int64_t mrt6s_mfc_misses; /* # forw. cache hash table misses */ + u_int64_t mrt6s_upcalls; /* # calls to multicast routing daemon */ + u_int64_t mrt6s_no_route; /* no route for packet's origin */ + u_int64_t mrt6s_bad_tunnel; /* malformed tunnel options */ + u_int64_t mrt6s_cant_tunnel; /* no room for tunnel options */ + u_int64_t mrt6s_wrong_if; /* arrived on wrong interface */ + u_int64_t mrt6s_upq_ovflw; /* upcall Q overflow */ + u_int64_t mrt6s_cache_cleanups; /* # entries with no upcalls */ + u_int64_t mrt6s_drop_sel; /* pkts dropped selectively */ + u_int64_t mrt6s_q_overflow; /* pkts dropped - Q overflow */ + u_int64_t mrt6s_pkt2large; /* pkts dropped - size > BKT SIZE */ + u_int64_t mrt6s_upq_sockfull; /* upcalls dropped - socket full */ }; #ifdef MRT6_OINIT @@ -199,6 +201,25 @@ u_quad_t obytes; /* Output byte count on mif */ }; +#define MIF6_STREAM_VERSION 0x00000001 + +struct mif6_stream { + u_int32_t ms_version; + u_int32_t ms_count; +}; + +struct mif6_data { + u_int8_t md_flags; + u_int16_t md_rate_limit; + u_int8_t md_lcl_addr[16]; /* 128-bit IP6 address */ + u_int32_t md_if_index; + u_int64_t md_pkt_in; + u_int64_t md_pkt_out; + u_int64_t md_bytes_in; + u_int64_t md_bytes_out; + u_int8_t _md_pad[9]; +}; + #if defined(_KERNEL) || defined(KERNEL) /* * The kernel's multicast-interface structure. @@ -239,6 +260,24 @@ #define MF6C_INCOMPLETE_PARENT ((mifi_t)-1) +#define MF6C_STREAM_VERSION 0x00000001 + +struct mf6c_stream { + u_int32_t ms_version; + u_int32_t ms_count; +}; + +struct mf6c_data { + u_int8_t md_origin[16]; /* 128-bit IP6 address */ + u_int8_t md_mcastgrp[16]; /* 128-bit IP6 address */ + u_int64_t md_pkt_cnt; + u_int64_t md_byte_cnt; + u_int64_t md_nstall; + u_int32_t md_parent; + u_int32_t md_ifs_bits[8]; + u_int8_t _md_pad[36]; +}; + /* * Argument structure used for pkt info. while upcall is made */ Index: sys/netinet6/raw_ip6.c =================================================================== --- sys/netinet6/raw_ip6.c (revision 209358) +++ sys/netinet6/raw_ip6.c (working copy) @@ -84,6 +84,7 @@ #include #include #include +#include #include #include @@ -119,6 +120,11 @@ #define V_ripcb VNET(ripcb) #define V_ripcbinfo VNET(ripcbinfo) +VNET_DEFINE(struct stat_header, rip6stat_header) = { + .sth_version = RIP6STAT_VERSION, + .sth_len = sizeof(struct rip6stat) +}; + extern u_long rip_sendspace; extern u_long rip_recvspace; Index: sys/netinet6/in6_var.h =================================================================== --- sys/netinet6/in6_var.h (revision 209358) +++ sys/netinet6/in6_var.h (working copy) @@ -489,6 +489,8 @@ VNET_DECLARE(struct in6_ifaddrhead, in6_ifaddrhead); #define V_in6_ifaddrhead VNET(in6_ifaddrhead) +VNET_DECLARE(struct stat_header, icmp6stat_header); + extern struct rwlock in6_ifaddr_lock; #define IN6_IFADDR_LOCK_ASSERT( ) rw_assert(&in6_ifaddr_lock, RA_LOCKED) #define IN6_IFADDR_RLOCK() rw_rlock(&in6_ifaddr_lock) Index: sys/netinet6/ip6_var.h =================================================================== --- sys/netinet6/ip6_var.h (revision 209358) +++ sys/netinet6/ip6_var.h (working copy) @@ -180,38 +180,40 @@ * Control options for incoming packets */ +#define IP6STAT_VERSION 0x00000001 + struct ip6stat { - u_quad_t ip6s_total; /* total packets received */ - u_quad_t ip6s_tooshort; /* packet too short */ - u_quad_t ip6s_toosmall; /* not enough data */ - u_quad_t ip6s_fragments; /* fragments received */ - u_quad_t ip6s_fragdropped; /* frags dropped(dups, out of space) */ - u_quad_t ip6s_fragtimeout; /* fragments timed out */ - u_quad_t ip6s_fragoverflow; /* fragments that exceeded limit */ - u_quad_t ip6s_forward; /* packets forwarded */ - u_quad_t ip6s_cantforward; /* packets rcvd for unreachable dest */ - u_quad_t ip6s_redirectsent; /* packets forwarded on same net */ - u_quad_t ip6s_delivered; /* datagrams delivered to upper level*/ - u_quad_t ip6s_localout; /* total ip packets generated here */ - u_quad_t ip6s_odropped; /* lost packets due to nobufs, etc. */ - u_quad_t ip6s_reassembled; /* total packets reassembled ok */ - u_quad_t ip6s_fragmented; /* datagrams successfully fragmented */ - u_quad_t ip6s_ofragments; /* output fragments created */ - u_quad_t ip6s_cantfrag; /* don't fragment flag was set, etc. */ - u_quad_t ip6s_badoptions; /* error in option processing */ - u_quad_t ip6s_noroute; /* packets discarded due to no route */ - u_quad_t ip6s_badvers; /* ip6 version != 6 */ - u_quad_t ip6s_rawout; /* total raw ip packets generated */ - u_quad_t ip6s_badscope; /* scope error */ - u_quad_t ip6s_notmember; /* don't join this multicast group */ - u_quad_t ip6s_nxthist[256]; /* next header history */ - u_quad_t ip6s_m1; /* one mbuf */ - u_quad_t ip6s_m2m[32]; /* two or more mbuf */ - u_quad_t ip6s_mext1; /* one ext mbuf */ - u_quad_t ip6s_mext2m; /* two or more ext mbuf */ - u_quad_t ip6s_exthdrtoolong; /* ext hdr are not continuous */ - u_quad_t ip6s_nogif; /* no match gif found */ - u_quad_t ip6s_toomanyhdr; /* discarded due to too many headers */ + u_int64_t ip6s_total; /* total packets received */ + u_int64_t ip6s_tooshort; /* packet too short */ + u_int64_t ip6s_toosmall; /* not enough data */ + u_int64_t ip6s_fragments; /* fragments received */ + u_int64_t ip6s_fragdropped; /* frags dropped(dups, out of space) */ + u_int64_t ip6s_fragtimeout; /* fragments timed out */ + u_int64_t ip6s_fragoverflow; /* fragments that exceeded limit */ + u_int64_t ip6s_forward; /* packets forwarded */ + u_int64_t ip6s_cantforward; /* packets rcvd for unreachable dest */ + u_int64_t ip6s_redirectsent; /* packets forwarded on same net */ + u_int64_t ip6s_delivered; /* datagrams delivered to upper level*/ + u_int64_t ip6s_localout; /* total ip packets generated here */ + u_int64_t ip6s_odropped; /* lost packets due to nobufs, etc. */ + u_int64_t ip6s_reassembled; /* total packets reassembled ok */ + u_int64_t ip6s_fragmented; /* datagrams successfully fragmented */ + u_int64_t ip6s_ofragments; /* output fragments created */ + u_int64_t ip6s_cantfrag; /* don't fragment flag was set, etc. */ + u_int64_t ip6s_badoptions; /* error in option processing */ + u_int64_t ip6s_noroute; /* packets discarded due to no route */ + u_int64_t ip6s_badvers; /* ip6 version != 6 */ + u_int64_t ip6s_rawout; /* total raw ip packets generated */ + u_int64_t ip6s_badscope; /* scope error */ + u_int64_t ip6s_notmember; /* don't join this multicast group */ + u_int64_t ip6s_nxthist[256]; /* next header history */ + u_int64_t ip6s_m1; /* one mbuf */ + u_int64_t ip6s_m2m[32]; /* two or more mbuf */ + u_int64_t ip6s_mext1; /* one ext mbuf */ + u_int64_t ip6s_mext2m; /* two or more ext mbuf */ + u_int64_t ip6s_exthdrtoolong; /* ext hdr are not continuous */ + u_int64_t ip6s_nogif; /* no match gif found */ + u_int64_t ip6s_toomanyhdr; /* discarded due to too many headers */ /* * statistics for improvement of the source address selection @@ -219,26 +221,26 @@ * XXX: hardcoded 16 = # of ip6 multicast scope types + 1 */ /* number of times that address selection fails */ - u_quad_t ip6s_sources_none; + u_int64_t ip6s_sources_none; /* number of times that an address on the outgoing I/F is chosen */ - u_quad_t ip6s_sources_sameif[16]; + u_int64_t ip6s_sources_sameif[16]; /* number of times that an address on a non-outgoing I/F is chosen */ - u_quad_t ip6s_sources_otherif[16]; + u_int64_t ip6s_sources_otherif[16]; /* * number of times that an address that has the same scope * from the destination is chosen. */ - u_quad_t ip6s_sources_samescope[16]; + u_int64_t ip6s_sources_samescope[16]; /* * number of times that an address that has a different scope * from the destination is chosen. */ - u_quad_t ip6s_sources_otherscope[16]; + u_int64_t ip6s_sources_otherscope[16]; /* number of times that a deprecated address is chosen */ - u_quad_t ip6s_sources_deprecated[16]; + u_int64_t ip6s_sources_deprecated[16]; /* number of times that each rule of source selection is applied. */ - u_quad_t ip6s_sources_rule[16]; + u_int64_t ip6s_sources_rule[16]; }; #ifdef _KERNEL @@ -292,6 +294,7 @@ #endif VNET_DECLARE(struct ip6stat, ip6stat); /* statistics */ +VNET_DECLARE(struct stat_header, ip6stat_header); VNET_DECLARE(int, ip6_defhlim); /* default hop limit */ VNET_DECLARE(int, ip6_defmcasthlim); /* default multicast hop limit */ VNET_DECLARE(int, ip6_forwarding); /* act as router? */ Index: sys/netinet6/raw_ip6.h =================================================================== --- sys/netinet6/raw_ip6.h (revision 209358) +++ sys/netinet6/raw_ip6.h (working copy) @@ -36,20 +36,27 @@ /* * ICMPv6 stat is counted separately. see netinet/icmp6.h */ + +#define RIP6STAT_VERSION 0x00000001 + struct rip6stat { - u_quad_t rip6s_ipackets; /* total input packets */ - u_quad_t rip6s_isum; /* input checksum computations */ - u_quad_t rip6s_badsum; /* of above, checksum error */ - u_quad_t rip6s_nosock; /* no matching socket */ - u_quad_t rip6s_nosockmcast; /* of above, arrived as multicast */ - u_quad_t rip6s_fullsock; /* not delivered, input socket full */ + u_int64_t rip6s_ipackets; /* total input packets */ + u_int64_t rip6s_isum; /* input checksum computations */ + u_int64_t rip6s_badsum; /* of above, checksum error */ + u_int64_t rip6s_nosock; /* no matching socket */ + u_int64_t rip6s_nosockmcast; /* of above, arrived as multicast */ + u_int64_t rip6s_fullsock; /* not delivered, input socket full */ - u_quad_t rip6s_opackets; /* total output packets */ + u_int64_t rip6s_opackets; /* total output packets */ + u_int64_t rip6s_delivered; /* derived field */ }; #ifdef _KERNEL + VNET_DECLARE(struct rip6stat, rip6stat); +VNET_DECLARE(struct stat_header, rip6stat_header); #define V_rip6stat VNET(rip6stat) + #endif #endif Index: sys/netinet6/icmp6.c =================================================================== --- sys/netinet6/icmp6.c (revision 209358) +++ sys/netinet6/icmp6.c (working copy) @@ -90,6 +90,7 @@ #include #include #include +#include #include #include @@ -129,6 +130,11 @@ #define V_icmp6errppslim_last VNET(icmp6errppslim_last) #define V_icmp6_nodeinfo VNET(icmp6_nodeinfo) +VNET_DEFINE(struct stat_header, icmp6stat_header) = { + .sth_version = ICMP6STAT_VERSION, + .sth_len = sizeof(struct icmp6stat) +}; + static void icmp6_errcount(struct icmp6errstat *, int, int); static int icmp6_rip6_input(struct mbuf **, int); static int icmp6_ratelimit(const struct in6_addr *, const int, const int); Index: sys/netinet6/in6_proto.c =================================================================== --- sys/netinet6/in6_proto.c (revision 209358) +++ sys/netinet6/in6_proto.c (working copy) @@ -521,6 +521,8 @@ &VNET_NAME(ip6_defhlim), 0, ""); SYSCTL_VNET_STRUCT(_net_inet6_ip6, IPV6CTL_STATS, stats, CTLFLAG_RD, &VNET_NAME(ip6stat), ip6stat, ""); +SYSCTL_VNET_STRUCT(_net_inet6_ip6, OID_AUTO, stats_header, CTLFLAG_RD, + &VNET_NAME(ip6stat_header), stat_header, ""); SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS, maxfragpackets, CTLFLAG_RW, &VNET_NAME(ip6_maxfragpackets), 0, ""); SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_ACCEPT_RTADV, accept_rtadv, @@ -553,14 +555,17 @@ SYSCTL_VNET_PROC(_net_inet6_ip6, IPV6CTL_TEMPVLTIME, tempvltime, CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(ip6_temp_valid_lifetime), 0, sysctl_ip6_tempvltime, "I", ""); + SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_V6ONLY, v6only, CTLFLAG_RW, &VNET_NAME(ip6_v6only), 0, ""); SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_AUTO_LINKLOCAL, auto_linklocal, CTLFLAG_RW, &VNET_NAME(ip6_auto_linklocal), 0, "Default value of per-interface flag for automatically adding an IPv6" " link-local address to interfaces when attached"); -SYSCTL_VNET_STRUCT(_net_inet6_ip6, IPV6CTL_RIP6STATS, rip6stats, CTLFLAG_RD, - &VNET_NAME(rip6stat), rip6stat, ""); +SYSCTL_VNET_STRUCT(_net_inet6_ip6, IPV6CTL_RIP6STATS, rip6stats, CTLFLAG_RW, + &VNET_NAME(rip6stat), rip6stat, "RIP6 Statistics"); +SYSCTL_VNET_STRUCT(_net_inet6_ip6, OID_AUTO, rip6stats_header, CTLFLAG_RD, + &VNET_NAME(rip6stat_header), stat_header, "RIP6 Statistics header"); SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_PREFER_TEMPADDR, prefer_tempaddr, CTLFLAG_RW, &VNET_NAME(ip6_prefer_tempaddr), 0, ""); SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_USE_DEFAULTZONE, use_defaultzone, @@ -569,6 +574,7 @@ &VNET_NAME(ip6_maxfrags), 0, ""); SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MCAST_PMTU, mcast_pmtu, CTLFLAG_RW, &VNET_NAME(ip6_mcast_pmtu), 0, ""); + #ifdef IPSTEALTH SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_STEALTH, stealth, CTLFLAG_RW, &VNET_NAME(ip6stealth), 0, ""); @@ -589,8 +595,10 @@ CTLFLAG_RW, &VNET_NAME(icmp6_rediraccept), 0, ""); SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRTIMEOUT, redirtimeout, CTLFLAG_RW, &VNET_NAME(icmp6_redirtimeout), 0, ""); -SYSCTL_VNET_STRUCT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats, CTLFLAG_RD, - &VNET_NAME(icmp6stat), icmp6stat, ""); +SYSCTL_VNET_STRUCT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats, CTLFLAG_RW, + &VNET_NAME(icmp6stat), icmp6stat, "ICMP6 Statistics"); +SYSCTL_VNET_STRUCT(_net_inet6_icmp6, OID_AUTO, stats_header, CTLFLAG_RD, + &VNET_NAME(icmp6stat_header), stat_header, "ICMP6 Statistics header"); SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PRUNE, nd6_prune, CTLFLAG_RW, &VNET_NAME(nd6_prune), 0, ""); SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DELAY, nd6_delay, CTLFLAG_RW, Index: sys/netinet6/pim6_var.h =================================================================== --- sys/netinet6/pim6_var.h (revision 209358) +++ sys/netinet6/pim6_var.h (working copy) @@ -41,14 +41,16 @@ #ifndef _NETINET6_PIM6_VAR_H_ #define _NETINET6_PIM6_VAR_H_ +#define PIM6STAT_VERSION 0x00000001 + struct pim6stat { - u_quad_t pim6s_rcv_total; /* total PIM messages received */ - u_quad_t pim6s_rcv_tooshort; /* received with too few bytes */ - u_quad_t pim6s_rcv_badsum; /* received with bad checksum */ - u_quad_t pim6s_rcv_badversion; /* received bad PIM version */ - u_quad_t pim6s_rcv_registers; /* received registers */ - u_quad_t pim6s_rcv_badregisters; /* received invalid registers */ - u_quad_t pim6s_snd_registers; /* sent registers */ + u_int64_t pim6s_rcv_total; /* total PIM messages received */ + u_int64_t pim6s_rcv_tooshort; /* received with too few bytes */ + u_int64_t pim6s_rcv_badsum; /* received with bad checksum */ + u_int64_t pim6s_rcv_badversion; /* received bad PIM version */ + u_int64_t pim6s_rcv_registers; /* received registers */ + u_int64_t pim6s_rcv_badregisters; /* received invalid registers */ + u_int64_t pim6s_snd_registers; /* sent registers */ }; #if (defined(KERNEL)) || (defined(_KERNEL)) Index: sys/netinet6/ip6_input.c =================================================================== --- sys/netinet6/ip6_input.c (revision 209358) +++ sys/netinet6/ip6_input.c (working copy) @@ -89,6 +89,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,10 @@ VNET_DEFINE(struct pfil_head, inet6_pfil_hook); VNET_DEFINE(struct ip6stat, ip6stat); +VNET_DEFINE(struct stat_header, ip6stat_header) = { + .sth_version = IP6STAT_VERSION, + .sth_len = sizeof(struct ip6stat) +}; struct rwlock in6_ifaddr_lock; RW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock"); Index: sys/netinet6/ip6_mroute.c =================================================================== --- sys/netinet6/ip6_mroute.c (revision 209358) +++ sys/netinet6/ip6_mroute.c (working copy) @@ -94,6 +94,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,7 @@ #include #include #include +#include #include #include @@ -158,10 +160,17 @@ SYSCTL_DECL(_net_inet6_ip6); SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); +static struct stat_header mrt6stat_header = { + .sth_version = MRT6STAT_VERSION, + .sth_len = sizeof(struct mrt6stat) +}; static struct mrt6stat mrt6stat; SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW, &mrt6stat, mrt6stat, "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)"); +SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat_header, CTLFLAG_RD, + &mrt6stat_header, stat_header, + "Multicast Routing Statistics header"); #define NO_RTE_FOUND 0x1 #define RTE_FOUND 0x2 @@ -249,10 +258,16 @@ static mifi_t nummifs = 0; static mifi_t reg_mif_num = (mifi_t)-1; +static struct stat_header pim6stat_header = { + .sth_version = PIM6STAT_VERSION, + .sth_len = sizeof(struct pim6stat) +}; static struct pim6stat pim6stat; -SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RD, +SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RW, &pim6stat, pim6stat, "PIM Statistics (struct pim6stat, netinet6/pim_var.h)"); +SYSCTL_STRUCT(_net_inet6_pim, OID_AUTO, stats_header, CTLFLAG_RD, + &pim6stat_header, stat_header, "PIM Statistics header"); static VNET_DEFINE(int, pim6); #define V_pim6 VNET(pim6) @@ -505,6 +520,158 @@ } static int +sysctl_export_mif6table(SYSCTL_HANDLER_ARGS) +{ + struct mif6_stream ms; + struct mif6_data md; + struct sbuf sbuf; + int error, buflen; + char *buffer; + struct mif6* m; + mifi_t mifi; + + error = 0; + bzero(&ms, sizeof(ms)); + ms.ms_version = MIF6_STREAM_VERSION; + + MIF6_LOCK(); + + ms.ms_count = nummifs; + + MIF6_UNLOCK(); + + buflen = sizeof(ms) + ms.ms_count * sizeof(md) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + + MIF6_LOCK(); + + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &ms, sizeof(ms)) < 0) { + MIF6_UNLOCK(); + error = ENOMEM; + goto out; + } + + for (mifi = 0; mifi < min(ms.ms_count, nummifs); mifi++) { + m = &mif6table[mifi]; + + bzero(&md, sizeof(md)); + md.md_flags = m->m6_flags; + md.md_rate_limit = m->m6_rate_limit; + bcopy(&m->m6_lcl_addr, md.md_lcl_addr, sizeof(md.md_lcl_addr)); + md.md_if_index = m->m6_ifp->if_index; + md.md_pkt_in = m->m6_pkt_in; + md.md_pkt_out = m->m6_pkt_out; + md.md_bytes_in = m->m6_bytes_in; + md.md_bytes_out = m->m6_bytes_out; + + if (sbuf_bcat(&sbuf, &md, sizeof(md)) < 0) { + MIF6_UNLOCK(); + error = ENOMEM; + goto out; + } + } + + MIF6_UNLOCK(); + + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(buffer, M_TEMP); + return (error); +} + +SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, smif6table, CTLFLAG_RD|CTLTYPE_STRUCT, + 0, 0, sysctl_export_mif6table, "s,struct mif6_data", + "IPv6 Multicast Interfaces (streamed)"); + +static int +sysctl_export_mf6ctable(SYSCTL_HANDLER_ARGS) +{ + struct mf6c_stream ms; + struct mf6c_data md; + struct sbuf sbuf; + int error, buflen; + char *buffer; + struct mf6c *m; + struct rtdetq *r; + u_int32_t i, j; + + error = 0; + bzero(&ms, sizeof(ms)); + ms.ms_version = MF6C_STREAM_VERSION; + + MFC6_LOCK(); + + /* Count entries. */ + ms.ms_count = 0; + for (i = 0; i < MF6CTBLSIZ; i++) { + for (m = mf6ctable[i]; m != NULL; m = m->mf6c_next) + ms.ms_count++; + } + + MFC6_UNLOCK(); + + buflen = sizeof(ms) + ms.ms_count * sizeof(md) + 1; + buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + + MFC6_LOCK(); + + sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN); + + if (sbuf_bcat(&sbuf, &ms, sizeof(ms)) < 0) { + MFC6_UNLOCK(); + error = ENOMEM; + goto out; + } + + j = 0; + for (i = 0; i < MF6CTBLSIZ; i++) { + for (m = mf6ctable[i]; m != NULL; m = m->mf6c_next) { + bzero(&md, sizeof(md)); + bcopy(&m->mf6c_origin.sin6_addr, md.md_origin, + sizeof(md.md_origin)); + bcopy(&m->mf6c_mcastgrp.sin6_addr, md.md_mcastgrp, + sizeof(md.md_mcastgrp)); + md.md_pkt_cnt = m->mf6c_pkt_cnt; + md.md_byte_cnt = m->mf6c_byte_cnt; + + md.md_nstall = 0; + for (r = m->mf6c_stall; r != NULL; r = r->next) + md.md_nstall++; + + md.md_parent = m->mf6c_parent; + bcopy(&m->mf6c_ifset, md.md_ifs_bits, + sizeof(md.md_ifs_bits)); + + if (sbuf_bcat(&sbuf, &md, sizeof(md)) < 0) { + MFC6_UNLOCK(); + error = ENOMEM; + goto out; + } + + if (j < ms.ms_count) + j++; + else + break; + } + } + + MFC6_UNLOCK(); + + sbuf_finish(&sbuf); + error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); +out: + free(buffer, M_TEMP); + return (error); +} + +SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, smf6ctable, CTLFLAG_RD|CTLTYPE_STRUCT, + 0, 0, sysctl_export_mf6ctable, "s,struct mf6c_data", + "IPv6 Multicast Forwarding Table (streamed)"); + +static int set_pim6(int *i) { if ((*i != 1) && (*i != 0)) Index: sys/contrib/pf/net/if_pfsync.c =================================================================== --- sys/contrib/pf/net/if_pfsync.c (revision 209358) +++ sys/contrib/pf/net/if_pfsync.c (working copy) @@ -91,6 +91,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + #ifdef INET #include #include @@ -128,12 +132,21 @@ #endif struct pfsync_softc *pfsyncif = NULL; +#ifdef __FreeBSD__ +struct stat_header pfsyncstats_header = { + .sth_version = PFSYNCSTAT_VERSION, + .sth_len = sizeof(struct pfsyncstats) +}; +#endif struct pfsyncstats pfsyncstats; #ifdef __FreeBSD__ SYSCTL_DECL(_net_inet_pfsync); SYSCTL_STRUCT(_net_inet_pfsync, 0, stats, CTLFLAG_RW, &pfsyncstats, pfsyncstats, "PFSYNC statistics (struct pfsyncstats, net/if_pfsync.h)"); + +SYSCTL_STRUCT(_net_inet_pfsync, OID_AUTO, stats_header, CTLFLAG_RD, + &pfsyncstats_header, stat_header, "PFSYNC statistics header"); #endif void pfsyncattach(int); Index: sys/contrib/pf/net/if_pfsync.h =================================================================== --- sys/contrib/pf/net/if_pfsync.h (revision 209358) +++ sys/contrib/pf/net/if_pfsync.h (working copy) @@ -249,6 +249,10 @@ #define PFSYNC_DFLTTL 255 +#ifdef __FreeBSD__ +#define PFSYNCSTAT_VERSION 0x00000001 +#endif + struct pfsyncstats { u_int64_t pfsyncs_ipackets; /* total input packets, IPv4 */ u_int64_t pfsyncs_ipackets6; /* total input packets, IPv6 */ Index: sys/netipsec/xform_ipcomp.c =================================================================== --- sys/netipsec/xform_ipcomp.c (revision 209358) +++ sys/netipsec/xform_ipcomp.c (working copy) @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ #include #include +#include #include #include @@ -71,11 +73,20 @@ VNET_DEFINE(int, ipcomp_enable) = 1; VNET_DEFINE(struct ipcompstat, ipcompstat); +VNET_DEFINE(struct stat_header, ipcompstat_header) = { + .sth_version = IPCOMPSTAT_VERSION, + .sth_len = sizeof(struct ipcompstat) +}; + SYSCTL_DECL(_net_inet_ipcomp); + SYSCTL_VNET_INT(_net_inet_ipcomp, OID_AUTO, ipcomp_enable, CTLFLAG_RW, &VNET_NAME(ipcomp_enable), 0, ""); SYSCTL_VNET_STRUCT(_net_inet_ipcomp, IPSECCTL_STATS, - stats, CTLFLAG_RD, &VNET_NAME(ipcompstat), ipcompstat, ""); + stats, CTLFLAG_RW, &VNET_NAME(ipcompstat), ipcompstat, ""); +SYSCTL_VNET_STRUCT(_net_inet_ipcomp, OID_AUTO, + stats_header, CTLFLAG_RD, &VNET_NAME(ipcompstat_header), + stat_header, ""); static int ipcomp_input_cb(struct cryptop *crp); static int ipcomp_output_cb(struct cryptop *crp); @@ -615,8 +626,6 @@ static void vnet_ipcomp_attach(const void *unused __unused) { - - V_ipcompstat.version = IPCOMPSTAT_VERSION; } VNET_SYSINIT(vnet_ipcomp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, Index: sys/netipsec/xform_esp.c =================================================================== --- sys/netipsec/xform_esp.c (revision 209358) +++ sys/netipsec/xform_esp.c (working copy) @@ -46,9 +46,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -79,15 +81,23 @@ VNET_DEFINE(int, esp_enable) = 1; VNET_DEFINE(struct espstat, espstat); +VNET_DEFINE(struct stat_header, espstat_header) = { + .sth_version = ESPSTAT_VERSION, + .sth_len = sizeof(struct espstat) +}; + SYSCTL_DECL(_net_inet_esp); SYSCTL_VNET_INT(_net_inet_esp, OID_AUTO, esp_enable, CTLFLAG_RW, &VNET_NAME(esp_enable), 0, ""); SYSCTL_VNET_STRUCT(_net_inet_esp, IPSECCTL_STATS, - stats, CTLFLAG_RD, &VNET_NAME(espstat), espstat, ""); + stats, CTLFLAG_RW, &VNET_NAME(espstat), espstat, ""); static VNET_DEFINE(int, esp_max_ivlen); /* max iv length over all algorithms */ #define V_esp_max_ivlen VNET(esp_max_ivlen) +SYSCTL_VNET_STRUCT(_net_inet_esp, OID_AUTO, stats_header, CTLFLAG_RD, + &VNET_NAME(espstat_header), stat_header, ""); + static int esp_input_cb(struct cryptop *op); static int esp_output_cb(struct cryptop *crp); Index: sys/netipsec/xform_ah.c =================================================================== --- sys/netipsec/xform_ah.c (revision 209358) +++ sys/netipsec/xform_ah.c (working copy) @@ -46,9 +46,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -92,13 +94,21 @@ VNET_DEFINE(int, ah_cleartos) = 1; /* clear ip_tos when doing AH calc */ VNET_DEFINE(struct ahstat, ahstat); +VNET_DEFINE(struct stat_header, ahstat_header) = { + .sth_version = AHSTAT_VERSION, + .sth_len = sizeof(struct ahstat) +}; + SYSCTL_DECL(_net_inet_ah); SYSCTL_VNET_INT(_net_inet_ah, OID_AUTO, ah_enable, CTLFLAG_RW, &VNET_NAME(ah_enable), 0, ""); SYSCTL_VNET_INT(_net_inet_ah, OID_AUTO, ah_cleartos, CTLFLAG_RW, &VNET_NAME(ah_cleartos), 0, ""); SYSCTL_VNET_STRUCT(_net_inet_ah, IPSECCTL_STATS, - stats, CTLFLAG_RD, &VNET_NAME(ahstat), ahstat, ""); + stats, CTLFLAG_RW, &VNET_NAME(ahstat), ahstat, ""); +SYSCTL_VNET_STRUCT(_net_inet_ah, OID_AUTO, + stats_header, CTLFLAG_RD, &VNET_NAME(ahstat_header), + stat_header, ""); static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */ Index: sys/netipsec/ipsec.c =================================================================== --- sys/netipsec/ipsec.c (revision 209358) +++ sys/netipsec/ipsec.c (working copy) @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,11 @@ VNET_DEFINE(int, ip4_ipsec_ecn) = 0; VNET_DEFINE(int, ip4_esp_randpad) = -1; +VNET_DEFINE(struct stat_header, ipsecstat_header) = { + .sth_version = IPSECSTAT_VERSION, + .sth_len = sizeof(struct ipsecstat) +}; + /* * Crypto support requirements: * @@ -163,9 +169,13 @@ CTLFLAG_RW, &VNET_NAME(crypto_support), 0, "Crypto driver selection."); SYSCTL_VNET_STRUCT(_net_inet_ipsec, OID_AUTO, ipsecstats, - CTLFLAG_RD, &VNET_NAME(ipsec4stat), ipsecstat, + CTLFLAG_RW, &VNET_NAME(ipsec4stat), ipsecstat, "IPsec IPv4 statistics."); +SYSCTL_VNET_STRUCT(_net_inet_ipsec, OID_AUTO, ipsecstats_header, CTLFLAG_RD, + &VNET_NAME(ipsecstat_header), stat_header, + "IPsec IPv4 statistics header."); + #ifdef REGRESSION /* * When set to 1, IPsec will send packets with the same sequence number. Index: sys/netipsec/esp_var.h =================================================================== --- sys/netipsec/esp_var.h (revision 209358) +++ sys/netipsec/esp_var.h (working copy) @@ -47,6 +47,8 @@ */ #define ESP_ALG_MAX 256 /* NB: could be < but skipjack is 249 */ +#define ESPSTAT_VERSION 0x00000001 + struct espstat { u_int32_t esps_hdrops; /* Packet shorter than header shows */ u_int32_t esps_nopf; /* Protocol family not supported */ Index: sys/netipsec/ipcomp_var.h =================================================================== --- sys/netipsec/ipcomp_var.h (revision 209358) +++ sys/netipsec/ipcomp_var.h (working copy) @@ -41,7 +41,8 @@ */ #define IPCOMP_ALG_MAX 8 -#define IPCOMPSTAT_VERSION 1 +#define IPCOMPSTAT_VERSION 0x00000001 + struct ipcompstat { u_int32_t ipcomps_hdrops; /* Packet shorter than header shows */ u_int32_t ipcomps_nopf; /* Protocol family not supported */ @@ -59,7 +60,6 @@ u_int32_t ipcomps_pdrops; /* Packet blocked due to policy */ u_int32_t ipcomps_crypto; /* "Crypto" processing failure */ u_int32_t ipcomps_hist[IPCOMP_ALG_MAX];/* Per-algorithm op count */ - u_int32_t version; /* Version of this structure. */ u_int32_t ipcomps_threshold; /* Packet < comp. algo. threshold. */ u_int32_t ipcomps_uncompr; /* Compression was useles. */ }; @@ -67,8 +67,10 @@ #ifdef _KERNEL VNET_DECLARE(int, ipcomp_enable); VNET_DECLARE(struct ipcompstat, ipcompstat); +VNET_DECLARE(struct stat_header, ipcompstat_header); #define V_ipcomp_enable VNET(ipcomp_enable) +#define V_ipcompstat_header VNET(ipcompstat_header) #define V_ipcompstat VNET(ipcompstat) #endif /* _KERNEL */ #endif /*_NETIPSEC_IPCOMP_VAR_H_*/ Index: sys/netipsec/ah_var.h =================================================================== --- sys/netipsec/ah_var.h (revision 209358) +++ sys/netipsec/ah_var.h (working copy) @@ -47,6 +47,8 @@ */ #define AH_ALG_MAX 16 +#define AHSTAT_VERSION 0x00000001 + struct ahstat { u_int32_t ahs_hdrops; /* Packet shorter than header shows */ u_int32_t ahs_nopf; /* Protocol family not supported */ Index: sys/netipsec/keysock.c =================================================================== --- sys/netipsec/keysock.c (revision 209358) +++ sys/netipsec/keysock.c (working copy) @@ -55,6 +55,7 @@ #include #include #include +#include #include @@ -69,10 +70,16 @@ struct key_cb { int key_count; int any_count; -}; +}; + static VNET_DEFINE(struct key_cb, key_cb); #define V_key_cb VNET(key_cb) +VNET_DEFINE(struct stat_header, pfkeystat_header) = { + .sth_version = PFKEYSTAT_VERSION, + .sth_len = sizeof(struct pfkeystat) +}; + static struct sockaddr key_src = { 2, PF_KEY, }; static int key_sendup0 __P((struct rawcb *, struct mbuf *, int)); @@ -541,6 +548,11 @@ /* sysctl */ SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family"); +SYSCTL_STRUCT(_net_key, OID_AUTO, stats, CTLFLAG_RW, &pfkeystat, pfkeystat, + "Key Statistics (struct pfkeystat, (netipsec/keysock.h)"); +SYSCTL_STRUCT(_net_key, OID_AUTO, stats_header, CTLFLAG_RD, &pfkeystat_header, + stat_header, "Key Statistics header"); + /* * Definitions of protocols supported in the KEY domain. */ Index: sys/netipsec/ipsec.h =================================================================== --- sys/netipsec/ipsec.h (revision 209358) +++ sys/netipsec/ipsec.h (working copy) @@ -212,36 +212,38 @@ #define IPSEC_REPLAYWSIZE 32 /* statistics for ipsec processing */ +#define IPSECSTAT_VERSION 0x00000001 + struct ipsecstat { - u_quad_t in_success; /* succeeded inbound process */ - u_quad_t in_polvio; + u_int64_t in_success; /* succeeded inbound process */ + u_int64_t in_polvio; /* security policy violation for inbound process */ - u_quad_t in_nosa; /* inbound SA is unavailable */ - u_quad_t in_inval; /* inbound processing failed due to EINVAL */ - u_quad_t in_nomem; /* inbound processing failed due to ENOBUFS */ - u_quad_t in_badspi; /* failed getting a SPI */ - u_quad_t in_ahreplay; /* AH replay check failed */ - u_quad_t in_espreplay; /* ESP replay check failed */ - u_quad_t in_ahauthsucc; /* AH authentication success */ - u_quad_t in_ahauthfail; /* AH authentication failure */ - u_quad_t in_espauthsucc; /* ESP authentication success */ - u_quad_t in_espauthfail; /* ESP authentication failure */ - u_quad_t in_esphist[256]; - u_quad_t in_ahhist[256]; - u_quad_t in_comphist[256]; - u_quad_t out_success; /* succeeded outbound process */ - u_quad_t out_polvio; + u_int64_t in_nosa; /* inbound SA is unavailable */ + u_int64_t in_inval; /* inbound processing failed due to EINVAL */ + u_int64_t in_nomem; /* inbound processing failed due to ENOBUFS */ + u_int64_t in_badspi; /* failed getting a SPI */ + u_int64_t in_ahreplay; /* AH replay check failed */ + u_int64_t in_espreplay; /* ESP replay check failed */ + u_int64_t in_ahauthsucc; /* AH authentication success */ + u_int64_t in_ahauthfail; /* AH authentication failure */ + u_int64_t in_espauthsucc; /* ESP authentication success */ + u_int64_t in_espauthfail; /* ESP authentication failure */ + u_int64_t in_esphist[256]; + u_int64_t in_ahhist[256]; + u_int64_t in_comphist[256]; + u_int64_t out_success; /* succeeded outbound process */ + u_int64_t out_polvio; /* security policy violation for outbound process */ - u_quad_t out_nosa; /* outbound SA is unavailable */ - u_quad_t out_inval; /* outbound process failed due to EINVAL */ - u_quad_t out_nomem; /* inbound processing failed due to ENOBUFS */ - u_quad_t out_noroute; /* there is no route */ - u_quad_t out_esphist[256]; - u_quad_t out_ahhist[256]; - u_quad_t out_comphist[256]; + u_int64_t out_nosa; /* outbound SA is unavailable */ + u_int64_t out_inval; /* outbound process failed due to EINVAL */ + u_int64_t out_nomem; /* inbound processing failed due to ENOBUFS */ + u_int64_t out_noroute; /* there is no route */ + u_int64_t out_esphist[256]; + u_int64_t out_ahhist[256]; + u_int64_t out_comphist[256]; - u_quad_t spdcachelookup; - u_quad_t spdcachemiss; + u_int64_t spdcachelookup; + u_int64_t spdcachemiss; u_int32_t ips_in_polvio; /* input: sec policy violation */ u_int32_t ips_out_polvio; /* output: sec policy violation */ Index: sys/netipsec/keysock.h =================================================================== --- sys/netipsec/keysock.h (revision 209358) +++ sys/netipsec/keysock.h (working copy) @@ -34,28 +34,30 @@ #define _NETIPSEC_KEYSOCK_H_ /* statistics for pfkey socket */ +#define PFKEYSTAT_VERSION 0x00000001 + struct pfkeystat { /* kernel -> userland */ - u_quad_t out_total; /* # of total calls */ - u_quad_t out_bytes; /* total bytecount */ - u_quad_t out_msgtype[256]; /* message type histogram */ - u_quad_t out_invlen; /* invalid length field */ - u_quad_t out_invver; /* invalid version field */ - u_quad_t out_invmsgtype; /* invalid message type field */ - u_quad_t out_tooshort; /* msg too short */ - u_quad_t out_nomem; /* memory allocation failure */ - u_quad_t out_dupext; /* duplicate extension */ - u_quad_t out_invexttype; /* invalid extension type */ - u_quad_t out_invsatype; /* invalid sa type */ - u_quad_t out_invaddr; /* invalid address extension */ + u_int64_t out_total; /* # of total calls */ + u_int64_t out_bytes; /* total bytecount */ + u_int64_t out_msgtype[256]; /* message type histogram */ + u_int64_t out_invlen; /* invalid length field */ + u_int64_t out_invver; /* invalid version field */ + u_int64_t out_invmsgtype; /* invalid message type field */ + u_int64_t out_tooshort; /* msg too short */ + u_int64_t out_nomem; /* memory allocation failure */ + u_int64_t out_dupext; /* duplicate extension */ + u_int64_t out_invexttype; /* invalid extension type */ + u_int64_t out_invsatype; /* invalid sa type */ + u_int64_t out_invaddr; /* invalid address extension */ /* userland -> kernel */ - u_quad_t in_total; /* # of total calls */ - u_quad_t in_bytes; /* total bytecount */ - u_quad_t in_msgtype[256]; /* message type histogram */ - u_quad_t in_msgtarget[3]; /* one/all/registered */ - u_quad_t in_nomem; /* memory allocation failure */ + u_int64_t in_total; /* # of total calls */ + u_int64_t in_bytes; /* total bytecount */ + u_int64_t in_msgtype[256]; /* message type histogram */ + u_int64_t in_msgtarget[3]; /* one/all/registered */ + u_int64_t in_nomem; /* memory allocation failure */ /* others */ - u_quad_t sockerr; /* # of socket related errors */ + u_int64_t sockerr; /* # of socket related errors */ }; #define KEY_SENDUP_ONE 0 Index: sys/sys/mbuf.h =================================================================== --- sys/sys/mbuf.h (revision 209358) +++ sys/sys/mbuf.h (working copy) @@ -302,6 +302,32 @@ }; /* + * Statistics structures to be used by user space monitoring tools. + */ +#define MBSTAT_DATA_VERSION 0x00000001 + +/* Exported by: kern.ipc.mbstats */ +struct mbstat_data { + u_int32_t mbd_version; + u_int64_t mbd_drain; + u_int8_t __mbd_pad[4]; +}; + +#define SFBUF_DATA_VERSION 0x00000001 + +/* Exported by: kern.ipc.sfbstats */ +struct sfbuf_data { + u_int32_t sfd_version; + u_int64_t sfd_nbufs; + u_int64_t sfd_nbufs_peak; + u_int64_t sfd_nbufs_used; + u_int64_t sfd_iocnt; + u_int64_t sfd_allocfail; + u_int64_t sfd_allocwait; + u_int8_t __sfd_pad[12]; +}; + +/* * Flags specifying how an allocation should be made. * * The flag to use is as follows: Index: sys/sys/unpcb.h =================================================================== --- sys/sys/unpcb.h (revision 209358) +++ sys/sys/unpcb.h (working copy) @@ -145,4 +145,46 @@ }; #endif /* _SYS_SOCKETVAR_H_ */ +/* + * Statistics structures to be used by user space monitoring tools. + */ + +#define UNPCB_STREAM_VERSION 0x00000001 + +struct unpcb_stream { + u_int32_t us_version; /* Stream format version. */ + u_int32_t us_count; + u_int64_t us_gencnt; +}; + +/* Exported data for user applications (not complete) */ +struct unpcb_data { + u_int64_t ud_gencnt; + u_int8_t ud_address_len; + char ud_address[104]; + u_int16_t ud_qlen; + u_int16_t ud_incqlen; + u_int16_t ud_qlimit; + u_int32_t ud_snd_cc; + u_int32_t ud_snd_mcnt; + u_int32_t ud_snd_ccnt; + u_int32_t ud_snd_hiwat; + u_int32_t ud_snd_lowat; + u_int32_t ud_snd_mbcnt; + u_int32_t ud_snd_mbmax; + u_int32_t ud_rcv_cc; + u_int32_t ud_rcv_mcnt; + u_int32_t ud_rcv_ccnt; + u_int32_t ud_rcv_hiwat; + u_int32_t ud_rcv_lowat; + u_int32_t ud_rcv_mbcnt; + u_int32_t ud_rcv_mbmax; + u_int64_t ud_pcb; + u_int64_t ud_vnode; + u_int64_t ud_conn; + u_int64_t ud_refs; + u_int64_t ud_reflink; + u_int8_t _ud_pad[38]; +}; + #endif /* _SYS_UNPCB_H_ */