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