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