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

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 1061324 was 1061324, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 18, 2015 at 8:47:10 AM

NETSTAT(1): Avoid use of uninitialized memory

  • 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        nlistf = NULL;
391        memf = NULL;
392
393        Aflag = 0;
394        aflag = 0;
395        Bflag = 0;
396        bflag = 0;
397        dflag = 0;
398        gflag = 0;
399        hflag = 0;
400        iflag = 0;
401        Lflag = 0;
402        mflag = 0;
403        noutputs = 0;
404        numeric_addr = 0;
405        numeric_port = 0;
406        pflag = 0;
407        rflag = 0;
408        sflag = 0;
409        Wflag = 0;
410        xflag = 0;
411        zflag = 0;
412        interval = 0;
413        interface = 0;
414        unit = 0;
415        af = 0;
416        live = 0;
417
418        protopr_initialized = 0;
419        do_rtent = 0;
420
421        rtems_bsd_netstat_inet_init();
422
423        exit_code = rtems_bsd_program_call_main("netstat", main, argc, argv);
424
425        free(rt_tables);
426        rt_tables = NULL;
427
428        rtems_bsd_program_unlock();
429
430        return exit_code;
431}
432#endif /* __rtems__ */
433int
434main(int argc, char *argv[])
435{
436        const struct protox *tp = NULL;  /* for printing cblocks & stats */
437        int ch;
438#ifdef __rtems__
439        struct getopt_data getopt_data;
440        memset(&getopt_data, 0, sizeof(getopt_data));
441#define optind getopt_data.optind
442#define optarg getopt_data.optarg
443#define opterr getopt_data.opterr
444#define optopt getopt_data.optopt
445#define getopt(argc, argv, opt) getopt_r(argc, argv, "+" opt, &getopt_data)
446#endif /* __rtems__ */
447
448        af = AF_UNSPEC;
449
450        while ((ch = getopt(argc, argv, "46AaBbdf:ghI:iLlM:mN:np:Qq:rSTsuWw:xz"))
451            != -1)
452                switch(ch) {
453                case '4':
454#ifdef INET
455                        af = AF_INET;
456#else
457                        errx(1, "IPv4 support is not compiled in");
458#endif
459                        break;
460                case '6':
461#ifdef INET6
462                        af = AF_INET6;
463#else
464                        errx(1, "IPv6 support is not compiled in");
465#endif
466                        break;
467                case 'A':
468                        Aflag = 1;
469                        break;
470                case 'a':
471                        aflag = 1;
472                        break;
473                case 'B':
474                        Bflag = 1;
475                        break;
476                case 'b':
477                        bflag = 1;
478                        break;
479                case 'd':
480                        dflag = 1;
481                        break;
482                case 'f':
483                        if (strcmp(optarg, "ipx") == 0)
484                                af = AF_IPX;
485                        else if (strcmp(optarg, "inet") == 0)
486                                af = AF_INET;
487#ifdef INET6
488                        else if (strcmp(optarg, "inet6") == 0)
489                                af = AF_INET6;
490#endif
491#ifdef IPSEC
492                        else if (strcmp(optarg, "pfkey") == 0)
493                                af = PF_KEY;
494#endif
495                        else if (strcmp(optarg, "unix") == 0)
496                                af = AF_UNIX;
497                        else if (strcmp(optarg, "atalk") == 0)
498                                af = AF_APPLETALK;
499#ifdef NETGRAPH
500                        else if (strcmp(optarg, "ng") == 0
501                            || strcmp(optarg, "netgraph") == 0)
502                                af = AF_NETGRAPH;
503#endif
504                        else if (strcmp(optarg, "link") == 0)
505                                af = AF_LINK;
506                        else {
507                                errx(1, "%s: unknown address family", optarg);
508                        }
509                        break;
510                case 'g':
511                        gflag = 1;
512                        break;
513                case 'h':
514                        hflag = 1;
515                        break;
516                case 'I': {
517                        char *cp;
518
519                        iflag = 1;
520                        for (cp = interface = optarg; isalpha((unsigned char) *cp); cp++)
521                                continue;
522                        unit = atoi(cp);
523                        break;
524                }
525                case 'i':
526                        iflag = 1;
527                        break;
528                case 'L':
529                        Lflag = 1;
530                        break;
531                case 'M':
532                        memf = optarg;
533                        break;
534                case 'm':
535                        mflag = 1;
536                        break;
537                case 'N':
538                        nlistf = optarg;
539                        break;
540                case 'n':
541                        numeric_addr = numeric_port = 1;
542                        break;
543                case 'p':
544                        if ((tp = name2protox(optarg)) == NULL) {
545                                errx(1,
546                                     "%s: unknown or uninstrumented protocol",
547                                     optarg);
548                        }
549                        pflag = 1;
550                        break;
551#ifndef __rtems__
552                case 'Q':
553                        Qflag = 1;
554                        break;
555#endif /* __rtems__ */
556                case 'q':
557                        noutputs = atoi(optarg);
558                        if (noutputs != 0)
559                                noutputs++;
560                        break;
561                case 'r':
562                        rflag = 1;
563                        break;
564                case 's':
565                        ++sflag;
566                        break;
567                case 'S':
568                        numeric_addr = 1;
569                        break;
570                case 'u':
571                        af = AF_UNIX;
572                        break;
573                case 'W':
574                case 'l':
575                        Wflag = 1;
576                        break;
577                case 'w':
578                        interval = atoi(optarg);
579                        iflag = 1;
580                        break;
581                case 'T':
582                        Tflag = 1;
583                        break;
584                case 'x':
585                        xflag = 1;
586                        break;
587                case 'z':
588                        zflag = 1;
589                        break;
590                case '?':
591                default:
592                        usage();
593                }
594        argv += optind;
595        argc -= optind;
596
597#define BACKWARD_COMPATIBILITY
598#ifdef  BACKWARD_COMPATIBILITY
599        if (*argv) {
600                if (isdigit((unsigned char) **argv)) {
601                        interval = atoi(*argv);
602                        if (interval <= 0)
603                                usage();
604                        ++argv;
605                        iflag = 1;
606                }
607                if (*argv) {
608                        nlistf = *argv;
609                        if (*++argv)
610                                memf = *argv;
611                }
612        }
613#endif
614
615        /*
616         * Discard setgid privileges if not the running kernel so that bad
617         * guys can't print interesting stuff from kernel memory.
618         */
619        live = (nlistf == NULL && memf == NULL);
620        if (!live)
621                setgid(getgid());
622
623        if (xflag && Tflag) 
624                errx(1, "-x and -T are incompatible, pick one.");
625
626        if (Bflag) {
627                if (!live)
628                        usage();
629                bpf_stats(interface);
630                exit(0);
631        }
632        if (mflag) {
633                if (!live) {
634                        if (kread(0, NULL, 0) == 0)
635                                mbpr(kvmd, nl[N_MBSTAT].n_value);
636                } else
637                        mbpr(NULL, 0);
638                exit(0);
639        }
640#ifndef __rtems__
641        if (Qflag) {
642                if (!live) {
643                        if (kread(0, NULL, 0) == 0)
644                                netisr_stats(kvmd);
645                } else
646                        netisr_stats(NULL);
647                exit(0);
648        }
649#endif /* __rtems__ */
650#if 0
651        /*
652         * Keep file descriptors open to avoid overhead
653         * of open/close on each call to get* routines.
654         */
655        sethostent(1);
656        setnetent(1);
657#else
658        /*
659         * This does not make sense any more with DNS being default over
660         * the files.  Doing a setXXXXent(1) causes a tcp connection to be
661         * used for the queries, which is slower.
662         */
663#endif
664        kread(0, NULL, 0);
665        if (iflag && !sflag) {
666                intpr(interval, nl[N_IFNET].n_value, NULL);
667                exit(0);
668        }
669        if (rflag) {
670                if (sflag)
671                        rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
672                else
673                        routepr(nl[N_RTREE].n_value);
674                exit(0);
675        }
676        if (gflag) {
677                if (sflag) {
678                        if (af == AF_INET || af == AF_UNSPEC)
679                                mrt_stats(nl[N_MRTSTAT].n_value);
680#ifdef INET6
681                        if (af == AF_INET6 || af == AF_UNSPEC)
682                                mrt6_stats(nl[N_MRT6STAT].n_value);
683#endif
684                } else {
685                        if (af == AF_INET || af == AF_UNSPEC)
686                                mroutepr(nl[N_MFCHASHTBL].n_value,
687                                         nl[N_MFCTABLESIZE].n_value,
688                                         nl[N_VIFTABLE].n_value);
689#ifdef INET6
690                        if (af == AF_INET6 || af == AF_UNSPEC)
691                                mroute6pr(nl[N_MF6CTABLE].n_value,
692                                          nl[N_MIF6TABLE].n_value);
693#endif
694                }
695                exit(0);
696        }
697
698        if (tp) {
699                printproto(tp, tp->pr_name);
700                exit(0);
701        }
702        if (af == AF_INET || af == AF_UNSPEC)
703                for (tp = protox; tp->pr_name; tp++)
704                        printproto(tp, tp->pr_name);
705#ifdef INET6
706        if (af == AF_INET6 || af == AF_UNSPEC)
707                for (tp = ip6protox; tp->pr_name; tp++)
708                        printproto(tp, tp->pr_name);
709#endif /*INET6*/
710#ifdef IPSEC
711        if (af == PF_KEY || af == AF_UNSPEC)
712                for (tp = pfkeyprotox; tp->pr_name; tp++)
713                        printproto(tp, tp->pr_name);
714#endif /*IPSEC*/
715#ifdef IPX
716        if (af == AF_IPX || af == AF_UNSPEC) {
717                for (tp = ipxprotox; tp->pr_name; tp++)
718                        printproto(tp, tp->pr_name);
719        }
720#endif /* IPX */
721#ifndef __rtems__
722        if (af == AF_APPLETALK || af == AF_UNSPEC)
723                for (tp = atalkprotox; tp->pr_name; tp++)
724                        printproto(tp, tp->pr_name);
725#endif
726#ifdef NETGRAPH
727        if (af == AF_NETGRAPH || af == AF_UNSPEC)
728                for (tp = netgraphprotox; tp->pr_name; tp++)
729                        printproto(tp, tp->pr_name);
730#endif /* NETGRAPH */
731#ifndef __rtems__
732        if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
733                unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
734                    nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value,
735                    nl[N_UNP_SPHEAD].n_value);
736#endif
737        exit(0);
738}
739
740/*
741 * Print out protocol statistics or control blocks (per sflag).
742 * If the interface was not specifically requested, and the symbol
743 * is not in the namelist, ignore this one.
744 */
745static void
746printproto(tp, name)
747        const struct protox *tp;
748        const char *name;
749{
750        void (*pr)(u_long, const char *, int, int);
751        u_long off;
752
753        if (sflag) {
754                if (iflag) {
755                        if (tp->pr_istats)
756                                intpr(interval, nl[N_IFNET].n_value,
757                                      tp->pr_istats);
758                        else if (pflag)
759                                printf("%s: no per-interface stats routine\n",
760                                    tp->pr_name);
761                        return;
762                } else {
763                        pr = tp->pr_stats;
764                        if (!pr) {
765                                if (pflag)
766                                        printf("%s: no stats routine\n",
767                                            tp->pr_name);
768                                return;
769                        }
770                        if (tp->pr_usesysctl && live)
771                                off = 0;
772                        else if (tp->pr_sindex < 0) {
773                                if (pflag)
774                                        printf(
775                                    "%s: stats routine doesn't work on cores\n",
776                                            tp->pr_name);
777                                return;
778                        } else
779                                off = nl[tp->pr_sindex].n_value;
780                }
781        } else {
782                pr = tp->pr_cblocks;
783                if (!pr) {
784                        if (pflag)
785                                printf("%s: no PCB routine\n", tp->pr_name);
786                        return;
787                }
788                if (tp->pr_usesysctl && live)
789                        off = 0;
790                else if (tp->pr_index < 0) {
791                        if (pflag)
792                                printf(
793                                    "%s: PCB routine doesn't work on cores\n",
794                                    tp->pr_name);
795                        return;
796                } else
797                        off = nl[tp->pr_index].n_value;
798        }
799        if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
800            af != AF_UNSPEC))
801                (*pr)(off, name, af, tp->pr_protocol);
802}
803
804/*
805 * Read kernel memory, return 0 on success.
806 */
807int
808kread(u_long addr, void *buf, size_t size)
809{
810        char errbuf[_POSIX2_LINE_MAX];
811
812        if (kvmd == NULL) {
813                kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
814                setgid(getgid());
815                if (kvmd != NULL) {
816                        if (kvm_nlist(kvmd, nl) < 0) {
817                                if (nlistf)
818                                        errx(1, "%s: kvm_nlist: %s", nlistf,
819                                             kvm_geterr(kvmd));
820                                else
821                                        errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
822                        }
823
824                        if (nl[0].n_type == 0) {
825                                if (nlistf)
826                                        errx(1, "%s: no namelist", nlistf);
827                                else
828                                        errx(1, "no namelist");
829                        }
830                } else {
831                        warnx("kvm not available: %s", errbuf);
832                        return(-1);
833                }
834        }
835        if (!buf)
836                return (0);
837        if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
838                warnx("%s", kvm_geterr(kvmd));
839                return (-1);
840        }
841        return (0);
842}
843
844const char *
845plural(uintmax_t n)
846{
847        return (n != 1 ? "s" : "");
848}
849
850const char *
851plurales(uintmax_t n)
852{
853        return (n != 1 ? "es" : "");
854}
855
856const char *
857pluralies(uintmax_t n)
858{
859        return (n != 1 ? "ies" : "y");
860}
861
862/*
863 * Find the protox for the given "well-known" name.
864 */
865static const struct protox *
866knownname(const char *name)
867{
868        const struct protox **tpp, *tp;
869
870        for (tpp = protoprotox; *tpp; tpp++)
871                for (tp = *tpp; tp->pr_name; tp++)
872                        if (strcmp(tp->pr_name, name) == 0)
873                                return (tp);
874        return (NULL);
875}
876
877/*
878 * Find the protox corresponding to name.
879 */
880static const struct protox *
881name2protox(const char *name)
882{
883        const struct protox *tp;
884        char **alias;                   /* alias from p->aliases */
885        struct protoent *p;
886
887        /*
888         * Try to find the name in the list of "well-known" names. If that
889         * fails, check if name is an alias for an Internet protocol.
890         */
891        if ((tp = knownname(name)) != NULL)
892                return (tp);
893
894        setprotoent(1);                 /* make protocol lookup cheaper */
895        while ((p = getprotoent()) != NULL) {
896                /* assert: name not same as p->name */
897                for (alias = p->p_aliases; *alias; alias++)
898                        if (strcmp(name, *alias) == 0) {
899                                endprotoent();
900                                return (knownname(p->p_name));
901                        }
902        }
903        endprotoent();
904        return (NULL);
905}
906
907static void
908usage(void)
909{
910        (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",
911"usage: netstat [-46AaLnSTWx] [-f protocol_family | -p protocol]\n"
912"               [-M core] [-N system]",
913"       netstat -i | -I interface [-46abdhnW] [-f address_family]\n"
914"               [-M core] [-N system]",
915"       netstat -w wait [-I interface] [-46d] [-M core] [-N system] [-q howmany]",
916"       netstat -s [-s] [-46z] [-f protocol_family | -p protocol]\n"
917"               [-M core] [-N system]",
918"       netstat -i | -I interface [-46s] [-f protocol_family | -p protocol]\n"
919"               [-M core] [-N system]",
920"       netstat -m [-M core] [-N system]",
921"       netstat -B [-I interface]",
922"       netstat -r [-46AanW] [-f address_family] [-M core] [-N system]",
923"       netstat -rs [-s] [-M core] [-N system]",
924"       netstat -g [-46W] [-f address_family] [-M core] [-N system]",
925"       netstat -gs [-46s] [-f address_family] [-M core] [-N system]",
926"       netstat -Q");
927        exit(1);
928}
Note: See TracBrowser for help on using the repository browser.