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