xref: /netbsd-src/usr.bin/netstat/inet.c (revision cb861154c176d3dcc8ff846f449e3c16a5f5edb5)
1 /*	$NetBSD: inet.c,v 1.95 2011/03/02 19:52:03 dyoung Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1988, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "from: @(#)inet.c	8.4 (Berkeley) 4/20/94";
36 #else
37 __RCSID("$NetBSD: inet.c,v 1.95 2011/03/02 19:52:03 dyoung Exp $");
38 #endif
39 #endif /* not lint */
40 
41 #define	_CALLOUT_PRIVATE	/* for defs in sys/callout.h */
42 
43 #include <sys/param.h>
44 #include <sys/queue.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/mbuf.h>
48 #include <sys/protosw.h>
49 #include <sys/sysctl.h>
50 
51 #include <net/if_arp.h>
52 #include <net/route.h>
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #include <netinet/in_pcb.h>
57 #include <netinet/ip_icmp.h>
58 
59 #ifdef INET6
60 #include <netinet/ip6.h>
61 #endif
62 
63 #include <netinet/icmp_var.h>
64 #include <netinet/igmp_var.h>
65 #include <netinet/ip_var.h>
66 #include <netinet/pim_var.h>
67 #include <netinet/tcp.h>
68 #include <netinet/tcpip.h>
69 #include <netinet/tcp_seq.h>
70 #define TCPSTATES
71 #include <netinet/tcp_fsm.h>
72 #define	TCPTIMERS
73 #include <netinet/tcp_timer.h>
74 #include <netinet/tcp_var.h>
75 #include <netinet/tcp_debug.h>
76 #include <netinet/udp.h>
77 #include <netinet/ip_carp.h>
78 #include <netinet/udp_var.h>
79 
80 #include <arpa/inet.h>
81 #include <kvm.h>
82 #include <netdb.h>
83 #include <stdio.h>
84 #include <string.h>
85 #include <unistd.h>
86 #include <stdlib.h>
87 #include <err.h>
88 #include "netstat.h"
89 #include "prog_ops.h"
90 
91 char	*inetname(struct in_addr *);
92 void	inetprint(struct in_addr *, u_int16_t, const char *, int);
93 
94 /*
95  * Print a summary of connections related to an Internet
96  * protocol.  For TCP, also give state of connection.
97  * Listening processes (aflag) are suppressed unless the
98  * -a (all) flag is specified.
99  */
100 static int width;
101 static int compact;
102 
103 static void
104 protoprhdr(void)
105 {
106 	printf("Active Internet connections");
107 	if (aflag)
108 		printf(" (including servers)");
109 	putchar('\n');
110 	if (Aflag)
111 		printf("%-8.8s ", "PCB");
112 	printf("%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n",
113 		"Proto", "Recv-Q", "Send-Q", compact ? "" : " ",
114 		width, width, "Local Address",
115 		width, width, "Foreign Address",
116 		"State");
117 }
118 
119 static void
120 protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc,
121 	 struct in_addr *laddr, u_int16_t lport,
122 	 struct in_addr *faddr, u_int16_t fport,
123 	 short t_state, const char *name, int inp_flags)
124 {
125 	static const char *shorttcpstates[] = {
126 		"CLOSED",	"LISTEN",	"SYNSEN",	"SYSRCV",
127 		"ESTABL",	"CLWAIT",	"FWAIT1",	"CLOSNG",
128 		"LASTAK",	"FWAIT2",	"TMWAIT",
129 	};
130 	int istcp;
131 
132 	istcp = strcmp(name, "tcp") == 0;
133 
134 	if (Aflag) {
135 		printf("%8" PRIxPTR " ", ppcb);
136 	}
137 	printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc,
138 	       compact ? "" : " ");
139 	if (numeric_port) {
140 		inetprint(laddr, lport, name, 1);
141 		inetprint(faddr, fport, name, 1);
142 	} else if (inp_flags & INP_ANONPORT) {
143 		inetprint(laddr, lport, name, 1);
144 		inetprint(faddr, fport, name, 0);
145 	} else {
146 		inetprint(laddr, lport, name, 0);
147 		inetprint(faddr, fport, name, 0);
148 	}
149 	if (istcp) {
150 		if (t_state < 0 || t_state >= TCP_NSTATES)
151 			printf(" %d", t_state);
152 		else
153 			printf(" %s", compact ? shorttcpstates[t_state] :
154 			       tcpstates[t_state]);
155 	}
156 	putchar('\n');
157 }
158 
159 void
160 protopr(u_long off, const char *name)
161 {
162 	struct inpcbtable table;
163 	struct inpcb *head, *next, *prev;
164 	struct inpcb inpcb;
165 	struct tcpcb tcpcb;
166 	struct socket sockb;
167 	int istcp;
168 	static int first = 1;
169 
170 	compact = 0;
171 	if (Aflag) {
172 		if (!numeric_addr)
173 			width = 18;
174 		else {
175 			width = 21;
176 			compact = 1;
177 		}
178 	} else
179 		width = 22;
180 
181 	if (use_sysctl) {
182 		struct kinfo_pcb *pcblist;
183 		int mib[8];
184 		size_t namelen = 0, size = 0, i;
185 		char *mibname = NULL;
186 
187 		memset(mib, 0, sizeof(mib));
188 
189 		if (asprintf(&mibname, "net.inet.%s.pcblist", name) == -1)
190 			err(1, "asprintf");
191 
192 		/* get dynamic pcblist node */
193 		if (sysctlnametomib(mibname, mib, &namelen) == -1)
194 			err(1, "sysctlnametomib: %s", mibname);
195 
196 		if (prog_sysctl(mib, __arraycount(mib),
197 		    NULL, &size, NULL, 0) == -1)
198 			err(1, "sysctl (query)");
199 
200 		if ((pcblist = malloc(size)) == NULL)
201 			err(1, "malloc");
202 		memset(pcblist, 0, size);
203 
204 	        mib[6] = sizeof(*pcblist);
205         	mib[7] = size / sizeof(*pcblist);
206 
207 		if (prog_sysctl(mib, __arraycount(mib),
208 		    pcblist, &size, NULL, 0) == -1)
209 			err(1, "sysctl (copy)");
210 
211 		for (i = 0; i < size / sizeof(*pcblist); i++) {
212 			struct sockaddr_in src, dst;
213 
214 			memcpy(&src, &pcblist[i].ki_s, sizeof(src));
215 			memcpy(&dst, &pcblist[i].ki_d, sizeof(dst));
216 
217 			if (!aflag &&
218 			    inet_lnaof(dst.sin_addr) == INADDR_ANY)
219 				continue;
220 
221 			if (first) {
222 				protoprhdr();
223 				first = 0;
224 			}
225 
226 	                protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
227 				 pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
228 				 &src.sin_addr, src.sin_port,
229 				 &dst.sin_addr, dst.sin_port,
230 				 pcblist[i].ki_tstate, name,
231 				 pcblist[i].ki_pflags);
232 		}
233 
234 		free(pcblist);
235 		return;
236 	}
237 
238 	if (off == 0)
239 		return;
240 	istcp = strcmp(name, "tcp") == 0;
241 	kread(off, (char *)&table, sizeof table);
242 	prev = head =
243 	    (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
244 	next = (struct inpcb *)table.inpt_queue.cqh_first;
245 
246 	while (next != head) {
247 		kread((u_long)next, (char *)&inpcb, sizeof inpcb);
248 		if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) {
249 			printf("???\n");
250 			break;
251 		}
252 		prev = next;
253 		next = (struct inpcb *)inpcb.inp_queue.cqe_next;
254 
255 		if (inpcb.inp_af != AF_INET)
256 			continue;
257 
258 		if (!aflag &&
259 		    inet_lnaof(inpcb.inp_faddr) == INADDR_ANY)
260 			continue;
261 		kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
262 		if (istcp) {
263 			kread((u_long)inpcb.inp_ppcb,
264 			    (char *)&tcpcb, sizeof (tcpcb));
265 		}
266 
267 		if (first) {
268 			protoprhdr();
269 			first = 0;
270 		}
271 
272 		protopr0(istcp ? (intptr_t) inpcb.inp_ppcb : (intptr_t) prev,
273 			 sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc,
274 			 &inpcb.inp_laddr, inpcb.inp_lport,
275 			 &inpcb.inp_faddr, inpcb.inp_fport,
276 			 tcpcb.t_state, name, inpcb.inp_flags);
277 	}
278 }
279 
280 /*
281  * Dump TCP statistics structure.
282  */
283 void
284 tcp_stats(u_long off, const char *name)
285 {
286 	uint64_t tcpstat[TCP_NSTATS];
287 
288 	if (use_sysctl) {
289 		size_t size = sizeof(tcpstat);
290 
291 		if (sysctlbyname("net.inet.tcp.stats", tcpstat, &size,
292 				 NULL, 0) == -1)
293 			return;
294 	} else {
295 		warnx("%s stats not available via KVM.", name);
296 		return;
297 	}
298 
299 	printf ("%s:\n", name);
300 
301 #define	ps(f, m) if (tcpstat[f] || sflag <= 1) \
302     printf(m, tcpstat[f])
303 #define	p(f, m) if (tcpstat[f] || sflag <= 1) \
304     printf(m, tcpstat[f], plural(tcpstat[f]))
305 #define	p2(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
306     printf(m, tcpstat[f1], plural(tcpstat[f1]), \
307     tcpstat[f2], plural(tcpstat[f2]))
308 #define	p2s(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
309     printf(m, tcpstat[f1], plural(tcpstat[f1]), \
310     tcpstat[f2])
311 #define	p3(f, m) if (tcpstat[f] || sflag <= 1) \
312     printf(m, tcpstat[f], plurales(tcpstat[f]))
313 
314 	p(TCP_STAT_SNDTOTAL, "\t%" PRIu64 " packet%s sent\n");
315 	p2(TCP_STAT_SNDPACK,TCP_STAT_SNDBYTE,
316 		"\t\t%" PRIu64 " data packet%s (%" PRIu64 " byte%s)\n");
317 	p2(TCP_STAT_SNDREXMITPACK, TCP_STAT_SNDREXMITBYTE,
318 		"\t\t%" PRIu64 " data packet%s (%" PRIu64 " byte%s) retransmitted\n");
319 	p2s(TCP_STAT_SNDACKS, TCP_STAT_DELACK,
320 		"\t\t%" PRIu64 " ack-only packet%s (%" PRIu64 " delayed)\n");
321 	p(TCP_STAT_SNDURG, "\t\t%" PRIu64 " URG only packet%s\n");
322 	p(TCP_STAT_SNDPROBE, "\t\t%" PRIu64 " window probe packet%s\n");
323 	p(TCP_STAT_SNDWINUP, "\t\t%" PRIu64 " window update packet%s\n");
324 	p(TCP_STAT_SNDCTRL, "\t\t%" PRIu64 " control packet%s\n");
325 	p(TCP_STAT_SELFQUENCH,
326 	    "\t\t%" PRIu64 " send attempt%s resulted in self-quench\n");
327 	p(TCP_STAT_RCVTOTAL, "\t%" PRIu64 " packet%s received\n");
328 	p2(TCP_STAT_RCVACKPACK, TCP_STAT_RCVACKBYTE,
329 		"\t\t%" PRIu64 " ack%s (for %" PRIu64 " byte%s)\n");
330 	p(TCP_STAT_RCVDUPACK, "\t\t%" PRIu64 " duplicate ack%s\n");
331 	p(TCP_STAT_RCVACKTOOMUCH, "\t\t%" PRIu64 " ack%s for unsent data\n");
332 	p2(TCP_STAT_RCVPACK, TCP_STAT_RCVBYTE,
333 		"\t\t%" PRIu64 " packet%s (%" PRIu64 " byte%s) received in-sequence\n");
334 	p2(TCP_STAT_RCVDUPPACK, TCP_STAT_RCVDUPBYTE,
335 		"\t\t%" PRIu64 " completely duplicate packet%s (%" PRIu64 " byte%s)\n");
336 	p(TCP_STAT_PAWSDROP, "\t\t%" PRIu64 " old duplicate packet%s\n");
337 	p2(TCP_STAT_RCVPARTDUPPACK, TCP_STAT_RCVPARTDUPBYTE,
338 		"\t\t%" PRIu64 " packet%s with some dup. data (%" PRIu64 " byte%s duped)\n");
339 	p2(TCP_STAT_RCVOOPACK, TCP_STAT_RCVOOBYTE,
340 		"\t\t%" PRIu64 " out-of-order packet%s (%" PRIu64 " byte%s)\n");
341 	p2(TCP_STAT_RCVPACKAFTERWIN, TCP_STAT_RCVBYTEAFTERWIN,
342 		"\t\t%" PRIu64 " packet%s (%" PRIu64 " byte%s) of data after window\n");
343 	p(TCP_STAT_RCVWINPROBE, "\t\t%" PRIu64 " window probe%s\n");
344 	p(TCP_STAT_RCVWINUPD, "\t\t%" PRIu64 " window update packet%s\n");
345 	p(TCP_STAT_RCVAFTERCLOSE, "\t\t%" PRIu64 " packet%s received after close\n");
346 	p(TCP_STAT_RCVBADSUM, "\t\t%" PRIu64 " discarded for bad checksum%s\n");
347 	p(TCP_STAT_RCVBADOFF, "\t\t%" PRIu64 " discarded for bad header offset field%s\n");
348 	ps(TCP_STAT_RCVSHORT, "\t\t%" PRIu64 " discarded because packet too short\n");
349 	p(TCP_STAT_CONNATTEMPT, "\t%" PRIu64 " connection request%s\n");
350 	p(TCP_STAT_ACCEPTS, "\t%" PRIu64 " connection accept%s\n");
351 	p(TCP_STAT_CONNECTS,
352 		"\t%" PRIu64 " connection%s established (including accepts)\n");
353 	p2(TCP_STAT_CLOSED, TCP_STAT_DROPS,
354 		"\t%" PRIu64 " connection%s closed (including %" PRIu64 " drop%s)\n");
355 	p(TCP_STAT_CONNDROPS, "\t%" PRIu64 " embryonic connection%s dropped\n");
356 	p(TCP_STAT_DELAYED_FREE, "\t%" PRIu64 " delayed free%s of tcpcb\n");
357 	p2(TCP_STAT_RTTUPDATED, TCP_STAT_SEGSTIMED,
358 		"\t%" PRIu64 " segment%s updated rtt (of %" PRIu64 " attempt%s)\n");
359 	p(TCP_STAT_REXMTTIMEO, "\t%" PRIu64 " retransmit timeout%s\n");
360 	p(TCP_STAT_TIMEOUTDROP,
361 		"\t\t%" PRIu64 " connection%s dropped by rexmit timeout\n");
362 	p2(TCP_STAT_PERSISTTIMEO, TCP_STAT_PERSISTDROPS,
363 	   "\t%" PRIu64 " persist timeout%s (resulting in %" PRIu64 " dropped "
364 		"connection%s)\n");
365 	p(TCP_STAT_KEEPTIMEO, "\t%" PRIu64 " keepalive timeout%s\n");
366 	p(TCP_STAT_KEEPPROBE, "\t\t%" PRIu64 " keepalive probe%s sent\n");
367 	p(TCP_STAT_KEEPDROPS, "\t\t%" PRIu64 " connection%s dropped by keepalive\n");
368 	p(TCP_STAT_PREDACK, "\t%" PRIu64 " correct ACK header prediction%s\n");
369 	p(TCP_STAT_PREDDAT, "\t%" PRIu64 " correct data packet header prediction%s\n");
370 	p3(TCP_STAT_PCBHASHMISS, "\t%" PRIu64 " PCB hash miss%s\n");
371 	ps(TCP_STAT_NOPORT, "\t%" PRIu64 " dropped due to no socket\n");
372 	p(TCP_STAT_CONNSDRAINED, "\t%" PRIu64 " connection%s drained due to memory "
373 		"shortage\n");
374 	p(TCP_STAT_PMTUBLACKHOLE, "\t%" PRIu64 " PMTUD blackhole%s detected\n");
375 
376 	p(TCP_STAT_BADSYN, "\t%" PRIu64 " bad connection attempt%s\n");
377 	ps(TCP_STAT_SC_ADDED, "\t%" PRIu64 " SYN cache entries added\n");
378 	p(TCP_STAT_SC_COLLISIONS, "\t\t%" PRIu64 " hash collision%s\n");
379 	ps(TCP_STAT_SC_COMPLETED, "\t\t%" PRIu64 " completed\n");
380 	ps(TCP_STAT_SC_ABORTED, "\t\t%" PRIu64 " aborted (no space to build PCB)\n");
381 	ps(TCP_STAT_SC_TIMED_OUT, "\t\t%" PRIu64 " timed out\n");
382 	ps(TCP_STAT_SC_OVERFLOWED, "\t\t%" PRIu64 " dropped due to overflow\n");
383 	ps(TCP_STAT_SC_BUCKETOVERFLOW, "\t\t%" PRIu64 " dropped due to bucket overflow\n");
384 	ps(TCP_STAT_SC_RESET, "\t\t%" PRIu64 " dropped due to RST\n");
385 	ps(TCP_STAT_SC_UNREACH, "\t\t%" PRIu64 " dropped due to ICMP unreachable\n");
386 	ps(TCP_STAT_SC_DELAYED_FREE, "\t\t%" PRIu64 " delayed free of SYN cache "
387 		"entries\n");
388 	p(TCP_STAT_SC_RETRANSMITTED, "\t%" PRIu64 " SYN,ACK%s retransmitted\n");
389 	p(TCP_STAT_SC_DUPESYN, "\t%" PRIu64 " duplicate SYN%s received for entries "
390 		"already in the cache\n");
391 	p(TCP_STAT_SC_DROPPED, "\t%" PRIu64 " SYN%s dropped (no route or no space)\n");
392 	p(TCP_STAT_BADSIG, "\t%" PRIu64 " packet%s with bad signature\n");
393 	p(TCP_STAT_GOODSIG, "\t%" PRIu64 " packet%s with good signature\n");
394 
395 	p(TCP_STAT_ECN_SHS, "\t%" PRIu64 " successful ECN handshake%s\n");
396 	p(TCP_STAT_ECN_CE, "\t%" PRIu64 " packet%s with ECN CE bit\n");
397 	p(TCP_STAT_ECN_ECT, "\t%" PRIu64 " packet%s ECN ECT(0) bit\n");
398 #undef p
399 #undef ps
400 #undef p2
401 #undef p2s
402 #undef p3
403 }
404 
405 /*
406  * Dump UDP statistics structure.
407  */
408 void
409 udp_stats(u_long off, const char *name)
410 {
411 	uint64_t udpstat[UDP_NSTATS];
412 	u_quad_t delivered;
413 
414 	if (use_sysctl) {
415 		size_t size = sizeof(udpstat);
416 
417 		if (sysctlbyname("net.inet.udp.stats", udpstat, &size,
418 				 NULL, 0) == -1)
419 			return;
420 	} else {
421 		warnx("%s stats not available via KVM.", name);
422 		return;
423 	}
424 
425 	printf ("%s:\n", name);
426 
427 #define	ps(f, m) if (udpstat[f] || sflag <= 1) \
428     printf(m, udpstat[f])
429 #define	p(f, m) if (udpstat[f] || sflag <= 1) \
430     printf(m, udpstat[f], plural(udpstat[f]))
431 #define	p3(f, m) if (udpstat[f] || sflag <= 1) \
432     printf(m, udpstat[f], plurales(udpstat[f]))
433 
434 	p(UDP_STAT_IPACKETS, "\t%" PRIu64 " datagram%s received\n");
435 	ps(UDP_STAT_HDROPS, "\t%" PRIu64 " with incomplete header\n");
436 	ps(UDP_STAT_BADLEN, "\t%" PRIu64 " with bad data length field\n");
437 	ps(UDP_STAT_BADSUM, "\t%" PRIu64 " with bad checksum\n");
438 	ps(UDP_STAT_NOPORT, "\t%" PRIu64 " dropped due to no socket\n");
439 	p(UDP_STAT_NOPORTBCAST,
440 	  "\t%" PRIu64 " broadcast/multicast datagram%s dropped due to no socket\n");
441 	ps(UDP_STAT_FULLSOCK, "\t%" PRIu64 " dropped due to full socket buffers\n");
442 	delivered = udpstat[UDP_STAT_IPACKETS] -
443 		    udpstat[UDP_STAT_HDROPS] -
444 		    udpstat[UDP_STAT_BADLEN] -
445 		    udpstat[UDP_STAT_BADSUM] -
446 		    udpstat[UDP_STAT_NOPORT] -
447 		    udpstat[UDP_STAT_NOPORTBCAST] -
448 		    udpstat[UDP_STAT_FULLSOCK];
449 	if (delivered || sflag <= 1)
450 		printf("\t%" PRIu64 " delivered\n", delivered);
451 	p3(UDP_STAT_PCBHASHMISS, "\t%" PRIu64 " PCB hash miss%s\n");
452 	p(UDP_STAT_OPACKETS, "\t%" PRIu64 " datagram%s output\n");
453 
454 #undef ps
455 #undef p
456 #undef p3
457 }
458 
459 /*
460  * Dump IP statistics structure.
461  */
462 void
463 ip_stats(u_long off, const char *name)
464 {
465 	uint64_t ipstat[IP_NSTATS];
466 
467 	if (use_sysctl) {
468 		size_t size = sizeof(ipstat);
469 
470 		if (sysctlbyname("net.inet.ip.stats", ipstat, &size,
471 				 NULL, 0) == -1)
472 			return;
473 	} else {
474 		warnx("%s stats not available via KVM.", name);
475 		return;
476 	}
477 
478 	printf("%s:\n", name);
479 
480 #define	ps(f, m) if (ipstat[f] || sflag <= 1) \
481     printf(m, ipstat[f])
482 #define	p(f, m) if (ipstat[f] || sflag <= 1) \
483     printf(m, ipstat[f], plural(ipstat[f]))
484 
485 	p(IP_STAT_TOTAL, "\t%" PRIu64 " total packet%s received\n");
486 	p(IP_STAT_BADSUM, "\t%" PRIu64 " bad header checksum%s\n");
487 	ps(IP_STAT_TOOSMALL, "\t%" PRIu64 " with size smaller than minimum\n");
488 	ps(IP_STAT_TOOSHORT, "\t%" PRIu64 " with data size < data length\n");
489 	ps(IP_STAT_TOOLONG, "\t%" PRIu64 " with length > max ip packet size\n");
490 	ps(IP_STAT_BADHLEN, "\t%" PRIu64 " with header length < data size\n");
491 	ps(IP_STAT_BADLEN, "\t%" PRIu64 " with data length < header length\n");
492 	ps(IP_STAT_BADOPTIONS, "\t%" PRIu64 " with bad options\n");
493 	ps(IP_STAT_BADVERS, "\t%" PRIu64 " with incorrect version number\n");
494 	p(IP_STAT_FRAGMENTS, "\t%" PRIu64 " fragment%s received\n");
495 	p(IP_STAT_FRAGDROPPED, "\t%" PRIu64 " fragment%s dropped (dup or out of space)\n");
496 	p(IP_STAT_RCVMEMDROP, "\t%" PRIu64 " fragment%s dropped (out of ipqent)\n");
497 	p(IP_STAT_BADFRAGS, "\t%" PRIu64 " malformed fragment%s dropped\n");
498 	p(IP_STAT_FRAGTIMEOUT, "\t%" PRIu64 " fragment%s dropped after timeout\n");
499 	p(IP_STAT_REASSEMBLED, "\t%" PRIu64 " packet%s reassembled ok\n");
500 	p(IP_STAT_DELIVERED, "\t%" PRIu64 " packet%s for this host\n");
501 	p(IP_STAT_NOPROTO, "\t%" PRIu64 " packet%s for unknown/unsupported protocol\n");
502 	p(IP_STAT_FORWARD, "\t%" PRIu64 " packet%s forwarded");
503 	p(IP_STAT_FASTFORWARD, " (%" PRIu64 " packet%s fast forwarded)");
504 	if (ipstat[IP_STAT_FORWARD] || sflag <= 1)
505 		putchar('\n');
506 	p(IP_STAT_CANTFORWARD, "\t%" PRIu64 " packet%s not forwardable\n");
507 	p(IP_STAT_REDIRECTSENT, "\t%" PRIu64 " redirect%s sent\n");
508 	p(IP_STAT_NOGIF, "\t%" PRIu64 " packet%s no matching gif found\n");
509 	p(IP_STAT_LOCALOUT, "\t%" PRIu64 " packet%s sent from this host\n");
510 	p(IP_STAT_RAWOUT, "\t%" PRIu64 " packet%s sent with fabricated ip header\n");
511 	p(IP_STAT_ODROPPED, "\t%" PRIu64 " output packet%s dropped due to no bufs, etc.\n");
512 	p(IP_STAT_NOROUTE, "\t%" PRIu64 " output packet%s discarded due to no route\n");
513 	p(IP_STAT_FRAGMENTED, "\t%" PRIu64 " output datagram%s fragmented\n");
514 	p(IP_STAT_OFRAGMENTS, "\t%" PRIu64 " fragment%s created\n");
515 	p(IP_STAT_CANTFRAG, "\t%" PRIu64 " datagram%s that can't be fragmented\n");
516 	p(IP_STAT_BADADDR, "\t%" PRIu64 " datagram%s with bad address in header\n");
517 #undef ps
518 #undef p
519 }
520 
521 static	const char *icmpnames[] = {
522 	"echo reply",
523 	"#1",
524 	"#2",
525 	"destination unreachable",
526 	"source quench",
527 	"routing redirect",
528 	"alternate host address",
529 	"#7",
530 	"echo",
531 	"router advertisement",
532 	"router solicitation",
533 	"time exceeded",
534 	"parameter problem",
535 	"time stamp",
536 	"time stamp reply",
537 	"information request",
538 	"information request reply",
539 	"address mask request",
540 	"address mask reply",
541 };
542 
543 /*
544  * Dump ICMP statistics.
545  */
546 void
547 icmp_stats(u_long off, const char *name)
548 {
549 	uint64_t icmpstat[ICMP_NSTATS];
550 	int i, first;
551 
552 	if (use_sysctl) {
553 		size_t size = sizeof(icmpstat);
554 
555 		if (sysctlbyname("net.inet.icmp.stats", icmpstat, &size,
556 				 NULL, 0) == -1)
557 			return;
558 	} else {
559 		warnx("%s stats not available via KVM.", name);
560 		return;
561 	}
562 
563 	printf("%s:\n", name);
564 
565 #define	p(f, m) if (icmpstat[f] || sflag <= 1) \
566     printf(m, icmpstat[f], plural(icmpstat[f]))
567 
568 	p(ICMP_STAT_ERROR, "\t%" PRIu64 " call%s to icmp_error\n");
569 	p(ICMP_STAT_OLDICMP,
570 	    "\t%" PRIu64 " error%s not generated because old message was icmp\n");
571 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
572 		if (icmpstat[ICMP_STAT_OUTHIST + i] != 0) {
573 			if (first) {
574 				printf("\tOutput histogram:\n");
575 				first = 0;
576 			}
577 			printf("\t\t%s: %" PRIu64 "\n", icmpnames[i],
578 			   icmpstat[ICMP_STAT_OUTHIST + i]);
579 		}
580 	p(ICMP_STAT_BADCODE, "\t%" PRIu64 " message%s with bad code fields\n");
581 	p(ICMP_STAT_TOOSHORT, "\t%" PRIu64 " message%s < minimum length\n");
582 	p(ICMP_STAT_CHECKSUM, "\t%" PRIu64 " bad checksum%s\n");
583 	p(ICMP_STAT_BADLEN, "\t%" PRIu64 " message%s with bad length\n");
584 	p(ICMP_STAT_BMCASTECHO, "\t%" PRIu64 " multicast echo request%s ignored\n");
585 	p(ICMP_STAT_BMCASTTSTAMP, "\t%" PRIu64 " multicast timestamp request%s ignored\n");
586 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
587 		if (icmpstat[ICMP_STAT_INHIST + i] != 0) {
588 			if (first) {
589 				printf("\tInput histogram:\n");
590 				first = 0;
591 			}
592 			printf("\t\t%s: %" PRIu64 "\n", icmpnames[i],
593 			    icmpstat[ICMP_STAT_INHIST + i]);
594 		}
595 	p(ICMP_STAT_REFLECT, "\t%" PRIu64 " message response%s generated\n");
596 	p(ICMP_STAT_PMTUCHG, "\t%" PRIu64 " path MTU change%s\n");
597 #undef p
598 }
599 
600 /*
601  * Dump IGMP statistics structure.
602  */
603 void
604 igmp_stats(u_long off, const char *name)
605 {
606 	uint64_t igmpstat[IGMP_NSTATS];
607 
608 	if (use_sysctl) {
609 		size_t size = sizeof(igmpstat);
610 
611 		if (sysctlbyname("net.inet.igmp.stats", igmpstat, &size,
612 				 NULL, 0) == -1)
613 			return;
614 	} else {
615 		warnx("%s stats not available via KVM.", name);
616 		return;
617 	}
618 
619 	printf("%s:\n", name);
620 
621 #define	p(f, m) if (igmpstat[f] || sflag <= 1) \
622     printf(m, igmpstat[f], plural(igmpstat[f]))
623 #define	py(f, m) if (igmpstat[f] || sflag <= 1) \
624     printf(m, igmpstat[f], igmpstat[f] != 1 ? "ies" : "y")
625 	p(IGMP_STAT_RCV_TOTAL, "\t%" PRIu64 " message%s received\n");
626         p(IGMP_STAT_RCV_TOOSHORT, "\t%" PRIu64 " message%s received with too few bytes\n");
627         p(IGMP_STAT_RCV_BADSUM, "\t%" PRIu64 " message%s received with bad checksum\n");
628         py(IGMP_STAT_RCV_QUERIES, "\t%" PRIu64 " membership quer%s received\n");
629         py(IGMP_STAT_RCV_BADQUERIES, "\t%" PRIu64 " membership quer%s received with invalid field(s)\n");
630         p(IGMP_STAT_RCV_REPORTS, "\t%" PRIu64 " membership report%s received\n");
631         p(IGMP_STAT_RCV_BADREPORTS, "\t%" PRIu64 " membership report%s received with invalid field(s)\n");
632         p(IGMP_STAT_RCV_OURREPORTS, "\t%" PRIu64 " membership report%s received for groups to which we belong\n");
633         p(IGMP_STAT_SND_REPORTS, "\t%" PRIu64 " membership report%s sent\n");
634 #undef p
635 #undef py
636 }
637 
638 /*
639  * Dump CARP statistics structure.
640  */
641 void
642 carp_stats(u_long off, const char *name)
643 {
644 	uint64_t carpstat[CARP_NSTATS];
645 
646 	if (use_sysctl) {
647 		size_t size = sizeof(carpstat);
648 
649 		if (sysctlbyname("net.inet.carp.stats", carpstat, &size,
650 				 NULL, 0) == -1)
651 			return;
652 	} else {
653 		warnx("%s stats not available via KVM.", name);
654 		return;
655 	}
656 
657 	printf("%s:\n", name);
658 
659 #define p(f, m) if (carpstat[f] || sflag <= 1) \
660 	printf(m, carpstat[f], plural(carpstat[f]))
661 #define p2(f, m) if (carpstat[f] || sflag <= 1) \
662 	printf(m, carpstat[f])
663 
664 	p(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n");
665 	p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n");
666 	p(CARP_STAT_BADIF,
667 	    "\t\t%" PRIu64 " packet%s discarded for bad interface\n");
668 	p(CARP_STAT_BADTTL,
669 	    "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n");
670 	p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n");
671 	p(CARP_STAT_BADSUM, "\t\t%" PRIu64
672 		" packet%s discarded for bad checksum\n");
673 	p(CARP_STAT_BADVER,
674 	    "\t\t%" PRIu64 " packet%s discarded with a bad version\n");
675 	p2(CARP_STAT_BADLEN,
676 	    "\t\t%" PRIu64 " discarded because packet was too short\n");
677 	p(CARP_STAT_BADAUTH,
678 	    "\t\t%" PRIu64 " packet%s discarded for bad authentication\n");
679 	p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n");
680 	p(CARP_STAT_BADADDRS, "\t\t%" PRIu64
681 		" packet%s discarded because of a bad address list\n");
682 	p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n");
683 	p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n");
684 	p2(CARP_STAT_ONOMEM,
685 	    "\t\t%" PRIu64 " send failed due to mbuf memory error\n");
686 #undef p
687 #undef p2
688 }
689 
690 /*
691  * Dump PIM statistics structure.
692  */
693 void
694 pim_stats(u_long off, const char *name)
695 {
696 	struct pimstat pimstat;
697 
698 	if (off == 0)
699 		return;
700 	if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) {
701 		/* XXX: PIM is probably not enabled in the kernel */
702 		return;
703 	}
704 
705 	printf("%s:\n", name);
706 
707 #define	p(f, m) if (pimstat.f || sflag <= 1) \
708 	printf(m, pimstat.f, plural(pimstat.f))
709 
710 	p(pims_rcv_total_msgs, "\t%" PRIu64 " message%s received\n");
711 	p(pims_rcv_total_bytes, "\t%" PRIu64 " byte%s received\n");
712 	p(pims_rcv_tooshort, "\t%" PRIu64 " message%s received with too few bytes\n");
713         p(pims_rcv_badsum, "\t%" PRIu64 " message%s received with bad checksum\n");
714 	p(pims_rcv_badversion, "\t%" PRIu64 " message%s received with bad version\n");
715 	p(pims_rcv_registers_msgs, "\t%" PRIu64 " data register message%s received\n");
716 	p(pims_rcv_registers_bytes, "\t%" PRIu64 " data register byte%s received\n");
717 	p(pims_rcv_registers_wrongiif, "\t%" PRIu64 " data register message%s received on wrong iif\n");
718 	p(pims_rcv_badregisters, "\t%" PRIu64 " bad register%s received\n");
719 	p(pims_snd_registers_msgs, "\t%" PRIu64 " data register message%s sent\n");
720 	p(pims_snd_registers_bytes, "\t%" PRIu64 " data register byte%s sent\n");
721 #undef p
722 }
723 
724 /*
725  * Dump the ARP statistics structure.
726  */
727 void
728 arp_stats(u_long off, const char *name)
729 {
730 	uint64_t arpstat[ARP_NSTATS];
731 
732 	if (use_sysctl) {
733 		size_t size = sizeof(arpstat);
734 
735 		if (sysctlbyname("net.inet.arp.stats", arpstat, &size,
736 				 NULL, 0) == -1)
737 			return;
738 	} else {
739 		warnx("%s stats not available via KVM.", name);
740 		return;
741 	}
742 
743 	printf("%s:\n", name);
744 
745 #define	ps(f, m) if (arpstat[f] || sflag <= 1) \
746     printf(m, arpstat[f])
747 #define	p(f, m) if (arpstat[f] || sflag <= 1) \
748     printf(m, arpstat[f], plural(arpstat[f]))
749 
750 	p(ARP_STAT_SNDTOTAL, "\t%" PRIu64 " packet%s sent\n");
751 	p(ARP_STAT_SNDREPLY, "\t\t%" PRIu64 " reply packet%s\n");
752 	p(ARP_STAT_SENDREQUEST, "\t\t%" PRIu64 " request packet%s\n");
753 
754 	p(ARP_STAT_RCVTOTAL, "\t%" PRIu64 " packet%s received\n");
755 	p(ARP_STAT_RCVREPLY, "\t\t%" PRIu64 " reply packet%s\n");
756 	p(ARP_STAT_RCVREQUEST, "\t\t%" PRIu64 " valid request packet%s\n");
757 	p(ARP_STAT_RCVMCAST, "\t\t%" PRIu64 " broadcast/multicast packet%s\n");
758 	p(ARP_STAT_RCVBADPROTO, "\t\t%" PRIu64 " packet%s with unknown protocol type\n");
759 	p(ARP_STAT_RCVBADLEN, "\t\t%" PRIu64 " packet%s with bad (short) length\n");
760 	p(ARP_STAT_RCVZEROTPA, "\t\t%" PRIu64 " packet%s with null target IP address\n");
761 	p(ARP_STAT_RCVZEROSPA, "\t\t%" PRIu64 " packet%s with null source IP address\n");
762 	ps(ARP_STAT_RCVNOINT, "\t\t%" PRIu64 " could not be mapped to an interface\n");
763 	p(ARP_STAT_RCVLOCALSHA, "\t\t%" PRIu64 " packet%s sourced from a local hardware "
764 	    "address\n");
765 	p(ARP_STAT_RCVBCASTSHA, "\t\t%" PRIu64 " packet%s with a broadcast "
766 	    "source hardware address\n");
767 	p(ARP_STAT_RCVLOCALSPA, "\t\t%" PRIu64 " duplicate%s for a local IP address\n");
768 	p(ARP_STAT_RCVOVERPERM, "\t\t%" PRIu64 " attempt%s to overwrite a static entry\n");
769 	p(ARP_STAT_RCVOVERINT, "\t\t%" PRIu64 " packet%s received on wrong interface\n");
770 	p(ARP_STAT_RCVOVER, "\t\t%" PRIu64 " entry%s overwritten\n");
771 	p(ARP_STAT_RCVLENCHG, "\t\t%" PRIu64 " change%s in hardware address length\n");
772 
773 	p(ARP_STAT_DFRTOTAL, "\t%" PRIu64 " packet%s deferred pending ARP resolution\n");
774 	ps(ARP_STAT_DFRSENT, "\t\t%" PRIu64 " sent\n");
775 	ps(ARP_STAT_DFRDROPPED, "\t\t%" PRIu64 " dropped\n");
776 
777 	p(ARP_STAT_ALLOCFAIL, "\t%" PRIu64 " failure%s to allocate llinfo\n");
778 
779 #undef ps
780 #undef p
781 }
782 
783 /*
784  * Pretty print an Internet address (net address + port).
785  * Take numeric_addr and numeric_port into consideration.
786  */
787 void
788 inetprint(struct in_addr *in, uint16_t port, const char *proto,
789 	  int port_numeric)
790 {
791 	struct servent *sp = 0;
792 	char line[80], *cp;
793 	size_t space;
794 
795 	(void)snprintf(line, sizeof line, "%.*s.",
796 	    (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
797 	cp = strchr(line, '\0');
798 	if (!port_numeric && port)
799 		sp = getservbyport((int)port, proto);
800 	space = sizeof line - (cp-line);
801 	if (sp || port == 0)
802 		(void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
803 	else
804 		(void)snprintf(cp, space, "%u", ntohs(port));
805 	(void)printf(" %-*.*s", width, width, line);
806 }
807 
808 /*
809  * Construct an Internet address representation.
810  * If numeric_addr has been supplied, give
811  * numeric value, otherwise try for symbolic name.
812  */
813 char *
814 inetname(struct in_addr *inp)
815 {
816 	char *cp;
817 	static char line[50];
818 	struct hostent *hp;
819 	struct netent *np;
820 	static char domain[MAXHOSTNAMELEN + 1];
821 	static int first = 1;
822 
823 	if (first && !numeric_addr) {
824 		first = 0;
825 		if (gethostname(domain, sizeof domain) == 0) {
826 			domain[sizeof(domain) - 1] = '\0';
827 			if ((cp = strchr(domain, '.')))
828 				(void) strlcpy(domain, cp + 1, sizeof(domain));
829 			else
830 				domain[0] = 0;
831 		} else
832 			domain[0] = 0;
833 	}
834 	cp = 0;
835 	if (!numeric_addr && inp->s_addr != INADDR_ANY) {
836 		int net = inet_netof(*inp);
837 		int lna = inet_lnaof(*inp);
838 
839 		if (lna == INADDR_ANY) {
840 			np = getnetbyaddr(net, AF_INET);
841 			if (np)
842 				cp = np->n_name;
843 		}
844 		if (cp == 0) {
845 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
846 			if (hp) {
847 				if ((cp = strchr(hp->h_name, '.')) &&
848 				    !strcmp(cp + 1, domain))
849 					*cp = 0;
850 				cp = hp->h_name;
851 			}
852 		}
853 	}
854 	if (inp->s_addr == INADDR_ANY)
855 		strlcpy(line, "*", sizeof line);
856 	else if (cp)
857 		strlcpy(line, cp, sizeof line);
858 	else {
859 		inp->s_addr = ntohl(inp->s_addr);
860 #define C(x)	((x) & 0xff)
861 		(void)snprintf(line, sizeof line, "%u.%u.%u.%u",
862 		    C(inp->s_addr >> 24), C(inp->s_addr >> 16),
863 		    C(inp->s_addr >> 8), C(inp->s_addr));
864 #undef C
865 	}
866 	return (line);
867 }
868 
869 /*
870  * Dump the contents of a TCP PCB.
871  */
872 void
873 tcp_dump(u_long pcbaddr)
874 {
875 	callout_impl_t *ci;
876 	struct tcpcb tcpcb;
877 	int i, hardticks;
878 
879 	kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
880 	hardticks = get_hardticks();
881 
882 	printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
883 
884 	printf("Timers:\n");
885 	for (i = 0; i < TCPT_NTIMERS; i++) {
886 		ci = (callout_impl_t *)&tcpcb.t_timer[i];
887 		printf("\t%s: %d", tcptimers[i],
888 		    (ci->c_flags & CALLOUT_PENDING) ?
889 		    ci->c_time - hardticks : 0);
890 	}
891 	printf("\n\n");
892 
893 	if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
894 		printf("State: %d", tcpcb.t_state);
895 	else
896 		printf("State: %s", tcpstates[tcpcb.t_state]);
897 	printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
898 	    (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
899 
900 	printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
901 	    tcpcb.t_rxtcur, tcpcb.t_dupacks);
902 	printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
903 	    tcpcb.t_ourmss, tcpcb.t_segsz);
904 
905 	printf("snd_una %u, snd_nxt %u, snd_up %u\n",
906 	    tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
907 	printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
908 	    tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
909 
910 	printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
911 	    tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
912 
913 	printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
914 	    tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
915 
916 	printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
917 	    "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
918 	    tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
919 	    tcpcb.max_sndwnd);
920 
921 	printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
922 	    tcpcb.t_iobc, tcpcb.t_softerror);
923 
924 	printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
925 	    tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
926 	    tcpcb.requested_s_scale);
927 	printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
928 	    tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
929 }
930