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

4.11
Last change on this file since fef6dd1 was fef6dd1, checked in by Christian Mauderer <Christian.Mauderer@…>, on 07/15/16 at 05:32:56

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