source: rtems-libbsd/freebsd/usr.bin/netstat/main.c @ 87d0cda

4.11
Last change on this file since 87d0cda was 7eeb079, checked in by Sebastian Huber <sebastian.huber@…>, on 02/02/15 at 13:27:13

Update to FreeBSD 9.3

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