source: rtems-libbsd/freebsd/usr.bin/netstat/main.c @ 95a3ba8

55-freebsd-126-freebsd-12
Last change on this file since 95a3ba8 was 95a3ba8, checked in by Sebastian Huber <sebastian.huber@…>, on 01/09/17 at 07:50:55

NETSTAT(1): Fix name list initialization

  • Property mode set to 100644
File size: 22.9 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3#ifdef __rtems__
4#include "rtems-bsd-netstat-namespace.h"
5#endif /* __rtems__ */
6
7/*-
8 * Copyright (c) 1983, 1988, 1993
9 *      Regents of the University of California.  All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef lint
37static char const copyright[] =
38"@(#) Copyright (c) 1983, 1988, 1993\n\
39        Regents of the University of California.  All rights reserved.\n";
40#endif /* not lint */
41
42#if 0
43#ifndef lint
44static char sccsid[] = "@(#)main.c      8.4 (Berkeley) 3/1/94";
45#endif /* not lint */
46#endif
47
48#ifdef __rtems__
49#define __need_getopt_newlib
50#include <getopt.h>
51#include <machine/rtems-bsd-program.h>
52#include <machine/rtems-bsd-commands.h>
53#endif /* __rtems__ */
54#include <sys/cdefs.h>
55__FBSDID("$FreeBSD$");
56
57#include <rtems/bsd/sys/param.h>
58#include <sys/file.h>
59#include <sys/protosw.h>
60#include <sys/socket.h>
61#include <sys/socketvar.h>
62#include <sys/sysctl.h>
63
64#include <netinet/in.h>
65
66#ifdef NETGRAPH
67#include <netgraph/ng_socket.h>
68#endif
69
70#include <ctype.h>
71#include <err.h>
72#include <errno.h>
73#include <kvm.h>
74#include <limits.h>
75#include <netdb.h>
76#include <nlist.h>
77#include <paths.h>
78#include <stdint.h>
79#include <stdio.h>
80#include <stdlib.h>
81#include <stdbool.h>
82#include <string.h>
83#include <unistd.h>
84#include "netstat.h"
85#include "nl_defs.h"
86#include <libxo/xo.h>
87#ifdef __rtems__
88#include "rtems-bsd-netstat-main-data.h"
89#endif /* __rtems__ */
90
91#ifndef __rtems__
92static struct protox {
93#else /* __rtems__ */
94static const struct protox {
95#endif /* __rtems__ */
96        int     pr_index;               /* index into nlist of cb head */
97        int     pr_sindex;              /* index into nlist of stat block */
98        u_char  pr_wanted;              /* 1 if wanted, 0 otherwise */
99        void    (*pr_cblocks)(u_long, const char *, int, int);
100                                        /* control blocks printing routine */
101        void    (*pr_stats)(u_long, const char *, int, int);
102                                        /* statistics printing routine */
103        void    (*pr_istats)(char *);   /* per/if statistics printing routine */
104        const char      *pr_name;               /* well-known name */
105        int     pr_usesysctl;           /* non-zero if we use sysctl, not kvm */
106        int     pr_protocol;
107} protox[] = {
108        { N_TCBINFO,    N_TCPSTAT,      1,      protopr,
109          tcp_stats,    NULL,           "tcp",  1,      IPPROTO_TCP },
110        { N_UDBINFO,    N_UDPSTAT,      1,      protopr,
111          udp_stats,    NULL,           "udp",  1,      IPPROTO_UDP },
112#ifdef SCTP
113        { -1,           N_SCTPSTAT,     1,      sctp_protopr,
114          sctp_stats,   NULL,           "sctp", 1,      IPPROTO_SCTP },
115#endif
116#ifdef SDP
117        { -1,           -1,             1,      protopr,
118         NULL,          NULL,           "sdp",  1,      IPPROTO_TCP },
119#endif
120        { N_DIVCBINFO,  -1,             1,      protopr,
121          NULL,         NULL,           "divert", 1,    IPPROTO_DIVERT },
122        { N_RIPCBINFO,  N_IPSTAT,       1,      protopr,
123          ip_stats,     NULL,           "ip",   1,      IPPROTO_RAW },
124        { N_RIPCBINFO,  N_ICMPSTAT,     1,      protopr,
125          icmp_stats,   NULL,           "icmp", 1,      IPPROTO_ICMP },
126        { N_RIPCBINFO,  N_IGMPSTAT,     1,      protopr,
127          igmp_stats,   NULL,           "igmp", 1,      IPPROTO_IGMP },
128#ifdef IPSEC
129        { -1,           N_IPSEC4STAT,   1,      NULL,   /* keep as compat */
130          ipsec_stats,  NULL,           "ipsec", 1,     0},
131        { -1,           N_AHSTAT,       1,      NULL,
132          ah_stats,     NULL,           "ah",   1,      0},
133        { -1,           N_ESPSTAT,      1,      NULL,
134          esp_stats,    NULL,           "esp",  1,      0},
135        { -1,           N_IPCOMPSTAT,   1,      NULL,
136          ipcomp_stats, NULL,           "ipcomp", 1,    0},
137#endif
138        { N_RIPCBINFO,  N_PIMSTAT,      1,      protopr,
139          pim_stats,    NULL,           "pim",  1,      IPPROTO_PIM },
140        { -1,           N_CARPSTATS,    1,      NULL,
141          carp_stats,   NULL,           "carp", 1,      0 },
142#ifdef PF
143        { -1,           N_PFSYNCSTATS,  1,      NULL,
144          pfsync_stats, NULL,           "pfsync", 1,    0 },
145#endif
146        { -1,           N_ARPSTAT,      1,      NULL,
147          arp_stats,    NULL,           "arp", 1,       0 },
148        { -1,           -1,             0,      NULL,
149          NULL,         NULL,           NULL,   0,      0 }
150};
151
152#ifdef INET6
153#ifndef __rtems__
154static struct protox ip6protox[] = {
155#else /* __rtems__ */
156static const struct protox ip6protox[] = {
157#endif /* __rtems__ */
158        { N_TCBINFO,    N_TCPSTAT,      1,      protopr,
159          tcp_stats,    NULL,           "tcp",  1,      IPPROTO_TCP },
160        { N_UDBINFO,    N_UDPSTAT,      1,      protopr,
161          udp_stats,    NULL,           "udp",  1,      IPPROTO_UDP },
162        { N_RIPCBINFO,  N_IP6STAT,      1,      protopr,
163          ip6_stats,    ip6_ifstats,    "ip6",  1,      IPPROTO_RAW },
164        { N_RIPCBINFO,  N_ICMP6STAT,    1,      protopr,
165          icmp6_stats,  icmp6_ifstats,  "icmp6", 1,     IPPROTO_ICMPV6 },
166#ifdef SDP
167        { -1,           -1,             1,      protopr,
168         NULL,          NULL,           "sdp",  1,      IPPROTO_TCP },
169#endif
170#ifdef IPSEC
171        { -1,           N_IPSEC6STAT,   1,      NULL,
172          ipsec_stats,  NULL,           "ipsec6", 1,    0 },
173#endif
174#ifdef notyet
175        { -1,           N_PIM6STAT,     1,      NULL,
176          pim6_stats,   NULL,           "pim6", 1,      0 },
177#endif
178        { -1,           N_RIP6STAT,     1,      NULL,
179          rip6_stats,   NULL,           "rip6", 1,      0 },
180        { -1,           -1,             0,      NULL,
181          NULL,         NULL,           NULL,   0,      0 }
182};
183#endif /*INET6*/
184
185#ifdef IPSEC
186#ifndef __rtems__
187static struct protox pfkeyprotox[] = {
188#else /* __rtems__ */
189static const struct protox pfkeyprotox[] = {
190#endif /* __rtems__ */
191        { -1,           N_PFKEYSTAT,    1,      NULL,
192          pfkey_stats,  NULL,           "pfkey", 0,     0 },
193        { -1,           -1,             0,      NULL,
194          NULL,         NULL,           NULL,   0,      0 }
195};
196#endif
197
198#ifdef NETGRAPH
199#ifndef __rtems__
200static struct protox netgraphprotox[] = {
201#else /* __rtems__ */
202static const struct protox netgraphprotox[] = {
203#endif /* __rtems__ */
204        { N_NGSOCKLIST, -1,             1,      netgraphprotopr,
205          NULL,         NULL,           "ctrl", 0,      0 },
206        { N_NGSOCKLIST, -1,             1,      netgraphprotopr,
207          NULL,         NULL,           "data", 0,      0 },
208        { -1,           -1,             0,      NULL,
209          NULL,         NULL,           NULL,   0,      0 }
210};
211#endif
212
213#ifndef __rtems__
214static struct protox *protoprotox[] = {
215#else /* __rtems__ */
216static const struct protox *const protoprotox[] = {
217#endif /* __rtems__ */
218                                         protox,
219#ifdef INET6
220                                         ip6protox,
221#endif
222#ifdef IPSEC
223                                         pfkeyprotox,
224#endif
225                                         NULL };
226
227#ifndef __rtems__
228static void printproto(struct protox *, const char *, bool *);
229#else /* __rtems__ */
230static void printproto(const struct protox *, const char *, bool *);
231#endif /* __rtems__ */
232static void usage(void);
233#ifndef __rtems__
234static struct protox *name2protox(const char *);
235static struct protox *knownname(const char *);
236#else /* __rtems__ */
237static const struct protox *name2protox(const char *);
238static const struct protox *knownname(const char *);
239#endif /* __rtems__ */
240
241static int kresolve_list(struct nlist *_nl);
242
243static kvm_t *kvmd;
244static char *nlistf = NULL, *memf = NULL;
245
246int     Aflag;          /* show addresses of protocol control block */
247int     aflag;          /* show all sockets (including servers) */
248static int      Bflag;          /* show information about bpf consumers */
249int     bflag;          /* show i/f total bytes in/out */
250int     dflag;          /* show i/f dropped packets */
251int     gflag;          /* show group (multicast) routing or stats */
252int     hflag;          /* show counters in human readable format */
253int     iflag;          /* show interfaces */
254int     Lflag;          /* show size of listen queues */
255int     mflag;          /* show memory stats */
256int     noutputs = 0;   /* how much outputs before we exit */
257int     numeric_addr;   /* show addresses numerically */
258int     numeric_port;   /* show ports numerically */
259static int pflag;       /* show given protocol */
260#ifndef __rtems__
261static int      Qflag;          /* show netisr information */
262#endif /* __rtems__ */
263int     rflag;          /* show routing tables (or routing stats) */
264int     Rflag;          /* show flow / RSS statistics */
265int     sflag;          /* show protocol statistics */
266int     Wflag;          /* wide display */
267int     Tflag;          /* TCP Information */
268int     xflag;          /* extra information, includes all socket buffer info */
269int     zflag;          /* zero stats */
270
271int     interval;       /* repeat interval for i/f stats */
272
273char    *interface;     /* desired i/f for stats, or NULL for all i/fs */
274int     unit;           /* unit number for above */
275
276static int      af;             /* address family */
277int     live;           /* true if we are examining a live system */
278
279#ifdef __rtems__
280static int main(int argc, char *argv[]);
281
282RTEMS_LINKER_RWSET(bsd_prog_netstat, char);
283
284int
285rtems_bsd_command_netstat(int argc, char *argv[])
286{
287        int exit_code;
288        void *data_begin;
289        size_t data_size;
290
291        data_begin = RTEMS_LINKER_SET_BEGIN(bsd_prog_netstat);
292        data_size = RTEMS_LINKER_SET_SIZE(bsd_prog_netstat);
293
294        rtems_bsd_program_lock();
295        exit_code = rtems_bsd_program_call_main_with_data_restore("netstat",
296            main, argc, argv, data_begin, data_size);
297        rtems_bsd_program_unlock();
298
299        return exit_code;
300}
301#endif /* __rtems__ */
302int
303main(int argc, char *argv[])
304{
305#ifndef __rtems__
306        struct protox *tp = NULL;  /* for printing cblocks & stats */
307#else /* __rtems__ */
308        const struct protox *tp = NULL;  /* for printing cblocks & stats */
309#endif /* __rtems__ */
310        int ch;
311        int fib = -1;
312        char *endptr;
313        bool first = true;
314#ifdef __rtems__
315        struct getopt_data getopt_data;
316        memset(&getopt_data, 0, sizeof(getopt_data));
317#define optind getopt_data.optind
318#define optarg getopt_data.optarg
319#define opterr getopt_data.opterr
320#define optopt getopt_data.optopt
321#define getopt(argc, argv, opt) getopt_r(argc, argv, "+" opt, &getopt_data)
322#endif /* __rtems__ */
323
324        af = AF_UNSPEC;
325
326        argc = xo_parse_args(argc, argv);
327        if (argc < 0)
328                exit(EXIT_FAILURE);
329
330        while ((ch = getopt(argc, argv, "46AaBbdF:f:ghI:iLlM:mN:np:Qq:RrSTsuWw:xz"))
331            != -1)
332                switch(ch) {
333                case '4':
334#ifdef INET
335                        af = AF_INET;
336#else
337                        errx(1, "IPv4 support is not compiled in");
338#endif
339                        break;
340                case '6':
341#ifdef INET6
342                        af = AF_INET6;
343#else
344                        errx(1, "IPv6 support is not compiled in");
345#endif
346                        break;
347                case 'A':
348                        Aflag = 1;
349                        break;
350                case 'a':
351                        aflag = 1;
352                        break;
353                case 'B':
354                        Bflag = 1;
355                        break;
356                case 'b':
357                        bflag = 1;
358                        break;
359                case 'd':
360                        dflag = 1;
361                        break;
362                case 'F':
363                        fib = strtol(optarg, &endptr, 0);
364                        if (*endptr != '\0' ||
365                            (fib == 0 && (errno == EINVAL || errno == ERANGE)))
366                                xo_errx(1, "%s: invalid fib", optarg);
367                        break;
368                case 'f':
369                        if (strcmp(optarg, "inet") == 0)
370                                af = AF_INET;
371#ifdef INET6
372                        else if (strcmp(optarg, "inet6") == 0)
373                                af = AF_INET6;
374#endif
375#ifdef IPSEC
376                        else if (strcmp(optarg, "pfkey") == 0)
377                                af = PF_KEY;
378#endif
379                        else if (strcmp(optarg, "unix") == 0 ||
380                                 strcmp(optarg, "local") == 0)
381                                af = AF_UNIX;
382#ifdef NETGRAPH
383                        else if (strcmp(optarg, "ng") == 0
384                            || strcmp(optarg, "netgraph") == 0)
385                                af = AF_NETGRAPH;
386#endif
387                        else if (strcmp(optarg, "link") == 0)
388                                af = AF_LINK;
389                        else {
390                                xo_errx(1, "%s: unknown address family",
391                                    optarg);
392                        }
393                        break;
394                case 'g':
395                        gflag = 1;
396                        break;
397                case 'h':
398                        hflag = 1;
399                        break;
400                case 'I': {
401                        char *cp;
402
403                        iflag = 1;
404#ifndef __rtems__
405                        for (cp = interface = optarg; isalpha(*cp); cp++)
406#else /* __rtems__ */
407                        for (cp = interface = optarg; isalpha(
408                            (unsigned char) *cp); cp++)
409#endif /* __rtems__ */
410                                continue;
411                        unit = atoi(cp);
412                        break;
413                }
414                case 'i':
415                        iflag = 1;
416                        break;
417                case 'L':
418                        Lflag = 1;
419                        break;
420                case 'M':
421                        memf = optarg;
422                        break;
423                case 'm':
424                        mflag = 1;
425                        break;
426                case 'N':
427                        nlistf = optarg;
428                        break;
429                case 'n':
430                        numeric_addr = numeric_port = 1;
431                        break;
432                case 'p':
433                        if ((tp = name2protox(optarg)) == NULL) {
434                                xo_errx(1, "%s: unknown or uninstrumented "
435                                    "protocol", optarg);
436                        }
437                        pflag = 1;
438                        break;
439#ifndef __rtems__
440                case 'Q':
441                        Qflag = 1;
442                        break;
443#endif /* __rtems__ */
444                case 'q':
445                        noutputs = atoi(optarg);
446                        if (noutputs != 0)
447                                noutputs++;
448                        break;
449                case 'r':
450                        rflag = 1;
451                        break;
452                case 'R':
453                        Rflag = 1;
454                        break;
455                case 's':
456                        ++sflag;
457                        break;
458                case 'S':
459                        numeric_addr = 1;
460                        break;
461                case 'u':
462                        af = AF_UNIX;
463                        break;
464                case 'W':
465                case 'l':
466                        Wflag = 1;
467                        break;
468                case 'w':
469                        interval = atoi(optarg);
470                        iflag = 1;
471                        break;
472                case 'T':
473                        Tflag = 1;
474                        break;
475                case 'x':
476                        xflag = 1;
477                        break;
478                case 'z':
479                        zflag = 1;
480                        break;
481                case '?':
482                default:
483                        usage();
484                }
485        argv += optind;
486        argc -= optind;
487
488#define BACKWARD_COMPATIBILITY
489#ifdef  BACKWARD_COMPATIBILITY
490        if (*argv) {
491#ifndef __rtems__
492                if (isdigit(**argv)) {
493#else /* __rtems__ */
494                if (isdigit((unsigned char) **argv)) {
495#endif /* __rtems__ */
496                        interval = atoi(*argv);
497                        if (interval <= 0)
498                                usage();
499                        ++argv;
500                        iflag = 1;
501                }
502                if (*argv) {
503                        nlistf = *argv;
504                        if (*++argv)
505                                memf = *argv;
506                }
507        }
508#endif
509
510        /*
511         * Discard setgid privileges if not the running kernel so that bad
512         * guys can't print interesting stuff from kernel memory.
513         */
514        live = (nlistf == NULL && memf == NULL);
515        if (!live) {
516                if (setgid(getgid()) != 0)
517                        xo_err(-1, "setgid");
518        }
519
520        if (xflag && Tflag)
521                xo_errx(1, "-x and -T are incompatible, pick one.");
522
523        /* Load all necessary kvm symbols */
524        kresolve_list(nl);
525
526        if (Bflag) {
527                if (!live)
528                        usage();
529                bpf_stats(interface);
530                xo_finish();
531                exit(0);
532        }
533        if (mflag) {
534                if (!live) {
535                        if (kread(0, NULL, 0) == 0)
536                                mbpr(kvmd, nl[N_SFSTAT].n_value);
537                } else
538                        mbpr(NULL, 0);
539                xo_finish();
540                exit(0);
541        }
542#ifndef __rtems__
543        if (Qflag) {
544                if (!live) {
545                        if (kread(0, NULL, 0) == 0)
546                                netisr_stats();
547                } else
548                        netisr_stats();
549                xo_finish();
550                exit(0);
551        }
552#endif /* __rtems__ */
553#if 0
554        /*
555         * Keep file descriptors open to avoid overhead
556         * of open/close on each call to get* routines.
557         */
558        sethostent(1);
559        setnetent(1);
560#else
561        /*
562         * This does not make sense any more with DNS being default over
563         * the files.  Doing a setXXXXent(1) causes a tcp connection to be
564         * used for the queries, which is slower.
565         */
566#endif
567        if (iflag && !sflag) {
568                xo_open_container("statistics");
569                intpr(NULL, af);
570                xo_close_container("statistics");
571                xo_finish();
572                exit(0);
573        }
574        if (rflag) {
575                xo_open_container("statistics");
576                if (sflag) {
577                        rt_stats();
578                        flowtable_stats();
579                } else
580                        routepr(fib, af);
581                xo_close_container("statistics");
582                xo_finish();
583                exit(0);
584        }
585
586        if (gflag) {
587                xo_open_container("statistics");
588                if (sflag) {
589                        if (af == AF_INET || af == AF_UNSPEC)
590                                mrt_stats();
591#ifdef INET6
592                        if (af == AF_INET6 || af == AF_UNSPEC)
593                                mrt6_stats();
594#endif
595                } else {
596                        if (af == AF_INET || af == AF_UNSPEC)
597                                mroutepr();
598#ifdef INET6
599                        if (af == AF_INET6 || af == AF_UNSPEC)
600                                mroute6pr();
601#endif
602                }
603                xo_close_container("statistics");
604                xo_finish();
605                exit(0);
606        }
607
608        if (tp) {
609                xo_open_container("statistics");
610                printproto(tp, tp->pr_name, &first);
611                if (!first)
612                        xo_close_list("socket");
613                xo_close_container("statistics");
614                xo_finish();
615                exit(0);
616        }
617
618        xo_open_container("statistics");
619        if (af == AF_INET || af == AF_UNSPEC)
620                for (tp = protox; tp->pr_name; tp++)
621                        printproto(tp, tp->pr_name, &first);
622#ifdef INET6
623        if (af == AF_INET6 || af == AF_UNSPEC)
624                for (tp = ip6protox; tp->pr_name; tp++)
625                        printproto(tp, tp->pr_name, &first);
626#endif /*INET6*/
627#ifdef IPSEC
628        if (af == PF_KEY || af == AF_UNSPEC)
629                for (tp = pfkeyprotox; tp->pr_name; tp++)
630                        printproto(tp, tp->pr_name, &first);
631#endif /*IPSEC*/
632#ifdef NETGRAPH
633        if (af == AF_NETGRAPH || af == AF_UNSPEC)
634                for (tp = netgraphprotox; tp->pr_name; tp++)
635                        printproto(tp, tp->pr_name, &first);
636#endif /* NETGRAPH */
637#ifndef __rtems__
638        if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
639                unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
640                    nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value,
641                    nl[N_UNP_SPHEAD].n_value, &first);
642#endif /* __rtems__ */
643
644        if (!first)
645                xo_close_list("socket");
646        xo_close_container("statistics");
647        xo_finish();
648        exit(0);
649}
650
651static int
652fetch_stats_internal(const char *sysctlname, u_long off, void *stats,
653    size_t len, kreadfn_t kreadfn, int zero)
654{
655        int error;
656
657        if (live) {
658                memset(stats, 0, len);
659                if (zero)
660                        error = sysctlbyname(sysctlname, NULL, NULL, stats,
661                            len);
662                else
663                        error = sysctlbyname(sysctlname, stats, &len, NULL, 0);
664                if (error == -1 && errno != ENOENT)
665                        xo_warn("sysctl %s", sysctlname);
666        } else {
667                if (off == 0)
668                        return (1);
669                error = kreadfn(off, stats, len);
670        }
671        return (error);
672}
673
674int
675fetch_stats(const char *sysctlname, u_long off, void *stats,
676    size_t len, kreadfn_t kreadfn)
677{
678
679        return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn,
680    zflag));
681}
682
683int
684fetch_stats_ro(const char *sysctlname, u_long off, void *stats,
685    size_t len, kreadfn_t kreadfn)
686{
687
688        return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn, 0));
689}
690
691/*
692 * Print out protocol statistics or control blocks (per sflag).
693 * If the interface was not specifically requested, and the symbol
694 * is not in the namelist, ignore this one.
695 */
696static void
697#ifndef __rtems__
698printproto(struct protox *tp, const char *name, bool *first)
699#else /* __rtems__ */
700printproto(const struct protox *tp, const char *name, bool *first)
701#endif /* __rtems__ */
702{
703        void (*pr)(u_long, const char *, int, int);
704        u_long off;
705        bool doingdblocks = false;
706
707        if (sflag) {
708                if (iflag) {
709                        if (tp->pr_istats)
710                                intpr(tp->pr_istats, af);
711                        else if (pflag)
712                                xo_message("%s: no per-interface stats routine",
713                                    tp->pr_name);
714                        return;
715                } else {
716                        pr = tp->pr_stats;
717                        if (!pr) {
718                                if (pflag)
719                                        xo_message("%s: no stats routine",
720                                            tp->pr_name);
721                                return;
722                        }
723                        if (tp->pr_usesysctl && live)
724                                off = 0;
725                        else if (tp->pr_sindex < 0) {
726                                if (pflag)
727                                        xo_message("%s: stats routine doesn't "
728                                            "work on cores", tp->pr_name);
729                                return;
730                        } else
731                                off = nl[tp->pr_sindex].n_value;
732                }
733        } else {
734                doingdblocks = true;
735                pr = tp->pr_cblocks;
736                if (!pr) {
737                        if (pflag)
738                                xo_message("%s: no PCB routine", tp->pr_name);
739                        return;
740                }
741                if (tp->pr_usesysctl && live)
742                        off = 0;
743                else if (tp->pr_index < 0) {
744                        if (pflag)
745                                xo_message("%s: PCB routine doesn't work on "
746                                    "cores", tp->pr_name);
747                        return;
748                } else
749                        off = nl[tp->pr_index].n_value;
750        }
751        if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
752            af != AF_UNSPEC)) {
753                if (doingdblocks && *first) {
754                        xo_open_list("socket");
755                        *first = false;
756                }
757
758                (*pr)(off, name, af, tp->pr_protocol);
759        }
760}
761
762static int
763kvmd_init(void)
764{
765        char errbuf[_POSIX2_LINE_MAX];
766
767        if (kvmd != NULL)
768                return (0);
769
770        kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
771        if (setgid(getgid()) != 0)
772                xo_err(-1, "setgid");
773
774        if (kvmd == NULL) {
775                xo_warnx("kvm not available: %s", errbuf);
776                return (-1);
777        }
778
779        return (0);
780}
781
782/*
783 * Resolve symbol list, return 0 on success.
784 */
785static int
786kresolve_list(struct nlist *_nl)
787{
788
789        if ((kvmd == NULL) && (kvmd_init() != 0))
790                return (-1);
791
792        if (_nl[0].n_type != 0)
793                return (0);
794
795        if (kvm_nlist(kvmd, _nl) < 0) {
796                if (nlistf)
797                        xo_errx(1, "%s: kvm_nlist: %s", nlistf,
798                            kvm_geterr(kvmd));
799                else
800                        xo_errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
801        }
802
803        return (0);
804}
805
806/*
807 * Wrapper of kvm_dpcpu_setcpu().
808 */
809void
810kset_dpcpu(u_int cpuid)
811{
812
813        if ((kvmd == NULL) && (kvmd_init() != 0))
814                xo_errx(-1, "%s: kvm is not available", __func__);
815
816        if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0)
817                xo_errx(-1, "%s: kvm_dpcpu_setcpu(%u): %s", __func__,
818                    cpuid, kvm_geterr(kvmd));
819        return;
820}
821
822/*
823 * Read kernel memory, return 0 on success.
824 */
825int
826kread(u_long addr, void *buf, size_t size)
827{
828
829        if (kvmd_init() < 0)
830                return (-1);
831
832        if (!buf)
833                return (0);
834        if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
835                xo_warnx("%s", kvm_geterr(kvmd));
836                return (-1);
837        }
838        return (0);
839}
840
841/*
842 * Read single counter(9).
843 */
844uint64_t
845kread_counter(u_long addr)
846{
847
848        if (kvmd_init() < 0)
849                return (-1);
850
851        return (kvm_counter_u64_fetch(kvmd, addr));
852}
853
854/*
855 * Read an array of N counters in kernel memory into array of N uint64_t's.
856 */
857int
858kread_counters(u_long addr, void *buf, size_t size)
859{
860#ifndef __rtems__
861        uint64_t *c;
862        u_long *counters;
863        size_t i, n;
864
865        if (kvmd_init() < 0)
866                return (-1);
867
868        if (size % sizeof(uint64_t) != 0) {
869                xo_warnx("kread_counters: invalid counter set size");
870                return (-1);
871        }
872
873        n = size / sizeof(uint64_t);
874        if ((counters = malloc(n * sizeof(u_long))) == NULL)
875                xo_err(-1, "malloc");
876        if (kread(addr, counters, n * sizeof(u_long)) < 0) {
877                free(counters);
878                return (-1);
879        }
880
881        c = buf;
882        for (i = 0; i < n; i++)
883                c[i] = kvm_counter_u64_fetch(kvmd, counters[i]);
884
885        free(counters);
886        return (0);
887#else /* __rtems__ */
888        return (-1);
889#endif /* __rtems__ */
890}
891
892const char *
893plural(uintmax_t n)
894{
895        return (n != 1 ? "s" : "");
896}
897
898const char *
899plurales(uintmax_t n)
900{
901        return (n != 1 ? "es" : "");
902}
903
904const char *
905pluralies(uintmax_t n)
906{
907        return (n != 1 ? "ies" : "y");
908}
909
910/*
911 * Find the protox for the given "well-known" name.
912 */
913#ifndef __rtems__
914static struct protox *
915#else /* __rtems__ */
916static const struct protox *
917#endif /* __rtems__ */
918knownname(const char *name)
919{
920#ifndef __rtems__
921        struct protox **tpp, *tp;
922#else /* __rtems__ */
923        const struct protox *const *tpp, *tp;
924#endif /* __rtems__ */
925
926        for (tpp = protoprotox; *tpp; tpp++)
927                for (tp = *tpp; tp->pr_name; tp++)
928                        if (strcmp(tp->pr_name, name) == 0)
929                                return (tp);
930        return (NULL);
931}
932
933/*
934 * Find the protox corresponding to name.
935 */
936#ifndef __rtems__
937static struct protox *
938#else /* __rtems__ */
939static const struct protox *
940#endif /* __rtems__ */
941name2protox(const char *name)
942{
943#ifndef __rtems__
944        struct protox *tp;
945#else /* __rtems__ */
946        const struct protox *tp;
947#endif /* __rtems__ */
948        char **alias;                   /* alias from p->aliases */
949        struct protoent *p;
950
951        /*
952         * Try to find the name in the list of "well-known" names. If that
953         * fails, check if name is an alias for an Internet protocol.
954         */
955        if ((tp = knownname(name)) != NULL)
956                return (tp);
957
958        setprotoent(1);                 /* make protocol lookup cheaper */
959        while ((p = getprotoent()) != NULL) {
960                /* assert: name not same as p->name */
961                for (alias = p->p_aliases; *alias; alias++)
962                        if (strcmp(name, *alias) == 0) {
963                                endprotoent();
964                                return (knownname(p->p_name));
965                        }
966        }
967        endprotoent();
968        return (NULL);
969}
970
971static void
972usage(void)
973{
974        (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",
975"usage: netstat [-46AaLnRSTWx] [-f protocol_family | -p protocol]\n"
976"               [-M core] [-N system]",
977"       netstat -i | -I interface [-46abdhnW] [-f address_family]\n"
978"               [-M core] [-N system]",
979"       netstat -w wait [-I interface] [-46d] [-M core] [-N system]\n"
980"               [-q howmany]",
981"       netstat -s [-46sz] [-f protocol_family | -p protocol]\n"
982"               [-M core] [-N system]",
983"       netstat -i | -I interface -s [-46s]\n"
984"               [-f protocol_family | -p protocol] [-M core] [-N system]",
985"       netstat -m [-M core] [-N system]",
986"       netstat -B [-z] [-I interface]",
987"       netstat -r [-46AnW] [-F fibnum] [-f address_family]\n"
988"               [-M core] [-N system]",
989"       netstat -rs [-s] [-M core] [-N system]",
990"       netstat -g [-46W] [-f address_family] [-M core] [-N system]",
991"       netstat -gs [-46s] [-f address_family] [-M core] [-N system]",
992"       netstat -Q");
993        xo_finish();
994        exit(1);
995}
Note: See TracBrowser for help on using the repository browser.