]> git.saurik.com Git - apple/network_cmds.git/blame - netstat.tproj/inet.c
network_cmds-606.40.2.tar.gz
[apple/network_cmds.git] / netstat.tproj / inet.c
CommitLineData
9c859447 1/*
a3cc5c72 2 * Copyright (c) 2008-2020 Apple Inc. All rights reserved.
9c859447
A
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.
fdfd5971 25 ** @APPLE_OSREFERENCE_LICENSE_HEADER_END@
9c859447 26 */
b7080c8e
A
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
b7080c8e
A
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>
b7080c8e
A
65
66#include <net/route.h>
9dc66a05 67#include <net/if_arp.h>
89c4ed63 68#include <net/net_perf.h>
b7080c8e
A
69#include <netinet/in.h>
70#include <netinet/in_systm.h>
71#include <netinet/ip.h>
7ba0088d
A
72#ifdef INET6
73#include <netinet/ip6.h>
74#endif /* INET6 */
b7080c8e
A
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>
b7080c8e 85#include <netinet/tcp_var.h>
b7080c8e
A
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>
ac2f15b3 95#include <stdint.h>
b7080c8e
A
96#include <string.h>
97#include <unistd.h>
98#include "netstat.h"
99
9dc66a05
A
100#ifdef __APPLE__
101#include <TargetConditionals.h>
102#endif
103
fdfd5971
A
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
7ba0088d
A
108char *inetname (struct in_addr *);
109void inetprint (struct in_addr *, int, char *, int);
110#ifdef INET6
111extern void inet6print (struct in6_addr *, int, char *, int);
112static int udp_done, tcp_done;
9dc66a05 113extern int mptcp_done;
7ba0088d 114#endif /* INET6 */
b7080c8e 115
ac2f15b3
A
116#ifdef SRVCACHE
117typedef struct __table_private table_t;
118
119extern table_t *_nc_table_new(uint32_t n);
120extern void _nc_table_free(table_t *tin);
121
122extern void _nc_table_insert(table_t *t, const char *key, void *datum);
123extern void *_nc_table_find(table_t *t, const char *key);
124extern void _nc_table_delete(table_t *t, const char *key);
125
126static table_t *_serv_cache = NULL;
127
128/*
129 * Read and cache all known services
130 */
131static void
132_serv_cache_open()
133{
134 struct servent *s;
b8dff150 135 char *key, *name, *test;
ac2f15b3
A
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);
b8dff150
A
148 test = _nc_table_find(_serv_cache, key);
149 if (test == NULL) _nc_table_insert(_serv_cache, key, name);
ac2f15b3
A
150 free(key);
151 }
152
153 endservent();
154}
155
156void
157_serv_cache_close()
158{
159 _nc_table_free(_serv_cache);
160 _serv_cache = NULL;
161}
162
163struct 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
7af5ce03 185#endif /* SRVCACHE */
ac2f15b3 186
b7080c8e
A
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 */
fdfd5971
A
193
194struct 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
b7080c8e 202void
9c859447 203protopr(uint32_t proto, /* for sysctl version we pass proto # */
fdfd5971 204 char *name, int af)
b7080c8e
A
205{
206 int istcp;
207 static int first = 1;
fdfd5971 208 char *buf, *next;
b7080c8e 209 const char *mibvar;
9c859447 210 struct xinpgen *xig, *oxig;
fdfd5971
A
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;
9dc66a05 220
fdfd5971
A
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 {
342c141e
A
307 if (vflag)
308 printf("got %d twice\n", xgn->xgn_kind);
fdfd5971
A
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');
7af5ce03 356 if (Aflag) {
fdfd5971 357 printf("%-16.16s ", "Socket");
7af5ce03
A
358 printf("%-9.9s", "Flowhash");
359 }
fdfd5971
A
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);
342c141e 374 if (vflag > 0)
213b8c4f
A
375 printf(" %6.6s %6.6s %6.6s %6.6s %6s %10s",
376 "rhiwat", "shiwat", "pid", "epid", "state", "options");
fdfd5971
A
377 printf("\n");
378 }
379 first = 0;
380 }
381 if (Aflag) {
382 if (istcp)
fdfd5971 383 printf("%16lx ", (u_long)inp->inp_ppcb);
fdfd5971 384 else
fdfd5971 385 printf("%16lx ", (u_long)so->so_pcb);
7af5ce03 386 printf("%8x ", inp->inp_flowhash);
fdfd5971
A
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]);
fdfd5971
A
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
9dc66a05 481 for (i = 0; i < SO_TC_STATS_MAX; i++) {
fdfd5971
A
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",
9dc66a05
A
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);
fdfd5971 492 }
342c141e 493 if (vflag > 0) {
213b8c4f 494 printf(" %6u %6u %6u %6u 0x%04x 0x%08x",
342c141e
A
495 so_rcv->sb_hiwat,
496 so_snd->sb_hiwat,
497 so->so_last_pid,
213b8c4f
A
498 so->so_e_pid,
499 so->so_state,
500 so->so_options);
342c141e 501 }
fdfd5971
A
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
b7080c8e
A
519/*
520 * Dump TCP statistics structure.
521 */
522void
9dc66a05 523tcp_stats(uint32_t off , char *name, int af)
b7080c8e 524{
b8dff150 525 static struct tcpstat ptcpstat;
b7080c8e
A
526 struct tcpstat tcpstat;
527 size_t len = sizeof tcpstat;
9dc66a05
A
528 static uint32_t r_swcsum, pr_swcsum;
529 static uint32_t t_swcsum, pt_swcsum;
b8dff150 530
b7080c8e
A
531 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
532 warn("sysctl: net.inet.tcp.stats");
533 return;
534 }
535
7ba0088d 536#ifdef INET6
b8dff150 537 if (tcp_done != 0 && interval == 0)
7ba0088d
A
538 return;
539 else
540 tcp_done = 1;
541#endif
542
342c141e
A
543 if (interval && vflag > 0)
544 print_time();
b7080c8e
A
545 printf ("%s:\n", name);
546
b8dff150
A
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");
b7080c8e 560 p2(tcps_sndpack,tcps_sndbyte,
b8dff150 561 "\t\t%u data packet%s (%u byte%s)\n");
b7080c8e 562 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
b8dff150
A
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");
b7080c8e 565 p2a(tcps_sndacks, tcps_delack,
b8dff150
A
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");
7af5ce03 571 p(tcps_fcholdpacket, "\t\t%u data packet%s sent after flow control\n");
213b8c4f
A
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");
9dc66a05
A
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 */
b8dff150
A
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");
b7080c8e 587 p2(tcps_rcvpack, tcps_rcvbyte,
b8dff150 588 "\t\t%u packet%s (%u byte%s) received in-sequence\n");
b7080c8e 589 p2(tcps_rcvduppack, tcps_rcvdupbyte,
b8dff150
A
590 "\t\t%u completely duplicate packet%s (%u byte%s)\n");
591 p(tcps_pawsdrop, "\t\t%u old duplicate packet%s\n");
342c141e 592 p(tcps_rcvmemdrop, "\t\t%u received packet%s dropped due to low memory\n");
b7080c8e 593 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
b8dff150 594 "\t\t%u packet%s with some dup. data (%u byte%s duped)\n");
b7080c8e 595 p2(tcps_rcvoopack, tcps_rcvoobyte,
b8dff150 596 "\t\t%u out-of-order packet%s (%u byte%s)\n");
b7080c8e 597 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
b8dff150
A
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");
213b8c4f 601 p(tcps_recovered_pkts, "\t\t%u packet%s recovered after loss\n");
b8dff150
A
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");
9dc66a05
A
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 */
b8dff150
A
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");
b7080c8e 622 p2(tcps_closed, tcps_drops,
b8dff150
A
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");
b7080c8e 625 p(tcps_cachedrttvar,
b8dff150 626 "\t\t%u connection%s updated cached RTT variance on close\n");
b7080c8e 627 p(tcps_cachedssthresh,
b8dff150 628 "\t\t%u connection%s updated cached ssthresh on close\n");
213b8c4f
A
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");
b8dff150 634 p(tcps_conndrops, "\t%u embryonic connection%s dropped\n");
b7080c8e 635 p2(tcps_rttupdated, tcps_segstimed,
b8dff150
A
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");
fdfd5971 639 p(tcps_rxtfindrop, "\t\t%u connection%s dropped after retransmitting FIN\n");
213b8c4f 640 p(tcps_sndrexmitbad, "\t\t%u unnecessary packet retransmissions%s\n");
b8dff150
A
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");
e0b07f2d 646 p(tcps_ka_offload_drops, "\t\t%u connection%s dropped by keepalive offload\n");
b8dff150
A
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");
f550d664 652 p(tcps_sack_rexmits,
b8dff150 653 "\t%u segment rexmit%s in SACK recovery episodes\n");
f550d664 654 p(tcps_sack_rexmit_bytes,
b8dff150 655 "\t%u byte rexmit%s in SACK recovery episodes\n");
f550d664 656 p(tcps_sack_rcv_blocks,
b8dff150
A
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 */
9dc66a05
A
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");
342c141e
A
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");
89c4ed63
A
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");
342c141e
A
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");
89c4ed63
A
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");
26c66ce9
A
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");
213b8c4f
A
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
342c141e
A
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");
213b8c4f 698 p(tcps_tailloss_rto, "\t%u retransmission%s due to tail loss\n");
89c4ed63
A
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");
213b8c4f 707 p(tcps_nostretchack, "\t%u connection%s had stretch ack algorithm disabled\n");
89c4ed63
A
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");
213b8c4f
A
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
26c66ce9
A
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");
9dc66a05 727
d9520f62
A
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
9dc66a05 738 if (interval > 0) {
b8dff150 739 bcopy(&tcpstat, &ptcpstat, len);
9dc66a05
A
740 pr_swcsum = r_swcsum;
741 pt_swcsum = t_swcsum;
742 }
f550d664 743
b8dff150 744#undef TCPDIFF
b7080c8e
A
745#undef p
746#undef p1a
747#undef p2
748#undef p2a
749#undef p3
750}
751
9dc66a05
A
752/*
753 * Dump MPTCP statistics
754 */
755void
756mptcp_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");
26c66ce9
A
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");
89c4ed63
A
811 p3(tcps_mp_num_probes, "\t%u number of subflow probe%s\n");
812
9dc66a05
A
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}
9dc66a05 824
b7080c8e
A
825/*
826 * Dump UDP statistics structure.
827 */
828void
9c859447 829udp_stats(uint32_t off , char *name, int af )
b7080c8e 830{
b8dff150 831 static struct udpstat pudpstat;
b7080c8e
A
832 struct udpstat udpstat;
833 size_t len = sizeof udpstat;
9c859447 834 uint32_t delivered;
9dc66a05
A
835 static uint32_t r_swcsum, pr_swcsum;
836 static uint32_t t_swcsum, pt_swcsum;
b7080c8e
A
837
838 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) {
839 warn("sysctl: net.inet.udp.stats");
840 return;
841 }
842
7ba0088d 843#ifdef INET6
b8dff150 844 if (udp_done != 0 && interval == 0)
7ba0088d
A
845 return;
846 else
847 udp_done = 1;
848#endif
849
342c141e
A
850 if (interval && vflag > 0)
851 print_time();
b7080c8e 852 printf("%s:\n", name);
b8dff150
A
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))
9dc66a05
A
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)))
b8dff150 861 p(udps_ipackets, "\t%u datagram%s received\n");
9dc66a05
A
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");
b7080c8e 876 p(udps_noportbcast,
9dc66a05
A
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");
b8dff150
A
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);
b7080c8e 890 if (delivered || sflag <= 1)
9dc66a05 891 printf("\t\t%u delivered\n", delivered);
b8dff150 892 p(udps_opackets, "\t%u datagram%s output\n");
9dc66a05
A
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 */
b8dff150 902
9dc66a05 903 if (interval > 0) {
b8dff150 904 bcopy(&udpstat, &pudpstat, len);
9dc66a05
A
905 pr_swcsum = r_swcsum;
906 pt_swcsum = t_swcsum;
907 }
b8dff150
A
908
909#undef UDPDIFF
b7080c8e
A
910#undef p
911#undef p1a
9dc66a05 912#undef p2
b7080c8e
A
913}
914
915/*
916 * Dump IP statistics structure.
917 */
918void
9c859447 919ip_stats(uint32_t off , char *name, int af )
b7080c8e 920{
b8dff150 921 static struct ipstat pipstat;
b7080c8e 922 struct ipstat ipstat;
89c4ed63
A
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);
b7080c8e 929
89c4ed63 930 if (sysctlbyname("net.inet.ip.stats", &ipstat, &ipstat_len, 0, 0) < 0) {
b7080c8e
A
931 warn("sysctl: net.inet.ip.stats");
932 return;
933 }
934
89c4ed63
A
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");
e0b07f2d 937 bzero(&out_net_perf, out_net_perf_len);
89c4ed63
A
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");
e0b07f2d 942 bzero(&in_net_perf, in_net_perf_len);
89c4ed63
A
943 }
944
342c141e
A
945 if (interval && vflag > 0)
946 print_time();
b7080c8e
A
947 printf("%s:\n", name);
948
b8dff150
A
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))
9dc66a05
A
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)))
b8dff150
A
956
957 p(ips_total, "\t%u total packet%s received\n");
9dc66a05
A
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");
b8dff150
A
978 p(ips_fastforward, " (%u packet%s fast forwarded)");
979 if (IPDIFF(ips_forward) || sflag <= 1)
b7080c8e 980 putchar('\n');
9dc66a05 981 p(ips_cantforward, "\t\t%u packet%s not forwardable\n");
b7080c8e 982 p(ips_notmember,
9dc66a05
A
983 "\t\t%u packet%s received for unknown multicast group\n");
984 p(ips_redirectsent, "\t\t%u redirect%s sent\n");
89c4ed63
A
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
a3cc5c72
A
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
89c4ed63
A
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
b8dff150 1024 p(ips_localout, "\t%u packet%s sent from this host\n");
9dc66a05 1025 p(ips_rawout, "\t\t%u packet%s sent with fabricated ip header\n");
b7080c8e 1026 p(ips_odropped,
9dc66a05
A
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");
d9520f62 1036 p(ips_necp_policy_drop, "\t\t%u packet%s dropped due to NECP policy\n");
9dc66a05
A
1037 p2(ips_snd_swcsum, ips_snd_swcsum_bytes,
1038 "\t\t%u header%s (%u byte%s) checksummed in software\n");
b8dff150 1039
89c4ed63
A
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 }
b8dff150
A
1069
1070#undef IPDIFF
b7080c8e
A
1071#undef p
1072#undef p1a
9dc66a05
A
1073#undef p2
1074}
1075
1076/*
1077 * Dump ARP statistics structure.
1078 */
1079void
1080arp_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
342c141e
A
1092 if (interval && vflag > 0)
1093 print_time();
9dc66a05
A
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)))
26c66ce9
A
1101#define p3(f, m) if (ARPDIFF(f) || sflag <= 1) \
1102 printf(m, ARPDIFF(f), plural(ARPDIFF(f)), pluralies(ARPDIFF(f)))
9dc66a05 1103
26c66ce9
A
1104 p(txrequests, "\t%u broadast ARP request%s sent\n");
1105 p(txurequests, "\t%u unicast ARP request%s sent\n");
9dc66a05
A
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");
26c66ce9 1114 p3(held, "\t%u total packet%s held awaiting ARP repl%s\n");
9dc66a05
A
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
b7080c8e
A
1126}
1127
1128static 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 */
1153void
9c859447 1154icmp_stats(uint32_t off , char *name, int af )
b7080c8e 1155{
b8dff150 1156 static struct icmpstat picmpstat;
b7080c8e
A
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
342c141e
A
1172 if (interval && vflag > 0)
1173 print_time();
b7080c8e
A
1174 printf("%s:\n", name);
1175
b8dff150
A
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))
b7080c8e 1181
b8dff150 1182 p(icps_error, "\t%u call%s to icmp_error\n");
b7080c8e 1183 p(icps_oldicmp,
b8dff150 1184 "\t%u error%s not generated 'cuz old message was icmp\n");
b7080c8e 1185 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
b8dff150 1186 if (ICMPDIFF(icps_outhist[i]) != 0) {
b7080c8e
A
1187 if (first) {
1188 printf("\tOutput histogram:\n");
1189 first = 0;
1190 }
b8dff150
A
1191 printf("\t\t%s: %u\n", icmpnames[i],
1192 ICMPDIFF(icps_outhist[i]));
b7080c8e 1193 }
b8dff150
A
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");
b7080c8e 1200 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
b8dff150 1201 if (ICMPDIFF(icps_inhist[i]) != 0) {
b7080c8e
A
1202 if (first) {
1203 printf("\tInput histogram:\n");
1204 first = 0;
1205 }
b8dff150
A
1206 printf("\t\t%s: %u\n", icmpnames[i],
1207 ICMPDIFF(icps_inhist[i]));
b7080c8e 1208 }
b8dff150
A
1209 p(icps_reflect, "\t%u message response%s generated\n");
1210
1211#undef ICMPDIFF
b7080c8e
A
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");
b8dff150
A
1220
1221 if (interval > 0)
1222 bcopy(&icmpstat, &picmpstat, sizeof (icmpstat));
b7080c8e
A
1223}
1224
1225/*
1226 * Dump IGMP statistics structure.
1227 */
1228void
9c859447 1229igmp_stats(uint32_t off , char *name, int af )
b7080c8e 1230{
fdfd5971
A
1231 static struct igmpstat_v3 pigmpstat;
1232 struct igmpstat_v3 igmpstat;
b7080c8e
A
1233 size_t len = sizeof igmpstat;
1234
fdfd5971
A
1235 if (sysctlbyname("net.inet.igmp.v3stats", &igmpstat, &len, 0, 0) < 0) {
1236 warn("sysctl: net.inet.igmp.v3stats");
b7080c8e
A
1237 return;
1238 }
1239
fdfd5971
A
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
342c141e
A
1249 if (interval && vflag > 0)
1250 print_time();
b7080c8e
A
1251 printf("%s:\n", name);
1252
fdfd5971
A
1253#define IGMPDIFF(f) ((uintmax_t)(igmpstat.f - pigmpstat.f))
1254#define p64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
b8dff150 1255 printf(m, IGMPDIFF(f), plural(IGMPDIFF(f)))
fdfd5971 1256#define py64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
b8dff150 1257 printf(m, IGMPDIFF(f), IGMPDIFF(f) != 1 ? "ies" : "y")
fdfd5971
A
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");
b8dff150
A
1278
1279 if (interval > 0)
1280 bcopy(&igmpstat, &pigmpstat, len);
1281
1282#undef IGMPDIFF
fdfd5971
A
1283#undef p64
1284#undef py64
b7080c8e
A
1285}
1286
1287/*
1288 * Pretty print an Internet address (net address + port).
1289 */
1290void
7ba0088d 1291inetprint(struct in_addr *in, int port, char *proto, int numeric_port)
b7080c8e
A
1292{
1293 struct servent *sp = 0;
1294 char line[80], *cp;
1295 int width;
1296
7ba0088d 1297 if (Wflag)
fdfd5971 1298 snprintf(line, sizeof(line), "%s.", inetname(in));
7ba0088d 1299 else
fdfd5971 1300 snprintf(line, sizeof(line), "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
b7080c8e 1301 cp = index(line, '\0');
7ba0088d 1302 if (!numeric_port && port)
ac2f15b3
A
1303#ifdef _SERVICE_CACHE_
1304 sp = _serv_cache_getservbyport(port, proto);
1305#else
b7080c8e 1306 sp = getservbyport((int)port, proto);
ac2f15b3 1307#endif
b7080c8e 1308 if (sp || port == 0)
fdfd5971 1309 snprintf(cp, sizeof(line) - (cp - line), "%.15s ", sp ? sp->s_name : "*");
7ba0088d 1310 else
fdfd5971 1311 snprintf(cp, sizeof(line) - (cp - line), "%d ", ntohs((u_short)port));
7ba0088d
A
1312 width = (Aflag && !Wflag) ? 18 : 22;
1313 if (Wflag)
1314 printf("%-*s ", width, line);
b7080c8e 1315 else
7ba0088d 1316 printf("%-*.*s ", width, width, line);
b7080c8e
A
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 */
1324char *
7ba0088d 1325inetname(struct in_addr *inp)
b7080c8e
A
1326{
1327 register char *cp;
7ba0088d 1328 static char line[MAXHOSTNAMELEN];
b7080c8e
A
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;
7ba0088d 1346 //### trimdomain(cp, strlen(cp));
b7080c8e
A
1347 }
1348 }
1349 }
1350 if (inp->s_addr == INADDR_ANY)
fdfd5971 1351 strlcpy(line, "*", sizeof(line));
b7080c8e 1352 else if (cp) {
e0b07f2d 1353 strlcpy(line, cp, sizeof(line));
b7080c8e
A
1354 } else {
1355 inp->s_addr = ntohl(inp->s_addr);
1356#define C(x) ((u_int)((x) & 0xff))
fdfd5971 1357 snprintf(line, sizeof(line), "%u.%u.%u.%u", C(inp->s_addr >> 24),
b7080c8e
A
1358 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
1359 }
1360 return (line);
1361}