netstat: Reduce SACK scoreboard statistics description verbosity
[dragonfly.git] / usr.bin / netstat / inet.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1983, 1988, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
1de703da
MD
32 *
33 * @(#)inet.c 8.5 (Berkeley) 5/24/95
58b6d24a 34 * $FreeBSD: src/usr.bin/netstat/inet.c,v 1.37.2.11 2003/11/27 14:46:49 ru Exp $
984263bc
MD
35 */
36
984263bc
MD
37#include <sys/param.h>
38#include <sys/queue.h>
39#include <sys/socket.h>
40#include <sys/socketvar.h>
41#include <sys/sysctl.h>
42#include <sys/protosw.h>
ae94c427 43#include <sys/time.h>
984263bc
MD
44
45#include <net/route.h>
46#include <netinet/in.h>
47#include <netinet/in_systm.h>
48#include <netinet/ip.h>
0d16ba1d 49#include <netinet/ip_carp.h>
984263bc
MD
50#ifdef INET6
51#include <netinet/ip6.h>
52#endif /* INET6 */
53#include <netinet/in_pcb.h>
54#include <netinet/ip_icmp.h>
55#include <netinet/icmp_var.h>
56#include <netinet/igmp_var.h>
57#include <netinet/ip_var.h>
ef73cf6c 58#include <netinet/pim_var.h>
984263bc
MD
59#include <netinet/tcp.h>
60#include <netinet/tcpip.h>
61#include <netinet/tcp_seq.h>
62#define TCPSTATES
63#include <netinet/tcp_fsm.h>
64#include <netinet/tcp_timer.h>
65#include <netinet/tcp_var.h>
66#include <netinet/tcp_debug.h>
67#include <netinet/udp.h>
68#include <netinet/udp_var.h>
69
70#include <arpa/inet.h>
71#include <err.h>
72#include <errno.h>
73#include <libutil.h>
74#include <netdb.h>
75#include <stdio.h>
76#include <stdlib.h>
77#include <string.h>
78#include <unistd.h>
79#include "netstat.h"
80
81char *inetname (struct in_addr *);
d2e9e54c 82void inetprint (struct in_addr *, int, const char *, int);
984263bc 83#ifdef INET6
d2e9e54c 84extern void inet6print (struct in6_addr *, int, const char *, int);
984263bc
MD
85static int udp_done, tcp_done;
86#endif /* INET6 */
87
88/*
89 * Print a summary of connections related to an Internet
90 * protocol. For TCP, also give state of connection.
91 * Listening processes (aflag) are suppressed unless the
92 * -a (all) flag is specified.
93 */
d2e9e54c
MD
94
95static int ppr_first = 1;
8d7c364e 96static void outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp);
d2e9e54c 97
984263bc 98void
b82e1528 99protopr(u_long proto, const char *name, int af1 __unused)
984263bc
MD
100{
101 int istcp;
8d7c364e 102 void *buf;
d2e9e54c 103 const char *mibvar;
b82e1528 104 size_t i, len;
984263bc
MD
105
106 istcp = 0;
107 switch (proto) {
108 case IPPROTO_TCP:
109#ifdef INET6
110 if (tcp_done != 0)
111 return;
112 else
113 tcp_done = 1;
114#endif
115 istcp = 1;
116 mibvar = "net.inet.tcp.pcblist";
117 break;
118 case IPPROTO_UDP:
119#ifdef INET6
120 if (udp_done != 0)
121 return;
122 else
123 udp_done = 1;
124#endif
125 mibvar = "net.inet.udp.pcblist";
126 break;
127 case IPPROTO_DIVERT:
128 mibvar = "net.inet.divert.pcblist";
129 break;
130 default:
131 mibvar = "net.inet.raw.pcblist";
132 break;
133 }
134 len = 0;
135 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
136 if (errno != ENOENT)
137 warn("sysctl: %s", mibvar);
138 return;
139 }
8d7c364e
JS
140 if (len == 0)
141 return;
678e8cc6 142 if ((buf = malloc(len)) == NULL) {
984263bc
MD
143 warn("malloc %lu bytes", (u_long)len);
144 return;
145 }
146 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
147 warn("sysctl: %s", mibvar);
148 free(buf);
149 return;
150 }
151
8d7c364e
JS
152 if (istcp) {
153 struct xtcpcb *tcp = buf;
154 len /= sizeof(*tcp);
155 for (i = 0; i < len; i++) {
156 if (tcp[i].xt_len != sizeof(*tcp))
157 break;
158 outputpcb(proto, name, &tcp[i].xt_inp,
159 &tcp[i].xt_socket, &tcp[i].xt_tp);
d2e9e54c 160 }
8d7c364e
JS
161 } else {
162 struct xinpcb *in = buf;
163 len /= sizeof(*in);
164 for (i = 0; i < len; i++) {
165 if (in[i].xi_len != sizeof(*in))
166 break;
167 outputpcb(proto, name, &in[i].xi_inp,
168 &in[i].xi_socket, NULL);
984263bc 169 }
d2e9e54c 170 }
d2e9e54c
MD
171 free(buf);
172}
984263bc 173
d2e9e54c 174static void
8d7c364e 175outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp)
d2e9e54c
MD
176{
177 const char *vchar;
ae94c427
MD
178 static struct clockinfo clockinfo;
179
180 if (clockinfo.hz == 0) {
e43bcaac 181 size_t size = sizeof(clockinfo);
ae94c427
MD
182 sysctlbyname("kern.clockrate", &clockinfo, &size, NULL, 0);
183 if (clockinfo.hz == 0)
184 clockinfo.hz = 100;
185 }
984263bc 186
d2e9e54c
MD
187 /* Ignore sockets for protocols other than the desired one. */
188 if (so->xso_protocol != (int)proto)
189 return;
984263bc 190
d2e9e54c 191 if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
984263bc 192#ifdef INET6
d2e9e54c 193 || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
984263bc 194#endif /* INET6 */
d2e9e54c 195 || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
984263bc 196#ifdef INET6
d2e9e54c 197 && (inp->inp_vflag & INP_IPV6) == 0
984263bc 198#endif /* INET6 */
d2e9e54c
MD
199 ))
200 ) {
201 return;
202 }
203 if (!aflag && (
26d88339 204 (proto == IPPROTO_TCP && tp->t_state == TCPS_LISTEN) ||
d2e9e54c 205 (af == AF_INET && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
984263bc 206#ifdef INET6
d2e9e54c 207 || (af == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
984263bc 208#endif /* INET6 */
d2e9e54c
MD
209 || (af == AF_UNSPEC && (((inp->inp_vflag & INP_IPV4) != 0 &&
210 inet_lnaof(inp->inp_laddr) == INADDR_ANY)
984263bc 211#ifdef INET6
d2e9e54c
MD
212 || ((inp->inp_vflag & INP_IPV6) != 0 &&
213 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
984263bc 214#endif
d2e9e54c
MD
215 ))
216 )) {
217 return;
218 }
219
220 if (ppr_first) {
221 if (!Lflag) {
222 printf("Active Internet connections");
223 if (aflag)
224 printf(" (including servers)");
225 } else {
226 printf("Current listen queue sizes "
227 "(qlen/incqlen/maxqlen)");
984263bc 228 }
d2e9e54c
MD
229 putchar('\n');
230 if (Aflag)
231 printf("%-8.8s ", "Socket");
ae94c427
MD
232 if (Pflag)
233 printf("%8.8s %8.8s %8.8s ", "TxWin", "Unacked", "RTT/ms");
d2e9e54c 234 if (Lflag) {
8d7c364e
JS
235 printf("%-5.5s %-14.14s %-22.22s\n",
236 "Proto", "Listen", "Local Address");
d2e9e54c
MD
237 } else {
238 printf((Aflag && !Wflag) ?
8d7c364e
JS
239 "%-5.5s %-6.6s %-6.6s %-17.17s %-17.17s %s\n" :
240 "%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n",
241 "Proto", "Recv-Q", "Send-Q",
d2e9e54c
MD
242 "Local Address", "Foreign Address",
243 "(state)");
984263bc 244 }
d2e9e54c
MD
245 ppr_first = 0;
246 }
247 if (Lflag && so->so_qlimit == 0)
248 return;
249 if (Aflag) {
250 if (tp)
251 printf("%8lx ", (u_long)inp->inp_ppcb);
984263bc 252 else
d2e9e54c
MD
253 printf("%8lx ", (u_long)so->so_pcb);
254 }
ae94c427
MD
255 if (Pflag) {
256 if (tp) {
257 int window = MIN(tp->snd_cwnd, tp->snd_bwnd);
258 if (window == 1073725440)
259 printf("%8s ", "max");
260 else
261 printf("%8d ", (int)MIN(tp->snd_cwnd, tp->snd_bwnd));
262 printf("%8d ", (int)(tp->snd_max - tp->snd_una));
263 if (tp->t_srtt == 0)
264 printf("%8s ", "-");
265 else
266 printf("%8.3f ", (double)tp->t_srtt * 1000.0 / TCP_RTT_SCALE / clockinfo.hz);
267 } else {
268 printf("%8s %8s %8s ", "-", "-", "-");
269 }
270 }
d2e9e54c
MD
271#ifdef INET6
272 if ((inp->inp_vflag & INP_IPV6) != 0)
273 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "46" : "6 ";
274 else
984263bc 275#endif
d2e9e54c
MD
276 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : " ";
277
8d7c364e 278 printf("%-3.3s%-2.2s ", name, vchar);
d2e9e54c
MD
279 if (Lflag) {
280 char buf[15];
281
282 snprintf(buf, sizeof(buf), "%d/%d/%d", so->so_qlen,
283 so->so_incqlen, so->so_qlimit);
284 printf("%-13.13s ", buf);
285 } else if (Bflag) {
286 printf("%6ld %6ld ",
287 so->so_rcv.sb_hiwat,
288 so->so_snd.sb_hiwat);
289 } else {
290 printf("%6ld %6ld ",
291 so->so_rcv.sb_cc,
292 so->so_snd.sb_cc);
293 }
294 if (numeric_port) {
295 if (inp->inp_vflag & INP_IPV4) {
296 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
297 name, 1);
298 if (!Lflag)
299 inetprint(&inp->inp_faddr,
300 (int)inp->inp_fport, name, 1);
984263bc 301 }
984263bc 302#ifdef INET6
d2e9e54c
MD
303 else if (inp->inp_vflag & INP_IPV6) {
304 inet6print(&inp->in6p_laddr,
305 (int)inp->inp_lport, name, 1);
306 if (!Lflag)
307 inet6print(&inp->in6p_faddr,
308 (int)inp->inp_fport, name, 1);
309 } /* else nothing printed now */
984263bc 310#endif /* INET6 */
d2e9e54c
MD
311 } else if (inp->inp_flags & INP_ANONPORT) {
312 if (inp->inp_vflag & INP_IPV4) {
313 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
314 name, 1);
315 if (!Lflag)
316 inetprint(&inp->inp_faddr,
317 (int)inp->inp_fport, name, 0);
318 }
984263bc 319#ifdef INET6
d2e9e54c
MD
320 else if (inp->inp_vflag & INP_IPV6) {
321 inet6print(&inp->in6p_laddr,
322 (int)inp->inp_lport, name, 1);
323 if (!Lflag)
324 inet6print(&inp->in6p_faddr,
325 (int)inp->inp_fport, name, 0);
326 } /* else nothing printed now */
984263bc 327#endif /* INET6 */
d2e9e54c
MD
328 } else {
329 if (inp->inp_vflag & INP_IPV4) {
330 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
331 name, 0);
332 if (!Lflag)
333 inetprint(&inp->inp_faddr,
334 (int)inp->inp_fport, name,
335 inp->inp_lport !=
336 inp->inp_fport);
337 }
984263bc 338#ifdef INET6
d2e9e54c
MD
339 else if (inp->inp_vflag & INP_IPV6) {
340 inet6print(&inp->in6p_laddr,
341 (int)inp->inp_lport, name, 0);
342 if (!Lflag)
343 inet6print(&inp->in6p_faddr,
344 (int)inp->inp_fport, name,
345 inp->inp_lport !=
346 inp->inp_fport);
347 } /* else nothing printed now */
984263bc 348#endif /* INET6 */
d2e9e54c
MD
349 }
350 if (tp && !Lflag) {
351 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
352 printf("%d", tp->t_state);
353 else {
354 printf("%s", tcpstates[tp->t_state]);
984263bc 355#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
d2e9e54c
MD
356 /* Show T/TCP `hidden state' */
357 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
358 putchar('*');
984263bc 359#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
d2e9e54c 360 }
984263bc 361 }
d2e9e54c 362 putchar('\n');
984263bc
MD
363}
364
d2e9e54c
MD
365
366
fc9c7b4f
HP
367#define CPU_STATS_FUNC(proto,type) \
368static void \
369proto ##_stats_agg(type *ary, type *ttl, int cpucnt) \
370{ \
371 int i, off, siz; \
372 siz = sizeof(type); \
373 \
374 if (!ary && !ttl) \
375 return; \
376 \
377 bzero(ttl, siz); \
378 if (cpucnt == 1) { \
379 *ttl = ary[0]; \
380 } else { \
381 for (i = 0; i < cpucnt; ++i) { \
382 for (off = 0; off < siz; off += sizeof(u_long)) { \
383 *(u_long *)((char *)(*(&ttl)) + off) += \
384 *(u_long *)((char *)&ary[i] + off); \
385 } \
386 } \
387 } \
2b57d013 388}
fc9c7b4f
HP
389CPU_STATS_FUNC(tcp, struct tcp_stats);
390CPU_STATS_FUNC(ip, struct ip_stats);
2b57d013 391
984263bc
MD
392/*
393 * Dump TCP statistics structure.
394 */
395void
b82e1528 396tcp_stats(u_long off __unused, const char *name, int af1 __unused)
984263bc 397{
2b57d013
MD
398 struct tcp_stats tcpstat, *stattmp;
399 struct tcp_stats zerostat[SMP_MAXCPU];
400 size_t len = sizeof(struct tcp_stats) * SMP_MAXCPU;
401 int cpucnt;
984263bc
MD
402
403 if (zflag)
2b57d013
MD
404 memset(zerostat, 0, len);
405
406 if ((stattmp = malloc(len)) == NULL) {
984263bc 407 return;
2b57d013
MD
408 } else {
409 if (sysctlbyname("net.inet.tcp.stats", stattmp, &len,
410 zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
411 warn("sysctl: net.inet.tcp.stats");
412 free(stattmp);
413 return;
414 } else {
415 if ((stattmp = realloc(stattmp, len)) == NULL) {
416 warn("tcp_stats");
417 return;
418 }
419 }
984263bc 420 }
2b57d013
MD
421 cpucnt = len / sizeof(struct tcp_stats);
422 tcp_stats_agg(stattmp, &tcpstat, cpucnt);
984263bc
MD
423
424#ifdef INET6
425 if (tcp_done != 0)
426 return;
427 else
428 tcp_done = 1;
429#endif
430
431 printf ("%s:\n", name);
432
433#define p(f, m) if (tcpstat.f || sflag <= 1) \
434 printf(m, tcpstat.f, plural(tcpstat.f))
435#define p1a(f, m) if (tcpstat.f || sflag <= 1) \
436 printf(m, tcpstat.f)
437#define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
438 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
439#define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
440 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
441#define p3(f, m) if (tcpstat.f || sflag <= 1) \
442 printf(m, tcpstat.f, plurales(tcpstat.f))
443
444 p(tcps_sndtotal, "\t%lu packet%s sent\n");
445 p2(tcps_sndpack,tcps_sndbyte,
446 "\t\t%lu data packet%s (%lu byte%s)\n");
447 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
448 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
90394ae1
SZ
449 p2(tcps_sndsackpack, tcps_sndsackbyte,
450 "\t\t%lu data packet%s (%lu byte%s) sent by SACK recovery\n");
451 p2(tcps_sndsackrtopack, tcps_sndsackrtobyte,
452 "\t\t%lu data packet%s (%lu byte%s) retransmitted by SACK\n");
ae8922cc
JH
453 p2a(tcps_sndfastrexmit, tcps_sndearlyrexmit,
454 "\t\t%lu Fast Retransmit%s (%lu early)\n");
455 p(tcps_sndlimited, "\t\t%lu packet%s sent by Limited Transmit\n");
7f8fbc35 456 p(tcps_sndrtobad, "\t\t%lu spurious RTO retransmit%s\n");
ae8922cc
JH
457 p2a(tcps_sndfastrexmitbad, tcps_sndearlyrexmitbad,
458 "\t\t%lu spurious Fast Retransmit%s (%lu early)\n");
6ca8ab5d
SZ
459 p2a(tcps_eifeldetected, tcps_rttcantdetect,
460 "\t\t%lu Eifel-detected spurious retransmit%s (%lu non-RTT)\n");
88f7ddb2 461 p(tcps_rttdetected, "\t\t%lu RTT-detected spurious retransmit%s\n");
984263bc 462 p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
90394ae1
SZ
463 p(tcps_sndsackopt, "\t\t%lu SACK option%s sent\n");
464 p(tcps_snddsackopt, "\t\t%lu D-SACK option%s sent\n");
984263bc
MD
465 p2a(tcps_sndacks, tcps_delack,
466 "\t\t%lu ack-only packet%s (%lu delayed)\n");
467 p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
468 p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
469 p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
470 p(tcps_sndctrl, "\t\t%lu control packet%s\n");
471 p(tcps_rcvtotal, "\t%lu packet%s received\n");
472 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
473 p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
474 p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
475 p2(tcps_rcvpack, tcps_rcvbyte,
476 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
477 p2(tcps_rcvduppack, tcps_rcvdupbyte,
478 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
479 p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
480 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
481 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
482 p2(tcps_rcvoopack, tcps_rcvoobyte,
483 "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
484 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
485 "\t\t%lu packet%s (%lu byte%s) of data after window\n");
486 p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
487 p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
488 p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
489 p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
490 p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
491 p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
90394ae1 492 p(tcps_rcvbadsackopt, "\t\t%lu bad SACK option%s\n");
984263bc
MD
493 p(tcps_connattempt, "\t%lu connection request%s\n");
494 p(tcps_accepts, "\t%lu connection accept%s\n");
495 p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
496 p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
497 p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
498 p2(tcps_closed, tcps_drops,
499 "\t%lu connection%s closed (including %lu drop%s)\n");
500 p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
501 p(tcps_cachedrttvar,
502 "\t\t%lu connection%s updated cached RTT variance on close\n");
503 p(tcps_cachedssthresh,
504 "\t\t%lu connection%s updated cached ssthresh on close\n");
505 p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
506 p2(tcps_rttupdated, tcps_segstimed,
507 "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
508 p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
509 p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
510 p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
511 p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
512 p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
513 p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
514 p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
515 p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
516 p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
517
6de4f7ba
HP
518 p1a(tcps_sc_added, "\t%lu syncache entries added\n");
519 p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n");
520 p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n");
521 p1a(tcps_sc_dropped, "\t\t%lu dropped\n");
522 p1a(tcps_sc_completed, "\t\t%lu completed\n");
523 p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n");
524 p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n");
525 p1a(tcps_sc_reset, "\t\t%lu reset\n");
526 p1a(tcps_sc_stale, "\t\t%lu stale\n");
527 p1a(tcps_sc_aborted, "\t\t%lu aborted\n");
528 p1a(tcps_sc_badack, "\t\t%lu badack\n");
529 p1a(tcps_sc_unreach, "\t\t%lu unreach\n");
530 p1a(tcps_sc_zonefail, "\t\t%lu zone failures\n");
90394ae1
SZ
531 p1a(tcps_sc_sendcookie, "\t\t%lu cookies sent\n");
532 p1a(tcps_sc_recvcookie, "\t\t%lu cookies received\n");
533
534 p(tcps_sacksbupdate, "\t%lu SACK scoreboard update%s\n");
1e945b1c
SZ
535 p(tcps_sacksboverflow, "\t\t%lu overflow%s\n");
536 p(tcps_sacksbfailed, "\t\t%lu failure%s\n");
537 p(tcps_sacksbreused, "\t\t%lu record%s reused\n");
90394ae1 538
2b57d013 539 free(stattmp);
984263bc
MD
540#undef p
541#undef p1a
542#undef p2
543#undef p2a
544#undef p3
545}
546
547/*
548 * Dump UDP statistics structure.
549 */
550void
b82e1528 551udp_stats(u_long off __unused, const char *name, int af1 __unused)
984263bc
MD
552{
553 struct udpstat udpstat, zerostat;
554 size_t len = sizeof udpstat;
555 u_long delivered;
556
557 if (zflag)
558 memset(&zerostat, 0, len);
559 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
560 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
561 warn("sysctl: net.inet.udp.stats");
562 return;
563 }
564
565#ifdef INET6
566 if (udp_done != 0)
567 return;
568 else
569 udp_done = 1;
570#endif
571
572 printf("%s:\n", name);
573#define p(f, m) if (udpstat.f || sflag <= 1) \
574 printf(m, udpstat.f, plural(udpstat.f))
575#define p1a(f, m) if (udpstat.f || sflag <= 1) \
576 printf(m, udpstat.f)
577 p(udps_ipackets, "\t%lu datagram%s received\n");
578 p1a(udps_hdrops, "\t%lu with incomplete header\n");
579 p1a(udps_badlen, "\t%lu with bad data length field\n");
580 p1a(udps_badsum, "\t%lu with bad checksum\n");
581 p1a(udps_nosum, "\t%lu with no checksum\n");
582 p1a(udps_noport, "\t%lu dropped due to no socket\n");
583 p(udps_noportbcast,
584 "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
585 p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
586 p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
587 delivered = udpstat.udps_ipackets -
588 udpstat.udps_hdrops -
589 udpstat.udps_badlen -
590 udpstat.udps_badsum -
591 udpstat.udps_noport -
592 udpstat.udps_noportbcast -
593 udpstat.udps_fullsock;
594 if (delivered || sflag <= 1)
595 printf("\t%lu delivered\n", delivered);
596 p(udps_opackets, "\t%lu datagram%s output\n");
597#undef p
598#undef p1a
599}
600
0d16ba1d
MD
601/*
602 * Dump CARP statistics structure.
603 */
604void
b82e1528 605carp_stats(u_long off __unused, const char *name, int af1 __unused)
0d16ba1d
MD
606{
607 struct carpstats carpstat, zerostat;
608 size_t len = sizeof(struct carpstats);
609
610 if (zflag)
611 memset(&zerostat, 0, len);
612 if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
613 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
614 warn("sysctl: net.inet.carp.stats");
615 return;
616 }
617
618 printf("%s:\n", name);
619
620#define p(f, m) if (carpstat.f || sflag <= 1) \
b82e1528 621 printf(m, (uintmax_t)carpstat.f, plural((int)carpstat.f))
0d16ba1d 622#define p2(f, m) if (carpstat.f || sflag <= 1) \
b82e1528
SW
623 printf(m, (uintmax_t)carpstat.f)
624
625 p(carps_ipackets, "\t%ju packet%s received (IPv4)\n");
626 p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n");
627 p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n");
628 p(carps_hdrops, "\t\t%ju packet%s shorter than header\n");
629 p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n");
630 p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n");
631 p2(carps_badlen, "\t\t%ju discarded because packet too short\n");
632 p2(carps_badauth, "\t\t%ju discarded for bad authentication\n");
633 p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n");
634 p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n");
635 p(carps_opackets, "\t%ju packet%s sent (IPv4)\n");
636 p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n");
637 p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n");
0d16ba1d
MD
638#if notyet
639 p(carps_ostates, "\t\t%s state update%s sent\n");
640#endif
641#undef p
642#undef p2
643}
644
984263bc
MD
645/*
646 * Dump IP statistics structure.
647 */
648void
b82e1528 649ip_stats(u_long off __unused, const char *name, int af1 __unused)
984263bc 650{
fc9c7b4f
HP
651 struct ip_stats ipstat, *stattmp;
652 struct ip_stats zerostat[SMP_MAXCPU];
653 size_t len = sizeof(struct ip_stats) * SMP_MAXCPU;
654 int cpucnt;
984263bc
MD
655
656 if (zflag)
fc9c7b4f
HP
657 memset(zerostat, 0, len);
658 if ((stattmp = malloc(len)) == NULL) {
984263bc 659 return;
fc9c7b4f
HP
660 } else {
661 if (sysctlbyname("net.inet.ip.stats", stattmp, &len,
662 zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
663 warn("sysctl: net.inet.ip.stats");
664 free(stattmp);
665 return;
666 } else {
667 if ((stattmp = realloc(stattmp, len)) == NULL) {
668 warn("ip_stats");
669 return;
670 }
671 }
984263bc 672 }
fc9c7b4f
HP
673 cpucnt = len / sizeof(struct ip_stats);
674 ip_stats_agg(stattmp, &ipstat, cpucnt);
984263bc
MD
675
676 printf("%s:\n", name);
677
678#define p(f, m) if (ipstat.f || sflag <= 1) \
679 printf(m, ipstat.f, plural(ipstat.f))
680#define p1a(f, m) if (ipstat.f || sflag <= 1) \
681 printf(m, ipstat.f)
682
683 p(ips_total, "\t%lu total packet%s received\n");
684 p(ips_badsum, "\t%lu bad header checksum%s\n");
685 p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
686 p1a(ips_tooshort, "\t%lu with data size < data length\n");
687 p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
688 p1a(ips_badhlen, "\t%lu with header length < data size\n");
689 p1a(ips_badlen, "\t%lu with data length < header length\n");
690 p1a(ips_badoptions, "\t%lu with bad options\n");
691 p1a(ips_badvers, "\t%lu with incorrect version number\n");
692 p(ips_fragments, "\t%lu fragment%s received\n");
693 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
694 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
695 p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
696 p(ips_delivered, "\t%lu packet%s for this host\n");
697 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
698 p(ips_forward, "\t%lu packet%s forwarded");
699 p(ips_fastforward, " (%lu packet%s fast forwarded)");
700 if (ipstat.ips_forward || sflag <= 1)
701 putchar('\n');
702 p(ips_cantforward, "\t%lu packet%s not forwardable\n");
703 p(ips_notmember,
704 "\t%lu packet%s received for unknown multicast group\n");
705 p(ips_redirectsent, "\t%lu redirect%s sent\n");
706 p(ips_localout, "\t%lu packet%s sent from this host\n");
707 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
708 p(ips_odropped,
709 "\t%lu output packet%s dropped due to no bufs, etc.\n");
710 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
711 p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
712 p(ips_ofragments, "\t%lu fragment%s created\n");
713 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
714 p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
715 p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
fc9c7b4f 716 free(stattmp);
984263bc
MD
717#undef p
718#undef p1a
719}
720
b82e1528 721static const char *icmpnames[] = {
984263bc
MD
722 "echo reply",
723 "#1",
724 "#2",
725 "destination unreachable",
726 "source quench",
727 "routing redirect",
728 "#6",
729 "#7",
730 "echo",
731 "router advertisement",
732 "router solicitation",
733 "time exceeded",
734 "parameter problem",
735 "time stamp",
736 "time stamp reply",
737 "information request",
738 "information request reply",
739 "address mask request",
740 "address mask reply",
741};
742
743/*
744 * Dump ICMP statistics.
745 */
746void
b82e1528 747icmp_stats(u_long off __unused, const char *name, int af1 __unused)
984263bc
MD
748{
749 struct icmpstat icmpstat, zerostat;
750 int i, first;
751 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
752 size_t len;
753
754 mib[0] = CTL_NET;
755 mib[1] = PF_INET;
756 mib[2] = IPPROTO_ICMP;
757 mib[3] = ICMPCTL_STATS;
758
759 len = sizeof icmpstat;
760 if (zflag)
761 memset(&zerostat, 0, len);
762 if (sysctl(mib, 4, &icmpstat, &len,
763 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
764 warn("sysctl: net.inet.icmp.stats");
765 return;
766 }
767
768 printf("%s:\n", name);
769
770#define p(f, m) if (icmpstat.f || sflag <= 1) \
771 printf(m, icmpstat.f, plural(icmpstat.f))
772#define p1a(f, m) if (icmpstat.f || sflag <= 1) \
773 printf(m, icmpstat.f)
774#define p2(f, m) if (icmpstat.f || sflag <= 1) \
775 printf(m, icmpstat.f, plurales(icmpstat.f))
776
777 p(icps_error, "\t%lu call%s to icmp_error\n");
778 p(icps_oldicmp,
779 "\t%lu error%s not generated 'cuz old message was icmp\n");
780 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
781 if (icmpstat.icps_outhist[i] != 0) {
782 if (first) {
783 printf("\tOutput histogram:\n");
784 first = 0;
785 }
786 printf("\t\t%s: %lu\n", icmpnames[i],
787 icmpstat.icps_outhist[i]);
788 }
789 p(icps_badcode, "\t%lu message%s with bad code fields\n");
790 p(icps_tooshort, "\t%lu message%s < minimum length\n");
791 p(icps_checksum, "\t%lu bad checksum%s\n");
792 p(icps_badlen, "\t%lu message%s with bad length\n");
793 p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
794 p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
795 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
796 if (icmpstat.icps_inhist[i] != 0) {
797 if (first) {
798 printf("\tInput histogram:\n");
799 first = 0;
800 }
801 printf("\t\t%s: %lu\n", icmpnames[i],
802 icmpstat.icps_inhist[i]);
803 }
804 p(icps_reflect, "\t%lu message response%s generated\n");
805 p2(icps_badaddr, "\t%lu invalid return address%s\n");
58b6d24a 806 p(icps_noroute, "\t%lu no return route%s\n");
984263bc
MD
807#undef p
808#undef p1a
809#undef p2
810 mib[3] = ICMPCTL_MASKREPL;
811 len = sizeof i;
60233e58 812 if (sysctl(mib, 4, &i, &len, NULL, 0) < 0)
984263bc
MD
813 return;
814 printf("\tICMP address mask responses are %sabled\n",
815 i ? "en" : "dis");
816}
817
818/*
819 * Dump IGMP statistics structure.
820 */
821void
b82e1528 822igmp_stats(u_long off __unused, const char *name, int af1 __unused)
984263bc
MD
823{
824 struct igmpstat igmpstat, zerostat;
825 size_t len = sizeof igmpstat;
826
827 if (zflag)
828 memset(&zerostat, 0, len);
829 if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
830 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
831 warn("sysctl: net.inet.igmp.stats");
832 return;
833 }
834
835 printf("%s:\n", name);
836
837#define p(f, m) if (igmpstat.f || sflag <= 1) \
838 printf(m, igmpstat.f, plural(igmpstat.f))
839#define py(f, m) if (igmpstat.f || sflag <= 1) \
840 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
841 p(igps_rcv_total, "\t%u message%s received\n");
842 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
843 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
844 py(igps_rcv_queries, "\t%u membership quer%s received\n");
845 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
846 p(igps_rcv_reports, "\t%u membership report%s received\n");
847 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
848 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
849 p(igps_snd_reports, "\t%u membership report%s sent\n");
850#undef p
851#undef py
852}
853
854/*
ef73cf6c
JH
855 * Dump PIM statistics structure.
856 */
857void
b82e1528 858pim_stats(u_long off __unused, const char *name, int af1 __unused)
ef73cf6c
JH
859{
860 struct pimstat pimstat, zerostat;
861 size_t len = sizeof pimstat;
862
863 if (zflag)
864 memset(&zerostat, 0, len);
8aa3893e
HP
865 if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
866 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
867 if (errno != ENOENT)
04652ffc 868 warn("sysctl: net.inet.pim.stats");
8aa3893e 869 return;
ef73cf6c
JH
870 }
871
872 printf("%s:\n", name);
873
874#define p(f, m) if (pimstat.f || sflag <= 1) \
b82e1528 875 printf(m, (uintmax_t)pimstat.f, plural(pimstat.f))
ef73cf6c 876#define py(f, m) if (pimstat.f || sflag <= 1) \
b82e1528
SW
877 printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y")
878 p(pims_rcv_total_msgs, "\t%ju message%s received\n");
879 p(pims_rcv_total_bytes, "\t%ju byte%s received\n");
880 p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
881 p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n");
882 p(pims_rcv_badversion, "\t%ju message%s received with bad version\n");
883 p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n");
884 p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n");
885 p(pims_rcv_registers_wrongiif, "\t%ju data register message%s received on wrong iif\n");
886 p(pims_rcv_badregisters, "\t%ju bad register%s received\n");
887 p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n");
888 p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n");
ef73cf6c
JH
889#undef p
890#undef py
891}
892
893/*
984263bc
MD
894 * Pretty print an Internet address (net address + port).
895 */
896void
b82e1528 897inetprint(struct in_addr *in, int port, const char *proto, int num_port)
984263bc 898{
678e8cc6 899 struct servent *sp = NULL;
984263bc
MD
900 char line[80], *cp;
901 int width;
902
903 if (Wflag)
904 sprintf(line, "%s.", inetname(in));
905 else
b82e1528 906 sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in));
43b4d1bd 907 cp = strchr(line, '\0');
b82e1528 908 if (!num_port && port)
984263bc
MD
909 sp = getservbyport((int)port, proto);
910 if (sp || port == 0)
911 sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
912 else
913 sprintf(cp, "%d ", ntohs((u_short)port));
d2e9e54c 914 width = (Aflag && !Wflag) ? 17 : 21;
984263bc
MD
915 if (Wflag)
916 printf("%-*s ", width, line);
917 else
918 printf("%-*.*s ", width, width, line);
919}
920
921/*
922 * Construct an Internet address representation.
923 * If numeric_addr has been supplied, give
924 * numeric value, otherwise try for symbolic name.
925 */
926char *
927inetname(struct in_addr *inp)
928{
6bd457ed 929 char *cp;
984263bc
MD
930 static char line[MAXHOSTNAMELEN];
931 struct hostent *hp;
932 struct netent *np;
933
678e8cc6 934 cp = NULL;
984263bc
MD
935 if (!numeric_addr && inp->s_addr != INADDR_ANY) {
936 int net = inet_netof(*inp);
937 int lna = inet_lnaof(*inp);
938
939 if (lna == INADDR_ANY) {
940 np = getnetbyaddr(net, AF_INET);
941 if (np)
942 cp = np->n_name;
943 }
678e8cc6 944 if (cp == NULL) {
15b85273 945 hp = gethostbyaddr(inp, sizeof (*inp), AF_INET);
984263bc
MD
946 if (hp) {
947 cp = hp->h_name;
948 trimdomain(cp, strlen(cp));
949 }
950 }
951 }
952 if (inp->s_addr == INADDR_ANY)
953 strcpy(line, "*");
954 else if (cp) {
955 strncpy(line, cp, sizeof(line) - 1);
956 line[sizeof(line) - 1] = '\0';
957 } else {
958 inp->s_addr = ntohl(inp->s_addr);
959#define C(x) ((u_int)((x) & 0xff))
960 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
961 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
962 }
963 return (line);
964}