]>
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 | ||
169 | ||
7ba0088d | 170 | struct protox *protoprotox[] = { |
9dc66a05 | 171 | protox, |
7ba0088d | 172 | #ifdef INET6 |
9dc66a05 | 173 | ip6protox, |
b7080c8e | 174 | #endif |
7ba0088d | 175 | #ifdef IPSEC |
9dc66a05 | 176 | pfkeyprotox, |
b7080c8e | 177 | #endif |
342c141e | 178 | systmprotox, |
89c4ed63 A |
179 | nstatprotox, |
180 | ipcprotox, | |
9dc66a05 A |
181 | NULL |
182 | }; | |
b7080c8e | 183 | |
7ba0088d A |
184 | static void printproto (struct protox *, char *); |
185 | static void usage (void); | |
186 | static struct protox *name2protox (char *); | |
187 | static struct protox *knownname (char *); | |
ac2f15b3 A |
188 | #ifdef SRVCACHE |
189 | extern void _serv_cache_close(); | |
190 | #endif | |
b7080c8e | 191 | |
7ba0088d A |
192 | int Aflag; /* show addresses of protocol control block */ |
193 | int aflag; /* show all sockets (including servers) */ | |
194 | int bflag; /* show i/f total bytes in/out */ | |
7af5ce03 | 195 | int cflag; /* show specific classq */ |
7ba0088d | 196 | int dflag; /* show i/f dropped packets */ |
9dc66a05 | 197 | int Fflag; /* show i/f forwarded packets */ |
7f5b2e89 | 198 | #if defined(__APPLE__) |
7ba0088d | 199 | int gflag; /* show group (multicast) routing or stats */ |
b8dff150 | 200 | #endif |
7ba0088d A |
201 | int iflag; /* show interfaces */ |
202 | int lflag; /* show routing table with use and ref */ | |
203 | int Lflag; /* show size of listen queues */ | |
204 | int mflag; /* show memory stats */ | |
205 | int nflag; /* show addresses numerically */ | |
206 | static int pflag; /* show given protocol */ | |
fdfd5971 A |
207 | int prioflag = -1; /* show packet priority statistics */ |
208 | int Rflag; /* show reachability information */ | |
7ba0088d A |
209 | int rflag; /* show routing tables (or routing stats) */ |
210 | int sflag; /* show protocol statistics */ | |
89c4ed63 | 211 | int Sflag; /* show additional i/f link status */ |
7ba0088d | 212 | int tflag; /* show i/f watchdog timers */ |
fdfd5971 | 213 | int vflag; /* more verbose */ |
7ba0088d | 214 | int Wflag; /* wide display */ |
7af5ce03 A |
215 | int qflag; /* classq stats display */ |
216 | int Qflag; /* opportunistic polling stats display */ | |
217 | int xflag; /* show extended link-layer reachability information */ | |
7ba0088d | 218 | |
7af5ce03 | 219 | int cq = -1; /* send classq index (-1 for all) */ |
7ba0088d A |
220 | int interval; /* repeat interval for i/f stats */ |
221 | ||
222 | char *interface; /* desired i/f for stats, or NULL for all i/fs */ | |
223 | int unit; /* unit number for above */ | |
224 | ||
225 | int af; /* address family */ | |
b7080c8e A |
226 | |
227 | int | |
228 | main(argc, argv) | |
229 | int argc; | |
230 | char *argv[]; | |
231 | { | |
7ba0088d | 232 | register struct protox *tp = NULL; /* for printing cblocks & stats */ |
b7080c8e A |
233 | int ch; |
234 | ||
235 | af = AF_UNSPEC; | |
236 | ||
89c4ed63 | 237 | while ((ch = getopt(argc, argv, "Aabc:dFf:gI:ikLlmnP:p:qQrRsStuvWw:x")) != -1) |
b7080c8e A |
238 | switch(ch) { |
239 | case 'A': | |
240 | Aflag = 1; | |
241 | break; | |
242 | case 'a': | |
243 | aflag = 1; | |
244 | break; | |
245 | case 'b': | |
246 | bflag = 1; | |
247 | break; | |
7af5ce03 A |
248 | case 'c': |
249 | cflag = 1; | |
250 | cq = atoi(optarg); | |
251 | break; | |
b7080c8e A |
252 | case 'd': |
253 | dflag = 1; | |
254 | break; | |
9dc66a05 A |
255 | case 'F': |
256 | Fflag = 1; | |
257 | break; | |
b7080c8e | 258 | case 'f': |
b7080c8e A |
259 | if (strcmp(optarg, "ipx") == 0) |
260 | af = AF_IPX; | |
261 | else if (strcmp(optarg, "inet") == 0) | |
262 | af = AF_INET; | |
7ba0088d A |
263 | #ifdef INET6 |
264 | else if (strcmp(optarg, "inet6") == 0) | |
265 | af = AF_INET6; | |
266 | #endif /*INET6*/ | |
267 | #ifdef INET6 | |
268 | else if (strcmp(optarg, "pfkey") == 0) | |
269 | af = PF_KEY; | |
270 | #endif /*INET6*/ | |
89c4ed63 A |
271 | else if (strcmp(optarg, "unix") == 0) |
272 | af = AF_UNIX; | |
273 | else if (strcmp(optarg, "systm") == 0) | |
274 | af = AF_SYSTEM; | |
b7080c8e A |
275 | else { |
276 | errx(1, "%s: unknown address family", optarg); | |
277 | } | |
278 | break; | |
7f5b2e89 | 279 | #if defined(__APPLE__) |
b7080c8e A |
280 | case 'g': |
281 | gflag = 1; | |
282 | break; | |
b8dff150 | 283 | #endif |
b7080c8e A |
284 | case 'I': { |
285 | char *cp; | |
286 | ||
287 | iflag = 1; | |
288 | for (cp = interface = optarg; isalpha(*cp); cp++) | |
289 | continue; | |
290 | unit = atoi(cp); | |
291 | break; | |
292 | } | |
293 | case 'i': | |
294 | iflag = 1; | |
295 | break; | |
7ba0088d A |
296 | case 'l': |
297 | lflag = 1; | |
298 | break; | |
299 | case 'L': | |
300 | Lflag = 1; | |
301 | break; | |
b7080c8e | 302 | case 'm': |
b8dff150 | 303 | mflag++; |
b7080c8e A |
304 | break; |
305 | case 'n': | |
306 | nflag = 1; | |
307 | break; | |
7f5b2e89 | 308 | case 'P': |
5902acfc | 309 | prioflag = atoi(optarg); |
7f5b2e89 | 310 | break; |
b7080c8e A |
311 | case 'p': |
312 | if ((tp = name2protox(optarg)) == NULL) { | |
313 | errx(1, | |
314 | "%s: unknown or uninstrumented protocol", | |
315 | optarg); | |
316 | } | |
317 | pflag = 1; | |
318 | break; | |
7af5ce03 A |
319 | case 'q': |
320 | qflag++; | |
321 | break; | |
322 | case 'Q': | |
323 | Qflag++; | |
324 | break; | |
fdfd5971 A |
325 | case 'R': |
326 | Rflag = 1; | |
327 | break; | |
b7080c8e A |
328 | case 'r': |
329 | rflag = 1; | |
330 | break; | |
331 | case 's': | |
332 | ++sflag; | |
333 | break; | |
89c4ed63 A |
334 | case 'S': |
335 | Sflag = 1; | |
336 | break; | |
b7080c8e A |
337 | case 't': |
338 | tflag = 1; | |
339 | break; | |
340 | case 'u': | |
341 | af = AF_UNIX; | |
342 | break; | |
fdfd5971 A |
343 | case 'v': |
344 | vflag++; | |
345 | break; | |
7ba0088d A |
346 | case 'W': |
347 | Wflag = 1; | |
348 | break; | |
b7080c8e A |
349 | case 'w': |
350 | interval = atoi(optarg); | |
351 | iflag = 1; | |
352 | break; | |
7af5ce03 A |
353 | case 'x': |
354 | xflag = 1; | |
355 | Rflag = 1; | |
356 | break; | |
b7080c8e A |
357 | case '?': |
358 | default: | |
359 | usage(); | |
360 | } | |
361 | argv += optind; | |
362 | argc -= optind; | |
363 | ||
364 | #define BACKWARD_COMPATIBILITY | |
365 | #ifdef BACKWARD_COMPATIBILITY | |
366 | if (*argv) { | |
367 | if (isdigit(**argv)) { | |
368 | interval = atoi(*argv); | |
369 | if (interval <= 0) | |
370 | usage(); | |
371 | ++argv; | |
372 | iflag = 1; | |
373 | } | |
b7080c8e A |
374 | } |
375 | #endif | |
376 | ||
b7080c8e | 377 | if (mflag) { |
2b484d24 | 378 | mbpr(); |
b7080c8e A |
379 | exit(0); |
380 | } | |
89c4ed63 | 381 | if (iflag && !sflag && !Sflag && !gflag && !qflag && !Qflag) { |
fdfd5971 A |
382 | if (Rflag) |
383 | intpr_ri(NULL); | |
384 | else | |
385 | intpr(NULL); | |
b7080c8e A |
386 | exit(0); |
387 | } | |
388 | if (rflag) { | |
b7080c8e | 389 | if (sflag) |
2b484d24 | 390 | rt_stats(); |
b7080c8e | 391 | else |
9dc66a05 | 392 | routepr(); |
b7080c8e A |
393 | exit(0); |
394 | } | |
7af5ce03 A |
395 | if (qflag || Qflag) { |
396 | if (interface == NULL) { | |
397 | fprintf(stderr, "%s statistics option " | |
398 | "requires interface name\n", qflag ? "Queue" : | |
399 | "Polling"); | |
400 | } else if (qflag) { | |
401 | aqstatpr(); | |
402 | } else { | |
403 | rxpollstatpr(); | |
404 | } | |
405 | exit(0); | |
406 | } | |
89c4ed63 A |
407 | if (Sflag) { |
408 | if (interface == NULL) { | |
409 | fprintf(stderr, "additional link status option" | |
410 | " requires interface name\n"); | |
411 | } else { | |
412 | print_link_status(interface); | |
413 | } | |
414 | exit(0); | |
415 | } | |
7af5ce03 | 416 | |
7f5b2e89 | 417 | #if defined(__APPLE__) |
b7080c8e | 418 | if (gflag) { |
b8dff150 | 419 | ifmalist_dump(); |
7ba0088d | 420 | exit(0); |
b7080c8e | 421 | } |
b8dff150 | 422 | #endif |
b7080c8e | 423 | |
7ba0088d A |
424 | if (tp) { |
425 | printproto(tp, tp->pr_name); | |
426 | exit(0); | |
427 | } | |
428 | if (af == AF_INET || af == AF_UNSPEC) | |
429 | for (tp = protox; tp->pr_name; tp++) | |
430 | printproto(tp, tp->pr_name); | |
431 | #ifdef INET6 | |
432 | if (af == AF_INET6 || af == AF_UNSPEC) | |
433 | for (tp = ip6protox; tp->pr_name; tp++) | |
434 | printproto(tp, tp->pr_name); | |
435 | #endif /*INET6*/ | |
436 | #ifdef IPSEC | |
437 | if (af == PF_KEY || af == AF_UNSPEC) | |
438 | for (tp = pfkeyprotox; tp->pr_name; tp++) | |
439 | printproto(tp, tp->pr_name); | |
440 | #endif /*IPSEC*/ | |
7ba0088d | 441 | if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) |
b7080c8e | 442 | unixpr(); |
342c141e A |
443 | |
444 | if ((af == AF_SYSTEM || af == AF_UNSPEC) && !Lflag) | |
445 | for (tp = systmprotox; tp->pr_name; tp++) | |
446 | printproto(tp, tp->pr_name); | |
89c4ed63 A |
447 | #if TARGET_OS_IPHONE |
448 | if (af == AF_UNSPEC && !Lflag) | |
449 | for (tp = nstatprotox; tp->pr_name; tp++) | |
450 | printproto(tp, tp->pr_name); | |
451 | #endif /* TARGET_OS_IPHONE */ | |
452 | ||
453 | if (af == AF_UNSPEC && !Lflag) | |
454 | for (tp = ipcprotox; tp->pr_name; tp++) | |
455 | printproto(tp, tp->pr_name); | |
456 | ||
ac2f15b3 A |
457 | #ifdef SRVCACHE |
458 | _serv_cache_close(); | |
459 | #endif | |
b7080c8e A |
460 | exit(0); |
461 | } | |
462 | ||
463 | /* | |
464 | * Print out protocol statistics or control blocks (per sflag). | |
465 | * If the interface was not specifically requested, and the symbol | |
466 | * is not in the namelist, ignore this one. | |
467 | */ | |
468 | static void | |
469 | printproto(tp, name) | |
470 | register struct protox *tp; | |
471 | char *name; | |
472 | { | |
9c859447 A |
473 | void (*pr)(uint32_t, char *, int); |
474 | uint32_t off; | |
b7080c8e A |
475 | |
476 | if (sflag) { | |
b8dff150 | 477 | if (iflag && !pflag) { |
7ba0088d | 478 | if (tp->pr_istats) |
2b484d24 | 479 | intpr(tp->pr_istats); |
9dc66a05 | 480 | else if (vflag) |
7ba0088d A |
481 | printf("%s: no per-interface stats routine\n", |
482 | tp->pr_name); | |
483 | return; | |
484 | } | |
485 | else { | |
486 | pr = tp->pr_stats; | |
487 | if (!pr) { | |
9dc66a05 | 488 | if (pflag && vflag) |
7ba0088d A |
489 | printf("%s: no stats routine\n", |
490 | tp->pr_name); | |
491 | return; | |
492 | } | |
9dc66a05 | 493 | off = tp->pr_protocol; |
7ba0088d | 494 | } |
b7080c8e A |
495 | } else { |
496 | pr = tp->pr_cblocks; | |
7ba0088d | 497 | if (!pr) { |
9dc66a05 | 498 | if (pflag && vflag) |
7ba0088d A |
499 | printf("%s: no PCB routine\n", tp->pr_name); |
500 | return; | |
501 | } | |
9dc66a05 | 502 | off = tp->pr_protocol; |
b7080c8e | 503 | } |
9dc66a05 | 504 | if (pr != NULL) { |
b8dff150 A |
505 | if (sflag && iflag && pflag) |
506 | intervalpr(pr, off, name, af); | |
507 | else | |
508 | (*pr)(off, name, af); | |
509 | } else { | |
2b484d24 | 510 | printf("### no stats for %s\n", name); |
b7080c8e | 511 | } |
b7080c8e A |
512 | } |
513 | ||
514 | char * | |
7ba0088d | 515 | plural(int n) |
b7080c8e | 516 | { |
89c4ed63 | 517 | return (n > 1 ? "s" : ""); |
b7080c8e A |
518 | } |
519 | ||
520 | char * | |
7ba0088d | 521 | plurales(int n) |
b7080c8e | 522 | { |
89c4ed63 | 523 | return (n > 1 ? "es" : ""); |
b7080c8e A |
524 | } |
525 | ||
9dc66a05 A |
526 | char * |
527 | pluralies(int n) | |
528 | { | |
89c4ed63 | 529 | return (n > 1 ? "ies" : "y"); |
9dc66a05 A |
530 | } |
531 | ||
b7080c8e A |
532 | /* |
533 | * Find the protox for the given "well-known" name. | |
534 | */ | |
535 | static struct protox * | |
7ba0088d | 536 | knownname(char *name) |
b7080c8e A |
537 | { |
538 | struct protox **tpp, *tp; | |
539 | ||
540 | for (tpp = protoprotox; *tpp; tpp++) | |
541 | for (tp = *tpp; tp->pr_name; tp++) | |
542 | if (strcmp(tp->pr_name, name) == 0) | |
543 | return (tp); | |
544 | return (NULL); | |
545 | } | |
546 | ||
547 | /* | |
548 | * Find the protox corresponding to name. | |
549 | */ | |
550 | static struct protox * | |
7ba0088d | 551 | name2protox(char *name) |
b7080c8e A |
552 | { |
553 | struct protox *tp; | |
554 | char **alias; /* alias from p->aliases */ | |
555 | struct protoent *p; | |
556 | ||
557 | /* | |
558 | * Try to find the name in the list of "well-known" names. If that | |
559 | * fails, check if name is an alias for an Internet protocol. | |
560 | */ | |
7ba0088d | 561 | if ((tp = knownname(name)) != NULL) |
b7080c8e A |
562 | return (tp); |
563 | ||
564 | setprotoent(1); /* make protocol lookup cheaper */ | |
7ba0088d | 565 | while ((p = getprotoent()) != NULL) { |
b7080c8e A |
566 | /* assert: name not same as p->name */ |
567 | for (alias = p->p_aliases; *alias; alias++) | |
568 | if (strcmp(name, *alias) == 0) { | |
569 | endprotoent(); | |
570 | return (knownname(p->p_name)); | |
571 | } | |
572 | } | |
573 | endprotoent(); | |
574 | return (NULL); | |
575 | } | |
576 | ||
b8dff150 A |
577 | #define NETSTAT_USAGE "\ |
578 | Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\ | |
579 | netstat [-gilns] [-f address_family]\n\ | |
89c4ed63 | 580 | netstat -i | -I interface [-w wait] [-abdgRtS]\n\ |
b8dff150 A |
581 | netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\ |
582 | netstat -i | -I interface -s [-f address_family | -p protocol]\n\ | |
583 | netstat -m [-m]\n\ | |
584 | netstat -r [-Aaln] [-f address_family]\n\ | |
585 | netstat -rs [-s]\n\ | |
586 | " | |
587 | ||
b7080c8e | 588 | static void |
7ba0088d | 589 | usage(void) |
b7080c8e | 590 | { |
b8dff150 | 591 | (void) fprintf(stderr, "%s\n", NETSTAT_USAGE); |
b7080c8e A |
592 | exit(1); |
593 | } | |
9dc66a05 A |
594 | |
595 | int | |
596 | print_time(void) | |
597 | { | |
598 | time_t now; | |
599 | struct tm tm; | |
600 | int num_written = 0; | |
601 | ||
602 | (void) time(&now); | |
603 | (void) localtime_r(&now, &tm); | |
604 | ||
605 | num_written += printf("%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec); | |
606 | ||
607 | return (num_written); | |
608 | } | |
609 |