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