]> git.cameronkatri.com Git - apple_cmds.git/blob - network_cmds/netstat.tproj/inet.c
Improve create_tarballs.sh
[apple_cmds.git] / network_cmds / netstat.tproj / inet.c
1 /*
2 * Copyright (c) 2008-2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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,
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.
25 ** @APPLE_OSREFERENCE_LICENSE_HEADER_END@
26 */
27 /*
28 * Copyright (c) 1983, 1988, 1993, 1995
29 * The Regents of the University of California. All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 */
59
60 #include <sys/param.h>
61 #include <sys/queue.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/sysctl.h>
65
66 #include <net/route.h>
67 #include <net/if_arp.h>
68 #include <net/net_perf.h>
69 #include <netinet/in.h>
70 #include <netinet/in_systm.h>
71 #include <netinet/ip.h>
72 #ifdef INET6
73 #include <netinet/ip6.h>
74 #endif /* INET6 */
75 #include <netinet/in_pcb.h>
76 #include <netinet/ip_icmp.h>
77 #include <netinet/icmp_var.h>
78 #include <netinet/igmp_var.h>
79 #include <netinet/ip_var.h>
80 #include <netinet/tcp.h>
81 #include <netinet/tcpip.h>
82 #include <netinet/tcp_seq.h>
83 #define TCPSTATES
84 #include <netinet/tcp_fsm.h>
85 #include <netinet/tcp_var.h>
86 #include <netinet/udp.h>
87 #include <netinet/udp_var.h>
88
89 #include <arpa/inet.h>
90 #include <err.h>
91 #include <errno.h>
92 #include <netdb.h>
93 #include <stdio.h>
94 #include <stdlib.h>
95 #include <stdint.h>
96 #include <string.h>
97 #include <unistd.h>
98 #include "netstat.h"
99
100 #ifdef __APPLE__
101 #include <TargetConditionals.h>
102 #endif
103
104 #define ROUNDUP64(a) \
105 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint64_t) - 1))) : sizeof(uint64_t))
106 #define ADVANCE64(x, n) (((char *)x) += ROUNDUP64(n))
107
108 char *inetname (struct in_addr *);
109 void inetprint (struct in_addr *, int, char *, int);
110 #ifdef INET6
111 extern void inet6print (struct in6_addr *, int, char *, int);
112 static int udp_done, tcp_done;
113 extern int mptcp_done;
114 #endif /* INET6 */
115
116 #ifdef SRVCACHE
117 typedef struct __table_private table_t;
118
119 extern table_t *_nc_table_new(uint32_t n);
120 extern void _nc_table_free(table_t *tin);
121
122 extern void _nc_table_insert(table_t *t, const char *key, void *datum);
123 extern void *_nc_table_find(table_t *t, const char *key);
124 extern void _nc_table_delete(table_t *t, const char *key);
125
126 static table_t *_serv_cache = NULL;
127
128 /*
129 * Read and cache all known services
130 */
131 static void
132 _serv_cache_open()
133 {
134 struct servent *s;
135 char *key, *name, *test;
136
137 if (_serv_cache != NULL) return;
138
139 _serv_cache = _nc_table_new(8192);
140 setservent(0);
141
142 while (NULL != (s = getservent()))
143 {
144 if (s->s_name == NULL) continue;
145 key = NULL;
146 asprintf(&key, "%hu/%s", (unsigned short)ntohs(s->s_port), s->s_proto);
147 name = strdup(s->s_name);
148 test = _nc_table_find(_serv_cache, key);
149 if (test == NULL) _nc_table_insert(_serv_cache, key, name);
150 free(key);
151 }
152
153 endservent();
154 }
155
156 void
157 _serv_cache_close()
158 {
159 _nc_table_free(_serv_cache);
160 _serv_cache = NULL;
161 }
162
163 struct servent *
164 _serv_cache_getservbyport(int port, char *proto)
165 {
166 static struct servent s;
167 char *key;
168 unsigned short p;
169
170 _serv_cache_open();
171
172 memset(&s, 0, sizeof(struct servent));
173 asprintf(&key, "%u/%s", port, (proto == NULL) ? "udp" : proto);
174
175 s.s_name = _nc_table_find(_serv_cache, key);
176 free(key);
177 if (s.s_name == NULL) return NULL;
178
179 p = port;
180 s.s_port = htons(p);
181 s.s_proto = proto;
182 return &s;
183 }
184
185 #endif /* SRVCACHE */
186
187 /*
188 * Print a summary of connections related to an Internet
189 * protocol. For TCP, also give state of connection.
190 * Listening processes (aflag) are suppressed unless the
191 * -a (all) flag is specified.
192 */
193
194 struct xgen_n {
195 u_int32_t xgn_len; /* length of this structure */
196 u_int32_t xgn_kind; /* number of PCBs at this time */
197 };
198
199 #define ALL_XGN_KIND_INP (XSO_SOCKET | XSO_RCVBUF | XSO_SNDBUF | XSO_STATS | XSO_INPCB)
200 #define ALL_XGN_KIND_TCP (ALL_XGN_KIND_INP | XSO_TCPCB)
201
202 void
203 protopr(uint32_t proto, /* for sysctl version we pass proto # */
204 char *name, int af)
205 {
206 int istcp;
207 static int first = 1;
208 char *buf, *next;
209 const char *mibvar;
210 struct xinpgen *xig, *oxig;
211 struct xgen_n *xgn;
212 size_t len;
213 struct xtcpcb_n *tp = NULL;
214 struct xinpcb_n *inp = NULL;
215 struct xsocket_n *so = NULL;
216 struct xsockbuf_n *so_rcv = NULL;
217 struct xsockbuf_n *so_snd = NULL;
218 struct xsockstat_n *so_stat = NULL;
219 int which = 0;
220
221 istcp = 0;
222 switch (proto) {
223 case IPPROTO_TCP:
224 #ifdef INET6
225 if (tcp_done != 0)
226 return;
227 else
228 tcp_done = 1;
229 #endif
230 istcp = 1;
231 mibvar = "net.inet.tcp.pcblist_n";
232 break;
233 case IPPROTO_UDP:
234 #ifdef INET6
235 if (udp_done != 0)
236 return;
237 else
238 udp_done = 1;
239 #endif
240 mibvar = "net.inet.udp.pcblist_n";
241 break;
242 case IPPROTO_DIVERT:
243 mibvar = "net.inet.divert.pcblist_n";
244 break;
245 default:
246 mibvar = "net.inet.raw.pcblist_n";
247 break;
248 }
249 len = 0;
250 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
251 if (errno != ENOENT)
252 warn("sysctl: %s", mibvar);
253 return;
254 }
255 if ((buf = malloc(len)) == 0) {
256 warn("malloc %lu bytes", (u_long)len);
257 return;
258 }
259 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
260 warn("sysctl: %s", mibvar);
261 free(buf);
262 return;
263 }
264
265 /*
266 * Bail-out to avoid logic error in the loop below when
267 * there is in fact no more control block to process
268 */
269 if (len <= sizeof(struct xinpgen)) {
270 free(buf);
271 return;
272 }
273
274 oxig = xig = (struct xinpgen *)buf;
275 for (next = buf + ROUNDUP64(xig->xig_len); next < buf + len; next += ROUNDUP64(xgn->xgn_len)) {
276
277 xgn = (struct xgen_n*)next;
278 if (xgn->xgn_len <= sizeof(struct xinpgen))
279 break;
280
281 if ((which & xgn->xgn_kind) == 0) {
282 which |= xgn->xgn_kind;
283 switch (xgn->xgn_kind) {
284 case XSO_SOCKET:
285 so = (struct xsocket_n *)xgn;
286 break;
287 case XSO_RCVBUF:
288 so_rcv = (struct xsockbuf_n *)xgn;
289 break;
290 case XSO_SNDBUF:
291 so_snd = (struct xsockbuf_n *)xgn;
292 break;
293 case XSO_STATS:
294 so_stat = (struct xsockstat_n *)xgn;
295 break;
296 case XSO_INPCB:
297 inp = (struct xinpcb_n *)xgn;
298 break;
299 case XSO_TCPCB:
300 tp = (struct xtcpcb_n *)xgn;
301 break;
302 default:
303 printf("unexpected kind %d\n", xgn->xgn_kind);
304 break;
305 }
306 } else {
307 if (vflag)
308 printf("got %d twice\n", xgn->xgn_kind);
309 }
310
311 if ((istcp && which != ALL_XGN_KIND_TCP) || (!istcp && which != ALL_XGN_KIND_INP))
312 continue;
313 which = 0;
314
315 /* Ignore sockets for protocols other than the desired one. */
316 if (so->xso_protocol != (int)proto)
317 continue;
318
319 /* Ignore PCBs which were freed during copyout. */
320 if (inp->inp_gencnt > oxig->xig_gen)
321 continue;
322
323 if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
324 #ifdef INET6
325 || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
326 #endif /* INET6 */
327 || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
328 #ifdef INET6
329 && (inp->inp_vflag &
330 INP_IPV6) == 0
331 #endif /* INET6 */
332 ))
333 )
334 continue;
335
336 /*
337 * Local address is not an indication of listening socket or
338 * server sockey but just rather the socket has been bound.
339 * That why many UDP sockets were not displayed in the original code.
340 */
341 if (!aflag && istcp && tp->t_state <= TCPS_LISTEN)
342 continue;
343
344 if (Lflag && !so->so_qlimit)
345 continue;
346
347 if (first) {
348 if (!Lflag) {
349 printf("Active Internet connections");
350 if (aflag)
351 printf(" (including servers)");
352 } else
353 printf(
354 "Current listen queue sizes (qlen/incqlen/maxqlen)");
355 putchar('\n');
356 if (Aflag) {
357 printf("%-16.16s ", "Socket");
358 printf("%-9.9s", "Flowhash");
359 }
360 if (Lflag)
361 printf("%-14.14s %-22.22s\n",
362 "Listen", "Local Address");
363 else {
364 printf((Aflag && !Wflag) ?
365 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %-11.11s" :
366 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %-11.11s",
367 "Proto", "Recv-Q", "Send-Q",
368 "Local Address", "Foreign Address",
369 "(state)");
370 if (bflag > 0)
371 printf(" %10.10s %10.10s", "rxbytes", "txbytes");
372 if (prioflag >= 0)
373 printf(" %7.7s[%1d] %7.7s[%1d]", "rxbytes", prioflag, "txbytes", prioflag);
374 if (vflag > 0)
375 printf(" %6.6s %6.6s %6.6s %6.6s %6s %10s",
376 "rhiwat", "shiwat", "pid", "epid", "state", "options");
377 printf("\n");
378 }
379 first = 0;
380 }
381 if (Aflag) {
382 if (istcp)
383 printf("%16lx ", (u_long)inp->inp_ppcb);
384 else
385 printf("%16lx ", (u_long)so->so_pcb);
386 printf("%8x ", inp->inp_flowhash);
387 }
388 if (Lflag) {
389 char buf[15];
390
391 snprintf(buf, 15, "%d/%d/%d", so->so_qlen,
392 so->so_incqlen, so->so_qlimit);
393 printf("%-14.14s ", buf);
394 }
395 else {
396 const char *vchar;
397
398 #ifdef INET6
399 if ((inp->inp_vflag & INP_IPV6) != 0)
400 vchar = ((inp->inp_vflag & INP_IPV4) != 0)
401 ? "46" : "6 ";
402 else
403 #endif
404 vchar = ((inp->inp_vflag & INP_IPV4) != 0)
405 ? "4 " : " ";
406
407 printf("%-3.3s%-2.2s %6u %6u ", name, vchar,
408 so_rcv->sb_cc,
409 so_snd->sb_cc);
410 }
411 if (nflag) {
412 if (inp->inp_vflag & INP_IPV4) {
413 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
414 name, 1);
415 if (!Lflag)
416 inetprint(&inp->inp_faddr,
417 (int)inp->inp_fport, name, 1);
418 }
419 #ifdef INET6
420 else if (inp->inp_vflag & INP_IPV6) {
421 inet6print(&inp->in6p_laddr,
422 (int)inp->inp_lport, name, 1);
423 if (!Lflag)
424 inet6print(&inp->in6p_faddr,
425 (int)inp->inp_fport, name, 1);
426 } /* else nothing printed now */
427 #endif /* INET6 */
428 } else if (inp->inp_flags & INP_ANONPORT) {
429 if (inp->inp_vflag & INP_IPV4) {
430 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
431 name, 1);
432 if (!Lflag)
433 inetprint(&inp->inp_faddr,
434 (int)inp->inp_fport, name, 0);
435 }
436 #ifdef INET6
437 else if (inp->inp_vflag & INP_IPV6) {
438 inet6print(&inp->in6p_laddr,
439 (int)inp->inp_lport, name, 1);
440 if (!Lflag)
441 inet6print(&inp->in6p_faddr,
442 (int)inp->inp_fport, name, 0);
443 } /* else nothing printed now */
444 #endif /* INET6 */
445 } else {
446 if (inp->inp_vflag & INP_IPV4) {
447 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
448 name, 0);
449 if (!Lflag)
450 inetprint(&inp->inp_faddr,
451 (int)inp->inp_fport, name,
452 inp->inp_lport !=
453 inp->inp_fport);
454 }
455 #ifdef INET6
456 else if (inp->inp_vflag & INP_IPV6) {
457 inet6print(&inp->in6p_laddr,
458 (int)inp->inp_lport, name, 0);
459 if (!Lflag)
460 inet6print(&inp->in6p_faddr,
461 (int)inp->inp_fport, name,
462 inp->inp_lport !=
463 inp->inp_fport);
464 } /* else nothing printed now */
465 #endif /* INET6 */
466 }
467 if (istcp && !Lflag) {
468 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
469 printf("%-11d", tp->t_state);
470 else {
471 printf("%-11s", tcpstates[tp->t_state]);
472 }
473 }
474 if (!istcp)
475 printf("%-11s", " ");
476 if (bflag > 0) {
477 int i;
478 u_int64_t rxbytes = 0;
479 u_int64_t txbytes = 0;
480
481 for (i = 0; i < SO_TC_STATS_MAX; i++) {
482 rxbytes += so_stat->xst_tc_stats[i].rxbytes;
483 txbytes += so_stat->xst_tc_stats[i].txbytes;
484 }
485
486 printf(" %10llu %10llu", rxbytes, txbytes);
487 }
488 if (prioflag >= 0) {
489 printf(" %10llu %10llu",
490 prioflag < SO_TC_STATS_MAX ? so_stat->xst_tc_stats[prioflag].rxbytes : 0,
491 prioflag < SO_TC_STATS_MAX ? so_stat->xst_tc_stats[prioflag].txbytes : 0);
492 }
493 if (vflag > 0) {
494 printf(" %6u %6u %6u %6u 0x%04x 0x%08x",
495 so_rcv->sb_hiwat,
496 so_snd->sb_hiwat,
497 so->so_last_pid,
498 so->so_e_pid,
499 so->so_state,
500 so->so_options);
501 }
502 putchar('\n');
503 }
504 if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
505 if (oxig->xig_count > xig->xig_count) {
506 printf("Some %s sockets may have been deleted.\n",
507 name);
508 } else if (oxig->xig_count < xig->xig_count) {
509 printf("Some %s sockets may have been created.\n",
510 name);
511 } else {
512 printf("Some %s sockets may have been created or deleted",
513 name);
514 }
515 }
516 free(buf);
517 }
518
519 /*
520 * Dump TCP statistics structure.
521 */
522 void
523 tcp_stats(uint32_t off , char *name, int af)
524 {
525 static struct tcpstat ptcpstat;
526 struct tcpstat tcpstat;
527 size_t len = sizeof tcpstat;
528 static uint32_t r_swcsum, pr_swcsum;
529 static uint32_t t_swcsum, pt_swcsum;
530
531 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
532 warn("sysctl: net.inet.tcp.stats");
533 return;
534 }
535
536 #ifdef INET6
537 if (tcp_done != 0 && interval == 0)
538 return;
539 else
540 tcp_done = 1;
541 #endif
542
543 if (interval && vflag > 0)
544 print_time();
545 printf ("%s:\n", name);
546
547 #define TCPDIFF(f) (tcpstat.f - ptcpstat.f)
548 #define p(f, m) if (TCPDIFF(f) || sflag <= 1) \
549 printf(m, TCPDIFF(f), plural(TCPDIFF(f)))
550 #define p1a(f, m) if (TCPDIFF(f) || sflag <= 1) \
551 printf(m, TCPDIFF(f))
552 #define p2(f1, f2, m) if (TCPDIFF(f1) || TCPDIFF(f2) || sflag <= 1) \
553 printf(m, TCPDIFF(f1), plural(TCPDIFF(f1)), TCPDIFF(f2), plural(TCPDIFF(f2)))
554 #define p2a(f1, f2, m) if (TCPDIFF(f1) || TCPDIFF(f2) || sflag <= 1) \
555 printf(m, TCPDIFF(f1), plural(TCPDIFF(f1)), TCPDIFF(f2))
556 #define p3(f, m) if (TCPDIFF(f) || sflag <= 1) \
557 printf(m, TCPDIFF(f), plurales(TCPDIFF(f)))
558
559 p(tcps_sndtotal, "\t%u packet%s sent\n");
560 p2(tcps_sndpack,tcps_sndbyte,
561 "\t\t%u data packet%s (%u byte%s)\n");
562 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
563 "\t\t%u data packet%s (%u byte%s) retransmitted\n");
564 p(tcps_mturesent, "\t\t%u resend%s initiated by MTU discovery\n");
565 p2a(tcps_sndacks, tcps_delack,
566 "\t\t%u ack-only packet%s (%u delayed)\n");
567 p(tcps_sndurg, "\t\t%u URG only packet%s\n");
568 p(tcps_sndprobe, "\t\t%u window probe packet%s\n");
569 p(tcps_sndwinup, "\t\t%u window update packet%s\n");
570 p(tcps_sndctrl, "\t\t%u control packet%s\n");
571 p(tcps_fcholdpacket, "\t\t%u data packet%s sent after flow control\n");
572 p(tcps_synchallenge, "\t\t%u challenge ACK%s sent due to unexpected SYN\n");
573 p(tcps_rstchallenge, "\t\t%u challenge ACK%s sent due to unexpected RST\n");
574 t_swcsum = tcpstat.tcps_snd_swcsum + tcpstat.tcps_snd6_swcsum;
575 if ((t_swcsum - pt_swcsum) || sflag <= 1)
576 printf("\t\t%u checksummed in software\n", (t_swcsum - pt_swcsum));
577 p2(tcps_snd_swcsum, tcps_snd_swcsum_bytes,
578 "\t\t\t%u segment%s (%u byte%s) over IPv4\n");
579 #if INET6
580 p2(tcps_snd6_swcsum, tcps_snd6_swcsum_bytes,
581 "\t\t\t%u segment%s (%u byte%s) over IPv6\n");
582 #endif /* INET6 */
583 p(tcps_rcvtotal, "\t%u packet%s received\n");
584 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%u ack%s (for %u byte%s)\n");
585 p(tcps_rcvdupack, "\t\t%u duplicate ack%s\n");
586 p(tcps_rcvacktoomuch, "\t\t%u ack%s for unsent data\n");
587 p2(tcps_rcvpack, tcps_rcvbyte,
588 "\t\t%u packet%s (%u byte%s) received in-sequence\n");
589 p2(tcps_rcvduppack, tcps_rcvdupbyte,
590 "\t\t%u completely duplicate packet%s (%u byte%s)\n");
591 p(tcps_pawsdrop, "\t\t%u old duplicate packet%s\n");
592 p(tcps_rcvmemdrop, "\t\t%u received packet%s dropped due to low memory\n");
593 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
594 "\t\t%u packet%s with some dup. data (%u byte%s duped)\n");
595 p2(tcps_rcvoopack, tcps_rcvoobyte,
596 "\t\t%u out-of-order packet%s (%u byte%s)\n");
597 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
598 "\t\t%u packet%s (%u byte%s) of data after window\n");
599 p(tcps_rcvwinprobe, "\t\t%u window probe%s\n");
600 p(tcps_rcvwinupd, "\t\t%u window update packet%s\n");
601 p(tcps_recovered_pkts, "\t\t%u packet%s recovered after loss\n");
602 p(tcps_rcvafterclose, "\t\t%u packet%s received after close\n");
603 p(tcps_badrst, "\t\t%u bad reset%s\n");
604 p(tcps_rcvbadsum, "\t\t%u discarded for bad checksum%s\n");
605 r_swcsum = tcpstat.tcps_rcv_swcsum + tcpstat.tcps_rcv6_swcsum;
606 if ((r_swcsum - pr_swcsum) || sflag <= 1)
607 printf("\t\t%u checksummed in software\n",
608 (r_swcsum - pr_swcsum));
609 p2(tcps_rcv_swcsum, tcps_rcv_swcsum_bytes,
610 "\t\t\t%u segment%s (%u byte%s) over IPv4\n");
611 #if INET6
612 p2(tcps_rcv6_swcsum, tcps_rcv6_swcsum_bytes,
613 "\t\t\t%u segment%s (%u byte%s) over IPv6\n");
614 #endif /* INET6 */
615 p(tcps_rcvbadoff, "\t\t%u discarded for bad header offset field%s\n");
616 p1a(tcps_rcvshort, "\t\t%u discarded because packet too short\n");
617 p(tcps_connattempt, "\t%u connection request%s\n");
618 p(tcps_accepts, "\t%u connection accept%s\n");
619 p(tcps_badsyn, "\t%u bad connection attempt%s\n");
620 p(tcps_listendrop, "\t%u listen queue overflow%s\n");
621 p(tcps_connects, "\t%u connection%s established (including accepts)\n");
622 p2(tcps_closed, tcps_drops,
623 "\t%u connection%s closed (including %u drop%s)\n");
624 p(tcps_cachedrtt, "\t\t%u connection%s updated cached RTT on close\n");
625 p(tcps_cachedrttvar,
626 "\t\t%u connection%s updated cached RTT variance on close\n");
627 p(tcps_cachedssthresh,
628 "\t\t%u connection%s updated cached ssthresh on close\n");
629 p(tcps_usedrtt, "\t\t%u connection%s initialized RTT from route cache\n");
630 p(tcps_usedrttvar,
631 "\t\t%u connection%s initialized RTT variance from route cache\n");
632 p(tcps_usedssthresh,
633 "\t\t%u connection%s initialized ssthresh from route cache\n");
634 p(tcps_conndrops, "\t%u embryonic connection%s dropped\n");
635 p2(tcps_rttupdated, tcps_segstimed,
636 "\t%u segment%s updated rtt (of %u attempt%s)\n");
637 p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n");
638 p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n");
639 p(tcps_rxtfindrop, "\t\t%u connection%s dropped after retransmitting FIN\n");
640 p(tcps_sndrexmitbad, "\t\t%u unnecessary packet retransmissions%s\n");
641 p(tcps_persisttimeo, "\t%u persist timeout%s\n");
642 p(tcps_persistdrop, "\t\t%u connection%s dropped by persist timeout\n");
643 p(tcps_keeptimeo, "\t%u keepalive timeout%s\n");
644 p(tcps_keepprobe, "\t\t%u keepalive probe%s sent\n");
645 p(tcps_keepdrops, "\t\t%u connection%s dropped by keepalive\n");
646 p(tcps_ka_offload_drops, "\t\t%u connection%s dropped by keepalive offload\n");
647 p(tcps_predack, "\t%u correct ACK header prediction%s\n");
648 p(tcps_preddat, "\t%u correct data packet header prediction%s\n");
649 #ifdef TCP_MAX_SACK
650 /* TCP_MAX_SACK indicates the header has the SACK structures */
651 p(tcps_sack_recovery_episode, "\t%u SACK recovery episode%s\n");
652 p(tcps_sack_rexmits,
653 "\t%u segment rexmit%s in SACK recovery episodes\n");
654 p(tcps_sack_rexmit_bytes,
655 "\t%u byte rexmit%s in SACK recovery episodes\n");
656 p(tcps_sack_rcv_blocks,
657 "\t%u SACK option%s (SACK blocks) received\n");
658 p(tcps_sack_send_blocks, "\t%u SACK option%s (SACK blocks) sent\n");
659 p1a(tcps_sack_sboverflow, "\t%u SACK scoreboard overflow\n");
660 #endif /* TCP_MAX_SACK */
661 p(tcps_limited_txt, "\t%u limited transmit%s done\n");
662 p(tcps_early_rexmt, "\t%u early retransmit%s done\n");
663 p(tcps_sack_ackadv, "\t%u time%s cumulative ack advanced along with SACK\n");
664 p(tcps_pto, "\t%u probe timeout%s\n");
665 p(tcps_rto_after_pto, "\t\t%u time%s retransmit timeout triggered after probe\n");
666 p(tcps_probe_if, "\t\t%u time%s probe packets were sent for an interface\n");
667 p(tcps_probe_if_conflict, "\t\t%u time%s couldn't send probe packets for an interface\n");
668 p(tcps_tlp_recovery, "\t\t%u time%s fast recovery after tail loss\n");
669 p(tcps_tlp_recoverlastpkt, "\t\t%u time%s recovered last packet \n");
670 p(tcps_pto_in_recovery, "\t\t%u SACK based rescue retransmit%s\n");
671 p(tcps_ecn_client_setup, "\t%u client connection%s attempted to negotiate ECN\n");
672 p(tcps_ecn_client_success, "\t\t%u client connection%s successfully negotiated ECN\n");
673 p(tcps_ecn_not_supported, "\t\t%u time%s graceful fallback to Non-ECN connection\n");
674 p(tcps_ecn_lost_syn, "\t\t%u time%s lost ECN negotiating SYN, followed by retransmission\n");
675 p(tcps_ecn_server_setup, "\t\t%u server connection%s attempted to negotiate ECN\n");
676 p(tcps_ecn_server_success, "\t\t%u server connection%s successfully negotiated ECN\n");
677 p(tcps_ecn_lost_synack, "\t\t%u time%s lost ECN negotiating SYN-ACK, followed by retransmission\n");
678 p(tcps_ecn_recv_ce, "\t\t%u time%s received congestion experienced (CE) notification\n");
679 p(tcps_ecn_recv_ece, "\t\t%u time%s CWR was sent in response to ECE\n");
680 p(tcps_ecn_sent_ece, "\t\t%u time%s sent ECE notification\n");
681 p(tcps_ecn_conn_recv_ce, "\t\t%u connection%s received CE atleast once\n");
682 p(tcps_ecn_conn_recv_ece, "\t\t%u connection%s received ECE atleast once\n");
683 p(tcps_ecn_conn_plnoce, "\t\t%u connection%s using ECN have seen packet loss but no CE\n");
684 p(tcps_ecn_conn_pl_ce, "\t\t%u connection%s using ECN have seen packet loss and CE\n");
685 p(tcps_ecn_conn_nopl_ce, "\t\t%u connection%s using ECN received CE but no packet loss\n");
686 p(tcps_ecn_fallback_synloss, "\t\t%u connection%s fell back to non-ECN due to SYN-loss\n");
687 p(tcps_ecn_fallback_reorder, "\t\t%u connection%s fell back to non-ECN due to reordering\n");
688 p(tcps_ecn_fallback_ce, "\t\t%u connection%s fell back to non-ECN due to excessive CE-markings\n");
689 p(tcps_ecn_fallback_droprst, "\t\t%u connection%s fell back caused by connection drop due to RST\n");
690 p(tcps_ecn_fallback_droprxmt, "\t\t%u connection%s fell back due to drop after multiple retransmits \n");
691 p(tcps_ecn_fallback_synrst, "\t\t%u connection%s fell back due to RST after SYN\n");
692
693 p(tcps_detect_reordering, "\t%u time%s packet reordering was detected on a connection\n");
694 p(tcps_reordered_pkts, "\t\t%u time%s transmitted packets were reordered\n");
695 p(tcps_delay_recovery, "\t\t%u time%s fast recovery was delayed to handle reordering\n");
696 p(tcps_avoid_rxmt, "\t\t%u time%s retransmission was avoided by delaying recovery\n");
697 p(tcps_unnecessary_rxmt, "\t\t%u retransmission%s not needed \n");
698 p(tcps_tailloss_rto, "\t%u retransmission%s due to tail loss\n");
699 p(tcps_dsack_sent, "\t%u time%s DSACK option was sent\n");
700 p(tcps_dsack_recvd, "\t\t%u time%s DSACK option was received\n");
701 p(tcps_dsack_disable, "\t\t%u time%s DSACK was disabled on a connection\n");
702 p(tcps_dsack_badrexmt, "\t\t%u time%s recovered from bad retransmission using DSACK\n");
703 p(tcps_dsack_ackloss,"\t\t%u time%s ignored DSACK due to ack loss\n");
704 p(tcps_dsack_recvd_old,"\t\t%u time%s ignored old DSACK options\n");
705 p(tcps_pmtudbh_reverted, "\t%u time%s PMTU Blackhole detection, size reverted\n");
706 p(tcps_drop_after_sleep, "\t%u connection%s were dropped after long sleep\n");
707 p(tcps_nostretchack, "\t%u connection%s had stretch ack algorithm disabled\n");
708
709 p(tcps_tfo_cookie_sent,"\t%u time%s a TFO-cookie has been announced\n");
710 p(tcps_tfo_syn_data_rcv,"\t%u SYN%s with data and a valid TFO-cookie have been received\n");
711 p(tcps_tfo_cookie_req_rcv,"\t%u SYN%s with TFO-cookie-request received\n");
712 p(tcps_tfo_cookie_invalid,"\t%u time%s an invalid TFO-cookie has been received\n");
713 p(tcps_tfo_cookie_req,"\t%u time%s we requested a TFO-cookie\n");
714 p(tcps_tfo_cookie_rcv,"\t\t%u time%s the peer announced a TFO-cookie\n");
715 p(tcps_tfo_syn_data_sent,"\t%u time%s we combined SYN with data and a TFO-cookie\n");
716 p(tcps_tfo_syn_data_acked,"\t\t%u time%s our SYN with data has been acknowledged\n");
717 p(tcps_tfo_syn_loss,"\t%u time%s a connection-attempt with TFO fell back to regular TCP\n");
718 p(tcps_tfo_blackhole,"\t%u time%s a TFO-connection blackhole'd\n");
719 p(tcps_tfo_cookie_wrong,"\t%u time%s a TFO-cookie we sent was wrong\n");
720 p(tcps_tfo_no_cookie_rcv,"\t%u time%s did not received a TFO-cookie we asked for\n");
721 p(tcps_tfo_heuristics_disable,"\t%u time%s TFO got disabled due to heuristicsn\n");
722 p(tcps_tfo_sndblackhole,"\t%u time%s TFO got blackholed in the sending direction\n");
723
724 p(tcps_mss_to_default,"\t%u time%s maximum segment size was changed to default\n");
725 p(tcps_mss_to_medium,"\t%u time%s maximum segment size was changed to medium\n");
726 p(tcps_mss_to_low,"\t%u time%s maximum segment size was changed to low\n");
727
728 p(tcps_timer_drift_le_1_ms,"\t%u timer drift%s less or equal to 1 ms\n");
729 p(tcps_timer_drift_le_10_ms,"\t%u timer drift%s less or equal to 10 ms\n");
730 p(tcps_timer_drift_le_20_ms,"\t%u timer drift%s less or equal to 20 ms\n");
731 p(tcps_timer_drift_le_50_ms,"\t%u timer drift%s less or equal to 50 ms\n");
732 p(tcps_timer_drift_le_100_ms,"\t%u timer drift%s less or equal to 100 ms\n");
733 p(tcps_timer_drift_le_200_ms,"\t%u timer drift%s less or equal to 200 ms\n");
734 p(tcps_timer_drift_le_500_ms,"\t%u timer drift%s less or equal to 500 ms\n");
735 p(tcps_timer_drift_le_1000_ms,"\t%u timer drift%s less or equal to 1000 ms\n");
736 p(tcps_timer_drift_gt_1000_ms,"\t%u timer drift%s greater than to 1000 ms\n");
737
738 if (interval > 0) {
739 bcopy(&tcpstat, &ptcpstat, len);
740 pr_swcsum = r_swcsum;
741 pt_swcsum = t_swcsum;
742 }
743
744 #undef TCPDIFF
745 #undef p
746 #undef p1a
747 #undef p2
748 #undef p2a
749 #undef p3
750 }
751
752 /*
753 * Dump MPTCP statistics
754 */
755 void
756 mptcp_stats(uint32_t off , char *name, int af)
757 {
758 static struct tcpstat ptcpstat;
759 struct tcpstat tcpstat;
760 size_t len = sizeof tcpstat;
761
762 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
763 warn("sysctl: net.inet.tcp.stats");
764 return;
765 }
766
767 #ifdef INET6
768 if (mptcp_done != 0 && interval == 0)
769 return;
770 else
771 mptcp_done = 1;
772 #endif
773
774 if (interval && vflag > 0)
775 print_time();
776 printf ("%s:\n", name);
777
778 #define MPTCPDIFF(f) (tcpstat.f - ptcpstat.f)
779 #define p(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
780 printf(m, MPTCPDIFF(f), plural(MPTCPDIFF(f)))
781 #define p1a(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
782 printf(m, MPTCPDIFF(f))
783 #define p2(f1, f2, m) if (MPTCPDIFF(f1) || MPTCPDIFF(f2) || sflag <= 1) \
784 printf(m, MPTCPDIFF(f1), plural(MPTCPDIFF(f1)), \
785 MPTCPDIFF(f2), plural(MPTCPDIFF(f2)))
786 #define p2a(f1, f2, m) if (MPTCPDIFF(f1) || MPTCPDIFF(f2) || sflag <= 1) \
787 printf(m, MPTCPDIFF(f1), plural(MPTCPDIFF(f1)), MPTCPDIFF(f2))
788 #define p3(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
789 printf(m, MPTCPDIFF(f), plurales(MPTCPDIFF(f)))
790
791 p(tcps_mp_sndpacks, "\t%u data packet%s sent\n");
792 p(tcps_mp_sndbytes, "\t%u data byte%s sent\n");
793 p(tcps_mp_rcvtotal, "\t%u data packet%s received\n");
794 p(tcps_mp_rcvbytes, "\t%u data byte%s received\n");
795 p(tcps_invalid_mpcap, "\t%u packet%s with an invalid MPCAP option\n");
796 p(tcps_invalid_joins, "\t%u packet%s with an invalid MPJOIN option\n");
797 p(tcps_mpcap_fallback, "\t%u time%s primary subflow fell back to "
798 "TCP\n");
799 p(tcps_join_fallback, "\t%u time%s secondary subflow fell back to "
800 "TCP\n");
801 p(tcps_estab_fallback, "\t%u DSS option drop%s\n");
802 p(tcps_invalid_opt, "\t%u other invalid MPTCP option%s\n");
803 p(tcps_mp_reducedwin, "\t%u time%s the MPTCP subflow window was reduced\n");
804 p(tcps_mp_badcsum, "\t%u bad DSS checksum%s\n");
805 p(tcps_mp_oodata, "\t%u time%s received out of order data \n");
806 p3(tcps_mp_switches, "\t%u subflow switch%s\n");
807 p3(tcps_mp_sel_symtomsd, "\t%u subflow switch%s due to advisory\n");
808 p3(tcps_mp_sel_rtt, "\t%u subflow switch%s due to rtt\n");
809 p3(tcps_mp_sel_rto, "\t%u subflow switch%s due to rto\n");
810 p3(tcps_mp_sel_peer, "\t%u subflow switch%s due to peer\n");
811 p3(tcps_mp_num_probes, "\t%u number of subflow probe%s\n");
812
813 if (interval > 0) {
814 bcopy(&tcpstat, &ptcpstat, len);
815 }
816
817 #undef MPTCPDIFF
818 #undef p
819 #undef p1a
820 #undef p2
821 #undef p2a
822 #undef p3
823 }
824
825 /*
826 * Dump UDP statistics structure.
827 */
828 void
829 udp_stats(uint32_t off , char *name, int af )
830 {
831 static struct udpstat pudpstat;
832 struct udpstat udpstat;
833 size_t len = sizeof udpstat;
834 uint32_t delivered;
835 static uint32_t r_swcsum, pr_swcsum;
836 static uint32_t t_swcsum, pt_swcsum;
837
838 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) {
839 warn("sysctl: net.inet.udp.stats");
840 return;
841 }
842
843 #ifdef INET6
844 if (udp_done != 0 && interval == 0)
845 return;
846 else
847 udp_done = 1;
848 #endif
849
850 if (interval && vflag > 0)
851 print_time();
852 printf("%s:\n", name);
853
854 #define UDPDIFF(f) (udpstat.f - pudpstat.f)
855 #define p(f, m) if (UDPDIFF(f) || sflag <= 1) \
856 printf(m, UDPDIFF(f), plural(UDPDIFF(f)))
857 #define p1a(f, m) if (UDPDIFF(f) || sflag <= 1) \
858 printf(m, UDPDIFF(f))
859 #define p2(f1, f2, m) if (UDPDIFF(f1) || UDPDIFF(f2) || sflag <= 1) \
860 printf(m, UDPDIFF(f1), plural(UDPDIFF(f1)), UDPDIFF(f2), plural(UDPDIFF(f2)))
861 p(udps_ipackets, "\t%u datagram%s received\n");
862 p1a(udps_hdrops, "\t\t%u with incomplete header\n");
863 p1a(udps_badlen, "\t\t%u with bad data length field\n");
864 p1a(udps_badsum, "\t\t%u with bad checksum\n");
865 p1a(udps_nosum, "\t\t%u with no checksum\n");
866 r_swcsum = udpstat.udps_rcv_swcsum + udpstat.udps_rcv6_swcsum;
867 if ((r_swcsum - pr_swcsum) || sflag <= 1)
868 printf("\t\t%u checksummed in software\n", (r_swcsum - pr_swcsum));
869 p2(udps_rcv_swcsum, udps_rcv_swcsum_bytes,
870 "\t\t\t%u datagram%s (%u byte%s) over IPv4\n");
871 #if INET6
872 p2(udps_rcv6_swcsum, udps_rcv6_swcsum_bytes,
873 "\t\t\t%u datagram%s (%u byte%s) over IPv6\n");
874 #endif /* INET6 */
875 p1a(udps_noport, "\t\t%u dropped due to no socket\n");
876 p(udps_noportbcast,
877 "\t\t%u broadcast/multicast datagram%s undelivered\n");
878 /* the next statistic is cumulative in udps_noportbcast */
879 p(udps_filtermcast,
880 "\t\t%u time%s multicast source filter matched\n");
881 p1a(udps_fullsock, "\t\t%u dropped due to full socket buffers\n");
882 p1a(udpps_pcbhashmiss, "\t\t%u not for hashed pcb\n");
883 delivered = UDPDIFF(udps_ipackets) -
884 UDPDIFF(udps_hdrops) -
885 UDPDIFF(udps_badlen) -
886 UDPDIFF(udps_badsum) -
887 UDPDIFF(udps_noport) -
888 UDPDIFF(udps_noportbcast) -
889 UDPDIFF(udps_fullsock);
890 if (delivered || sflag <= 1)
891 printf("\t\t%u delivered\n", delivered);
892 p(udps_opackets, "\t%u datagram%s output\n");
893 t_swcsum = udpstat.udps_snd_swcsum + udpstat.udps_snd6_swcsum;
894 if ((t_swcsum - pt_swcsum) || sflag <= 1)
895 printf("\t\t%u checksummed in software\n", (t_swcsum - pt_swcsum));
896 p2(udps_snd_swcsum, udps_snd_swcsum_bytes,
897 "\t\t\t%u datagram%s (%u byte%s) over IPv4\n");
898 #if INET6
899 p2(udps_snd6_swcsum, udps_snd6_swcsum_bytes,
900 "\t\t\t%u datagram%s (%u byte%s) over IPv6\n");
901 #endif /* INET6 */
902
903 if (interval > 0) {
904 bcopy(&udpstat, &pudpstat, len);
905 pr_swcsum = r_swcsum;
906 pt_swcsum = t_swcsum;
907 }
908
909 #undef UDPDIFF
910 #undef p
911 #undef p1a
912 #undef p2
913 }
914
915 /*
916 * Dump IP statistics structure.
917 */
918 void
919 ip_stats(uint32_t off , char *name, int af )
920 {
921 static struct ipstat pipstat;
922 struct ipstat ipstat;
923 size_t ipstat_len = sizeof ipstat;
924
925 static net_perf_t pout_net_perf, pin_net_perf;
926 net_perf_t out_net_perf, in_net_perf;
927 size_t out_net_perf_len = sizeof (out_net_perf);
928 size_t in_net_perf_len = sizeof (in_net_perf);
929
930 if (sysctlbyname("net.inet.ip.stats", &ipstat, &ipstat_len, 0, 0) < 0) {
931 warn("sysctl: net.inet.ip.stats");
932 return;
933 }
934
935 if (sysctlbyname("net.inet.ip.output_perf_data", &out_net_perf, &out_net_perf_len, 0, 0) < 0) {
936 warn("sysctl: net.inet.ip.output_perf_data");
937 bzero(&out_net_perf, out_net_perf_len);
938 }
939
940 if (sysctlbyname("net.inet.ip.input_perf_data", &in_net_perf, &in_net_perf_len, 0, 0) < 0) {
941 warn("sysctl: net.inet.ip.input_perf_data");
942 bzero(&in_net_perf, in_net_perf_len);
943 }
944
945 if (interval && vflag > 0)
946 print_time();
947 printf("%s:\n", name);
948
949 #define IPDIFF(f) (ipstat.f - pipstat.f)
950 #define p(f, m) if (IPDIFF(f) || sflag <= 1) \
951 printf(m, IPDIFF(f), plural(IPDIFF(f)))
952 #define p1a(f, m) if (IPDIFF(f) || sflag <= 1) \
953 printf(m, IPDIFF(f))
954 #define p2(f1, f2, m) if (IPDIFF(f1) || IPDIFF(f2) || sflag <= 1) \
955 printf(m, IPDIFF(f1), plural(IPDIFF(f1)), IPDIFF(f2), plural(IPDIFF(f2)))
956
957 p(ips_total, "\t%u total packet%s received\n");
958 p(ips_badsum, "\t\t%u bad header checksum%s\n");
959 p2(ips_rcv_swcsum, ips_rcv_swcsum_bytes,
960 "\t\t%u header%s (%u byte%s) checksummed in software\n");
961 p1a(ips_toosmall, "\t\t%u with size smaller than minimum\n");
962 p1a(ips_tooshort, "\t\t%u with data size < data length\n");
963 p1a(ips_adj, "\t\t%u with data size > data length\n");
964 p(ips_adj_hwcsum_clr,
965 "\t\t\t%u packet%s forced to software checksum\n");
966 p1a(ips_toolong, "\t\t%u with ip length > max ip packet size\n");
967 p1a(ips_badhlen, "\t\t%u with header length < data size\n");
968 p1a(ips_badlen, "\t\t%u with data length < header length\n");
969 p1a(ips_badoptions, "\t\t%u with bad options\n");
970 p1a(ips_badvers, "\t\t%u with incorrect version number\n");
971 p(ips_fragments, "\t\t%u fragment%s received\n");
972 p1a(ips_fragdropped, "\t\t\t%u dropped (dup or out of space)\n");
973 p1a(ips_fragtimeout, "\t\t\t%u dropped after timeout\n");
974 p1a(ips_reassembled, "\t\t\t%u reassembled ok\n");
975 p(ips_delivered, "\t\t%u packet%s for this host\n");
976 p(ips_noproto, "\t\t%u packet%s for unknown/unsupported protocol\n");
977 p(ips_forward, "\t\t%u packet%s forwarded");
978 p(ips_fastforward, " (%u packet%s fast forwarded)");
979 if (IPDIFF(ips_forward) || sflag <= 1)
980 putchar('\n');
981 p(ips_cantforward, "\t\t%u packet%s not forwardable\n");
982 p(ips_notmember,
983 "\t\t%u packet%s received for unknown multicast group\n");
984 p(ips_redirectsent, "\t\t%u redirect%s sent\n");
985 p(ips_rxc_collisions, "\t\t%u input packet%s not chained due to collision\n");
986 p(ips_rxc_chained, "\t\t%u input packet%s processed in a chain\n");
987 p(ips_rxc_notchain, "\t\t%u input packet%s unable to chain\n");
988 p(ips_rxc_chainsz_gt2,
989 "\t\t%u input packet chain%s processed with length greater than 2\n");
990 p(ips_rxc_chainsz_gt4,
991 "\t\t%u input packet chain%s processed with length greater than 4\n");
992 p(ips_rxc_notlist,
993 "\t\t%u input packet%s did not go through list processing path\n");
994
995 p(ips_rcv_if_weak_match,
996 "\t\t%u input packet%s that passed the weak ES interface address match\n");
997 p(ips_rcv_if_no_match,
998 "\t\t%u input packet%s with no interface address match\n");
999
1000 #define INPERFDIFF(f) (in_net_perf.f - pin_net_perf.f)
1001 if (INPERFDIFF(np_total_pkts) > 0 && in_net_perf.np_total_usecs > 0) {
1002 printf("\tInput Performance Stats:\n");
1003 printf("\t\t%llu total packets measured\n", INPERFDIFF(np_total_pkts));
1004 printf("\t\t%llu total usec elapsed\n", INPERFDIFF(np_total_usecs));
1005 printf("\t\t%f usec per packet\n",
1006 (double)in_net_perf.np_total_usecs/(double)in_net_perf.np_total_pkts);
1007 printf("\t\tHistogram:\n");
1008 printf("\t\t\t x <= %u: %llu\n", in_net_perf.np_hist_bars[0],
1009 INPERFDIFF(np_hist1));
1010 printf("\t\t\t %u < x <= %u: %llu\n",
1011 in_net_perf.np_hist_bars[0], in_net_perf.np_hist_bars[1],
1012 INPERFDIFF(np_hist2));
1013 printf("\t\t\t %u < x <= %u: %llu\n",
1014 in_net_perf.np_hist_bars[1], in_net_perf.np_hist_bars[2],
1015 INPERFDIFF(np_hist3));
1016 printf("\t\t\t %u < x <= %u: %llu\n",
1017 in_net_perf.np_hist_bars[2], in_net_perf.np_hist_bars[3],
1018 INPERFDIFF(np_hist4));
1019 printf("\t\t\t %u < x: %llu\n",
1020 in_net_perf.np_hist_bars[3], INPERFDIFF(np_hist5));
1021 }
1022 #undef INPERFDIFF
1023
1024 p(ips_localout, "\t%u packet%s sent from this host\n");
1025 p(ips_rawout, "\t\t%u packet%s sent with fabricated ip header\n");
1026 p(ips_odropped,
1027 "\t\t%u output packet%s dropped due to no bufs, etc.\n");
1028 p(ips_noroute, "\t\t%u output packet%s discarded due to no route\n");
1029 p(ips_fragmented, "\t\t%u output datagram%s fragmented\n");
1030 p(ips_ofragments, "\t\t%u fragment%s created\n");
1031 p(ips_cantfrag, "\t\t%u datagram%s that can't be fragmented\n");
1032 p(ips_nogif, "\t\t%u tunneling packet%s that can't find gif\n");
1033 p(ips_badaddr, "\t\t%u datagram%s with bad address in header\n");
1034 p(ips_pktdropcntrl,
1035 "\t\t%u packet%s dropped due to no bufs for control data\n");
1036 p(ips_necp_policy_drop, "\t\t%u packet%s dropped due to NECP policy\n");
1037 p2(ips_snd_swcsum, ips_snd_swcsum_bytes,
1038 "\t\t%u header%s (%u byte%s) checksummed in software\n");
1039
1040 #define OUTPERFDIFF(f) (out_net_perf.f - pout_net_perf.f)
1041 if (OUTPERFDIFF(np_total_pkts) > 0 && out_net_perf.np_total_usecs > 0) {
1042 printf("\tOutput Performance Stats:\n");
1043 printf("\t\t%llu total packets measured\n", OUTPERFDIFF(np_total_pkts));
1044 printf("\t\t%llu total usec elapsed\n", OUTPERFDIFF(np_total_usecs));
1045 printf("\t\t%f usec per packet\n",
1046 (double)out_net_perf.np_total_usecs/(double)out_net_perf.np_total_pkts);
1047 printf("\t\tHistogram:\n");
1048 printf("\t\t\t x <= %u: %llu\n", out_net_perf.np_hist_bars[0],
1049 OUTPERFDIFF(np_hist1));
1050 printf("\t\t\t %u < x <= %u: %llu\n",
1051 out_net_perf.np_hist_bars[0], out_net_perf.np_hist_bars[1],
1052 OUTPERFDIFF(np_hist2));
1053 printf("\t\t\t %u < x <= %u: %llu\n",
1054 out_net_perf.np_hist_bars[1], out_net_perf.np_hist_bars[2],
1055 OUTPERFDIFF(np_hist3));
1056 printf("\t\t\t %u < x <= %u: %llu\n",
1057 out_net_perf.np_hist_bars[2], out_net_perf.np_hist_bars[3],
1058 OUTPERFDIFF(np_hist4));
1059 printf("\t\t\t %u < x: %llu\n",
1060 out_net_perf.np_hist_bars[3], OUTPERFDIFF(np_hist5));
1061 }
1062 #undef OUTPERFDIFF
1063
1064 if (interval > 0) {
1065 bcopy(&ipstat, &pipstat, ipstat_len);
1066 bcopy(&in_net_perf, &pin_net_perf, in_net_perf_len);
1067 bcopy(&out_net_perf, &pout_net_perf, out_net_perf_len);
1068 }
1069
1070 #undef IPDIFF
1071 #undef p
1072 #undef p1a
1073 #undef p2
1074 }
1075
1076 /*
1077 * Dump ARP statistics structure.
1078 */
1079 void
1080 arp_stats(uint32_t off, char *name, int af)
1081 {
1082 static struct arpstat parpstat;
1083 struct arpstat arpstat;
1084 size_t len = sizeof (arpstat);
1085
1086 if (sysctlbyname("net.link.ether.inet.stats", &arpstat,
1087 &len, 0, 0) < 0) {
1088 warn("sysctl: net.link.ether.inet.stats");
1089 return;
1090 }
1091
1092 if (interval && vflag > 0)
1093 print_time();
1094 printf("%s:\n", name);
1095
1096 #define ARPDIFF(f) (arpstat.f - parpstat.f)
1097 #define p(f, m) if (ARPDIFF(f) || sflag <= 1) \
1098 printf(m, ARPDIFF(f), plural(ARPDIFF(f)))
1099 #define p2(f, m) if (ARPDIFF(f) || sflag <= 1) \
1100 printf(m, ARPDIFF(f), pluralies(ARPDIFF(f)))
1101 #define p3(f, m) if (ARPDIFF(f) || sflag <= 1) \
1102 printf(m, ARPDIFF(f), plural(ARPDIFF(f)), pluralies(ARPDIFF(f)))
1103
1104 p(txrequests, "\t%u broadast ARP request%s sent\n");
1105 p(txurequests, "\t%u unicast ARP request%s sent\n");
1106 p2(txreplies, "\t%u ARP repl%s sent\n");
1107 p(txannounces, "\t%u ARP announcement%s sent\n");
1108 p(rxrequests, "\t%u ARP request%s received\n");
1109 p2(rxreplies, "\t%u ARP repl%s received\n");
1110 p(received, "\t%u total ARP packet%s received\n");
1111 p(txconflicts, "\t%u ARP conflict probe%s sent\n");
1112 p(invalidreqs, "\t%u invalid ARP resolve request%s\n");
1113 p(reqnobufs, "\t%u total packet%s dropped due to lack of memory\n");
1114 p3(held, "\t%u total packet%s held awaiting ARP repl%s\n");
1115 p(dropped, "\t%u total packet%s dropped due to no ARP entry\n");
1116 p(purged, "\t%u total packet%s dropped during ARP entry removal\n");
1117 p2(timeouts, "\t%u ARP entr%s timed out\n");
1118 p(dupips, "\t%u Duplicate IP%s seen\n");
1119
1120 if (interval > 0)
1121 bcopy(&arpstat, &parpstat, len);
1122
1123 #undef ARPDIFF
1124 #undef p
1125 #undef p2
1126 }
1127
1128 static char *icmpnames[] = {
1129 "echo reply",
1130 "#1",
1131 "#2",
1132 "destination unreachable",
1133 "source quench",
1134 "routing redirect",
1135 "#6",
1136 "#7",
1137 "echo",
1138 "router advertisement",
1139 "router solicitation",
1140 "time exceeded",
1141 "parameter problem",
1142 "time stamp",
1143 "time stamp reply",
1144 "information request",
1145 "information request reply",
1146 "address mask request",
1147 "address mask reply",
1148 };
1149
1150 /*
1151 * Dump ICMP statistics.
1152 */
1153 void
1154 icmp_stats(uint32_t off , char *name, int af )
1155 {
1156 static struct icmpstat picmpstat;
1157 struct icmpstat icmpstat;
1158 int i, first;
1159 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
1160 size_t len;
1161
1162 mib[0] = CTL_NET;
1163 mib[1] = PF_INET;
1164 mib[2] = IPPROTO_ICMP;
1165 mib[3] = ICMPCTL_STATS;
1166
1167 len = sizeof icmpstat;
1168 memset(&icmpstat, 0, len);
1169 if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0)
1170 return; /* XXX should complain, but not traditional */
1171
1172 if (interval && vflag > 0)
1173 print_time();
1174 printf("%s:\n", name);
1175
1176 #define ICMPDIFF(f) (icmpstat.f - picmpstat.f)
1177 #define p(f, m) if (ICMPDIFF(f) || sflag <= 1) \
1178 printf(m, ICMPDIFF(f), plural(ICMPDIFF(f)))
1179 #define p1a(f, m) if (ICMPDIFF(f) || sflag <= 1) \
1180 printf(m, ICMPDIFF(f))
1181
1182 p(icps_error, "\t%u call%s to icmp_error\n");
1183 p(icps_oldicmp,
1184 "\t%u error%s not generated 'cuz old message was icmp\n");
1185 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
1186 if (ICMPDIFF(icps_outhist[i]) != 0) {
1187 if (first) {
1188 printf("\tOutput histogram:\n");
1189 first = 0;
1190 }
1191 printf("\t\t%s: %u\n", icmpnames[i],
1192 ICMPDIFF(icps_outhist[i]));
1193 }
1194 p(icps_badcode, "\t%u message%s with bad code fields\n");
1195 p(icps_tooshort, "\t%u message%s < minimum length\n");
1196 p(icps_checksum, "\t%u bad checksum%s\n");
1197 p(icps_badlen, "\t%u message%s with bad length\n");
1198 p1a(icps_bmcastecho, "\t%u multicast echo requests ignored\n");
1199 p1a(icps_bmcasttstamp, "\t%u multicast timestamp requests ignored\n");
1200 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
1201 if (ICMPDIFF(icps_inhist[i]) != 0) {
1202 if (first) {
1203 printf("\tInput histogram:\n");
1204 first = 0;
1205 }
1206 printf("\t\t%s: %u\n", icmpnames[i],
1207 ICMPDIFF(icps_inhist[i]));
1208 }
1209 p(icps_reflect, "\t%u message response%s generated\n");
1210
1211 #undef ICMPDIFF
1212 #undef p
1213 #undef p1a
1214 mib[3] = ICMPCTL_MASKREPL;
1215 len = sizeof i;
1216 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
1217 return;
1218 printf("\tICMP address mask responses are %sabled\n",
1219 i ? "en" : "dis");
1220
1221 if (interval > 0)
1222 bcopy(&icmpstat, &picmpstat, sizeof (icmpstat));
1223 }
1224
1225 /*
1226 * Dump IGMP statistics structure.
1227 */
1228 void
1229 igmp_stats(uint32_t off , char *name, int af )
1230 {
1231 static struct igmpstat_v3 pigmpstat;
1232 struct igmpstat_v3 igmpstat;
1233 size_t len = sizeof igmpstat;
1234
1235 if (sysctlbyname("net.inet.igmp.v3stats", &igmpstat, &len, 0, 0) < 0) {
1236 warn("sysctl: net.inet.igmp.v3stats");
1237 return;
1238 }
1239
1240 if (igmpstat.igps_version != IGPS_VERSION_3) {
1241 warnx("%s: version mismatch (%d != %d)", __func__,
1242 igmpstat.igps_version, IGPS_VERSION_3);
1243 }
1244 if (igmpstat.igps_len != IGPS_VERSION3_LEN) {
1245 warnx("%s: size mismatch (%d != %d)", __func__,
1246 igmpstat.igps_len, IGPS_VERSION3_LEN);
1247 }
1248
1249 if (interval && vflag > 0)
1250 print_time();
1251 printf("%s:\n", name);
1252
1253 #define IGMPDIFF(f) ((uintmax_t)(igmpstat.f - pigmpstat.f))
1254 #define p64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
1255 printf(m, IGMPDIFF(f), plural(IGMPDIFF(f)))
1256 #define py64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
1257 printf(m, IGMPDIFF(f), IGMPDIFF(f) != 1 ? "ies" : "y")
1258
1259 p64(igps_rcv_total, "\t%ju message%s received\n");
1260 p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
1261 p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n");
1262 p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n");
1263 py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n");
1264 py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n");
1265 py64(igps_rcv_badqueries,
1266 "\t%ju membership quer%s received with invalid field(s)\n");
1267 py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n");
1268 py64(igps_rcv_group_queries, "\t%ju group quer%s received\n");
1269 py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n");
1270 py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n");
1271 p64(igps_rcv_reports, "\t%ju membership report%s received\n");
1272 p64(igps_rcv_badreports,
1273 "\t%ju membership report%s received with invalid field(s)\n");
1274 p64(igps_rcv_ourreports,
1275 "\t%ju membership report%s received for groups to which we belong\n");
1276 p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n");
1277 p64(igps_snd_reports, "\t%ju membership report%s sent\n");
1278
1279 if (interval > 0)
1280 bcopy(&igmpstat, &pigmpstat, len);
1281
1282 #undef IGMPDIFF
1283 #undef p64
1284 #undef py64
1285 }
1286
1287 /*
1288 * Pretty print an Internet address (net address + port).
1289 */
1290 void
1291 inetprint(struct in_addr *in, int port, char *proto, int numeric_port)
1292 {
1293 struct servent *sp = 0;
1294 char line[80], *cp;
1295 int width;
1296
1297 if (Wflag)
1298 snprintf(line, sizeof(line), "%s.", inetname(in));
1299 else
1300 snprintf(line, sizeof(line), "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
1301 cp = index(line, '\0');
1302 if (!numeric_port && port)
1303 #ifdef _SERVICE_CACHE_
1304 sp = _serv_cache_getservbyport(port, proto);
1305 #else
1306 sp = getservbyport((int)port, proto);
1307 #endif
1308 if (sp || port == 0)
1309 snprintf(cp, sizeof(line) - (cp - line), "%.15s ", sp ? sp->s_name : "*");
1310 else
1311 snprintf(cp, sizeof(line) - (cp - line), "%d ", ntohs((u_short)port));
1312 width = (Aflag && !Wflag) ? 18 : 22;
1313 if (Wflag)
1314 printf("%-*s ", width, line);
1315 else
1316 printf("%-*.*s ", width, width, line);
1317 }
1318
1319 /*
1320 * Construct an Internet address representation.
1321 * If the nflag has been supplied, give
1322 * numeric value, otherwise try for symbolic name.
1323 */
1324 char *
1325 inetname(struct in_addr *inp)
1326 {
1327 register char *cp;
1328 static char line[MAXHOSTNAMELEN];
1329 struct hostent *hp;
1330 struct netent *np;
1331
1332 cp = 0;
1333 if (!nflag && inp->s_addr != INADDR_ANY) {
1334 int net = inet_netof(*inp);
1335 int lna = inet_lnaof(*inp);
1336
1337 if (lna == INADDR_ANY) {
1338 np = getnetbyaddr(net, AF_INET);
1339 if (np)
1340 cp = np->n_name;
1341 }
1342 if (cp == 0) {
1343 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
1344 if (hp) {
1345 cp = hp->h_name;
1346 //### trimdomain(cp, strlen(cp));
1347 }
1348 }
1349 }
1350 if (inp->s_addr == INADDR_ANY)
1351 strlcpy(line, "*", sizeof(line));
1352 else if (cp) {
1353 strlcpy(line, cp, sizeof(line));
1354 } else {
1355 inp->s_addr = ntohl(inp->s_addr);
1356 #define C(x) ((u_int)((x) & 0xff))
1357 snprintf(line, sizeof(line), "%u.%u.%u.%u", C(inp->s_addr >> 24),
1358 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
1359 }
1360 return (line);
1361 }