]>
Commit | Line | Data |
---|---|---|
b7080c8e | 1 | /* |
89c4ed63 | 2 | * Copyright (c) 2008-2015 Apple Inc. All rights reserved. |
b7080c8e | 3 | * |
9c859447 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
b7080c8e | 5 | * |
9c859447 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
b7080c8e | 14 | * |
9c859447 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
b7080c8e A |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
9c859447 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
b7080c8e | 25 | * |
9c859447 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
b7080c8e A |
27 | */ |
28 | /* | |
29 | * Copyright (c) 1983, 1988, 1993 | |
30 | * Regents of the University of California. All rights reserved. | |
31 | * | |
32 | * Redistribution and use in source and binary forms, with or without | |
33 | * modification, are permitted provided that the following conditions | |
34 | * are met: | |
35 | * 1. Redistributions of source code must retain the above copyright | |
36 | * notice, this list of conditions and the following disclaimer. | |
37 | * 2. Redistributions in binary form must reproduce the above copyright | |
38 | * notice, this list of conditions and the following disclaimer in the | |
39 | * documentation and/or other materials provided with the distribution. | |
40 | * 3. All advertising materials mentioning features or use of this software | |
41 | * must display the following acknowledgement: | |
42 | * This product includes software developed by the University of | |
43 | * California, Berkeley and its contributors. | |
44 | * 4. Neither the name of the University nor the names of its contributors | |
45 | * may be used to endorse or promote products derived from this software | |
46 | * without specific prior written permission. | |
47 | * | |
48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
58 | * SUCH DAMAGE. | |
59 | */ | |
60 | ||
61 | #ifndef lint | |
62 | char const copyright[] = | |
63 | "@(#) Copyright (c) 1983, 1988, 1993\n\ | |
64 | Regents of the University of California. All rights reserved.\n"; | |
65 | #endif /* not lint */ | |
66 | ||
b7080c8e A |
67 | #include <sys/param.h> |
68 | #include <sys/file.h> | |
b7080c8e | 69 | #include <sys/socket.h> |
342c141e | 70 | #include <sys/sys_domain.h> |
b7080c8e A |
71 | |
72 | #include <netinet/in.h> | |
2b484d24 | 73 | #include <net/pfkeyv2.h> |
b7080c8e A |
74 | |
75 | #include <ctype.h> | |
76 | #include <err.h> | |
77 | #include <errno.h> | |
b7080c8e A |
78 | #include <limits.h> |
79 | #include <netdb.h> | |
80 | #include <nlist.h> | |
81 | #include <paths.h> | |
82 | #include <stdio.h> | |
83 | #include <stdlib.h> | |
84 | #include <string.h> | |
85 | #include <unistd.h> | |
86 | #include "netstat.h" | |
87 | #include <sys/types.h> | |
88 | #include <sys/sysctl.h> | |
89 | ||
b8dff150 A |
90 | #ifdef __APPLE__ |
91 | #include <TargetConditionals.h> | |
92 | #endif | |
b7080c8e A |
93 | |
94 | /* | |
95 | * ---------------------------------------------------------------------------- | |
96 | * "THE BEER-WARE LICENSE" (Revision 42): | |
97 | * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you | |
98 | * can do whatever you want with this stuff. If we meet some day, and you think | |
99 | * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp | |
100 | * ---------------------------------------------------------------------------- | |
101 | * | |
2b484d24 | 102 | * $Id: main.c,v 1.8 2004/10/14 22:24:09 lindak Exp $ |
b7080c8e A |
103 | * |
104 | */ | |
105 | ||
b7080c8e | 106 | struct protox { |
9c859447 | 107 | void (*pr_cblocks)(uint32_t, char *, int); |
7ba0088d | 108 | /* control blocks printing routine */ |
9c859447 | 109 | void (*pr_stats)(uint32_t, char *, int); |
7ba0088d A |
110 | /* statistics printing routine */ |
111 | void (*pr_istats)(char *); /* per/if statistics printing routine */ | |
b7080c8e | 112 | char *pr_name; /* well-known name */ |
9dc66a05 | 113 | int pr_protocol; |
b7080c8e | 114 | } protox[] = { |
9dc66a05 A |
115 | { protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP }, |
116 | { protopr, udp_stats, NULL, "udp", IPPROTO_UDP }, | |
117 | { protopr, NULL, NULL, "divert", IPPROTO_DIVERT }, | |
118 | { protopr, ip_stats, NULL, "ip", IPPROTO_RAW }, | |
119 | { protopr, icmp_stats, NULL, "icmp", IPPROTO_ICMP }, | |
120 | { protopr, igmp_stats, NULL, "igmp", IPPROTO_IGMP }, | |
7ba0088d | 121 | #ifdef IPSEC |
9dc66a05 A |
122 | { NULL, ipsec_stats, NULL, "ipsec", IPPROTO_ESP}, |
123 | #endif | |
124 | { NULL, arp_stats, NULL, "arp", 0 }, | |
9dc66a05 | 125 | { mptcppr, mptcp_stats, NULL, "mptcp", IPPROTO_TCP }, |
9dc66a05 | 126 | { NULL, NULL, NULL, NULL, 0 } |
7ba0088d A |
127 | }; |
128 | ||
129 | #ifdef INET6 | |
130 | struct protox ip6protox[] = { | |
9dc66a05 A |
131 | { protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP }, |
132 | { protopr, udp_stats, NULL, "udp", IPPROTO_UDP }, | |
133 | { protopr, ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW }, | |
134 | { protopr, icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 }, | |
7ba0088d | 135 | #ifdef IPSEC |
9dc66a05 | 136 | { NULL, ipsec_stats, NULL, "ipsec6", IPPROTO_ESP }, |
7ba0088d | 137 | #endif |
9dc66a05 | 138 | { NULL, rip6_stats, NULL, "rip6", IPPROTO_RAW }, |
9dc66a05 | 139 | { mptcppr, mptcp_stats, NULL, "mptcp", IPPROTO_TCP }, |
9dc66a05 | 140 | { NULL, NULL, NULL, NULL, 0 } |
b7080c8e | 141 | }; |
7ba0088d | 142 | #endif /*INET6*/ |
b7080c8e | 143 | |
7ba0088d A |
144 | #ifdef IPSEC |
145 | struct protox pfkeyprotox[] = { | |
9dc66a05 A |
146 | { NULL, pfkey_stats, NULL, "pfkey", PF_KEY_V2 }, |
147 | { NULL, NULL, NULL, NULL, 0 } | |
7ba0088d A |
148 | }; |
149 | #endif | |
b7080c8e | 150 | |
342c141e A |
151 | |
152 | struct protox systmprotox[] = { | |
153 | { systmpr, NULL, NULL, "reg", 0 }, | |
154 | { systmpr, kevt_stats, NULL, "kevt", SYSPROTO_EVENT }, | |
155 | { systmpr, kctl_stats, NULL, "kctl", SYSPROTO_CONTROL }, | |
156 | { NULL, NULL, NULL, NULL, 0 } | |
157 | }; | |
158 | ||
89c4ed63 A |
159 | struct protox nstatprotox[] = { |
160 | { NULL, print_nstat_stats, NULL, "nstat", 0 }, | |
161 | { NULL, NULL, NULL, NULL, 0 } | |
162 | }; | |
163 | ||
164 | struct protox ipcprotox[] = { | |
165 | { NULL, print_extbkidle_stats, NULL, "xbkidle", 0 }, | |
166 | { NULL, NULL, NULL, NULL, 0 } | |
167 | }; | |
168 | ||
d9520f62 A |
169 | struct protox kernprotox[] = { |
170 | { NULL, print_net_api_stats, NULL, "net_api", 0 }, | |
171 | { NULL, NULL, NULL, NULL, 0 } | |
172 | }; | |
89c4ed63 | 173 | |
7ba0088d | 174 | struct protox *protoprotox[] = { |
9dc66a05 | 175 | protox, |
7ba0088d | 176 | #ifdef INET6 |
9dc66a05 | 177 | ip6protox, |
b7080c8e | 178 | #endif |
7ba0088d | 179 | #ifdef IPSEC |
9dc66a05 | 180 | pfkeyprotox, |
b7080c8e | 181 | #endif |
342c141e | 182 | systmprotox, |
89c4ed63 A |
183 | nstatprotox, |
184 | ipcprotox, | |
d9520f62 | 185 | kernprotox, |
9dc66a05 A |
186 | NULL |
187 | }; | |
b7080c8e | 188 | |
7ba0088d A |
189 | static void printproto (struct protox *, char *); |
190 | static void usage (void); | |
191 | static struct protox *name2protox (char *); | |
192 | static struct protox *knownname (char *); | |
ac2f15b3 A |
193 | #ifdef SRVCACHE |
194 | extern void _serv_cache_close(); | |
195 | #endif | |
b7080c8e | 196 | |
7ba0088d A |
197 | int Aflag; /* show addresses of protocol control block */ |
198 | int aflag; /* show all sockets (including servers) */ | |
199 | int bflag; /* show i/f total bytes in/out */ | |
7af5ce03 | 200 | int cflag; /* show specific classq */ |
7ba0088d | 201 | int dflag; /* show i/f dropped packets */ |
9dc66a05 | 202 | int Fflag; /* show i/f forwarded packets */ |
7f5b2e89 | 203 | #if defined(__APPLE__) |
7ba0088d | 204 | int gflag; /* show group (multicast) routing or stats */ |
b8dff150 | 205 | #endif |
7ba0088d | 206 | int iflag; /* show interfaces */ |
e0b07f2d | 207 | int lflag; /* show routing table with more information */ |
7ba0088d A |
208 | int Lflag; /* show size of listen queues */ |
209 | int mflag; /* show memory stats */ | |
210 | int nflag; /* show addresses numerically */ | |
211 | static int pflag; /* show given protocol */ | |
fdfd5971 A |
212 | int prioflag = -1; /* show packet priority statistics */ |
213 | int Rflag; /* show reachability information */ | |
7ba0088d A |
214 | int rflag; /* show routing tables (or routing stats) */ |
215 | int sflag; /* show protocol statistics */ | |
89c4ed63 | 216 | int Sflag; /* show additional i/f link status */ |
7ba0088d | 217 | int tflag; /* show i/f watchdog timers */ |
fdfd5971 | 218 | int vflag; /* more verbose */ |
7ba0088d | 219 | int Wflag; /* wide display */ |
7af5ce03 A |
220 | int qflag; /* classq stats display */ |
221 | int Qflag; /* opportunistic polling stats display */ | |
222 | int xflag; /* show extended link-layer reachability information */ | |
213b8c4f | 223 | int zflag; /* show only entries with non zero rtt metrics */ |
7ba0088d | 224 | |
7af5ce03 | 225 | int cq = -1; /* send classq index (-1 for all) */ |
7ba0088d A |
226 | int interval; /* repeat interval for i/f stats */ |
227 | ||
228 | char *interface; /* desired i/f for stats, or NULL for all i/fs */ | |
229 | int unit; /* unit number for above */ | |
230 | ||
231 | int af; /* address family */ | |
b7080c8e A |
232 | |
233 | int | |
234 | main(argc, argv) | |
235 | int argc; | |
236 | char *argv[]; | |
237 | { | |
7ba0088d | 238 | register struct protox *tp = NULL; /* for printing cblocks & stats */ |
b7080c8e A |
239 | int ch; |
240 | ||
241 | af = AF_UNSPEC; | |
242 | ||
213b8c4f | 243 | while ((ch = getopt(argc, argv, "Aabc:dFf:gI:ikLlmnP:p:qQrRsStuvWw:xz")) != -1) |
b7080c8e A |
244 | switch(ch) { |
245 | case 'A': | |
246 | Aflag = 1; | |
247 | break; | |
248 | case 'a': | |
249 | aflag = 1; | |
250 | break; | |
251 | case 'b': | |
252 | bflag = 1; | |
253 | break; | |
7af5ce03 A |
254 | case 'c': |
255 | cflag = 1; | |
256 | cq = atoi(optarg); | |
257 | break; | |
b7080c8e A |
258 | case 'd': |
259 | dflag = 1; | |
260 | break; | |
9dc66a05 A |
261 | case 'F': |
262 | Fflag = 1; | |
263 | break; | |
b7080c8e | 264 | case 'f': |
b7080c8e A |
265 | if (strcmp(optarg, "ipx") == 0) |
266 | af = AF_IPX; | |
267 | else if (strcmp(optarg, "inet") == 0) | |
268 | af = AF_INET; | |
7ba0088d A |
269 | #ifdef INET6 |
270 | else if (strcmp(optarg, "inet6") == 0) | |
271 | af = AF_INET6; | |
272 | #endif /*INET6*/ | |
273 | #ifdef INET6 | |
274 | else if (strcmp(optarg, "pfkey") == 0) | |
275 | af = PF_KEY; | |
276 | #endif /*INET6*/ | |
89c4ed63 A |
277 | else if (strcmp(optarg, "unix") == 0) |
278 | af = AF_UNIX; | |
279 | else if (strcmp(optarg, "systm") == 0) | |
280 | af = AF_SYSTEM; | |
b7080c8e A |
281 | else { |
282 | errx(1, "%s: unknown address family", optarg); | |
283 | } | |
284 | break; | |
7f5b2e89 | 285 | #if defined(__APPLE__) |
b7080c8e A |
286 | case 'g': |
287 | gflag = 1; | |
288 | break; | |
b8dff150 | 289 | #endif |
b7080c8e A |
290 | case 'I': { |
291 | char *cp; | |
292 | ||
293 | iflag = 1; | |
294 | for (cp = interface = optarg; isalpha(*cp); cp++) | |
295 | continue; | |
296 | unit = atoi(cp); | |
297 | break; | |
298 | } | |
299 | case 'i': | |
300 | iflag = 1; | |
301 | break; | |
7ba0088d | 302 | case 'l': |
213b8c4f | 303 | lflag += 1; |
7ba0088d A |
304 | break; |
305 | case 'L': | |
306 | Lflag = 1; | |
307 | break; | |
b7080c8e | 308 | case 'm': |
b8dff150 | 309 | mflag++; |
b7080c8e A |
310 | break; |
311 | case 'n': | |
312 | nflag = 1; | |
313 | break; | |
7f5b2e89 | 314 | case 'P': |
5902acfc | 315 | prioflag = atoi(optarg); |
7f5b2e89 | 316 | break; |
b7080c8e A |
317 | case 'p': |
318 | if ((tp = name2protox(optarg)) == NULL) { | |
319 | errx(1, | |
320 | "%s: unknown or uninstrumented protocol", | |
321 | optarg); | |
322 | } | |
323 | pflag = 1; | |
324 | break; | |
7af5ce03 A |
325 | case 'q': |
326 | qflag++; | |
327 | break; | |
328 | case 'Q': | |
329 | Qflag++; | |
330 | break; | |
fdfd5971 A |
331 | case 'R': |
332 | Rflag = 1; | |
333 | break; | |
b7080c8e A |
334 | case 'r': |
335 | rflag = 1; | |
336 | break; | |
337 | case 's': | |
338 | ++sflag; | |
339 | break; | |
89c4ed63 A |
340 | case 'S': |
341 | Sflag = 1; | |
342 | break; | |
b7080c8e A |
343 | case 't': |
344 | tflag = 1; | |
345 | break; | |
346 | case 'u': | |
347 | af = AF_UNIX; | |
348 | break; | |
fdfd5971 A |
349 | case 'v': |
350 | vflag++; | |
351 | break; | |
7ba0088d A |
352 | case 'W': |
353 | Wflag = 1; | |
354 | break; | |
b7080c8e A |
355 | case 'w': |
356 | interval = atoi(optarg); | |
357 | iflag = 1; | |
358 | break; | |
7af5ce03 A |
359 | case 'x': |
360 | xflag = 1; | |
361 | Rflag = 1; | |
362 | break; | |
213b8c4f A |
363 | case 'z': |
364 | zflag = 1; | |
365 | break; | |
b7080c8e A |
366 | case '?': |
367 | default: | |
368 | usage(); | |
369 | } | |
370 | argv += optind; | |
371 | argc -= optind; | |
372 | ||
373 | #define BACKWARD_COMPATIBILITY | |
374 | #ifdef BACKWARD_COMPATIBILITY | |
375 | if (*argv) { | |
376 | if (isdigit(**argv)) { | |
377 | interval = atoi(*argv); | |
378 | if (interval <= 0) | |
379 | usage(); | |
380 | ++argv; | |
381 | iflag = 1; | |
382 | } | |
b7080c8e A |
383 | } |
384 | #endif | |
385 | ||
b7080c8e | 386 | if (mflag) { |
2b484d24 | 387 | mbpr(); |
b7080c8e A |
388 | exit(0); |
389 | } | |
89c4ed63 | 390 | if (iflag && !sflag && !Sflag && !gflag && !qflag && !Qflag) { |
fdfd5971 A |
391 | if (Rflag) |
392 | intpr_ri(NULL); | |
393 | else | |
394 | intpr(NULL); | |
b7080c8e A |
395 | exit(0); |
396 | } | |
397 | if (rflag) { | |
b7080c8e | 398 | if (sflag) |
2b484d24 | 399 | rt_stats(); |
b7080c8e | 400 | else |
9dc66a05 | 401 | routepr(); |
b7080c8e A |
402 | exit(0); |
403 | } | |
7af5ce03 A |
404 | if (qflag || Qflag) { |
405 | if (interface == NULL) { | |
406 | fprintf(stderr, "%s statistics option " | |
407 | "requires interface name\n", qflag ? "Queue" : | |
408 | "Polling"); | |
409 | } else if (qflag) { | |
410 | aqstatpr(); | |
411 | } else { | |
412 | rxpollstatpr(); | |
413 | } | |
414 | exit(0); | |
415 | } | |
89c4ed63 A |
416 | if (Sflag) { |
417 | if (interface == NULL) { | |
418 | fprintf(stderr, "additional link status option" | |
419 | " requires interface name\n"); | |
420 | } else { | |
421 | print_link_status(interface); | |
422 | } | |
423 | exit(0); | |
424 | } | |
7af5ce03 | 425 | |
7f5b2e89 | 426 | #if defined(__APPLE__) |
b7080c8e | 427 | if (gflag) { |
b8dff150 | 428 | ifmalist_dump(); |
7ba0088d | 429 | exit(0); |
b7080c8e | 430 | } |
b8dff150 | 431 | #endif |
b7080c8e | 432 | |
7ba0088d A |
433 | if (tp) { |
434 | printproto(tp, tp->pr_name); | |
435 | exit(0); | |
436 | } | |
437 | if (af == AF_INET || af == AF_UNSPEC) | |
438 | for (tp = protox; tp->pr_name; tp++) | |
439 | printproto(tp, tp->pr_name); | |
440 | #ifdef INET6 | |
441 | if (af == AF_INET6 || af == AF_UNSPEC) | |
442 | for (tp = ip6protox; tp->pr_name; tp++) | |
443 | printproto(tp, tp->pr_name); | |
444 | #endif /*INET6*/ | |
445 | #ifdef IPSEC | |
446 | if (af == PF_KEY || af == AF_UNSPEC) | |
447 | for (tp = pfkeyprotox; tp->pr_name; tp++) | |
448 | printproto(tp, tp->pr_name); | |
449 | #endif /*IPSEC*/ | |
7ba0088d | 450 | if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) |
b7080c8e | 451 | unixpr(); |
342c141e A |
452 | |
453 | if ((af == AF_SYSTEM || af == AF_UNSPEC) && !Lflag) | |
454 | for (tp = systmprotox; tp->pr_name; tp++) | |
455 | printproto(tp, tp->pr_name); | |
89c4ed63 A |
456 | #if TARGET_OS_IPHONE |
457 | if (af == AF_UNSPEC && !Lflag) | |
458 | for (tp = nstatprotox; tp->pr_name; tp++) | |
459 | printproto(tp, tp->pr_name); | |
460 | #endif /* TARGET_OS_IPHONE */ | |
461 | ||
462 | if (af == AF_UNSPEC && !Lflag) | |
463 | for (tp = ipcprotox; tp->pr_name; tp++) | |
464 | printproto(tp, tp->pr_name); | |
465 | ||
d9520f62 A |
466 | if (af == AF_UNSPEC && !Lflag) |
467 | for (tp = kernprotox; tp->pr_name; tp++) | |
468 | printproto(tp, tp->pr_name); | |
469 | ||
470 | ||
ac2f15b3 A |
471 | #ifdef SRVCACHE |
472 | _serv_cache_close(); | |
473 | #endif | |
b7080c8e A |
474 | exit(0); |
475 | } | |
476 | ||
477 | /* | |
478 | * Print out protocol statistics or control blocks (per sflag). | |
479 | * If the interface was not specifically requested, and the symbol | |
480 | * is not in the namelist, ignore this one. | |
481 | */ | |
482 | static void | |
483 | printproto(tp, name) | |
484 | register struct protox *tp; | |
485 | char *name; | |
486 | { | |
9c859447 A |
487 | void (*pr)(uint32_t, char *, int); |
488 | uint32_t off; | |
b7080c8e A |
489 | |
490 | if (sflag) { | |
b8dff150 | 491 | if (iflag && !pflag) { |
7ba0088d | 492 | if (tp->pr_istats) |
2b484d24 | 493 | intpr(tp->pr_istats); |
9dc66a05 | 494 | else if (vflag) |
7ba0088d A |
495 | printf("%s: no per-interface stats routine\n", |
496 | tp->pr_name); | |
497 | return; | |
498 | } | |
499 | else { | |
500 | pr = tp->pr_stats; | |
501 | if (!pr) { | |
9dc66a05 | 502 | if (pflag && vflag) |
7ba0088d A |
503 | printf("%s: no stats routine\n", |
504 | tp->pr_name); | |
505 | return; | |
506 | } | |
9dc66a05 | 507 | off = tp->pr_protocol; |
7ba0088d | 508 | } |
b7080c8e A |
509 | } else { |
510 | pr = tp->pr_cblocks; | |
7ba0088d | 511 | if (!pr) { |
9dc66a05 | 512 | if (pflag && vflag) |
7ba0088d A |
513 | printf("%s: no PCB routine\n", tp->pr_name); |
514 | return; | |
515 | } | |
9dc66a05 | 516 | off = tp->pr_protocol; |
b7080c8e | 517 | } |
9dc66a05 | 518 | if (pr != NULL) { |
b8dff150 A |
519 | if (sflag && iflag && pflag) |
520 | intervalpr(pr, off, name, af); | |
521 | else | |
522 | (*pr)(off, name, af); | |
523 | } else { | |
2b484d24 | 524 | printf("### no stats for %s\n", name); |
b7080c8e | 525 | } |
b7080c8e A |
526 | } |
527 | ||
528 | char * | |
7ba0088d | 529 | plural(int n) |
b7080c8e | 530 | { |
89c4ed63 | 531 | return (n > 1 ? "s" : ""); |
b7080c8e A |
532 | } |
533 | ||
534 | char * | |
7ba0088d | 535 | plurales(int n) |
b7080c8e | 536 | { |
89c4ed63 | 537 | return (n > 1 ? "es" : ""); |
b7080c8e A |
538 | } |
539 | ||
9dc66a05 A |
540 | char * |
541 | pluralies(int n) | |
542 | { | |
89c4ed63 | 543 | return (n > 1 ? "ies" : "y"); |
9dc66a05 A |
544 | } |
545 | ||
b7080c8e A |
546 | /* |
547 | * Find the protox for the given "well-known" name. | |
548 | */ | |
549 | static struct protox * | |
7ba0088d | 550 | knownname(char *name) |
b7080c8e A |
551 | { |
552 | struct protox **tpp, *tp; | |
553 | ||
554 | for (tpp = protoprotox; *tpp; tpp++) | |
555 | for (tp = *tpp; tp->pr_name; tp++) | |
556 | if (strcmp(tp->pr_name, name) == 0) | |
557 | return (tp); | |
558 | return (NULL); | |
559 | } | |
560 | ||
561 | /* | |
562 | * Find the protox corresponding to name. | |
563 | */ | |
564 | static struct protox * | |
7ba0088d | 565 | name2protox(char *name) |
b7080c8e A |
566 | { |
567 | struct protox *tp; | |
568 | char **alias; /* alias from p->aliases */ | |
569 | struct protoent *p; | |
570 | ||
571 | /* | |
572 | * Try to find the name in the list of "well-known" names. If that | |
573 | * fails, check if name is an alias for an Internet protocol. | |
574 | */ | |
7ba0088d | 575 | if ((tp = knownname(name)) != NULL) |
b7080c8e A |
576 | return (tp); |
577 | ||
578 | setprotoent(1); /* make protocol lookup cheaper */ | |
7ba0088d | 579 | while ((p = getprotoent()) != NULL) { |
b7080c8e A |
580 | /* assert: name not same as p->name */ |
581 | for (alias = p->p_aliases; *alias; alias++) | |
582 | if (strcmp(name, *alias) == 0) { | |
583 | endprotoent(); | |
584 | return (knownname(p->p_name)); | |
585 | } | |
586 | } | |
587 | endprotoent(); | |
588 | return (NULL); | |
589 | } | |
590 | ||
b8dff150 A |
591 | #define NETSTAT_USAGE "\ |
592 | Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\ | |
593 | netstat [-gilns] [-f address_family]\n\ | |
89c4ed63 | 594 | netstat -i | -I interface [-w wait] [-abdgRtS]\n\ |
b8dff150 A |
595 | netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\ |
596 | netstat -i | -I interface -s [-f address_family | -p protocol]\n\ | |
597 | netstat -m [-m]\n\ | |
598 | netstat -r [-Aaln] [-f address_family]\n\ | |
599 | netstat -rs [-s]\n\ | |
600 | " | |
601 | ||
b7080c8e | 602 | static void |
7ba0088d | 603 | usage(void) |
b7080c8e | 604 | { |
b8dff150 | 605 | (void) fprintf(stderr, "%s\n", NETSTAT_USAGE); |
b7080c8e A |
606 | exit(1); |
607 | } | |
9dc66a05 A |
608 | |
609 | int | |
610 | print_time(void) | |
611 | { | |
612 | time_t now; | |
613 | struct tm tm; | |
614 | int num_written = 0; | |
615 | ||
616 | (void) time(&now); | |
617 | (void) localtime_r(&now, &tm); | |
618 | ||
619 | num_written += printf("%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec); | |
620 | ||
621 | return (num_written); | |
622 | } | |
623 |