]> git.saurik.com Git - apple/network_cmds.git/blame - netstat.tproj/inet.c
network_cmds-596.100.2.tar.gz
[apple/network_cmds.git] / netstat.tproj / inet.c
CommitLineData
9c859447 1/*
26c66ce9 2 * Copyright (c) 2008-2016 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 */
661
9dc66a05
A
662 p(tcps_coalesced_pack, "\t%u LRO coalesced packet%s\n");
663 p(tcps_flowtbl_full, "\t\t%u time%s LRO flow table was full\n");
664 p(tcps_flowtbl_collision, "\t\t%u collision%s in LRO flow table\n");
665 p(tcps_lro_twopack, "\t\t%u time%s LRO coalesced 2 packets\n");
666 p(tcps_lro_multpack, "\t\t%u time%s LRO coalesced 3 or 4 packets\n");
667 p(tcps_lro_largepack, "\t\t%u time%s LRO coalesced 5 or more packets\n");
668
669 p(tcps_limited_txt, "\t%u limited transmit%s done\n");
670 p(tcps_early_rexmt, "\t%u early retransmit%s done\n");
671 p(tcps_sack_ackadv, "\t%u time%s cumulative ack advanced along with SACK\n");
342c141e
A
672 p(tcps_pto, "\t%u probe timeout%s\n");
673 p(tcps_rto_after_pto, "\t\t%u time%s retransmit timeout triggered after probe\n");
89c4ed63
A
674 p(tcps_probe_if, "\t\t%u time%s probe packets were sent for an interface\n");
675 p(tcps_probe_if_conflict, "\t\t%u time%s couldn't send probe packets for an interface\n");
342c141e
A
676 p(tcps_tlp_recovery, "\t\t%u time%s fast recovery after tail loss\n");
677 p(tcps_tlp_recoverlastpkt, "\t\t%u time%s recovered last packet \n");
89c4ed63
A
678 p(tcps_pto_in_recovery, "\t\t%u SACK based rescue retransmit%s\n");
679 p(tcps_ecn_client_setup, "\t%u client connection%s attempted to negotiate ECN\n");
680 p(tcps_ecn_client_success, "\t\t%u client connection%s successfully negotiated ECN\n");
681 p(tcps_ecn_not_supported, "\t\t%u time%s graceful fallback to Non-ECN connection\n");
682 p(tcps_ecn_lost_syn, "\t\t%u time%s lost ECN negotiating SYN, followed by retransmission\n");
683 p(tcps_ecn_server_setup, "\t\t%u server connection%s attempted to negotiate ECN\n");
684 p(tcps_ecn_server_success, "\t\t%u server connection%s successfully negotiated ECN\n");
685 p(tcps_ecn_lost_synack, "\t\t%u time%s lost ECN negotiating SYN-ACK, followed by retransmission\n");
686 p(tcps_ecn_recv_ce, "\t\t%u time%s received congestion experienced (CE) notification\n");
687 p(tcps_ecn_recv_ece, "\t\t%u time%s CWR was sent in response to ECE\n");
688 p(tcps_ecn_sent_ece, "\t\t%u time%s sent ECE notification\n");
689 p(tcps_ecn_conn_recv_ce, "\t\t%u connection%s received CE atleast once\n");
690 p(tcps_ecn_conn_recv_ece, "\t\t%u connection%s received ECE atleast once\n");
691 p(tcps_ecn_conn_plnoce, "\t\t%u connection%s using ECN have seen packet loss but no CE\n");
692 p(tcps_ecn_conn_pl_ce, "\t\t%u connection%s using ECN have seen packet loss and CE\n");
693 p(tcps_ecn_conn_nopl_ce, "\t\t%u connection%s using ECN received CE but no packet loss\n");
26c66ce9
A
694 p(tcps_ecn_fallback_synloss, "\t\t%u connection%s fell back to non-ECN due to SYN-loss\n");
695 p(tcps_ecn_fallback_reorder, "\t\t%u connection%s fell back to non-ECN due to reordering\n");
696 p(tcps_ecn_fallback_ce, "\t\t%u connection%s fell back to non-ECN due to excessive CE-markings\n");
213b8c4f
A
697 p(tcps_ecn_fallback_droprst, "\t\t%u connection%s fell back caused by connection drop due to RST\n");
698 p(tcps_ecn_fallback_droprxmt, "\t\t%u connection%s fell back due to drop after multiple retransmits \n");
699 p(tcps_ecn_fallback_synrst, "\t\t%u connection%s fell back due to RST after SYN\n");
700
342c141e
A
701 p(tcps_detect_reordering, "\t%u time%s packet reordering was detected on a connection\n");
702 p(tcps_reordered_pkts, "\t\t%u time%s transmitted packets were reordered\n");
703 p(tcps_delay_recovery, "\t\t%u time%s fast recovery was delayed to handle reordering\n");
704 p(tcps_avoid_rxmt, "\t\t%u time%s retransmission was avoided by delaying recovery\n");
705 p(tcps_unnecessary_rxmt, "\t\t%u retransmission%s not needed \n");
213b8c4f 706 p(tcps_tailloss_rto, "\t%u retransmission%s due to tail loss\n");
89c4ed63
A
707 p(tcps_dsack_sent, "\t%u time%s DSACK option was sent\n");
708 p(tcps_dsack_recvd, "\t\t%u time%s DSACK option was received\n");
709 p(tcps_dsack_disable, "\t\t%u time%s DSACK was disabled on a connection\n");
710 p(tcps_dsack_badrexmt, "\t\t%u time%s recovered from bad retransmission using DSACK\n");
711 p(tcps_dsack_ackloss,"\t\t%u time%s ignored DSACK due to ack loss\n");
712 p(tcps_dsack_recvd_old,"\t\t%u time%s ignored old DSACK options\n");
713 p(tcps_pmtudbh_reverted, "\t%u time%s PMTU Blackhole detection, size reverted\n");
714 p(tcps_drop_after_sleep, "\t%u connection%s were dropped after long sleep\n");
213b8c4f 715 p(tcps_nostretchack, "\t%u connection%s had stretch ack algorithm disabled\n");
89c4ed63
A
716
717 p(tcps_tfo_cookie_sent,"\t%u time%s a TFO-cookie has been announced\n");
718 p(tcps_tfo_syn_data_rcv,"\t%u SYN%s with data and a valid TFO-cookie have been received\n");
719 p(tcps_tfo_cookie_req_rcv,"\t%u SYN%s with TFO-cookie-request received\n");
720 p(tcps_tfo_cookie_invalid,"\t%u time%s an invalid TFO-cookie has been received\n");
721 p(tcps_tfo_cookie_req,"\t%u time%s we requested a TFO-cookie\n");
722 p(tcps_tfo_cookie_rcv,"\t\t%u time%s the peer announced a TFO-cookie\n");
723 p(tcps_tfo_syn_data_sent,"\t%u time%s we combined SYN with data and a TFO-cookie\n");
724 p(tcps_tfo_syn_data_acked,"\t\t%u time%s our SYN with data has been acknowledged\n");
725 p(tcps_tfo_syn_loss,"\t%u time%s a connection-attempt with TFO fell back to regular TCP\n");
726 p(tcps_tfo_blackhole,"\t%u time%s a TFO-connection blackhole'd\n");
213b8c4f
A
727 p(tcps_tfo_cookie_wrong,"\t%u time%s a TFO-cookie we sent was wrong\n");
728 p(tcps_tfo_no_cookie_rcv,"\t%u time%s did not received a TFO-cookie we asked for\n");
729 p(tcps_tfo_heuristics_disable,"\t%u time%s TFO got disabled due to heuristicsn\n");
730 p(tcps_tfo_sndblackhole,"\t%u time%s TFO got blackholed in the sending direction\n");
731
26c66ce9
A
732 p(tcps_mss_to_default,"\t%u time%s maximum segment size was changed to default\n");
733 p(tcps_mss_to_medium,"\t%u time%s maximum segment size was changed to medium\n");
734 p(tcps_mss_to_low,"\t%u time%s maximum segment size was changed to low\n");
9dc66a05 735
d9520f62
A
736 p(tcps_timer_drift_le_1_ms,"\t%u timer drift%s less or equal to 1 ms\n");
737 p(tcps_timer_drift_le_10_ms,"\t%u timer drift%s less or equal to 10 ms\n");
738 p(tcps_timer_drift_le_20_ms,"\t%u timer drift%s less or equal to 20 ms\n");
739 p(tcps_timer_drift_le_50_ms,"\t%u timer drift%s less or equal to 50 ms\n");
740 p(tcps_timer_drift_le_100_ms,"\t%u timer drift%s less or equal to 100 ms\n");
741 p(tcps_timer_drift_le_200_ms,"\t%u timer drift%s less or equal to 200 ms\n");
742 p(tcps_timer_drift_le_500_ms,"\t%u timer drift%s less or equal to 500 ms\n");
743 p(tcps_timer_drift_le_1000_ms,"\t%u timer drift%s less or equal to 1000 ms\n");
744 p(tcps_timer_drift_gt_1000_ms,"\t%u timer drift%s greater than to 1000 ms\n");
745
9dc66a05 746 if (interval > 0) {
b8dff150 747 bcopy(&tcpstat, &ptcpstat, len);
9dc66a05
A
748 pr_swcsum = r_swcsum;
749 pt_swcsum = t_swcsum;
750 }
f550d664 751
b8dff150 752#undef TCPDIFF
b7080c8e
A
753#undef p
754#undef p1a
755#undef p2
756#undef p2a
757#undef p3
758}
759
9dc66a05
A
760/*
761 * Dump MPTCP statistics
762 */
763void
764mptcp_stats(uint32_t off , char *name, int af)
765{
766 static struct tcpstat ptcpstat;
767 struct tcpstat tcpstat;
768 size_t len = sizeof tcpstat;
769
770 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
771 warn("sysctl: net.inet.tcp.stats");
772 return;
773 }
774
775#ifdef INET6
776 if (mptcp_done != 0 && interval == 0)
777 return;
778 else
779 mptcp_done = 1;
780#endif
781
782 if (interval && vflag > 0)
783 print_time();
784 printf ("%s:\n", name);
785
786#define MPTCPDIFF(f) (tcpstat.f - ptcpstat.f)
787#define p(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
788 printf(m, MPTCPDIFF(f), plural(MPTCPDIFF(f)))
789#define p1a(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
790 printf(m, MPTCPDIFF(f))
791#define p2(f1, f2, m) if (MPTCPDIFF(f1) || MPTCPDIFF(f2) || sflag <= 1) \
792 printf(m, MPTCPDIFF(f1), plural(MPTCPDIFF(f1)), \
793 MPTCPDIFF(f2), plural(MPTCPDIFF(f2)))
794#define p2a(f1, f2, m) if (MPTCPDIFF(f1) || MPTCPDIFF(f2) || sflag <= 1) \
795 printf(m, MPTCPDIFF(f1), plural(MPTCPDIFF(f1)), MPTCPDIFF(f2))
796#define p3(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
797 printf(m, MPTCPDIFF(f), plurales(MPTCPDIFF(f)))
798
799 p(tcps_mp_sndpacks, "\t%u data packet%s sent\n");
800 p(tcps_mp_sndbytes, "\t%u data byte%s sent\n");
801 p(tcps_mp_rcvtotal, "\t%u data packet%s received\n");
802 p(tcps_mp_rcvbytes, "\t%u data byte%s received\n");
803 p(tcps_invalid_mpcap, "\t%u packet%s with an invalid MPCAP option\n");
804 p(tcps_invalid_joins, "\t%u packet%s with an invalid MPJOIN option\n");
805 p(tcps_mpcap_fallback, "\t%u time%s primary subflow fell back to "
806 "TCP\n");
807 p(tcps_join_fallback, "\t%u time%s secondary subflow fell back to "
808 "TCP\n");
809 p(tcps_estab_fallback, "\t%u DSS option drop%s\n");
810 p(tcps_invalid_opt, "\t%u other invalid MPTCP option%s\n");
811 p(tcps_mp_reducedwin, "\t%u time%s the MPTCP subflow window was reduced\n");
812 p(tcps_mp_badcsum, "\t%u bad DSS checksum%s\n");
813 p(tcps_mp_oodata, "\t%u time%s received out of order data \n");
814 p3(tcps_mp_switches, "\t%u subflow switch%s\n");
26c66ce9
A
815 p3(tcps_mp_sel_symtomsd, "\t%u subflow switch%s due to advisory\n");
816 p3(tcps_mp_sel_rtt, "\t%u subflow switch%s due to rtt\n");
817 p3(tcps_mp_sel_rto, "\t%u subflow switch%s due to rto\n");
818 p3(tcps_mp_sel_peer, "\t%u subflow switch%s due to peer\n");
89c4ed63
A
819 p3(tcps_mp_num_probes, "\t%u number of subflow probe%s\n");
820
9dc66a05
A
821 if (interval > 0) {
822 bcopy(&tcpstat, &ptcpstat, len);
823 }
824
825#undef MPTCPDIFF
826#undef p
827#undef p1a
828#undef p2
829#undef p2a
830#undef p3
831}
9dc66a05 832
b7080c8e
A
833/*
834 * Dump UDP statistics structure.
835 */
836void
9c859447 837udp_stats(uint32_t off , char *name, int af )
b7080c8e 838{
b8dff150 839 static struct udpstat pudpstat;
b7080c8e
A
840 struct udpstat udpstat;
841 size_t len = sizeof udpstat;
9c859447 842 uint32_t delivered;
9dc66a05
A
843 static uint32_t r_swcsum, pr_swcsum;
844 static uint32_t t_swcsum, pt_swcsum;
b7080c8e
A
845
846 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) {
847 warn("sysctl: net.inet.udp.stats");
848 return;
849 }
850
7ba0088d 851#ifdef INET6
b8dff150 852 if (udp_done != 0 && interval == 0)
7ba0088d
A
853 return;
854 else
855 udp_done = 1;
856#endif
857
342c141e
A
858 if (interval && vflag > 0)
859 print_time();
b7080c8e 860 printf("%s:\n", name);
b8dff150
A
861
862#define UDPDIFF(f) (udpstat.f - pudpstat.f)
863#define p(f, m) if (UDPDIFF(f) || sflag <= 1) \
864 printf(m, UDPDIFF(f), plural(UDPDIFF(f)))
865#define p1a(f, m) if (UDPDIFF(f) || sflag <= 1) \
866 printf(m, UDPDIFF(f))
9dc66a05
A
867#define p2(f1, f2, m) if (UDPDIFF(f1) || UDPDIFF(f2) || sflag <= 1) \
868 printf(m, UDPDIFF(f1), plural(UDPDIFF(f1)), UDPDIFF(f2), plural(UDPDIFF(f2)))
b8dff150 869 p(udps_ipackets, "\t%u datagram%s received\n");
9dc66a05
A
870 p1a(udps_hdrops, "\t\t%u with incomplete header\n");
871 p1a(udps_badlen, "\t\t%u with bad data length field\n");
872 p1a(udps_badsum, "\t\t%u with bad checksum\n");
873 p1a(udps_nosum, "\t\t%u with no checksum\n");
874 r_swcsum = udpstat.udps_rcv_swcsum + udpstat.udps_rcv6_swcsum;
875 if ((r_swcsum - pr_swcsum) || sflag <= 1)
876 printf("\t\t%u checksummed in software\n", (r_swcsum - pr_swcsum));
877 p2(udps_rcv_swcsum, udps_rcv_swcsum_bytes,
878 "\t\t\t%u datagram%s (%u byte%s) over IPv4\n");
879#if INET6
880 p2(udps_rcv6_swcsum, udps_rcv6_swcsum_bytes,
881 "\t\t\t%u datagram%s (%u byte%s) over IPv6\n");
882#endif /* INET6 */
883 p1a(udps_noport, "\t\t%u dropped due to no socket\n");
b7080c8e 884 p(udps_noportbcast,
9dc66a05
A
885 "\t\t%u broadcast/multicast datagram%s undelivered\n");
886 /* the next statistic is cumulative in udps_noportbcast */
887 p(udps_filtermcast,
888 "\t\t%u time%s multicast source filter matched\n");
889 p1a(udps_fullsock, "\t\t%u dropped due to full socket buffers\n");
890 p1a(udpps_pcbhashmiss, "\t\t%u not for hashed pcb\n");
b8dff150
A
891 delivered = UDPDIFF(udps_ipackets) -
892 UDPDIFF(udps_hdrops) -
893 UDPDIFF(udps_badlen) -
894 UDPDIFF(udps_badsum) -
895 UDPDIFF(udps_noport) -
896 UDPDIFF(udps_noportbcast) -
897 UDPDIFF(udps_fullsock);
b7080c8e 898 if (delivered || sflag <= 1)
9dc66a05 899 printf("\t\t%u delivered\n", delivered);
b8dff150 900 p(udps_opackets, "\t%u datagram%s output\n");
9dc66a05
A
901 t_swcsum = udpstat.udps_snd_swcsum + udpstat.udps_snd6_swcsum;
902 if ((t_swcsum - pt_swcsum) || sflag <= 1)
903 printf("\t\t%u checksummed in software\n", (t_swcsum - pt_swcsum));
904 p2(udps_snd_swcsum, udps_snd_swcsum_bytes,
905 "\t\t\t%u datagram%s (%u byte%s) over IPv4\n");
906#if INET6
907 p2(udps_snd6_swcsum, udps_snd6_swcsum_bytes,
908 "\t\t\t%u datagram%s (%u byte%s) over IPv6\n");
909#endif /* INET6 */
b8dff150 910
9dc66a05 911 if (interval > 0) {
b8dff150 912 bcopy(&udpstat, &pudpstat, len);
9dc66a05
A
913 pr_swcsum = r_swcsum;
914 pt_swcsum = t_swcsum;
915 }
b8dff150
A
916
917#undef UDPDIFF
b7080c8e
A
918#undef p
919#undef p1a
9dc66a05 920#undef p2
b7080c8e
A
921}
922
923/*
924 * Dump IP statistics structure.
925 */
926void
9c859447 927ip_stats(uint32_t off , char *name, int af )
b7080c8e 928{
b8dff150 929 static struct ipstat pipstat;
b7080c8e 930 struct ipstat ipstat;
89c4ed63
A
931 size_t ipstat_len = sizeof ipstat;
932
933 static net_perf_t pout_net_perf, pin_net_perf;
934 net_perf_t out_net_perf, in_net_perf;
935 size_t out_net_perf_len = sizeof (out_net_perf);
936 size_t in_net_perf_len = sizeof (in_net_perf);
b7080c8e 937
89c4ed63 938 if (sysctlbyname("net.inet.ip.stats", &ipstat, &ipstat_len, 0, 0) < 0) {
b7080c8e
A
939 warn("sysctl: net.inet.ip.stats");
940 return;
941 }
942
89c4ed63
A
943 if (sysctlbyname("net.inet.ip.output_perf_data", &out_net_perf, &out_net_perf_len, 0, 0) < 0) {
944 warn("sysctl: net.inet.ip.output_perf_data");
e0b07f2d 945 bzero(&out_net_perf, out_net_perf_len);
89c4ed63
A
946 }
947
948 if (sysctlbyname("net.inet.ip.input_perf_data", &in_net_perf, &in_net_perf_len, 0, 0) < 0) {
949 warn("sysctl: net.inet.ip.input_perf_data");
e0b07f2d 950 bzero(&in_net_perf, in_net_perf_len);
89c4ed63
A
951 }
952
342c141e
A
953 if (interval && vflag > 0)
954 print_time();
b7080c8e
A
955 printf("%s:\n", name);
956
b8dff150
A
957#define IPDIFF(f) (ipstat.f - pipstat.f)
958#define p(f, m) if (IPDIFF(f) || sflag <= 1) \
959 printf(m, IPDIFF(f), plural(IPDIFF(f)))
960#define p1a(f, m) if (IPDIFF(f) || sflag <= 1) \
961 printf(m, IPDIFF(f))
9dc66a05
A
962#define p2(f1, f2, m) if (IPDIFF(f1) || IPDIFF(f2) || sflag <= 1) \
963 printf(m, IPDIFF(f1), plural(IPDIFF(f1)), IPDIFF(f2), plural(IPDIFF(f2)))
b8dff150
A
964
965 p(ips_total, "\t%u total packet%s received\n");
9dc66a05
A
966 p(ips_badsum, "\t\t%u bad header checksum%s\n");
967 p2(ips_rcv_swcsum, ips_rcv_swcsum_bytes,
968 "\t\t%u header%s (%u byte%s) checksummed in software\n");
969 p1a(ips_toosmall, "\t\t%u with size smaller than minimum\n");
970 p1a(ips_tooshort, "\t\t%u with data size < data length\n");
971 p1a(ips_adj, "\t\t%u with data size > data length\n");
972 p(ips_adj_hwcsum_clr,
973 "\t\t\t%u packet%s forced to software checksum\n");
974 p1a(ips_toolong, "\t\t%u with ip length > max ip packet size\n");
975 p1a(ips_badhlen, "\t\t%u with header length < data size\n");
976 p1a(ips_badlen, "\t\t%u with data length < header length\n");
977 p1a(ips_badoptions, "\t\t%u with bad options\n");
978 p1a(ips_badvers, "\t\t%u with incorrect version number\n");
979 p(ips_fragments, "\t\t%u fragment%s received\n");
980 p1a(ips_fragdropped, "\t\t\t%u dropped (dup or out of space)\n");
981 p1a(ips_fragtimeout, "\t\t\t%u dropped after timeout\n");
982 p1a(ips_reassembled, "\t\t\t%u reassembled ok\n");
983 p(ips_delivered, "\t\t%u packet%s for this host\n");
984 p(ips_noproto, "\t\t%u packet%s for unknown/unsupported protocol\n");
985 p(ips_forward, "\t\t%u packet%s forwarded");
b8dff150
A
986 p(ips_fastforward, " (%u packet%s fast forwarded)");
987 if (IPDIFF(ips_forward) || sflag <= 1)
b7080c8e 988 putchar('\n');
9dc66a05 989 p(ips_cantforward, "\t\t%u packet%s not forwardable\n");
b7080c8e 990 p(ips_notmember,
9dc66a05
A
991 "\t\t%u packet%s received for unknown multicast group\n");
992 p(ips_redirectsent, "\t\t%u redirect%s sent\n");
89c4ed63
A
993 p(ips_rxc_collisions, "\t\t%u input packet%s not chained due to collision\n");
994 p(ips_rxc_chained, "\t\t%u input packet%s processed in a chain\n");
995 p(ips_rxc_notchain, "\t\t%u input packet%s unable to chain\n");
996 p(ips_rxc_chainsz_gt2,
997 "\t\t%u input packet chain%s processed with length greater than 2\n");
998 p(ips_rxc_chainsz_gt4,
999 "\t\t%u input packet chain%s processed with length greater than 4\n");
1000 p(ips_rxc_notlist,
1001 "\t\t%u input packet%s did not go through list processing path\n");
1002
1003#define INPERFDIFF(f) (in_net_perf.f - pin_net_perf.f)
1004 if (INPERFDIFF(np_total_pkts) > 0 && in_net_perf.np_total_usecs > 0) {
1005 printf("\tInput Performance Stats:\n");
1006 printf("\t\t%llu total packets measured\n", INPERFDIFF(np_total_pkts));
1007 printf("\t\t%llu total usec elapsed\n", INPERFDIFF(np_total_usecs));
1008 printf("\t\t%f usec per packet\n",
1009 (double)in_net_perf.np_total_usecs/(double)in_net_perf.np_total_pkts);
1010 printf("\t\tHistogram:\n");
1011 printf("\t\t\t x <= %u: %llu\n", in_net_perf.np_hist_bars[0],
1012 INPERFDIFF(np_hist1));
1013 printf("\t\t\t %u < x <= %u: %llu\n",
1014 in_net_perf.np_hist_bars[0], in_net_perf.np_hist_bars[1],
1015 INPERFDIFF(np_hist2));
1016 printf("\t\t\t %u < x <= %u: %llu\n",
1017 in_net_perf.np_hist_bars[1], in_net_perf.np_hist_bars[2],
1018 INPERFDIFF(np_hist3));
1019 printf("\t\t\t %u < x <= %u: %llu\n",
1020 in_net_perf.np_hist_bars[2], in_net_perf.np_hist_bars[3],
1021 INPERFDIFF(np_hist4));
1022 printf("\t\t\t %u < x: %llu\n",
1023 in_net_perf.np_hist_bars[3], INPERFDIFF(np_hist5));
1024 }
1025#undef INPERFDIFF
1026
b8dff150 1027 p(ips_localout, "\t%u packet%s sent from this host\n");
9dc66a05 1028 p(ips_rawout, "\t\t%u packet%s sent with fabricated ip header\n");
b7080c8e 1029 p(ips_odropped,
9dc66a05
A
1030 "\t\t%u output packet%s dropped due to no bufs, etc.\n");
1031 p(ips_noroute, "\t\t%u output packet%s discarded due to no route\n");
1032 p(ips_fragmented, "\t\t%u output datagram%s fragmented\n");
1033 p(ips_ofragments, "\t\t%u fragment%s created\n");
1034 p(ips_cantfrag, "\t\t%u datagram%s that can't be fragmented\n");
1035 p(ips_nogif, "\t\t%u tunneling packet%s that can't find gif\n");
1036 p(ips_badaddr, "\t\t%u datagram%s with bad address in header\n");
1037 p(ips_pktdropcntrl,
1038 "\t\t%u packet%s dropped due to no bufs for control data\n");
d9520f62 1039 p(ips_necp_policy_drop, "\t\t%u packet%s dropped due to NECP policy\n");
9dc66a05
A
1040 p2(ips_snd_swcsum, ips_snd_swcsum_bytes,
1041 "\t\t%u header%s (%u byte%s) checksummed in software\n");
b8dff150 1042
89c4ed63
A
1043#define OUTPERFDIFF(f) (out_net_perf.f - pout_net_perf.f)
1044 if (OUTPERFDIFF(np_total_pkts) > 0 && out_net_perf.np_total_usecs > 0) {
1045 printf("\tOutput Performance Stats:\n");
1046 printf("\t\t%llu total packets measured\n", OUTPERFDIFF(np_total_pkts));
1047 printf("\t\t%llu total usec elapsed\n", OUTPERFDIFF(np_total_usecs));
1048 printf("\t\t%f usec per packet\n",
1049 (double)out_net_perf.np_total_usecs/(double)out_net_perf.np_total_pkts);
1050 printf("\t\tHistogram:\n");
1051 printf("\t\t\t x <= %u: %llu\n", out_net_perf.np_hist_bars[0],
1052 OUTPERFDIFF(np_hist1));
1053 printf("\t\t\t %u < x <= %u: %llu\n",
1054 out_net_perf.np_hist_bars[0], out_net_perf.np_hist_bars[1],
1055 OUTPERFDIFF(np_hist2));
1056 printf("\t\t\t %u < x <= %u: %llu\n",
1057 out_net_perf.np_hist_bars[1], out_net_perf.np_hist_bars[2],
1058 OUTPERFDIFF(np_hist3));
1059 printf("\t\t\t %u < x <= %u: %llu\n",
1060 out_net_perf.np_hist_bars[2], out_net_perf.np_hist_bars[3],
1061 OUTPERFDIFF(np_hist4));
1062 printf("\t\t\t %u < x: %llu\n",
1063 out_net_perf.np_hist_bars[3], OUTPERFDIFF(np_hist5));
1064 }
1065#undef OUTPERFDIFF
1066
1067 if (interval > 0) {
1068 bcopy(&ipstat, &pipstat, ipstat_len);
1069 bcopy(&in_net_perf, &pin_net_perf, in_net_perf_len);
1070 bcopy(&out_net_perf, &pout_net_perf, out_net_perf_len);
1071 }
b8dff150
A
1072
1073#undef IPDIFF
b7080c8e
A
1074#undef p
1075#undef p1a
9dc66a05
A
1076#undef p2
1077}
1078
1079/*
1080 * Dump ARP statistics structure.
1081 */
1082void
1083arp_stats(uint32_t off, char *name, int af)
1084{
1085 static struct arpstat parpstat;
1086 struct arpstat arpstat;
1087 size_t len = sizeof (arpstat);
1088
1089 if (sysctlbyname("net.link.ether.inet.stats", &arpstat,
1090 &len, 0, 0) < 0) {
1091 warn("sysctl: net.link.ether.inet.stats");
1092 return;
1093 }
1094
342c141e
A
1095 if (interval && vflag > 0)
1096 print_time();
9dc66a05
A
1097 printf("%s:\n", name);
1098
1099#define ARPDIFF(f) (arpstat.f - parpstat.f)
1100#define p(f, m) if (ARPDIFF(f) || sflag <= 1) \
1101 printf(m, ARPDIFF(f), plural(ARPDIFF(f)))
1102#define p2(f, m) if (ARPDIFF(f) || sflag <= 1) \
1103 printf(m, ARPDIFF(f), pluralies(ARPDIFF(f)))
26c66ce9
A
1104#define p3(f, m) if (ARPDIFF(f) || sflag <= 1) \
1105 printf(m, ARPDIFF(f), plural(ARPDIFF(f)), pluralies(ARPDIFF(f)))
9dc66a05 1106
26c66ce9
A
1107 p(txrequests, "\t%u broadast ARP request%s sent\n");
1108 p(txurequests, "\t%u unicast ARP request%s sent\n");
9dc66a05
A
1109 p2(txreplies, "\t%u ARP repl%s sent\n");
1110 p(txannounces, "\t%u ARP announcement%s sent\n");
1111 p(rxrequests, "\t%u ARP request%s received\n");
1112 p2(rxreplies, "\t%u ARP repl%s received\n");
1113 p(received, "\t%u total ARP packet%s received\n");
1114 p(txconflicts, "\t%u ARP conflict probe%s sent\n");
1115 p(invalidreqs, "\t%u invalid ARP resolve request%s\n");
1116 p(reqnobufs, "\t%u total packet%s dropped due to lack of memory\n");
26c66ce9 1117 p3(held, "\t%u total packet%s held awaiting ARP repl%s\n");
9dc66a05
A
1118 p(dropped, "\t%u total packet%s dropped due to no ARP entry\n");
1119 p(purged, "\t%u total packet%s dropped during ARP entry removal\n");
1120 p2(timeouts, "\t%u ARP entr%s timed out\n");
1121 p(dupips, "\t%u Duplicate IP%s seen\n");
1122
1123 if (interval > 0)
1124 bcopy(&arpstat, &parpstat, len);
1125
1126#undef ARPDIFF
1127#undef p
1128#undef p2
b7080c8e
A
1129}
1130
1131static char *icmpnames[] = {
1132 "echo reply",
1133 "#1",
1134 "#2",
1135 "destination unreachable",
1136 "source quench",
1137 "routing redirect",
1138 "#6",
1139 "#7",
1140 "echo",
1141 "router advertisement",
1142 "router solicitation",
1143 "time exceeded",
1144 "parameter problem",
1145 "time stamp",
1146 "time stamp reply",
1147 "information request",
1148 "information request reply",
1149 "address mask request",
1150 "address mask reply",
1151};
1152
1153/*
1154 * Dump ICMP statistics.
1155 */
1156void
9c859447 1157icmp_stats(uint32_t off , char *name, int af )
b7080c8e 1158{
b8dff150 1159 static struct icmpstat picmpstat;
b7080c8e
A
1160 struct icmpstat icmpstat;
1161 int i, first;
1162 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
1163 size_t len;
1164
1165 mib[0] = CTL_NET;
1166 mib[1] = PF_INET;
1167 mib[2] = IPPROTO_ICMP;
1168 mib[3] = ICMPCTL_STATS;
1169
1170 len = sizeof icmpstat;
1171 memset(&icmpstat, 0, len);
1172 if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0)
1173 return; /* XXX should complain, but not traditional */
1174
342c141e
A
1175 if (interval && vflag > 0)
1176 print_time();
b7080c8e
A
1177 printf("%s:\n", name);
1178
b8dff150
A
1179#define ICMPDIFF(f) (icmpstat.f - picmpstat.f)
1180#define p(f, m) if (ICMPDIFF(f) || sflag <= 1) \
1181 printf(m, ICMPDIFF(f), plural(ICMPDIFF(f)))
1182#define p1a(f, m) if (ICMPDIFF(f) || sflag <= 1) \
1183 printf(m, ICMPDIFF(f))
b7080c8e 1184
b8dff150 1185 p(icps_error, "\t%u call%s to icmp_error\n");
b7080c8e 1186 p(icps_oldicmp,
b8dff150 1187 "\t%u error%s not generated 'cuz old message was icmp\n");
b7080c8e 1188 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
b8dff150 1189 if (ICMPDIFF(icps_outhist[i]) != 0) {
b7080c8e
A
1190 if (first) {
1191 printf("\tOutput histogram:\n");
1192 first = 0;
1193 }
b8dff150
A
1194 printf("\t\t%s: %u\n", icmpnames[i],
1195 ICMPDIFF(icps_outhist[i]));
b7080c8e 1196 }
b8dff150
A
1197 p(icps_badcode, "\t%u message%s with bad code fields\n");
1198 p(icps_tooshort, "\t%u message%s < minimum length\n");
1199 p(icps_checksum, "\t%u bad checksum%s\n");
1200 p(icps_badlen, "\t%u message%s with bad length\n");
1201 p1a(icps_bmcastecho, "\t%u multicast echo requests ignored\n");
1202 p1a(icps_bmcasttstamp, "\t%u multicast timestamp requests ignored\n");
b7080c8e 1203 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
b8dff150 1204 if (ICMPDIFF(icps_inhist[i]) != 0) {
b7080c8e
A
1205 if (first) {
1206 printf("\tInput histogram:\n");
1207 first = 0;
1208 }
b8dff150
A
1209 printf("\t\t%s: %u\n", icmpnames[i],
1210 ICMPDIFF(icps_inhist[i]));
b7080c8e 1211 }
b8dff150
A
1212 p(icps_reflect, "\t%u message response%s generated\n");
1213
1214#undef ICMPDIFF
b7080c8e
A
1215#undef p
1216#undef p1a
1217 mib[3] = ICMPCTL_MASKREPL;
1218 len = sizeof i;
1219 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
1220 return;
1221 printf("\tICMP address mask responses are %sabled\n",
1222 i ? "en" : "dis");
b8dff150
A
1223
1224 if (interval > 0)
1225 bcopy(&icmpstat, &picmpstat, sizeof (icmpstat));
b7080c8e
A
1226}
1227
1228/*
1229 * Dump IGMP statistics structure.
1230 */
1231void
9c859447 1232igmp_stats(uint32_t off , char *name, int af )
b7080c8e 1233{
fdfd5971
A
1234 static struct igmpstat_v3 pigmpstat;
1235 struct igmpstat_v3 igmpstat;
b7080c8e
A
1236 size_t len = sizeof igmpstat;
1237
fdfd5971
A
1238 if (sysctlbyname("net.inet.igmp.v3stats", &igmpstat, &len, 0, 0) < 0) {
1239 warn("sysctl: net.inet.igmp.v3stats");
b7080c8e
A
1240 return;
1241 }
1242
fdfd5971
A
1243 if (igmpstat.igps_version != IGPS_VERSION_3) {
1244 warnx("%s: version mismatch (%d != %d)", __func__,
1245 igmpstat.igps_version, IGPS_VERSION_3);
1246 }
1247 if (igmpstat.igps_len != IGPS_VERSION3_LEN) {
1248 warnx("%s: size mismatch (%d != %d)", __func__,
1249 igmpstat.igps_len, IGPS_VERSION3_LEN);
1250 }
1251
342c141e
A
1252 if (interval && vflag > 0)
1253 print_time();
b7080c8e
A
1254 printf("%s:\n", name);
1255
fdfd5971
A
1256#define IGMPDIFF(f) ((uintmax_t)(igmpstat.f - pigmpstat.f))
1257#define p64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
b8dff150 1258 printf(m, IGMPDIFF(f), plural(IGMPDIFF(f)))
fdfd5971 1259#define py64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
b8dff150 1260 printf(m, IGMPDIFF(f), IGMPDIFF(f) != 1 ? "ies" : "y")
fdfd5971
A
1261
1262 p64(igps_rcv_total, "\t%ju message%s received\n");
1263 p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
1264 p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n");
1265 p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n");
1266 py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n");
1267 py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n");
1268 py64(igps_rcv_badqueries,
1269 "\t%ju membership quer%s received with invalid field(s)\n");
1270 py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n");
1271 py64(igps_rcv_group_queries, "\t%ju group quer%s received\n");
1272 py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n");
1273 py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n");
1274 p64(igps_rcv_reports, "\t%ju membership report%s received\n");
1275 p64(igps_rcv_badreports,
1276 "\t%ju membership report%s received with invalid field(s)\n");
1277 p64(igps_rcv_ourreports,
1278"\t%ju membership report%s received for groups to which we belong\n");
1279 p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n");
1280 p64(igps_snd_reports, "\t%ju membership report%s sent\n");
b8dff150
A
1281
1282 if (interval > 0)
1283 bcopy(&igmpstat, &pigmpstat, len);
1284
1285#undef IGMPDIFF
fdfd5971
A
1286#undef p64
1287#undef py64
b7080c8e
A
1288}
1289
1290/*
1291 * Pretty print an Internet address (net address + port).
1292 */
1293void
7ba0088d 1294inetprint(struct in_addr *in, int port, char *proto, int numeric_port)
b7080c8e
A
1295{
1296 struct servent *sp = 0;
1297 char line[80], *cp;
1298 int width;
1299
7ba0088d 1300 if (Wflag)
fdfd5971 1301 snprintf(line, sizeof(line), "%s.", inetname(in));
7ba0088d 1302 else
fdfd5971 1303 snprintf(line, sizeof(line), "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
b7080c8e 1304 cp = index(line, '\0');
7ba0088d 1305 if (!numeric_port && port)
ac2f15b3
A
1306#ifdef _SERVICE_CACHE_
1307 sp = _serv_cache_getservbyport(port, proto);
1308#else
b7080c8e 1309 sp = getservbyport((int)port, proto);
ac2f15b3 1310#endif
b7080c8e 1311 if (sp || port == 0)
fdfd5971 1312 snprintf(cp, sizeof(line) - (cp - line), "%.15s ", sp ? sp->s_name : "*");
7ba0088d 1313 else
fdfd5971 1314 snprintf(cp, sizeof(line) - (cp - line), "%d ", ntohs((u_short)port));
7ba0088d
A
1315 width = (Aflag && !Wflag) ? 18 : 22;
1316 if (Wflag)
1317 printf("%-*s ", width, line);
b7080c8e 1318 else
7ba0088d 1319 printf("%-*.*s ", width, width, line);
b7080c8e
A
1320}
1321
1322/*
1323 * Construct an Internet address representation.
1324 * If the nflag has been supplied, give
1325 * numeric value, otherwise try for symbolic name.
1326 */
1327char *
7ba0088d 1328inetname(struct in_addr *inp)
b7080c8e
A
1329{
1330 register char *cp;
7ba0088d 1331 static char line[MAXHOSTNAMELEN];
b7080c8e
A
1332 struct hostent *hp;
1333 struct netent *np;
1334
1335 cp = 0;
1336 if (!nflag && inp->s_addr != INADDR_ANY) {
1337 int net = inet_netof(*inp);
1338 int lna = inet_lnaof(*inp);
1339
1340 if (lna == INADDR_ANY) {
1341 np = getnetbyaddr(net, AF_INET);
1342 if (np)
1343 cp = np->n_name;
1344 }
1345 if (cp == 0) {
1346 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
1347 if (hp) {
1348 cp = hp->h_name;
7ba0088d 1349 //### trimdomain(cp, strlen(cp));
b7080c8e
A
1350 }
1351 }
1352 }
1353 if (inp->s_addr == INADDR_ANY)
fdfd5971 1354 strlcpy(line, "*", sizeof(line));
b7080c8e 1355 else if (cp) {
e0b07f2d 1356 strlcpy(line, cp, sizeof(line));
b7080c8e
A
1357 } else {
1358 inp->s_addr = ntohl(inp->s_addr);
1359#define C(x) ((u_int)((x) & 0xff))
fdfd5971 1360 snprintf(line, sizeof(line), "%u.%u.%u.%u", C(inp->s_addr >> 24),
b7080c8e
A
1361 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
1362 }
1363 return (line);
1364}