xref: /dflybsd-src/usr.bin/netstat/inet.c (revision 1732ee5d0e558c47be9e1c8151e529c16e3514ed)
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.
32  *
33  * @(#)inet.c	8.5 (Berkeley) 5/24/95
34  * $FreeBSD: src/usr.bin/netstat/inet.c,v 1.37.2.11 2003/11/27 14:46:49 ru Exp $
35  */
36 
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>
43 #include <sys/time.h>
44 
45 #include <net/route.h>
46 #include <netinet/in.h>
47 #include <netinet/in_systm.h>
48 #include <netinet/ip.h>
49 #include <netinet/ip_carp.h>
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>
58 #include <netinet/pim_var.h>
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 
81 char	*inetname (struct in_addr *);
82 void	inetprint (struct in_addr *, int, const char *, int);
83 #ifdef INET6
84 extern void	inet6print (struct in6_addr *, int, const char *, int);
85 static 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  */
94 
95 static int ppr_first = 1;
96 static void outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp);
97 
98 void
99 protopr(u_long proto, const char *name, int af1 __unused)
100 {
101 	int istcp;
102 	void *buf;
103 	const char *mibvar;
104 	size_t i, len;
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 	}
140 	if (len == 0)
141 		return;
142 	if ((buf = malloc(len)) == NULL) {
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 
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);
160 		}
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);
169 		}
170 	}
171 	free(buf);
172 }
173 
174 static void
175 outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp)
176 {
177 	const char *vchar;
178 	static struct clockinfo clockinfo;
179 
180 	if (clockinfo.hz == 0) {
181 		size_t size = sizeof(clockinfo);
182 		sysctlbyname("kern.clockrate", &clockinfo, &size, NULL, 0);
183 		if (clockinfo.hz == 0)
184 			clockinfo.hz = 100;
185 	}
186 
187 	/* Ignore sockets for protocols other than the desired one. */
188 	if (so->xso_protocol != (int)proto)
189 		return;
190 
191 	if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
192 #ifdef INET6
193 	    || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
194 #endif /* INET6 */
195 	    || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
196 #ifdef INET6
197 		&& (inp->inp_vflag & INP_IPV6) == 0
198 #endif /* INET6 */
199 		))
200 	    ) {
201 		return;
202 	}
203 	if (!aflag && (
204 		(proto == IPPROTO_TCP && tp->t_state == TCPS_LISTEN) ||
205 		(af == AF_INET && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
206 #ifdef INET6
207 	    || (af == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
208 #endif /* INET6 */
209 	    || (af == AF_UNSPEC && (((inp->inp_vflag & INP_IPV4) != 0 &&
210 		inet_lnaof(inp->inp_laddr) == INADDR_ANY)
211 #ifdef INET6
212 	    || ((inp->inp_vflag & INP_IPV6) != 0 &&
213 		IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
214 #endif
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)");
228 		}
229 		putchar('\n');
230 		if (Aflag)
231 			printf("%-8.8s ", "Socket");
232 		if (Pflag)
233 			printf("%8.8s %8.8s %8.8s ", "TxWin", "Unacked", "RTT/ms");
234 		if (Lflag) {
235 			printf("%-5.5s %-14.14s %-22.22s\n",
236 				"Proto", "Listen", "Local Address");
237 		} else {
238 			printf((Aflag && !Wflag) ?
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",
242 			    "Local Address", "Foreign Address",
243 			    "(state)");
244 		}
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);
252 		else
253 			printf("%8lx ", (u_long)so->so_pcb);
254 	}
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 	}
271 #ifdef INET6
272 	if ((inp->inp_vflag & INP_IPV6) != 0)
273 		vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "46" : "6 ";
274 	else
275 #endif
276 		vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : "  ";
277 
278 	printf("%-3.3s%-2.2s ", name, vchar);
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);
301 		}
302 #ifdef INET6
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 */
310 #endif /* INET6 */
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 		}
319 #ifdef INET6
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 */
327 #endif /* INET6 */
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 		}
338 #ifdef INET6
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 */
348 #endif /* INET6 */
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]);
355 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
356 		      /* Show T/TCP `hidden state' */
357 		      if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
358 			      putchar('*');
359 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
360 	      }
361 	}
362 	putchar('\n');
363 }
364 
365 
366 
367 #define CPU_STATS_FUNC(proto,type)                            \
368 static void                                                   \
369 proto ##_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     }                                                         \
388 }
389 CPU_STATS_FUNC(tcp, struct tcp_stats);
390 CPU_STATS_FUNC(ip, struct ip_stats);
391 CPU_STATS_FUNC(udp, struct udpstat);
392 
393 /*
394  * Dump TCP statistics structure.
395  */
396 void
397 tcp_stats(u_long off __unused, const char *name, int af1 __unused)
398 {
399 	struct tcp_stats tcpstat, *stattmp;
400 	struct tcp_stats zerostat[SMP_MAXCPU];
401 	size_t len = sizeof(struct tcp_stats) * SMP_MAXCPU;
402 	int cpucnt;
403 
404 	if (zflag)
405 		memset(zerostat, 0, len);
406 
407 	if ((stattmp = malloc(len)) == NULL) {
408 		return;
409 	} else {
410 		if (sysctlbyname("net.inet.tcp.stats", stattmp, &len,
411 			zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
412 			warn("sysctl: net.inet.tcp.stats");
413 			free(stattmp);
414 			return;
415 		} else {
416 			if ((stattmp = realloc(stattmp, len)) == NULL) {
417 				warn("tcp_stats");
418 				return;
419 			}
420 		}
421 	}
422 	cpucnt = len / sizeof(struct tcp_stats);
423 	tcp_stats_agg(stattmp, &tcpstat, cpucnt);
424 
425 #ifdef INET6
426 	if (tcp_done != 0)
427 		return;
428 	else
429 		tcp_done = 1;
430 #endif
431 
432 	printf ("%s:\n", name);
433 
434 #define	p(f, m) if (tcpstat.f || sflag <= 1) \
435     printf(m, tcpstat.f, plural(tcpstat.f))
436 #define	p1a(f, m) if (tcpstat.f || sflag <= 1) \
437     printf(m, tcpstat.f)
438 #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
439     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
440 #define	p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
441     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
442 #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
443     printf(m, tcpstat.f, plurales(tcpstat.f))
444 
445 	p(tcps_sndtotal, "\t%lu packet%s sent\n");
446 	p2(tcps_sndpack,tcps_sndbyte,
447 		"\t\t%lu data packet%s (%lu byte%s)\n");
448 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
449 		"\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
450 	p2(tcps_sndsackrtopack, tcps_sndsackrtobyte,
451 		"\t\t%lu data packet%s (%lu byte%s) retransmitted by SACK\n");
452 	p2(tcps_sndsackpack, tcps_sndsackbyte,
453 		"\t\t%lu data packet%s (%lu byte%s) sent by SACK recovery\n");
454 	p2(tcps_sackrescue, tcps_sackrescue_try,
455 		"\t\t%lu SACK rescue packet%s sent (of %lu attempt%s)\n");
456 	p2a(tcps_sndfastrexmit, tcps_sndearlyrexmit,
457 		"\t\t%lu Fast Retransmit%s (%lu early)\n");
458 	p(tcps_sndlimited, "\t\t%lu packet%s sent by Limited Transmit\n");
459 	p2(tcps_sndrtobad, tcps_eifelresponse,
460 		"\t\t%lu spurious RTO retransmit%s (%lu Eifel-response%s)\n");
461 	p2a(tcps_sndfastrexmitbad, tcps_sndearlyrexmitbad,
462 		"\t\t%lu spurious Fast Retransmit%s (%lu early)\n");
463 	p2a(tcps_eifeldetected, tcps_rttcantdetect,
464 		"\t\t%lu Eifel-detected spurious retransmit%s (%lu non-RTT)\n");
465 	p(tcps_rttdetected, "\t\t%lu RTT-detected spurious retransmit%s\n");
466 	p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
467 	p(tcps_sndsackopt, "\t\t%lu SACK option%s sent\n");
468 	p(tcps_snddsackopt, "\t\t%lu D-SACK option%s sent\n");
469 	p2a(tcps_sndacks, tcps_delack,
470 		"\t\t%lu ack-only packet%s (%lu delayed)\n");
471 	p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
472 	p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
473 	p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
474 	p(tcps_sndctrl, "\t\t%lu control packet%s\n");
475 	p(tcps_rcvtotal, "\t%lu packet%s received\n");
476 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
477 	p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
478 	p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
479 	p2(tcps_rcvpack, tcps_rcvbyte,
480 		"\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
481 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
482 		"\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
483 	p2(tcps_pawsdrop, tcps_pawsaccept,
484 		"\t\t%lu old duplicate packet%s (%lu packet%s accepted)\n");
485 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
486 		"\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
487 	p2(tcps_rcvoopack, tcps_rcvoobyte,
488 		"\t\t%lu out-of-order packet%s (%lu byte%s)\n");
489 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
490 		"\t\t%lu packet%s (%lu byte%s) of data after window\n");
491 	p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
492 	p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
493 	p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
494 	p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
495 	p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
496 	p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
497 	p(tcps_rcvbadsackopt, "\t\t%lu bad SACK option%s\n");
498 	p1a(tcps_sackrenege, "\t\t%lu other side reneged\n");
499 	p(tcps_connattempt, "\t%lu connection request%s\n");
500 	p(tcps_accepts, "\t%lu connection accept%s\n");
501 	p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
502 	p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
503 	p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
504 	p2(tcps_closed, tcps_drops,
505 		"\t%lu connection%s closed (including %lu drop%s)\n");
506 	p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
507 	p(tcps_cachedrttvar,
508 	  "\t\t%lu connection%s updated cached RTT variance on close\n");
509 	p(tcps_cachedssthresh,
510 	  "\t\t%lu connection%s updated cached ssthresh on close\n");
511 	p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
512 	p2(tcps_rttupdated, tcps_segstimed,
513 		"\t%lu segment%s updated rtt (of %lu attempt%s)\n");
514 	p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
515 	p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
516 	p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
517 	p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
518 	p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
519 	p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
520 	p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
521 	p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
522 	p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
523 	p(tcps_sndidle, "\t%lu send idle%s\n");
524 
525 	p1a(tcps_sc_added, "\t%lu syncache entries added\n");
526 	p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n");
527 	p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n");
528 	p1a(tcps_sc_dropped, "\t\t%lu dropped\n");
529 	p1a(tcps_sc_completed, "\t\t%lu completed\n");
530 	p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n");
531 	p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n");
532 	p1a(tcps_sc_reset, "\t\t%lu reset\n");
533 	p1a(tcps_sc_stale, "\t\t%lu stale\n");
534 	p1a(tcps_sc_aborted, "\t\t%lu aborted\n");
535 	p1a(tcps_sc_badack, "\t\t%lu badack\n");
536 	p1a(tcps_sc_unreach, "\t\t%lu unreach\n");
537 	p1a(tcps_sc_zonefail, "\t\t%lu zone failures\n");
538 	p1a(tcps_sc_sendcookie, "\t\t%lu cookies sent\n");
539 	p1a(tcps_sc_recvcookie, "\t\t%lu cookies received\n");
540 
541 	p(tcps_sacksbupdate, "\t%lu SACK scoreboard update%s\n");
542 	p(tcps_sacksboverflow, "\t\t%lu overflow%s\n");
543 	p(tcps_sacksbfailed, "\t\t%lu failure%s\n");
544 	p(tcps_sacksbreused, "\t\t%lu record%s reused\n");
545 	p(tcps_sacksbfast, "\t\t%lu record%s fast allocated\n");
546 
547 	free(stattmp);
548 #undef p
549 #undef p1a
550 #undef p2
551 #undef p2a
552 #undef p3
553 }
554 
555 /*
556  * Dump UDP statistics structure.
557  */
558 void
559 udp_stats(u_long off __unused, const char *name, int af1 __unused)
560 {
561 	struct udpstat udpstat, *stattmp;
562 	struct udpstat zerostat[SMP_MAXCPU];
563 	size_t len = sizeof(struct udpstat) * SMP_MAXCPU;
564 	int cpucnt;
565 	u_long delivered;
566 
567 	if (zflag)
568 		memset(&zerostat, 0, len);
569 
570 	if ((stattmp = malloc(len)) == NULL) {
571 		return;
572 	} else {
573 		if (sysctlbyname("net.inet.udp.stats", stattmp, &len,
574 			zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
575 			warn("sysctl: net.inet.udp.stats");
576 			free(stattmp);
577 			return;
578 		} else {
579 			if ((stattmp = realloc(stattmp, len)) == NULL) {
580 				warn("udp_stats");
581 				return;
582 			}
583 		}
584 	}
585 	cpucnt = len / sizeof(struct udpstat);
586 	udp_stats_agg(stattmp, &udpstat, cpucnt);
587 
588 #ifdef INET6
589 	if (udp_done != 0)
590 		return;
591 	else
592 		udp_done = 1;
593 #endif
594 
595 	printf("%s:\n", name);
596 #define	p(f, m) if (udpstat.f || sflag <= 1) \
597     printf(m, udpstat.f, plural(udpstat.f))
598 #define	p1a(f, m) if (udpstat.f || sflag <= 1) \
599     printf(m, udpstat.f)
600 	p(udps_ipackets, "\t%lu datagram%s received\n");
601 	p1a(udps_hdrops, "\t%lu with incomplete header\n");
602 	p1a(udps_badlen, "\t%lu with bad data length field\n");
603 	p1a(udps_badsum, "\t%lu with bad checksum\n");
604 	p1a(udps_nosum, "\t%lu with no checksum\n");
605 	p1a(udps_noport, "\t%lu dropped due to no socket\n");
606 	p(udps_noportbcast,
607 	    "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
608 	p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
609 	p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
610 	delivered = udpstat.udps_ipackets -
611 		    udpstat.udps_hdrops -
612 		    udpstat.udps_badlen -
613 		    udpstat.udps_badsum -
614 		    udpstat.udps_noport -
615 		    udpstat.udps_noportbcast -
616 		    udpstat.udps_fullsock;
617 	if (delivered || sflag <= 1)
618 		printf("\t%lu delivered\n", delivered);
619 	p(udps_opackets, "\t%lu datagram%s output\n");
620 #undef p
621 #undef p1a
622 }
623 
624 /*
625  * Dump CARP statistics structure.
626  */
627 void
628 carp_stats(u_long off __unused, const char *name, int af1 __unused)
629 {
630        struct carpstats carpstat, zerostat;
631        size_t len = sizeof(struct carpstats);
632 
633        if (zflag)
634                memset(&zerostat, 0, len);
635        if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
636            zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
637                warn("sysctl: net.inet.carp.stats");
638                return;
639        }
640 
641        printf("%s:\n", name);
642 
643 #define p(f, m) if (carpstat.f || sflag <= 1) \
644        printf(m, (uintmax_t)carpstat.f, plural((int)carpstat.f))
645 #define p2(f, m) if (carpstat.f || sflag <= 1) \
646        printf(m, (uintmax_t)carpstat.f)
647 
648        p(carps_ipackets, "\t%ju packet%s received (IPv4)\n");
649        p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n");
650        p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n");
651        p(carps_hdrops, "\t\t%ju packet%s shorter than header\n");
652        p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n");
653        p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n");
654        p2(carps_badlen, "\t\t%ju discarded because packet too short\n");
655        p2(carps_badauth, "\t\t%ju discarded for bad authentication\n");
656        p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n");
657        p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n");
658        p(carps_opackets, "\t%ju packet%s sent (IPv4)\n");
659        p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n");
660        p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n");
661 #if notyet
662        p(carps_ostates, "\t\t%s state update%s sent\n");
663 #endif
664 #undef p
665 #undef p2
666 }
667 
668 /*
669  * Dump IP statistics structure.
670  */
671 void
672 ip_stats(u_long off __unused, const char *name, int af1 __unused)
673 {
674 	struct ip_stats ipstat, *stattmp;
675 	struct ip_stats zerostat[SMP_MAXCPU];
676 	size_t len = sizeof(struct ip_stats) * SMP_MAXCPU;
677 	int cpucnt;
678 
679 	if (zflag)
680 		memset(zerostat, 0, len);
681 	if ((stattmp = malloc(len)) == NULL) {
682 		return;
683 	} else {
684 		if (sysctlbyname("net.inet.ip.stats", stattmp, &len,
685 			zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
686 				warn("sysctl: net.inet.ip.stats");
687 				free(stattmp);
688 				return;
689 		} else {
690 			if ((stattmp = realloc(stattmp, len)) == NULL) {
691 				warn("ip_stats");
692 				return;
693 			}
694 		}
695 	}
696 	cpucnt = len / sizeof(struct ip_stats);
697 	ip_stats_agg(stattmp, &ipstat, cpucnt);
698 
699 	printf("%s:\n", name);
700 
701 #define	p(f, m) if (ipstat.f || sflag <= 1) \
702     printf(m, ipstat.f, plural(ipstat.f))
703 #define	p1a(f, m) if (ipstat.f || sflag <= 1) \
704     printf(m, ipstat.f)
705 
706 	p(ips_total, "\t%lu total packet%s received\n");
707 	p(ips_badsum, "\t%lu bad header checksum%s\n");
708 	p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
709 	p1a(ips_tooshort, "\t%lu with data size < data length\n");
710 	p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
711 	p1a(ips_badhlen, "\t%lu with header length < data size\n");
712 	p1a(ips_badlen, "\t%lu with data length < header length\n");
713 	p1a(ips_badoptions, "\t%lu with bad options\n");
714 	p1a(ips_badvers, "\t%lu with incorrect version number\n");
715 	p(ips_fragments, "\t%lu fragment%s received\n");
716 	p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
717 	p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
718 	p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
719 	p(ips_delivered, "\t%lu packet%s for this host\n");
720 	p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
721 	p(ips_forward, "\t%lu packet%s forwarded");
722 	p(ips_fastforward, " (%lu packet%s fast forwarded)");
723 	if (ipstat.ips_forward || sflag <= 1)
724 		putchar('\n');
725 	p(ips_cantforward, "\t%lu packet%s not forwardable\n");
726 	p(ips_notmember,
727 	  "\t%lu packet%s received for unknown multicast group\n");
728 	p(ips_redirectsent, "\t%lu redirect%s sent\n");
729 	p(ips_localout, "\t%lu packet%s sent from this host\n");
730 	p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
731 	p(ips_odropped,
732 	  "\t%lu output packet%s dropped due to no bufs, etc.\n");
733 	p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
734 	p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
735 	p(ips_ofragments, "\t%lu fragment%s created\n");
736 	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
737 	p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
738 	p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
739 	free(stattmp);
740 #undef p
741 #undef p1a
742 }
743 
744 static	const char *icmpnames[] = {
745 	"echo reply",
746 	"#1",
747 	"#2",
748 	"destination unreachable",
749 	"source quench",
750 	"routing redirect",
751 	"#6",
752 	"#7",
753 	"echo",
754 	"router advertisement",
755 	"router solicitation",
756 	"time exceeded",
757 	"parameter problem",
758 	"time stamp",
759 	"time stamp reply",
760 	"information request",
761 	"information request reply",
762 	"address mask request",
763 	"address mask reply",
764 };
765 
766 /*
767  * Dump ICMP statistics.
768  */
769 void
770 icmp_stats(u_long off __unused, const char *name, int af1 __unused)
771 {
772 	struct icmpstat icmpstat, zerostat;
773 	int i, first;
774 	int mib[4];		/* CTL_NET + PF_INET + IPPROTO_ICMP + req */
775 	size_t len;
776 
777 	mib[0] = CTL_NET;
778 	mib[1] = PF_INET;
779 	mib[2] = IPPROTO_ICMP;
780 	mib[3] = ICMPCTL_STATS;
781 
782 	len = sizeof icmpstat;
783 	if (zflag)
784 		memset(&zerostat, 0, len);
785 	if (sysctl(mib, 4, &icmpstat, &len,
786 	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
787 		warn("sysctl: net.inet.icmp.stats");
788 		return;
789 	}
790 
791 	printf("%s:\n", name);
792 
793 #define	p(f, m) if (icmpstat.f || sflag <= 1) \
794     printf(m, icmpstat.f, plural(icmpstat.f))
795 #define	p1a(f, m) if (icmpstat.f || sflag <= 1) \
796     printf(m, icmpstat.f)
797 #define	p2(f, m) if (icmpstat.f || sflag <= 1) \
798     printf(m, icmpstat.f, plurales(icmpstat.f))
799 
800 	p(icps_error, "\t%lu call%s to icmp_error\n");
801 	p(icps_oldicmp,
802 	    "\t%lu error%s not generated 'cuz old message was icmp\n");
803 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
804 		if (icmpstat.icps_outhist[i] != 0) {
805 			if (first) {
806 				printf("\tOutput histogram:\n");
807 				first = 0;
808 			}
809 			printf("\t\t%s: %lu\n", icmpnames[i],
810 				icmpstat.icps_outhist[i]);
811 		}
812 	p(icps_badcode, "\t%lu message%s with bad code fields\n");
813 	p(icps_tooshort, "\t%lu message%s < minimum length\n");
814 	p(icps_checksum, "\t%lu bad checksum%s\n");
815 	p(icps_badlen, "\t%lu message%s with bad length\n");
816 	p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
817 	p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
818 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
819 		if (icmpstat.icps_inhist[i] != 0) {
820 			if (first) {
821 				printf("\tInput histogram:\n");
822 				first = 0;
823 			}
824 			printf("\t\t%s: %lu\n", icmpnames[i],
825 				icmpstat.icps_inhist[i]);
826 		}
827 	p(icps_reflect, "\t%lu message response%s generated\n");
828 	p2(icps_badaddr, "\t%lu invalid return address%s\n");
829 	p(icps_noroute, "\t%lu no return route%s\n");
830 #undef p
831 #undef p1a
832 #undef p2
833 	mib[3] = ICMPCTL_MASKREPL;
834 	len = sizeof i;
835 	if (sysctl(mib, 4, &i, &len, NULL, 0) < 0)
836 		return;
837 	printf("\tICMP address mask responses are %sabled\n",
838 	       i ? "en" : "dis");
839 }
840 
841 /*
842  * Dump IGMP statistics structure.
843  */
844 void
845 igmp_stats(u_long off __unused, const char *name, int af1 __unused)
846 {
847 	struct igmpstat igmpstat, zerostat;
848 	size_t len = sizeof igmpstat;
849 
850 	if (zflag)
851 		memset(&zerostat, 0, len);
852 	if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
853 	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
854 		warn("sysctl: net.inet.igmp.stats");
855 		return;
856 	}
857 
858 	printf("%s:\n", name);
859 
860 #define	p(f, m) if (igmpstat.f || sflag <= 1) \
861     printf(m, igmpstat.f, plural(igmpstat.f))
862 #define	py(f, m) if (igmpstat.f || sflag <= 1) \
863     printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
864 	p(igps_rcv_total, "\t%u message%s received\n");
865         p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
866         p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
867         py(igps_rcv_queries, "\t%u membership quer%s received\n");
868         py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
869         p(igps_rcv_reports, "\t%u membership report%s received\n");
870         p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
871         p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
872         p(igps_snd_reports, "\t%u membership report%s sent\n");
873 #undef p
874 #undef py
875 }
876 
877 /*
878  * Dump PIM statistics structure.
879  */
880 void
881 pim_stats(u_long off __unused, const char *name, int af1 __unused)
882 {
883 	struct pimstat pimstat, zerostat;
884 	size_t len = sizeof pimstat;
885 
886 	if (zflag)
887 		memset(&zerostat, 0, len);
888 	if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
889 	    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
890 		if (errno != ENOENT)
891 			warn("sysctl: net.inet.pim.stats");
892 		return;
893 	}
894 
895 	printf("%s:\n", name);
896 
897 #define	p(f, m) if (pimstat.f || sflag <= 1) \
898     printf(m, (uintmax_t)pimstat.f, plural(pimstat.f))
899 #define	py(f, m) if (pimstat.f || sflag <= 1) \
900     printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y")
901 	p(pims_rcv_total_msgs, "\t%ju message%s received\n");
902 	p(pims_rcv_total_bytes, "\t%ju byte%s received\n");
903 	p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
904         p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n");
905 	p(pims_rcv_badversion, "\t%ju message%s received with bad version\n");
906 	p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n");
907 	p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n");
908 	p(pims_rcv_registers_wrongiif, "\t%ju data register message%s received on wrong iif\n");
909 	p(pims_rcv_badregisters, "\t%ju bad register%s received\n");
910 	p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n");
911 	p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n");
912 #undef p
913 #undef py
914 }
915 
916 /*
917  * Pretty print an Internet address (net address + port).
918  */
919 void
920 inetprint(struct in_addr *in, int port, const char *proto, int num_port)
921 {
922 	struct servent *sp = NULL;
923 	char line[80], *cp;
924 	int width;
925 
926 	if (Wflag)
927 	    sprintf(line, "%s.", inetname(in));
928 	else
929 	    sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in));
930 	cp = strchr(line, '\0');
931 	if (!num_port && port)
932 		sp = getservbyport((int)port, proto);
933 	if (sp || port == 0)
934 		sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
935 	else
936 		sprintf(cp, "%d ", ntohs((u_short)port));
937 	width = (Aflag && !Wflag) ? 17 : 21;
938 	if (Wflag)
939 	    printf("%-*s ", width, line);
940 	else
941 	    printf("%-*.*s ", width, width, line);
942 }
943 
944 /*
945  * Construct an Internet address representation.
946  * If numeric_addr has been supplied, give
947  * numeric value, otherwise try for symbolic name.
948  */
949 char *
950 inetname(struct in_addr *inp)
951 {
952 	char *cp;
953 	static char line[MAXHOSTNAMELEN];
954 	struct hostent *hp;
955 	struct netent *np;
956 
957 	cp = NULL;
958 	if (!numeric_addr && inp->s_addr != INADDR_ANY) {
959 		int net = inet_netof(*inp);
960 		int lna = inet_lnaof(*inp);
961 
962 		if (lna == INADDR_ANY) {
963 			np = getnetbyaddr(net, AF_INET);
964 			if (np)
965 				cp = np->n_name;
966 		}
967 		if (cp == NULL) {
968 			hp = gethostbyaddr(inp, sizeof (*inp), AF_INET);
969 			if (hp) {
970 				cp = hp->h_name;
971 				trimdomain(cp, strlen(cp));
972 			}
973 		}
974 	}
975 	if (inp->s_addr == INADDR_ANY)
976 		strcpy(line, "*");
977 	else if (cp) {
978 		strncpy(line, cp, sizeof(line) - 1);
979 		line[sizeof(line) - 1] = '\0';
980 	} else {
981 		inp->s_addr = ntohl(inp->s_addr);
982 #define C(x)	((u_int)((x) & 0xff))
983 		sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
984 		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
985 	}
986 	return (line);
987 }
988