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

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 21abaef was 21abaef, checked in by Christian Mauderer <Christian.Mauderer@…>, on Jul 15, 2016 at 5:32:56 AM

freebsd: Don't use new wrappers for old ports.

Some of the commands have been adapted manually. So the wrapper
currently don't necessarily work as expected. For example ifconfig calls
malloc outside of the program call.

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