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

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since d01564c was d01564c, checked in by Sebastian Huber <sebastian.huber@…>, on 10/17/13 at 08:38:34

Move program control to thread structure

  • Property mode set to 100644
File size: 31.6 KB
Line 
1/*-
2 * Copyright (c) 1983, 1988, 1993
3 *      Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35char const copyright[] =
36"@(#) Copyright (c) 1983, 1988, 1993\n\
37        Regents of the University of California.  All rights reserved.\n";
38#endif /* not lint */
39
40#if 0
41#ifndef lint
42static char sccsid[] = "@(#)main.c      8.4 (Berkeley) 3/1/94";
43#endif /* not lint */
44#endif
45
46#ifdef __rtems__
47#define __need_getopt_newlib
48#include <getopt.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        { .n_name = NULL },
194};
195
196struct protox {
197        int     pr_index;               /* index into nlist of cb head */
198        int     pr_sindex;              /* index into nlist of stat block */
199        u_char  pr_wanted;              /* 1 if wanted, 0 otherwise */
200        void    (*pr_cblocks)(u_long, const char *, int, int);
201                                        /* control blocks printing routine */
202        void    (*pr_stats)(u_long, const char *, int, int);
203                                        /* statistics printing routine */
204        void    (*pr_istats)(char *);   /* per/if statistics printing routine */
205        const char      *pr_name;               /* well-known name */
206        int     pr_usesysctl;           /* non-zero if we use sysctl, not kvm */
207        int     pr_protocol;
208} protox[] = {
209        { N_TCBINFO,    N_TCPSTAT,      1,      protopr,
210          tcp_stats,    NULL,           "tcp",  1,      IPPROTO_TCP },
211        { N_UDBINFO,    N_UDPSTAT,      1,      protopr,
212          udp_stats,    NULL,           "udp",  1,      IPPROTO_UDP },
213#ifdef SCTP
214        { -1,           N_SCTPSTAT,     1,      sctp_protopr,
215          sctp_stats,   NULL,           "sctp", 1,      IPPROTO_SCTP },
216#endif
217        { N_DIVCBINFO,  -1,             1,      protopr,
218          NULL,         NULL,           "divert", 1,    IPPROTO_DIVERT },
219        { N_RIPCBINFO,  N_IPSTAT,       1,      protopr,
220          ip_stats,     NULL,           "ip",   1,      IPPROTO_RAW },
221        { N_RIPCBINFO,  N_ICMPSTAT,     1,      protopr,
222          icmp_stats,   NULL,           "icmp", 1,      IPPROTO_ICMP },
223        { N_RIPCBINFO,  N_IGMPSTAT,     1,      protopr,
224          igmp_stats,   NULL,           "igmp", 1,      IPPROTO_IGMP },
225#ifdef IPSEC
226        { -1,           N_IPSECSTAT,    1,      NULL,   /* keep as compat */
227          ipsec_stats,  NULL,           "ipsec", 0,     0},
228        { -1,           N_AHSTAT,       1,      NULL,
229          ah_stats,     NULL,           "ah",   0,      0},
230        { -1,           N_ESPSTAT,      1,      NULL,
231          esp_stats,    NULL,           "esp",  0,      0},
232        { -1,           N_IPCOMPSTAT,   1,      NULL,
233          ipcomp_stats, NULL,           "ipcomp", 0,    0},
234#endif
235        { N_RIPCBINFO,  N_PIMSTAT,      1,      protopr,
236          pim_stats,    NULL,           "pim",  1,      IPPROTO_PIM },
237        { -1,           N_CARPSTAT,     1,      NULL,
238          carp_stats,   NULL,           "carp", 1,      0 },
239        { -1,           N_PFSYNCSTAT,   1,      NULL,
240          pfsync_stats, NULL,           "pfsync", 1,    0 },
241        { -1,           N_ARPSTAT,      1,      NULL,
242          arp_stats,    NULL,           "arp", 1,       0 },
243        { -1,           -1,             0,      NULL,
244          NULL,         NULL,           NULL,   0,      0 }
245};
246
247#ifdef INET6
248struct protox ip6protox[] = {
249        { N_TCBINFO,    N_TCPSTAT,      1,      protopr,
250          tcp_stats,    NULL,           "tcp",  1,      IPPROTO_TCP },
251        { N_UDBINFO,    N_UDPSTAT,      1,      protopr,
252          udp_stats,    NULL,           "udp",  1,      IPPROTO_UDP },
253        { N_RIPCBINFO,  N_IP6STAT,      1,      protopr,
254          ip6_stats,    ip6_ifstats,    "ip6",  1,      IPPROTO_RAW },
255        { N_RIPCBINFO,  N_ICMP6STAT,    1,      protopr,
256          icmp6_stats,  icmp6_ifstats,  "icmp6", 1,     IPPROTO_ICMPV6 },
257#ifdef IPSEC
258        { -1,           N_IPSEC6STAT,   1,      NULL,
259          ipsec_stats,  NULL,           "ipsec6", 0,    0 },
260#endif
261#ifdef notyet
262        { -1,           N_PIM6STAT,     1,      NULL,
263          pim6_stats,   NULL,           "pim6", 1,      0 },
264#endif
265        { -1,           N_RIP6STAT,     1,      NULL,
266          rip6_stats,   NULL,           "rip6", 1,      0 },
267        { -1,           -1,             0,      NULL,
268          NULL,         NULL,           NULL,   0,      0 }
269};
270#endif /*INET6*/
271
272#ifdef IPSEC
273struct protox pfkeyprotox[] = {
274        { -1,           N_PFKEYSTAT,    1,      NULL,
275          pfkey_stats,  NULL,           "pfkey", 0,     0 },
276        { -1,           -1,             0,      NULL,
277          NULL,         NULL,           NULL,   0,      0 }
278};
279#endif
280
281#ifndef __rtems__
282struct protox atalkprotox[] = {
283        { N_DDPCB,      N_DDPSTAT,      1,      atalkprotopr,
284          ddp_stats,    NULL,           "ddp",  0,      0 },
285        { -1,           -1,             0,      NULL,
286          NULL,         NULL,           NULL,   0,      0 }
287};
288#endif
289#ifdef NETGRAPH
290struct protox netgraphprotox[] = {
291        { N_NGSOCKS,    -1,             1,      netgraphprotopr,
292          NULL,         NULL,           "ctrl", 0,      0 },
293        { N_NGSOCKS,    -1,             1,      netgraphprotopr,
294          NULL,         NULL,           "data", 0,      0 },
295        { -1,           -1,             0,      NULL,
296          NULL,         NULL,           NULL,   0,      0 }
297};
298#endif
299#ifdef IPX
300struct protox ipxprotox[] = {
301        { N_IPX,        N_IPXSTAT,      1,      ipxprotopr,
302          ipx_stats,    NULL,           "ipx",  0,      0 },
303        { N_IPX,        N_SPXSTAT,      1,      ipxprotopr,
304          spx_stats,    NULL,           "spx",  0,      0 },
305        { -1,           -1,             0,      NULL,
306          NULL,         NULL,           0,      0,      0 }
307};
308#endif
309
310struct protox *protoprotox[] = {
311                                         protox,
312#ifdef INET6
313                                         ip6protox,
314#endif
315#ifdef IPSEC
316                                         pfkeyprotox,
317#endif
318#ifdef IPX
319                                         ipxprotox,
320#endif
321#ifndef __rtems__
322                                         atalkprotox, NULL };
323#else
324                                NULL };
325#endif
326
327static void printproto(struct protox *, const char *);
328static void usage(void);
329static struct protox *name2protox(const char *);
330static struct protox *knownname(const char *);
331
332static kvm_t *kvmd;
333static char *nlistf = NULL, *memf = NULL;
334
335int     Aflag;          /* show addresses of protocol control block */
336int     aflag;          /* show all sockets (including servers) */
337int     Bflag;          /* show information about bpf consumers */
338int     bflag;          /* show i/f total bytes in/out */
339int     dflag;          /* show i/f dropped packets */
340int     gflag;          /* show group (multicast) routing or stats */
341int     hflag;          /* show counters in human readable format */
342int     iflag;          /* show interfaces */
343int     Lflag;          /* show size of listen queues */
344int     mflag;          /* show memory stats */
345int     noutputs = 0;   /* how much outputs before we exit */
346int     numeric_addr;   /* show addresses numerically */
347int     numeric_port;   /* show ports numerically */
348static int pflag;       /* show given protocol */
349int     rflag;          /* show routing tables (or routing stats) */
350int     sflag;          /* show protocol statistics */
351int     tflag;          /* show i/f watchdog timers */
352int     Wflag;          /* wide display */
353int     xflag;          /* extra information, includes all socket buffer info */
354int     zflag;          /* zero stats */
355
356int     interval;       /* repeat interval for i/f stats */
357
358char    *interface;     /* desired i/f for stats, or NULL for all i/fs */
359int     unit;           /* unit number for above */
360
361int     af;             /* address family */
362int     live;           /* true if we are examining a live system */
363
364#ifdef __rtems__
365#include <machine/rtems-bsd-program.h>
366
367static int main(int argc, char *argv[]);
368
369static int rtems_shell_main_netstat(int argc, char *argv[])
370{
371  int i;
372
373  i = 0;
374  protox[i].pr_index     = N_TCBINFO;
375  protox[i].pr_sindex    = N_TCPSTAT;
376  protox[i].pr_wanted    = 1;
377  protox[i].pr_cblocks   = protopr;
378  protox[i].pr_stats     = tcp_stats;
379  protox[i].pr_istats    = NULL;
380  protox[i].pr_name      = "tcp";
381  protox[i].pr_usesysctl = 1;
382  protox[i].pr_protocol  = IPPROTO_TCP;
383  i++;
384  protox[i].pr_index     = N_UDBINFO;
385  protox[i].pr_sindex    = N_UDPSTAT;
386  protox[i].pr_wanted    = 1;
387  protox[i].pr_cblocks   = protopr;
388  protox[i].pr_stats     = udp_stats;
389  protox[i].pr_istats    = NULL;
390  protox[i].pr_name      = "udp";
391  protox[i].pr_usesysctl = 1;
392  protox[i].pr_protocol  = IPPROTO_UDP;
393  i++;
394#ifdef SCTP
395  protox[i].pr_index     = -1;
396  protox[i].pr_sindex    = N_SCTPSTAT;
397  protox[i].pr_wanted    = 1;
398  protox[i].pr_cblocks   = sctp_protopr;
399  protox[i].pr_stats     = sctp_stats;
400  protox[i].pr_istats    = NULL;
401  protox[i].pr_name      = "sctp";
402  protox[i].pr_usesysctl = 1;
403  protox[i].pr_protocol  = IPPROTO_SCTP;
404  i++;
405#endif
406  protox[i].pr_index     = N_DIVCBINFO;
407  protox[i].pr_sindex    = -1;
408  protox[i].pr_wanted    = 1;
409  protox[i].pr_cblocks   = protopr;
410  protox[i].pr_stats     = NULL;
411  protox[i].pr_istats    = NULL;
412  protox[i].pr_name      = "divert";
413  protox[i].pr_usesysctl = 1;
414  protox[i].pr_protocol  = IPPROTO_DIVERT;
415  i++;
416  protox[i].pr_index     = N_RIPCBINFO;
417  protox[i].pr_sindex    = N_IPSTAT;
418  protox[i].pr_wanted    = 1;
419  protox[i].pr_cblocks   = protopr;
420  protox[i].pr_stats     = ip_stats;
421  protox[i].pr_istats    = NULL;
422  protox[i].pr_name      = "ip";
423  protox[i].pr_usesysctl = 1;
424  protox[i].pr_protocol  = IPPROTO_RAW;
425  i++;
426  protox[i].pr_index     = N_RIPCBINFO;
427  protox[i].pr_sindex    = N_ICMPSTAT;
428  protox[i].pr_wanted    = 1;
429  protox[i].pr_cblocks   = protopr;
430  protox[i].pr_stats     = icmp_stats;
431  protox[i].pr_istats    = NULL;
432  protox[i].pr_name      = "icmp";
433  protox[i].pr_usesysctl = 1;
434  protox[i].pr_protocol  = IPPROTO_ICMP;
435  i++;
436  protox[i].pr_index     = N_RIPCBINFO;
437  protox[i].pr_sindex    = N_IGMPSTAT;
438  protox[i].pr_wanted    = 1;
439  protox[i].pr_cblocks   = protopr;
440  protox[i].pr_stats     = igmp_stats;
441  protox[i].pr_istats    = NULL;
442  protox[i].pr_name      = "igmp";
443  protox[i].pr_usesysctl = 1;
444  protox[i].pr_protocol  = IPPROTO_IGMP;
445  i++;
446#ifdef IPSEC
447  protox[i].pr_index     = -1;
448  protox[i].pr_sindex    = N_IPSECSTAT;
449  protox[i].pr_wanted    = 1;
450  protox[i].pr_cblocks   = NULL;
451  protox[i].pr_stats     = ipsec_stats;
452  protox[i].pr_istats    = NULL;
453  protox[i].pr_name      = "ipsec";
454  protox[i].pr_usesysctl = 0;
455  protox[i].pr_protocol  = 0;
456  i++;
457  protox[i].pr_index     = -1;
458  protox[i].pr_sindex    = N_AHSTAT;
459  protox[i].pr_wanted    = 1;
460  protox[i].pr_cblocks   = NULL;
461  protox[i].pr_stats     = ah_stats;
462  protox[i].pr_istats    = NULL;
463  protox[i].pr_name      = "ah";
464  protox[i].pr_usesysctl = 0;
465  protox[i].pr_protocol  = 0;
466  i++;
467  protox[i].pr_index     = -1;
468  protox[i].pr_sindex    = N_ESPSTAT;
469  protox[i].pr_wanted    = 1;
470  protox[i].pr_cblocks   = NULL;
471  protox[i].pr_stats     = esp_stats;
472  protox[i].pr_istats    = NULL;
473  protox[i].pr_name      = "esp";
474  protox[i].pr_usesysctl = 0;
475  protox[i].pr_protocol  = 0;
476  i++;
477  protox[i].pr_index     = -1;
478  protox[i].pr_sindex    = N_IPCOMPSTAT;
479  protox[i].pr_wanted    = 1;
480  protox[i].pr_cblocks   = NULL;
481  protox[i].pr_stats     = ipcomp_stats;
482  protox[i].pr_istats    = NULL;
483  protox[i].pr_name      = "ipcomp";
484  protox[i].pr_usesysctl = 0;
485  protox[i].pr_protocol  = 0;
486  i++;
487#endif
488  protox[i].pr_index     = N_RIPCBINFO;
489  protox[i].pr_sindex    = N_PIMSTAT;
490  protox[i].pr_wanted    = 1;
491  protox[i].pr_cblocks   = protopr;
492  protox[i].pr_stats     = pim_stats;
493  protox[i].pr_istats    = NULL;
494  protox[i].pr_name      = "pim";
495  protox[i].pr_usesysctl = 1;
496  protox[i].pr_protocol  = IPPROTO_PIM;
497  i++;
498  protox[i].pr_index     =  -1;
499  protox[i].pr_sindex    = N_CARPSTAT;
500  protox[i].pr_wanted    = 1;
501  protox[i].pr_cblocks   = NULL;
502  protox[i].pr_stats     = carp_stats;
503  protox[i].pr_istats    = NULL;
504  protox[i].pr_name      = "carp";
505  protox[i].pr_usesysctl = 1;
506  protox[i].pr_protocol  = 0;
507  i++;
508  protox[i].pr_index     =  -1;
509  protox[i].pr_sindex    = N_PFSYNCSTAT;
510  protox[i].pr_wanted    = 1;
511  protox[i].pr_cblocks   = NULL;
512  protox[i].pr_stats     = pfsync_stats;
513  protox[i].pr_istats    = NULL;
514  protox[i].pr_name      = "pfsync";
515  protox[i].pr_usesysctl = 1;
516  protox[i].pr_protocol  = 0;
517  i++;
518  protox[i].pr_index     = -1;
519  protox[i].pr_sindex    = N_ARPSTAT;
520  protox[i].pr_wanted    = 1;
521  protox[i].pr_cblocks   = NULL;
522  protox[i].pr_stats     = arp_stats;
523  protox[i].pr_istats    = NULL;
524  protox[i].pr_name      = "arp";
525  protox[i].pr_usesysctl = 1;
526  protox[i].pr_protocol  = 0;
527  i++;
528  protox[i].pr_index     = -1;
529  protox[i].pr_sindex    = -1;
530  protox[i].pr_wanted    = 0;
531  protox[i].pr_cblocks   = NULL;
532  protox[i].pr_stats     = NULL;
533  protox[i].pr_istats    = NULL;
534  protox[i].pr_name      = NULL;
535  protox[i].pr_usesysctl = 0;
536  protox[i].pr_protocol  = 0;
537
538#ifdef INET6
539  i=0;
540  ip6protox[i].pr_index     = N_TCBINFO;
541  ip6protox[i].pr_sindex    = N_TCPSTAT;
542  ip6protox[i].pr_wanted    = 1;
543  ip6protox[i].pr_cblocks   = protopr;
544  ip6protox[i].pr_stats     = tcp_stats;
545  ip6protox[i].pr_istats    = NULL;
546  ip6protox[i].pr_name      = "tcp";
547  ip6protox[i].pr_usesysctl = 1;
548  ip6protox[i].pr_protocol  = IPPROTO_TCP;
549  i++;
550  ip6protox[i].pr_index     = N_UDBINFO;
551  ip6protox[i].pr_sindex    = N_UDPSTAT;
552  ip6protox[i].pr_wanted    = 1;
553  ip6protox[i].pr_cblocks   = protopr;
554  ip6protox[i].pr_stats     = udp_stats;
555  ip6protox[i].pr_istats    = NULL;
556  ip6protox[i].pr_name      = "udp";
557  ip6protox[i].pr_usesysctl = 1;
558  ip6protox[i].pr_protocol  = IPPROTO_UDP;
559  i++;
560  ip6protox[i].pr_index     = N_RIPCBINFO;
561  ip6protox[i].pr_sindex    = N_IP6STAT;
562  ip6protox[i].pr_wanted    = 1;
563  ip6protox[i].pr_cblocks   = protopr;
564  ip6protox[i].pr_stats     = ip6_stats;
565  ip6protox[i].pr_istats    = ip6_ifstats;
566  ip6protox[i].pr_name      = "ip6";
567  ip6protox[i].pr_usesysctl = 1;
568  ip6protox[i].pr_protocol  = IPPROTO_RAW;
569  i++;
570  ip6protox[i].pr_index     = N_RIPCBINFO;
571  ip6protox[i].pr_sindex    = N_ICMP6STAT;
572  ip6protox[i].pr_wanted    = 1;
573  ip6protox[i].pr_cblocks   = protopr;
574  ip6protox[i].pr_stats     = icmp6_stats;
575  ip6protox[i].pr_istats    = icmp6_ifstats;
576  ip6protox[i].pr_name      = "icmp6";
577  ip6protox[i].pr_usesysctl = 1;
578  ip6protox[i].pr_protocol  = IPPROTO_ICMPV6;
579  i++;
580#ifdef IPSEC
581  ip6protox[i].pr_index     = -1;
582  ip6protox[i].pr_sindex    = N_IPSEC6STAT;
583  ip6protox[i].pr_wanted    = 1;
584  ip6protox[i].pr_cblocks   = NULL;
585  ip6protox[i].pr_stats     = ipsec_stats;
586  ip6protox[i].pr_istats    = NULL;
587  ip6protox[i].pr_name      = "ipsec6";
588  ip6protox[i].pr_usesysctl = 0;
589  ip6protox[i].pr_protocol  = 0;
590  i++;
591#endif
592#ifdef notyet
593  ip6protox[i].pr_index     = -1;
594  ip6protox[i].pr_sindex    = N_PIM6STAT;
595  ip6protox[i].pr_wanted    = 1;
596  ip6protox[i].pr_cblocks   = NULL;
597  ip6protox[i].pr_stats     = pim6_stats;
598  ip6protox[i].pr_istats    = NULL;
599  ip6protox[i].pr_name      = "pim6";
600  ip6protox[i].pr_usesysctl = 1;
601  ip6protox[i].pr_protocol  = 0;
602  i++;
603#endif
604  ip6protox[i].pr_index     = -1;
605  ip6protox[i].pr_sindex    = N_RIP6STAT;
606  ip6protox[i].pr_wanted    = 1;
607  ip6protox[i].pr_cblocks   = NULL;
608  ip6protox[i].pr_stats     = rip6_stats;
609  ip6protox[i].pr_istats    = NULL;
610  ip6protox[i].pr_name      = "rip6";
611  ip6protox[i].pr_usesysctl = 1;
612  ip6protox[i].pr_protocol  = 0;
613  i++;
614  ip6protox[i].pr_index     = -1;
615  ip6protox[i].pr_sindex    = -1;
616  ip6protox[i].pr_wanted    = 0;
617  ip6protox[i].pr_cblocks   = NULL;
618  ip6protox[i].pr_stats     = NULL;
619  ip6protox[i].pr_istats    = NULL;
620  ip6protox[i].pr_name      = NULL;
621  ip6protox[i].pr_usesysctl = 0;
622  ip6protox[i].pr_protocol  = 0;
623  i++;
624#endif /*INET6*/
625
626#ifdef IPSEC
627  i=0;
628  pfkeyprotox[i].pr_index     = -1;
629  pfkeyprotox[i].pr_sindex    = N_PFKEYSTAT;
630  pfkeyprotox[i].pr_wanted    = 1;
631  pfkeyprotox[i].pr_cblocks   = NULL;
632  pfkeyprotox[i].pr_stats     = pfkey_stats;
633  pfkeyprotox[i].pr_istats    = NULL;
634  pfkeyprotox[i].pr_name      = "pfkey";
635  pfkeyprotox[i].pr_usesysctl = 0;
636  pfkeyprotox[i].pr_protocol  = 0;
637  i++;
638  pfkeyprotox[i].pr_index     = -1;
639  pfkeyprotox[i].pr_sindex    = -1;
640  pfkeyprotox[i].pr_wanted    = 0;
641  pfkeyprotox[i].pr_cblocks   = NULL;
642  pfkeyprotox[i].pr_stats     = NULL;
643  pfkeyprotox[i].pr_istats    = NULL;
644  pfkeyprotox[i].pr_name      = NULL;
645  pfkeyprotox[i].pr_usesysctl = 0;
646  pfkeyprotox[i].pr_protocol  = 0;
647#endif
648
649#ifdef NETGRAPH
650  netgraphprotox[i].pr_index     = N_NGSOCKS;
651  netgraphprotox[i].pr_sindex    = -1;
652  netgraphprotox[i].pr_wanted    = 1;
653  netgraphprotox[i].pr_cblocks   = netgraphprotopr;
654  netgraphprotox[i].pr_stats     = NULL;
655  netgraphprotox[i].pr_istats    = NULL;
656  netgraphprotox[i].pr_name      = "ctrl";
657  netgraphprotox[i].pr_usesysctl = 0;
658  netgraphprotox[i].pr_protocol  = 0;
659  i++;
660  netgraphprotox[i].pr_index     = N_NGSOCKS;
661  netgraphprotox[i].pr_sindex    = -1;
662  netgraphprotox[i].pr_wanted    = 1;
663  netgraphprotox[i].pr_cblocks   = netgraphprotopr;
664  netgraphprotox[i].pr_stats     = NULL;
665  netgraphprotox[i].pr_istats    = NULL;
666  netgraphprotox[i].pr_name      = "data";
667  netgraphprotox[i].pr_usesysctl = 0;
668  netgraphprotox[i].pr_protocol  = 0;
669  i++;
670  netgraphprotox[i].pr_index     = -1;
671  netgraphprotox[i].pr_sindex    = -1;
672  netgraphprotox[i].pr_wanted    = 0;
673  netgraphprotox[i].pr_cblocks   = NULL;
674  netgraphprotox[i].pr_stats     = NULL;
675  netgraphprotox[i].pr_istats    = NULL;
676  netgraphprotox[i].pr_name      = NULL;
677  netgraphprotox[i].pr_usesysctl = 0;
678  netgraphprotox[i].pr_protocol  = 0;
679#endif
680#ifdef IPX
681  i=0;
682  ipxprotox[i].pr_index     = N_IPX;
683  ipxprotox[i].pr_sindex    = N_IPXSTAT;
684  ipxprotox[i].pr_wanted    = 1;
685  ipxprotox[i].pr_cblocks   = ipxprotopr;
686  ipxprotox[i].pr_stats     = ipx_stats;
687  ipxprotox[i].pr_istats    = NULL;
688  ipxprotox[i].pr_name      = "ipx";
689  ipxprotox[i].pr_usesysctl = 0;
690  ipxprotox[i].pr_protocol  = 0;
691  i++;
692  ipxprotox[i].pr_index     = N_IPX;
693  ipxprotox[i].pr_sindex    = N_SPXSTAT;
694  ipxprotox[i].pr_wanted    = 1;
695  ipxprotox[i].pr_cblocks   = ipxprotopr;
696  ipxprotox[i].pr_stats     = spx_stats;
697  ipxprotox[i].pr_istats    = NULL;
698  ipxprotox[i].pr_name      = "spx";
699  ipxprotox[i].pr_usesysctl = 0;
700  ipxprotox[i].pr_protocol  = 0;
701  i++;
702  ipxprotox[i].pr_index     = -1;
703  ipxprotox[i].pr_sindex    = -1;
704  ipxprotox[i].pr_wanted    = 0;
705  ipxprotox[i].pr_cblocks   = NULL;
706  ipxprotox[i].pr_stats     = NULL;
707  ipxprotox[i].pr_istats    = NULL;
708  ipxprotox[i].pr_name      = 0;
709  ipxprotox[i].pr_usesysctl = 0;
710  ipxprotox[i].pr_protocol  = 0;
711  i++;
712#endif
713
714  i=0;
715  protoprotox[i] = protox;
716  i++;
717#ifdef INET6
718  protoprotox[i] = ip6protox,
719  i++;
720#endif
721#ifdef IPSEC
722  protoprotox[i] = pfkeyprotox,
723  i++;
724#endif
725#ifdef IPX
726  protoprotox[i] = ipxprotox,
727#endif
728  noutputs = 0;
729
730  return rtems_bsd_program_call_main("netstat", main, argc, argv);
731}
732#endif /* __rtems__ */
733int
734main(int argc, char *argv[])
735{
736        struct protox *tp = NULL;  /* for printing cblocks & stats */
737        int ch;
738#ifdef __rtems__
739        struct getopt_data getopt_data;
740        memset(&getopt_data, 0, sizeof(getopt_data));
741#define optind getopt_data.optind
742#define optarg getopt_data.optarg
743#define opterr getopt_data.opterr
744#define optopt getopt_data.optopt
745#define getopt(argc, argv, opt) getopt_r(argc, argv, opt, &getopt_data)
746#endif /* __rtems__ */
747
748        af = AF_UNSPEC;
749
750        while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz")) != -1)
751                switch(ch) {
752                case 'A':
753                        Aflag = 1;
754                        break;
755                case 'a':
756                        aflag = 1;
757                        break;
758                case 'B':
759                        Bflag = 1;
760                        break;
761                case 'b':
762                        bflag = 1;
763                        break;
764                case 'd':
765                        dflag = 1;
766                        break;
767                case 'f':
768                        if (strcmp(optarg, "ipx") == 0)
769                                af = AF_IPX;
770                        else if (strcmp(optarg, "inet") == 0)
771                                af = AF_INET;
772#ifdef INET6
773                        else if (strcmp(optarg, "inet6") == 0)
774                                af = AF_INET6;
775#endif
776#ifdef IPSEC
777                        else if (strcmp(optarg, "pfkey") == 0)
778                                af = PF_KEY;
779#endif
780                        else if (strcmp(optarg, "unix") == 0)
781                                af = AF_UNIX;
782                        else if (strcmp(optarg, "atalk") == 0)
783                                af = AF_APPLETALK;
784#ifdef NETGRAPH
785                        else if (strcmp(optarg, "ng") == 0
786                            || strcmp(optarg, "netgraph") == 0)
787                                af = AF_NETGRAPH;
788#endif
789                        else if (strcmp(optarg, "link") == 0)
790                                af = AF_LINK;
791                        else {
792                                errx(1, "%s: unknown address family", optarg);
793                        }
794                        break;
795                case 'g':
796                        gflag = 1;
797                        break;
798                case 'h':
799                        hflag = 1;
800                        break;
801                case 'I': {
802                        char *cp;
803
804                        iflag = 1;
805                        for (cp = interface = optarg; isalpha(*cp); cp++)
806                                continue;
807                        unit = atoi(cp);
808                        break;
809                }
810                case 'i':
811                        iflag = 1;
812                        break;
813                case 'L':
814                        Lflag = 1;
815                        break;
816                case 'M':
817                        memf = optarg;
818                        break;
819                case 'm':
820                        mflag = 1;
821                        break;
822                case 'N':
823                        nlistf = optarg;
824                        break;
825                case 'n':
826                        numeric_addr = numeric_port = 1;
827                        break;
828                case 'p':
829                        if ((tp = name2protox(optarg)) == NULL) {
830                                errx(1,
831                                     "%s: unknown or uninstrumented protocol",
832                                     optarg);
833                        }
834                        pflag = 1;
835                        break;
836                case 'q':
837                        noutputs = atoi(optarg);
838                        if (noutputs != 0)
839                                noutputs++;
840                        break;
841                case 'r':
842                        rflag = 1;
843                        break;
844                case 's':
845                        ++sflag;
846                        break;
847                case 'S':
848                        numeric_addr = 1;
849                        break;
850                case 't':
851                        tflag = 1;
852                        break;
853                case 'u':
854                        af = AF_UNIX;
855                        break;
856                case 'W':
857                case 'l':
858                        Wflag = 1;
859                        break;
860                case 'w':
861                        interval = atoi(optarg);
862                        iflag = 1;
863                        break;
864                case 'x':
865                        xflag = 1;
866                        break;
867                case 'z':
868                        zflag = 1;
869                        break;
870                case '?':
871                default:
872                        usage();
873                }
874        argv += optind;
875        argc -= optind;
876
877#define BACKWARD_COMPATIBILITY
878#ifdef  BACKWARD_COMPATIBILITY
879        if (*argv) {
880                if (isdigit(**argv)) {
881                        interval = atoi(*argv);
882                        if (interval <= 0)
883                                usage();
884                        ++argv;
885                        iflag = 1;
886                }
887                if (*argv) {
888                        nlistf = *argv;
889                        if (*++argv)
890                                memf = *argv;
891                }
892        }
893#endif
894
895        /*
896         * Discard setgid privileges if not the running kernel so that bad
897         * guys can't print interesting stuff from kernel memory.
898         */
899        live = (nlistf == NULL && memf == NULL);
900        if (!live)
901                setgid(getgid());
902
903        if (Bflag) {
904                if (!live)
905                        usage();
906                bpf_stats(interface);
907                exit(0);
908        }
909        if (mflag) {
910                if (!live) {
911                        if (kread(0, NULL, 0) == 0)
912                                mbpr(kvmd, nl[N_MBSTAT].n_value);
913                } else
914                        mbpr(NULL, 0);
915                exit(0);
916        }
917#if 0
918        /*
919         * Keep file descriptors open to avoid overhead
920         * of open/close on each call to get* routines.
921         */
922        sethostent(1);
923        setnetent(1);
924#else
925        /*
926         * This does not make sense any more with DNS being default over
927         * the files.  Doing a setXXXXent(1) causes a tcp connection to be
928         * used for the queries, which is slower.
929         */
930#endif
931        kread(0, NULL, 0);
932        if (iflag && !sflag) {
933                intpr(interval, nl[N_IFNET].n_value, NULL);
934                exit(0);
935        }
936        if (rflag) {
937                if (sflag)
938                        rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
939                else
940                        routepr(nl[N_RTREE].n_value);
941                exit(0);
942        }
943        if (gflag) {
944                if (sflag) {
945                        if (af == AF_INET || af == AF_UNSPEC)
946                                mrt_stats(nl[N_MRTSTAT].n_value);
947#ifdef INET6
948                        if (af == AF_INET6 || af == AF_UNSPEC)
949                                mrt6_stats(nl[N_MRT6STAT].n_value);
950#endif
951                } else {
952                        if (af == AF_INET || af == AF_UNSPEC)
953                                mroutepr(nl[N_MFCHASHTBL].n_value,
954                                         nl[N_MFCTABLESIZE].n_value,
955                                         nl[N_VIFTABLE].n_value);
956#ifdef INET6
957                        if (af == AF_INET6 || af == AF_UNSPEC)
958                                mroute6pr(nl[N_MF6CTABLE].n_value,
959                                          nl[N_MIF6TABLE].n_value);
960#endif
961                }
962                exit(0);
963        }
964
965        if (tp) {
966                printproto(tp, tp->pr_name);
967                exit(0);
968        }
969        if (af == AF_INET || af == AF_UNSPEC)
970                for (tp = protox; tp->pr_name; tp++)
971                        printproto(tp, tp->pr_name);
972#ifdef INET6
973        if (af == AF_INET6 || af == AF_UNSPEC)
974                for (tp = ip6protox; tp->pr_name; tp++)
975                        printproto(tp, tp->pr_name);
976#endif /*INET6*/
977#ifdef IPSEC
978        if (af == PF_KEY || af == AF_UNSPEC)
979                for (tp = pfkeyprotox; tp->pr_name; tp++)
980                        printproto(tp, tp->pr_name);
981#endif /*IPSEC*/
982#ifdef IPX
983        if (af == AF_IPX || af == AF_UNSPEC) {
984                for (tp = ipxprotox; tp->pr_name; tp++)
985                        printproto(tp, tp->pr_name);
986        }
987#endif /* IPX */
988#ifndef __rtems__
989        if (af == AF_APPLETALK || af == AF_UNSPEC)
990                for (tp = atalkprotox; tp->pr_name; tp++)
991                        printproto(tp, tp->pr_name);
992#endif
993#ifdef NETGRAPH
994        if (af == AF_NETGRAPH || af == AF_UNSPEC)
995                for (tp = netgraphprotox; tp->pr_name; tp++)
996                        printproto(tp, tp->pr_name);
997#endif /* NETGRAPH */
998#ifndef __rtems__
999        if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
1000                unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
1001                    nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value);
1002#endif
1003        exit(0);
1004}
1005
1006/*
1007 * Print out protocol statistics or control blocks (per sflag).
1008 * If the interface was not specifically requested, and the symbol
1009 * is not in the namelist, ignore this one.
1010 */
1011static void
1012printproto(tp, name)
1013        struct protox *tp;
1014        const char *name;
1015{
1016        void (*pr)(u_long, const char *, int, int);
1017        u_long off;
1018
1019        if (sflag) {
1020                if (iflag) {
1021                        if (tp->pr_istats)
1022                                intpr(interval, nl[N_IFNET].n_value,
1023                                      tp->pr_istats);
1024                        else if (pflag)
1025                                printf("%s: no per-interface stats routine\n",
1026                                    tp->pr_name);
1027                        return;
1028                } else {
1029                        pr = tp->pr_stats;
1030                        if (!pr) {
1031                                if (pflag)
1032                                        printf("%s: no stats routine\n",
1033                                            tp->pr_name);
1034                                return;
1035                        }
1036                        if (tp->pr_usesysctl && live)
1037                                off = 0;
1038                        else if (tp->pr_sindex < 0) {
1039                                if (pflag)
1040                                        printf(
1041                                    "%s: stats routine doesn't work on cores\n",
1042                                            tp->pr_name);
1043                                return;
1044                        } else
1045                                off = nl[tp->pr_sindex].n_value;
1046                }
1047        } else {
1048                pr = tp->pr_cblocks;
1049                if (!pr) {
1050                        if (pflag)
1051                                printf("%s: no PCB routine\n", tp->pr_name);
1052                        return;
1053                }
1054                if (tp->pr_usesysctl && live)
1055                        off = 0;
1056                else if (tp->pr_index < 0) {
1057                        if (pflag)
1058                                printf(
1059                                    "%s: PCB routine doesn't work on cores\n",
1060                                    tp->pr_name);
1061                        return;
1062                } else
1063                        off = nl[tp->pr_index].n_value;
1064        }
1065        if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
1066            af != AF_UNSPEC))
1067                (*pr)(off, name, af, tp->pr_protocol);
1068}
1069
1070#ifdef __rtems__
1071#define _POSIX2_LINE_MAX 128
1072#endif
1073
1074/*
1075 * Read kernel memory, return 0 on success.
1076 */
1077int
1078kread(u_long addr, void *buf, size_t size)
1079{
1080        char errbuf[_POSIX2_LINE_MAX];
1081#ifdef __rtems__
1082        /* printf( "kread( %p to %p for %d)\n", (void *)addr, buf, size ); */
1083#endif
1084
1085        if (kvmd == NULL) {
1086                kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
1087                setgid(getgid());
1088                if (kvmd != NULL) {
1089                        if (kvm_nlist(kvmd, nl) < 0) {
1090                                if (nlistf)
1091                                        errx(1, "%s: kvm_nlist: %s", nlistf,
1092                                             kvm_geterr(kvmd));
1093                                else
1094                                        errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
1095                        }
1096
1097                        if (nl[0].n_type == 0) {
1098                                if (nlistf)
1099                                        errx(1, "%s: no namelist", nlistf);
1100                                else
1101                                        errx(1, "no namelist");
1102                        }
1103                } else {
1104                        warnx("kvm not available: %s", errbuf);
1105                        return(-1);
1106                }
1107        }
1108        if (!buf)
1109                return (0);
1110        if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
1111                warnx("%s", kvm_geterr(kvmd));
1112                return (-1);
1113        }
1114        return (0);
1115}
1116
1117const char *
1118plural(uintmax_t n)
1119{
1120        return (n != 1 ? "s" : "");
1121}
1122
1123const char *
1124plurales(uintmax_t n)
1125{
1126        return (n != 1 ? "es" : "");
1127}
1128
1129const char *
1130pluralies(uintmax_t n)
1131{
1132        return (n != 1 ? "ies" : "y");
1133}
1134
1135/*
1136 * Find the protox for the given "well-known" name.
1137 */
1138static struct protox *
1139knownname(const char *name)
1140{
1141        struct protox **tpp, *tp;
1142
1143        for (tpp = protoprotox; *tpp; tpp++)
1144                for (tp = *tpp; tp->pr_name; tp++)
1145                        if (strcmp(tp->pr_name, name) == 0)
1146                                return (tp);
1147        return (NULL);
1148}
1149
1150/*
1151 * Find the protox corresponding to name.
1152 */
1153static struct protox *
1154name2protox(const char *name)
1155{
1156        struct protox *tp;
1157        char **alias;                   /* alias from p->aliases */
1158        struct protoent *p;
1159
1160        /*
1161         * Try to find the name in the list of "well-known" names. If that
1162         * fails, check if name is an alias for an Internet protocol.
1163         */
1164        if ((tp = knownname(name)) != NULL)
1165                return (tp);
1166
1167        setprotoent(1);                 /* make protocol lookup cheaper */
1168        while ((p = getprotoent()) != NULL) {
1169                /* assert: name not same as p->name */
1170                for (alias = p->p_aliases; *alias; alias++)
1171                        if (strcmp(name, *alias) == 0) {
1172                                endprotoent();
1173                                return (knownname(p->p_name));
1174                        }
1175        }
1176        endprotoent();
1177        return (NULL);
1178}
1179
1180static void
1181usage(void)
1182{
1183        (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",
1184"usage: netstat [-AaLnSWx] [-f protocol_family | -p protocol]\n"
1185"               [-M core] [-N system]",
1186"       netstat -i | -I interface [-abdhntW] [-f address_family]\n"
1187"               [-M core] [-N system]",
1188"       netstat -w wait [-I interface] [-d] [-M core] [-N system] [-q howmany]",
1189"       netstat -s [-s] [-z] [-f protocol_family | -p protocol]\n"
1190"               [-M core] [-N system]",
1191"       netstat -i | -I interface -s [-f protocol_family | -p protocol]\n"
1192"               [-M core] [-N system]",
1193"       netstat -m [-M core] [-N system]",
1194"       netstat -B [-I interface]",
1195"       netstat -r [-AanW] [-f address_family] [-M core] [-N system]",
1196"       netstat -rs [-s] [-M core] [-N system]",
1197"       netstat -g [-W] [-f address_family] [-M core] [-N system]",
1198"       netstat -gs [-s] [-f address_family] [-M core] [-N system]");
1199        exit(1);
1200}
1201
1202#ifdef __rtems__
1203  #include <rtems/shell.h>
1204
1205  rtems_shell_cmd_t rtems_shell_NETSTAT_Command = {
1206    "netstat",                     /* name */
1207    "netstat [args]",              /* usage */
1208    "net",                         /* topic */
1209    rtems_shell_main_netstat,      /* command */
1210    NULL,                          /* alias */
1211    NULL                           /* next */
1212  };
1213#endif
Note: See TracBrowser for help on using the repository browser.