diff options
Diffstat (limited to 'freebsd/usr.bin/netstat/main.c')
-rw-r--r-- | freebsd/usr.bin/netstat/main.c | 684 |
1 files changed, 371 insertions, 313 deletions
diff --git a/freebsd/usr.bin/netstat/main.c b/freebsd/usr.bin/netstat/main.c index a1d66376..a58ee648 100644 --- a/freebsd/usr.bin/netstat/main.c +++ b/freebsd/usr.bin/netstat/main.c @@ -1,5 +1,9 @@ #include <machine/rtems-bsd-user-space.h> +#ifdef __rtems__ +#include "rtems-bsd-netstat-namespace.h" +#endif /* __rtems__ */ + /*- * Copyright (c) 1983, 1988, 1993 * Regents of the University of California. All rights reserved. @@ -30,7 +34,7 @@ */ #ifndef lint -char const copyright[] = +static char const copyright[] = "@(#) Copyright (c) 1983, 1988, 1993\n\ Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ @@ -44,15 +48,6 @@ static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; #ifdef __rtems__ #define __need_getopt_newlib #include <getopt.h> -#define RTEMS_BSD_PROGRAM_NO_OPEN_WRAP -#define RTEMS_BSD_PROGRAM_NO_SOCKET_WRAP -#define RTEMS_BSD_PROGRAM_NO_CLOSE_WRAP -#define RTEMS_BSD_PROGRAM_NO_FOPEN_WRAP -#define RTEMS_BSD_PROGRAM_NO_FCLOSE_WRAP -#define RTEMS_BSD_PROGRAM_NO_MALLOC_WRAP -#define RTEMS_BSD_PROGRAM_NO_CALLOC_WRAP -#define RTEMS_BSD_PROGRAM_NO_REALLOC_WRAP -#define RTEMS_BSD_PROGRAM_NO_FREE_WRAP #include <machine/rtems-bsd-program.h> #include <machine/rtems-bsd-commands.h> #endif /* __rtems__ */ @@ -64,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> +#include <sys/sysctl.h> #include <netinet/in.h> @@ -82,129 +78,21 @@ __FBSDID("$FreeBSD$"); #include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <string.h> #include <unistd.h> #include "netstat.h" +#include "nl_defs.h" +#include <libxo/xo.h> +#ifdef __rtems__ +#include "rtems-bsd-netstat-main-data.h" +#endif /* __rtems__ */ -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 - { .n_name = "_ipxpcb_list"}, -#define N_IPXSTAT 7 - { .n_name = "_ipxstat"}, -#define N_SPXSTAT 8 - { .n_name = "_spx_istat"}, -#define N_DDPSTAT 9 - { .n_name = "_ddpstat"}, -#define N_DDPCB 10 - { .n_name = "_ddpcb"}, -#define N_NGSOCKS 11 - { .n_name = "_ngsocklist"}, -#define N_IP6STAT 12 - { .n_name = "_ip6stat" }, -#define N_ICMP6STAT 13 - { .n_name = "_icmp6stat" }, -#define N_IPSECSTAT 14 - { .n_name = "_ipsec4stat" }, -#define N_IPSEC6STAT 15 - { .n_name = "_ipsec6stat" }, -#define N_PIM6STAT 16 - { .n_name = "_pim6stat" }, -#define N_MRT6STAT 17 - { .n_name = "_mrt6stat" }, -#define N_MF6CTABLE 18 - { .n_name = "_mf6ctable" }, -#define N_MIF6TABLE 19 - { .n_name = "_mif6table" }, -#define N_PFKEYSTAT 20 - { .n_name = "_pfkeystat" }, -#define N_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 - { .n_name = "unp_sphead" }, - { .n_name = NULL }, -}; - -struct protox { +#ifndef __rtems__ +static struct protox { +#else /* __rtems__ */ +static const struct protox { +#endif /* __rtems__ */ 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 */ @@ -216,7 +104,7 @@ struct protox { const char *pr_name; /* well-known name */ int pr_usesysctl; /* non-zero if we use sysctl, not kvm */ int pr_protocol; -} static const protox[] = { +} protox[] = { { N_TCBINFO, N_TCPSTAT, 1, protopr, tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { N_UDBINFO, N_UDPSTAT, 1, protopr, @@ -238,21 +126,23 @@ struct protox { { N_RIPCBINFO, N_IGMPSTAT, 1, protopr, igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP }, #ifdef IPSEC - { -1, N_IPSECSTAT, 1, NULL, /* keep as compat */ - ipsec_stats, NULL, "ipsec", 0, 0}, + { -1, N_IPSEC4STAT, 1, NULL, /* keep as compat */ + ipsec_stats, NULL, "ipsec", 1, 0}, { -1, N_AHSTAT, 1, NULL, - ah_stats, NULL, "ah", 0, 0}, + ah_stats, NULL, "ah", 1, 0}, { -1, N_ESPSTAT, 1, NULL, - esp_stats, NULL, "esp", 0, 0}, + esp_stats, NULL, "esp", 1, 0}, { -1, N_IPCOMPSTAT, 1, NULL, - ipcomp_stats, NULL, "ipcomp", 0, 0}, + ipcomp_stats, NULL, "ipcomp", 1, 0}, #endif { N_RIPCBINFO, N_PIMSTAT, 1, protopr, pim_stats, NULL, "pim", 1, IPPROTO_PIM }, - { -1, N_CARPSTAT, 1, NULL, + { -1, N_CARPSTATS, 1, NULL, carp_stats, NULL, "carp", 1, 0 }, - { -1, N_PFSYNCSTAT, 1, NULL, +#ifdef PF + { -1, N_PFSYNCSTATS, 1, NULL, pfsync_stats, NULL, "pfsync", 1, 0 }, +#endif { -1, N_ARPSTAT, 1, NULL, arp_stats, NULL, "arp", 1, 0 }, { -1, -1, 0, NULL, @@ -260,7 +150,11 @@ struct protox { }; #ifdef INET6 +#ifndef __rtems__ +static struct protox ip6protox[] = { +#else /* __rtems__ */ static const struct protox ip6protox[] = { +#endif /* __rtems__ */ { N_TCBINFO, N_TCPSTAT, 1, protopr, tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { N_UDBINFO, N_UDPSTAT, 1, protopr, @@ -275,7 +169,7 @@ static const struct protox ip6protox[] = { #endif #ifdef IPSEC { -1, N_IPSEC6STAT, 1, NULL, - ipsec_stats, NULL, "ipsec6", 0, 0 }, + ipsec_stats, NULL, "ipsec6", 1, 0 }, #endif #ifdef notyet { -1, N_PIM6STAT, 1, NULL, @@ -289,7 +183,11 @@ static const struct protox ip6protox[] = { #endif /*INET6*/ #ifdef IPSEC +#ifndef __rtems__ +static struct protox pfkeyprotox[] = { +#else /* __rtems__ */ static const struct protox pfkeyprotox[] = { +#endif /* __rtems__ */ { -1, N_PFKEYSTAT, 1, NULL, pfkey_stats, NULL, "pfkey", 0, 0 }, { -1, -1, 0, NULL, @@ -297,36 +195,26 @@ static const struct protox pfkeyprotox[] = { }; #endif -#ifndef __rtems__ -static const struct protox atalkprotox[] = { - { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, - ddp_stats, NULL, "ddp", 0, 0 }, - { -1, -1, 0, NULL, - NULL, NULL, NULL, 0, 0 } -}; -#endif #ifdef NETGRAPH +#ifndef __rtems__ +static struct protox netgraphprotox[] = { +#else /* __rtems__ */ static const struct protox netgraphprotox[] = { - { N_NGSOCKS, -1, 1, netgraphprotopr, +#endif /* __rtems__ */ + { N_NGSOCKLIST, -1, 1, netgraphprotopr, NULL, NULL, "ctrl", 0, 0 }, - { N_NGSOCKS, -1, 1, netgraphprotopr, + { N_NGSOCKLIST, -1, 1, netgraphprotopr, NULL, NULL, "data", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif -#ifdef IPX -static const struct protox ipxprotox[] = { - { N_IPX, N_IPXSTAT, 1, ipxprotopr, - ipx_stats, NULL, "ipx", 0, 0 }, - { N_IPX, N_SPXSTAT, 1, ipxprotopr, - spx_stats, NULL, "spx", 0, 0 }, - { -1, -1, 0, NULL, - NULL, NULL, 0, 0, 0 } -}; -#endif -static const struct protox *protoprotox[] = { +#ifndef __rtems__ +static struct protox *protoprotox[] = { +#else /* __rtems__ */ +static const struct protox *const protoprotox[] = { +#endif /* __rtems__ */ protox, #ifdef INET6 ip6protox, @@ -334,26 +222,30 @@ static const struct protox *protoprotox[] = { #ifdef IPSEC pfkeyprotox, #endif -#ifdef IPX - ipxprotox, -#endif -#ifndef __rtems__ - atalkprotox, NULL }; -#else - NULL }; -#endif + NULL }; -static void printproto(const struct protox *, const char *); +#ifndef __rtems__ +static void printproto(struct protox *, const char *, bool *); +#else /* __rtems__ */ +static void printproto(const struct protox *, const char *, bool *); +#endif /* __rtems__ */ static void usage(void); +#ifndef __rtems__ +static struct protox *name2protox(const char *); +static struct protox *knownname(const char *); +#else /* __rtems__ */ static const struct protox *name2protox(const char *); static const struct protox *knownname(const char *); +#endif /* __rtems__ */ + +static int kresolve_list(struct nlist *_nl); static kvm_t *kvmd; static char *nlistf = NULL, *memf = NULL; int Aflag; /* show addresses of protocol control block */ int aflag; /* show all sockets (including servers) */ -int Bflag; /* show information about bpf consumers */ +static int Bflag; /* show information about bpf consumers */ int bflag; /* show i/f total bytes in/out */ int dflag; /* show i/f dropped packets */ int gflag; /* show group (multicast) routing or stats */ @@ -366,9 +258,10 @@ int numeric_addr; /* show addresses numerically */ int numeric_port; /* show ports numerically */ static int pflag; /* show given protocol */ #ifndef __rtems__ -int Qflag; /* show netisr information */ +static int Qflag; /* show netisr information */ #endif /* __rtems__ */ int rflag; /* show routing tables (or routing stats) */ +int Rflag; /* show flow / RSS statistics */ int sflag; /* show protocol statistics */ int Wflag; /* wide display */ int Tflag; /* TCP Information */ @@ -380,60 +273,27 @@ int interval; /* repeat interval for i/f stats */ char *interface; /* desired i/f for stats, or NULL for all i/fs */ int unit; /* unit number for above */ -int af; /* address family */ +static int af; /* address family */ int live; /* true if we are examining a live system */ #ifdef __rtems__ -int protopr_initialized; -int do_rtent; -struct radix_node_head **rt_tables; - static int main(int argc, char *argv[]); -int rtems_bsd_command_netstat(int argc, char *argv[]) +RTEMS_LINKER_RWSET(bsd_prog_netstat, char); + +int +rtems_bsd_command_netstat(int argc, char *argv[]) { int exit_code; + void *data_begin; + size_t data_size; - rtems_bsd_program_lock(); - - nlistf = NULL; - memf = NULL; - - Aflag = 0; - aflag = 0; - Bflag = 0; - bflag = 0; - dflag = 0; - gflag = 0; - hflag = 0; - iflag = 0; - Lflag = 0; - mflag = 0; - noutputs = 0; - numeric_addr = 0; - numeric_port = 0; - pflag = 0; - rflag = 0; - sflag = 0; - Wflag = 0; - xflag = 0; - zflag = 0; - interval = 0; - interface = 0; - unit = 0; - af = 0; - live = 0; - - protopr_initialized = 0; - do_rtent = 0; - - rtems_bsd_netstat_inet_init(); - - exit_code = rtems_bsd_program_call_main("netstat", main, argc, argv); - - free(rt_tables); - rt_tables = NULL; + data_begin = RTEMS_LINKER_SET_BEGIN(bsd_prog_netstat); + data_size = RTEMS_LINKER_SET_SIZE(bsd_prog_netstat); + rtems_bsd_program_lock(); + exit_code = rtems_bsd_program_call_main_with_data_restore("netstat", + main, argc, argv, data_begin, data_size); rtems_bsd_program_unlock(); return exit_code; @@ -442,8 +302,15 @@ int rtems_bsd_command_netstat(int argc, char *argv[]) int main(int argc, char *argv[]) { +#ifndef __rtems__ + struct protox *tp = NULL; /* for printing cblocks & stats */ +#else /* __rtems__ */ const struct protox *tp = NULL; /* for printing cblocks & stats */ +#endif /* __rtems__ */ int ch; + int fib = -1; + char *endptr; + bool first = true; #ifdef __rtems__ struct getopt_data getopt_data; memset(&getopt_data, 0, sizeof(getopt_data)); @@ -456,7 +323,11 @@ main(int argc, char *argv[]) af = AF_UNSPEC; - while ((ch = getopt(argc, argv, "46AaBbdf:ghI:iLlM:mN:np:Qq:rSTsuWw:xz")) + argc = xo_parse_args(argc, argv); + if (argc < 0) + exit(EXIT_FAILURE); + + while ((ch = getopt(argc, argv, "46AaBbdF:f:ghI:iLlM:mN:np:Qq:RrSTsuWw:xz")) != -1) switch(ch) { case '4': @@ -488,10 +359,14 @@ main(int argc, char *argv[]) case 'd': dflag = 1; break; + case 'F': + fib = strtol(optarg, &endptr, 0); + if (*endptr != '\0' || + (fib == 0 && (errno == EINVAL || errno == ERANGE))) + xo_errx(1, "%s: invalid fib", optarg); + break; case 'f': - if (strcmp(optarg, "ipx") == 0) - af = AF_IPX; - else if (strcmp(optarg, "inet") == 0) + if (strcmp(optarg, "inet") == 0) af = AF_INET; #ifdef INET6 else if (strcmp(optarg, "inet6") == 0) @@ -501,10 +376,9 @@ main(int argc, char *argv[]) else if (strcmp(optarg, "pfkey") == 0) af = PF_KEY; #endif - else if (strcmp(optarg, "unix") == 0) + else if (strcmp(optarg, "unix") == 0 || + strcmp(optarg, "local") == 0) af = AF_UNIX; - else if (strcmp(optarg, "atalk") == 0) - af = AF_APPLETALK; #ifdef NETGRAPH else if (strcmp(optarg, "ng") == 0 || strcmp(optarg, "netgraph") == 0) @@ -513,7 +387,8 @@ main(int argc, char *argv[]) else if (strcmp(optarg, "link") == 0) af = AF_LINK; else { - errx(1, "%s: unknown address family", optarg); + xo_errx(1, "%s: unknown address family", + optarg); } break; case 'g': @@ -526,7 +401,12 @@ main(int argc, char *argv[]) char *cp; iflag = 1; - for (cp = interface = optarg; isalpha((unsigned char) *cp); cp++) +#ifndef __rtems__ + for (cp = interface = optarg; isalpha(*cp); cp++) +#else /* __rtems__ */ + for (cp = interface = optarg; isalpha( + (unsigned char) *cp); cp++) +#endif /* __rtems__ */ continue; unit = atoi(cp); break; @@ -551,9 +431,8 @@ main(int argc, char *argv[]) break; case 'p': if ((tp = name2protox(optarg)) == NULL) { - errx(1, - "%s: unknown or uninstrumented protocol", - optarg); + xo_errx(1, "%s: unknown or uninstrumented " + "protocol", optarg); } pflag = 1; break; @@ -570,6 +449,9 @@ main(int argc, char *argv[]) case 'r': rflag = 1; break; + case 'R': + Rflag = 1; + break; case 's': ++sflag; break; @@ -606,7 +488,11 @@ main(int argc, char *argv[]) #define BACKWARD_COMPATIBILITY #ifdef BACKWARD_COMPATIBILITY if (*argv) { +#ifndef __rtems__ + if (isdigit(**argv)) { +#else /* __rtems__ */ if (isdigit((unsigned char) **argv)) { +#endif /* __rtems__ */ interval = atoi(*argv); if (interval <= 0) usage(); @@ -626,33 +512,38 @@ main(int argc, char *argv[]) * guys can't print interesting stuff from kernel memory. */ live = (nlistf == NULL && memf == NULL); - if (!live) - setgid(getgid()); + if (!live) { + if (setgid(getgid()) != 0) + xo_err(-1, "setgid"); + } - if (xflag && Tflag) - errx(1, "-x and -T are incompatible, pick one."); + if (xflag && Tflag) + xo_errx(1, "-x and -T are incompatible, pick one."); if (Bflag) { if (!live) usage(); bpf_stats(interface); + xo_finish(); exit(0); } if (mflag) { if (!live) { if (kread(0, NULL, 0) == 0) - mbpr(kvmd, nl[N_MBSTAT].n_value); + mbpr(kvmd, nl[N_SFSTAT].n_value); } else mbpr(NULL, 0); + xo_finish(); exit(0); } #ifndef __rtems__ if (Qflag) { if (!live) { if (kread(0, NULL, 0) == 0) - netisr_stats(kvmd); + netisr_stats(); } else - netisr_stats(NULL); + netisr_stats(); + xo_finish(); exit(0); } #endif /* __rtems__ */ @@ -670,109 +561,162 @@ main(int argc, char *argv[]) * used for the queries, which is slower. */ #endif - kread(0, NULL, 0); if (iflag && !sflag) { - intpr(interval, nl[N_IFNET].n_value, NULL); + xo_open_container("statistics"); + intpr(NULL, af); + xo_close_container("statistics"); + xo_finish(); 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); + xo_open_container("statistics"); + if (sflag) { + rt_stats(); + flowtable_stats(); + } else + routepr(fib, af); + xo_close_container("statistics"); + xo_finish(); exit(0); } + if (gflag) { + xo_open_container("statistics"); if (sflag) { if (af == AF_INET || af == AF_UNSPEC) - mrt_stats(nl[N_MRTSTAT].n_value); + mrt_stats(); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) - mrt6_stats(nl[N_MRT6STAT].n_value); + mrt6_stats(); #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(); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) - mroute6pr(nl[N_MF6CTABLE].n_value, - nl[N_MIF6TABLE].n_value); + mroute6pr(); #endif } + xo_close_container("statistics"); + xo_finish(); exit(0); } + /* Load all necessary kvm symbols */ + kresolve_list(nl); + if (tp) { - printproto(tp, tp->pr_name); + xo_open_container("statistics"); + printproto(tp, tp->pr_name, &first); + if (!first) + xo_close_list("socket"); + xo_close_container("statistics"); + xo_finish(); exit(0); } + + xo_open_container("statistics"); if (af == AF_INET || af == AF_UNSPEC) for (tp = protox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); + printproto(tp, tp->pr_name, &first); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) for (tp = ip6protox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); + printproto(tp, tp->pr_name, &first); #endif /*INET6*/ #ifdef IPSEC if (af == PF_KEY || af == AF_UNSPEC) for (tp = pfkeyprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); + printproto(tp, tp->pr_name, &first); #endif /*IPSEC*/ -#ifdef IPX - if (af == AF_IPX || af == AF_UNSPEC) { - for (tp = ipxprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); - } -#endif /* IPX */ -#ifndef __rtems__ - if (af == AF_APPLETALK || af == AF_UNSPEC) - for (tp = atalkprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); -#endif #ifdef NETGRAPH if (af == AF_NETGRAPH || af == AF_UNSPEC) for (tp = netgraphprotox; tp->pr_name; tp++) - printproto(tp, tp->pr_name); + printproto(tp, tp->pr_name, &first); #endif /* NETGRAPH */ #ifndef __rtems__ 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); -#endif + nl[N_UNP_SPHEAD].n_value, &first); +#endif /* __rtems__ */ + + if (!first) + xo_close_list("socket"); + xo_close_container("statistics"); + xo_finish(); exit(0); } +static int +fetch_stats_internal(const char *sysctlname, u_long off, void *stats, + size_t len, kreadfn_t kreadfn, int zero) +{ + int error; + + if (live) { + memset(stats, 0, len); + if (zero) + error = sysctlbyname(sysctlname, NULL, NULL, stats, + len); + else + error = sysctlbyname(sysctlname, stats, &len, NULL, 0); + if (error == -1 && errno != ENOENT) + xo_warn("sysctl %s", sysctlname); + } else { + if (off == 0) + return (1); + error = kreadfn(off, stats, len); + } + return (error); +} + +int +fetch_stats(const char *sysctlname, u_long off, void *stats, + size_t len, kreadfn_t kreadfn) +{ + + return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn, + zflag)); +} + +int +fetch_stats_ro(const char *sysctlname, u_long off, void *stats, + size_t len, kreadfn_t kreadfn) +{ + + return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn, 0)); +} + /* * Print out protocol statistics or control blocks (per sflag). * If the interface was not specifically requested, and the symbol * is not in the namelist, ignore this one. */ static void -printproto(tp, name) - const struct protox *tp; - const char *name; +#ifndef __rtems__ +printproto(struct protox *tp, const char *name, bool *first) +#else /* __rtems__ */ +printproto(const struct protox *tp, const char *name, bool *first) +#endif /* __rtems__ */ { void (*pr)(u_long, const char *, int, int); u_long off; + bool doingdblocks = false; if (sflag) { if (iflag) { if (tp->pr_istats) - intpr(interval, nl[N_IFNET].n_value, - tp->pr_istats); + intpr(tp->pr_istats, af); else if (pflag) - printf("%s: no per-interface stats routine\n", + xo_message("%s: no per-interface stats routine", tp->pr_name); return; } else { pr = tp->pr_stats; if (!pr) { if (pflag) - printf("%s: no stats routine\n", + xo_message("%s: no stats routine", tp->pr_name); return; } @@ -780,34 +724,99 @@ printproto(tp, name) off = 0; else if (tp->pr_sindex < 0) { if (pflag) - printf( - "%s: stats routine doesn't work on cores\n", - tp->pr_name); + xo_message("%s: stats routine doesn't " + "work on cores", tp->pr_name); return; } else off = nl[tp->pr_sindex].n_value; } } else { + doingdblocks = true; pr = tp->pr_cblocks; if (!pr) { if (pflag) - printf("%s: no PCB routine\n", tp->pr_name); + xo_message("%s: no PCB routine", tp->pr_name); return; } if (tp->pr_usesysctl && live) off = 0; else if (tp->pr_index < 0) { if (pflag) - printf( - "%s: PCB routine doesn't work on cores\n", - tp->pr_name); + xo_message("%s: PCB routine doesn't work on " + "cores", tp->pr_name); return; } else off = nl[tp->pr_index].n_value; } if (pr != NULL && (off || (live && tp->pr_usesysctl) || - af != AF_UNSPEC)) + af != AF_UNSPEC)) { + if (doingdblocks && *first) { + xo_open_list("socket"); + *first = false; + } + (*pr)(off, name, af, tp->pr_protocol); + } +} + +static int +kvmd_init(void) +{ + char errbuf[_POSIX2_LINE_MAX]; + + if (kvmd != NULL) + return (0); + + kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); + if (setgid(getgid()) != 0) + xo_err(-1, "setgid"); + + if (kvmd == NULL) { + xo_warnx("kvm not available: %s", errbuf); + return (-1); + } + + return (0); +} + +/* + * Resolve symbol list, return 0 on success. + */ +static int +kresolve_list(struct nlist *_nl) +{ + + if ((kvmd == NULL) && (kvmd_init() != 0)) + return (-1); + + if (_nl[0].n_type != 0) + return (0); + + if (kvm_nlist(kvmd, _nl) < 0) { + if (nlistf) + xo_errx(1, "%s: kvm_nlist: %s", nlistf, + kvm_geterr(kvmd)); + else + xo_errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); + } + + return (0); +} + +/* + * Wrapper of kvm_dpcpu_setcpu(). + */ +void +kset_dpcpu(u_int cpuid) +{ + + if ((kvmd == NULL) && (kvmd_init() != 0)) + xo_errx(-1, "%s: kvm is not available", __func__); + + if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0) + xo_errx(-1, "%s: kvm_dpcpu_setcpu(%u): %s", __func__, + cpuid, kvm_geterr(kvmd)); + return; } /* @@ -816,40 +825,70 @@ printproto(tp, name) int kread(u_long addr, void *buf, size_t size) { - char errbuf[_POSIX2_LINE_MAX]; - if (kvmd == NULL) { - kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); - setgid(getgid()); - if (kvmd != NULL) { - if (kvm_nlist(kvmd, nl) < 0) { - if (nlistf) - errx(1, "%s: kvm_nlist: %s", nlistf, - kvm_geterr(kvmd)); - else - errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); - } + if (kvmd_init() < 0) + return (-1); - if (nl[0].n_type == 0) { - if (nlistf) - errx(1, "%s: no namelist", nlistf); - else - errx(1, "no namelist"); - } - } else { - warnx("kvm not available: %s", errbuf); - return(-1); - } - } if (!buf) return (0); if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) { - warnx("%s", kvm_geterr(kvmd)); + xo_warnx("%s", kvm_geterr(kvmd)); return (-1); } return (0); } +/* + * Read single counter(9). + */ +uint64_t +kread_counter(u_long addr) +{ + + if (kvmd_init() < 0) + return (-1); + + return (kvm_counter_u64_fetch(kvmd, addr)); +} + +/* + * Read an array of N counters in kernel memory into array of N uint64_t's. + */ +int +kread_counters(u_long addr, void *buf, size_t size) +{ +#ifndef __rtems__ + uint64_t *c; + u_long *counters; + size_t i, n; + + if (kvmd_init() < 0) + return (-1); + + if (size % sizeof(uint64_t) != 0) { + xo_warnx("kread_counters: invalid counter set size"); + return (-1); + } + + n = size / sizeof(uint64_t); + if ((counters = malloc(n * sizeof(u_long))) == NULL) + xo_err(-1, "malloc"); + if (kread(addr, counters, n * sizeof(u_long)) < 0) { + free(counters); + return (-1); + } + + c = buf; + for (i = 0; i < n; i++) + c[i] = kvm_counter_u64_fetch(kvmd, counters[i]); + + free(counters); + return (0); +#else /* __rtems__ */ + return (-1); +#endif /* __rtems__ */ +} + const char * plural(uintmax_t n) { @@ -871,10 +910,18 @@ pluralies(uintmax_t n) /* * Find the protox for the given "well-known" name. */ +#ifndef __rtems__ +static struct protox * +#else /* __rtems__ */ static const struct protox * +#endif /* __rtems__ */ knownname(const char *name) { - const struct protox **tpp, *tp; +#ifndef __rtems__ + struct protox **tpp, *tp; +#else /* __rtems__ */ + const struct protox *const *tpp, *tp; +#endif /* __rtems__ */ for (tpp = protoprotox; *tpp; tpp++) for (tp = *tpp; tp->pr_name; tp++) @@ -886,10 +933,18 @@ knownname(const char *name) /* * Find the protox corresponding to name. */ +#ifndef __rtems__ +static struct protox * +#else /* __rtems__ */ static const struct protox * +#endif /* __rtems__ */ name2protox(const char *name) { +#ifndef __rtems__ + struct protox *tp; +#else /* __rtems__ */ const struct protox *tp; +#endif /* __rtems__ */ char **alias; /* alias from p->aliases */ struct protoent *p; @@ -916,22 +971,25 @@ name2protox(const char *name) static void usage(void) { - (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", -"usage: netstat [-46AaLnSTWx] [-f protocol_family | -p protocol]\n" + (void)xo_error("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", +"usage: netstat [-46AaLnRSTWx] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -i | -I interface [-46abdhnW] [-f address_family]\n" " [-M core] [-N system]", -" netstat -w wait [-I interface] [-46d] [-M core] [-N system] [-q howmany]", -" netstat -s [-s] [-46z] [-f protocol_family | -p protocol]\n" -" [-M core] [-N system]", -" netstat -i | -I interface [-46s] [-f protocol_family | -p protocol]\n" +" netstat -w wait [-I interface] [-46d] [-M core] [-N system]\n" +" [-q howmany]", +" netstat -s [-46sz] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", +" netstat -i | -I interface -s [-46s]\n" +" [-f protocol_family | -p protocol] [-M core] [-N system]", " netstat -m [-M core] [-N system]", -" netstat -B [-I interface]", -" netstat -r [-46AanW] [-f address_family] [-M core] [-N system]", +" netstat -B [-z] [-I interface]", +" netstat -r [-46AnW] [-F fibnum] [-f address_family]\n" +" [-M core] [-N system]", " netstat -rs [-s] [-M core] [-N system]", " netstat -g [-46W] [-f address_family] [-M core] [-N system]", " netstat -gs [-46s] [-f address_family] [-M core] [-N system]", " netstat -Q"); + xo_finish(); exit(1); } |