xref: /netbsd-src/usr.bin/netstat/inet.c (revision b5677b36047b601b9addaaa494a58ceae82c2a6c)
1 /*	$NetBSD: inet.c,v 1.89 2009/02/22 07:43:01 dholland 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.89 2009/02/22 07:43:01 dholland 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 (!aflag &&
219 			    inet_lnaof(dst.sin_addr) == INADDR_ANY)
220 				continue;
221 
222 			if (first) {
223 				protoprhdr();
224 				first = 0;
225 			}
226 
227 	                protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
228 				 pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
229 				 &src.sin_addr, src.sin_port,
230 				 &dst.sin_addr, dst.sin_port,
231 				 pcblist[i].ki_tstate, name);
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);
277 	}
278 }
279 
280 /*
281  * Dump TCP statistics structure.
282  */
283 void
284 tcp_stats(u_long off, 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, (unsigned long long)tcpstat[f])
303 #define	p(f, m) if (tcpstat[f] || sflag <= 1) \
304     printf(m, (unsigned long long)tcpstat[f], plural(tcpstat[f]))
305 #define	p2(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
306     printf(m, (unsigned long long)tcpstat[f1], plural(tcpstat[f1]), \
307     (unsigned long long)tcpstat[f2], plural(tcpstat[f2]))
308 #define	p2s(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
309     printf(m, (unsigned long long)tcpstat[f1], plural(tcpstat[f1]), \
310     (unsigned long long)tcpstat[f2])
311 #define	p3(f, m) if (tcpstat[f] || sflag <= 1) \
312     printf(m, (unsigned long long)tcpstat[f], plurales(tcpstat[f]))
313 
314 	p(TCP_STAT_SNDTOTAL, "\t%llu packet%s sent\n");
315 	p2(TCP_STAT_SNDPACK,TCP_STAT_SNDBYTE,
316 		"\t\t%llu data packet%s (%llu byte%s)\n");
317 	p2(TCP_STAT_SNDREXMITPACK, TCP_STAT_SNDREXMITBYTE,
318 		"\t\t%llu data packet%s (%llu byte%s) retransmitted\n");
319 	p2s(TCP_STAT_SNDACKS, TCP_STAT_DELACK,
320 		"\t\t%llu ack-only packet%s (%llu delayed)\n");
321 	p(TCP_STAT_SNDURG, "\t\t%llu URG only packet%s\n");
322 	p(TCP_STAT_SNDPROBE, "\t\t%llu window probe packet%s\n");
323 	p(TCP_STAT_SNDWINUP, "\t\t%llu window update packet%s\n");
324 	p(TCP_STAT_SNDCTRL, "\t\t%llu control packet%s\n");
325 	p(TCP_STAT_SELFQUENCH,
326 	    "\t\t%llu send attempt%s resulted in self-quench\n");
327 	p(TCP_STAT_RCVTOTAL, "\t%llu packet%s received\n");
328 	p2(TCP_STAT_RCVACKPACK, TCP_STAT_RCVACKBYTE,
329 		"\t\t%llu ack%s (for %llu byte%s)\n");
330 	p(TCP_STAT_RCVDUPACK, "\t\t%llu duplicate ack%s\n");
331 	p(TCP_STAT_RCVACKTOOMUCH, "\t\t%llu ack%s for unsent data\n");
332 	p2(TCP_STAT_RCVPACK, TCP_STAT_RCVBYTE,
333 		"\t\t%llu packet%s (%llu byte%s) received in-sequence\n");
334 	p2(TCP_STAT_RCVDUPPACK, TCP_STAT_RCVDUPBYTE,
335 		"\t\t%llu completely duplicate packet%s (%llu byte%s)\n");
336 	p(TCP_STAT_PAWSDROP, "\t\t%llu old duplicate packet%s\n");
337 	p2(TCP_STAT_RCVPARTDUPPACK, TCP_STAT_RCVPARTDUPBYTE,
338 		"\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n");
339 	p2(TCP_STAT_RCVOOPACK, TCP_STAT_RCVOOBYTE,
340 		"\t\t%llu out-of-order packet%s (%llu byte%s)\n");
341 	p2(TCP_STAT_RCVPACKAFTERWIN, TCP_STAT_RCVBYTEAFTERWIN,
342 		"\t\t%llu packet%s (%llu byte%s) of data after window\n");
343 	p(TCP_STAT_RCVWINPROBE, "\t\t%llu window probe%s\n");
344 	p(TCP_STAT_RCVWINUPD, "\t\t%llu window update packet%s\n");
345 	p(TCP_STAT_RCVAFTERCLOSE, "\t\t%llu packet%s received after close\n");
346 	p(TCP_STAT_RCVBADSUM, "\t\t%llu discarded for bad checksum%s\n");
347 	p(TCP_STAT_RCVBADOFF, "\t\t%llu discarded for bad header offset field%s\n");
348 	ps(TCP_STAT_RCVSHORT, "\t\t%llu discarded because packet too short\n");
349 	p(TCP_STAT_CONNATTEMPT, "\t%llu connection request%s\n");
350 	p(TCP_STAT_ACCEPTS, "\t%llu connection accept%s\n");
351 	p(TCP_STAT_CONNECTS,
352 		"\t%llu connection%s established (including accepts)\n");
353 	p2(TCP_STAT_CLOSED, TCP_STAT_DROPS,
354 		"\t%llu connection%s closed (including %llu drop%s)\n");
355 	p(TCP_STAT_CONNDROPS, "\t%llu embryonic connection%s dropped\n");
356 	p(TCP_STAT_DELAYED_FREE, "\t%llu delayed free%s of tcpcb\n");
357 	p2(TCP_STAT_RTTUPDATED, TCP_STAT_SEGSTIMED,
358 		"\t%llu segment%s updated rtt (of %llu attempt%s)\n");
359 	p(TCP_STAT_REXMTTIMEO, "\t%llu retransmit timeout%s\n");
360 	p(TCP_STAT_TIMEOUTDROP,
361 		"\t\t%llu connection%s dropped by rexmit timeout\n");
362 	p2(TCP_STAT_PERSISTTIMEO, TCP_STAT_PERSISTDROPS,
363 	   "\t%llu persist timeout%s (resulting in %llu dropped "
364 		"connection%s)\n");
365 	p(TCP_STAT_KEEPTIMEO, "\t%llu keepalive timeout%s\n");
366 	p(TCP_STAT_KEEPPROBE, "\t\t%llu keepalive probe%s sent\n");
367 	p(TCP_STAT_KEEPDROPS, "\t\t%llu connection%s dropped by keepalive\n");
368 	p(TCP_STAT_PREDACK, "\t%llu correct ACK header prediction%s\n");
369 	p(TCP_STAT_PREDDAT, "\t%llu correct data packet header prediction%s\n");
370 	p3(TCP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n");
371 	ps(TCP_STAT_NOPORT, "\t%llu dropped due to no socket\n");
372 	p(TCP_STAT_CONNSDRAINED, "\t%llu connection%s drained due to memory "
373 		"shortage\n");
374 	p(TCP_STAT_PMTUBLACKHOLE, "\t%llu PMTUD blackhole%s detected\n");
375 
376 	p(TCP_STAT_BADSYN, "\t%llu bad connection attempt%s\n");
377 	ps(TCP_STAT_SC_ADDED, "\t%llu SYN cache entries added\n");
378 	p(TCP_STAT_SC_COLLISIONS, "\t\t%llu hash collision%s\n");
379 	ps(TCP_STAT_SC_COMPLETED, "\t\t%llu completed\n");
380 	ps(TCP_STAT_SC_ABORTED, "\t\t%llu aborted (no space to build PCB)\n");
381 	ps(TCP_STAT_SC_TIMED_OUT, "\t\t%llu timed out\n");
382 	ps(TCP_STAT_SC_OVERFLOWED, "\t\t%llu dropped due to overflow\n");
383 	ps(TCP_STAT_SC_BUCKETOVERFLOW, "\t\t%llu dropped due to bucket overflow\n");
384 	ps(TCP_STAT_SC_RESET, "\t\t%llu dropped due to RST\n");
385 	ps(TCP_STAT_SC_UNREACH, "\t\t%llu dropped due to ICMP unreachable\n");
386 	ps(TCP_STAT_SC_DELAYED_FREE, "\t\t%llu delayed free of SYN cache "
387 		"entries\n");
388 	p(TCP_STAT_SC_RETRANSMITTED, "\t%llu SYN,ACK%s retransmitted\n");
389 	p(TCP_STAT_SC_DUPESYN, "\t%llu duplicate SYN%s received for entries "
390 		"already in the cache\n");
391 	p(TCP_STAT_SC_DROPPED, "\t%llu SYN%s dropped (no route or no space)\n");
392 	p(TCP_STAT_BADSIG, "\t%llu packet%s with bad signature\n");
393 	p(TCP_STAT_GOODSIG, "\t%llu packet%s with good signature\n");
394 
395 	p(TCP_STAT_ECN_SHS, "\t%llu sucessful ECN handshake%s\n");
396 	p(TCP_STAT_ECN_CE, "\t%llu packet%s with ECN CE bit\n");
397 	p(TCP_STAT_ECN_ECT, "\t%llu 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, 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, (unsigned long long)udpstat[f])
429 #define	p(f, m) if (udpstat[f] || sflag <= 1) \
430     printf(m, (unsigned long long)udpstat[f], plural(udpstat[f]))
431 #define	p3(f, m) if (udpstat[f] || sflag <= 1) \
432     printf(m, (unsigned long long)udpstat[f], plurales(udpstat[f]))
433 
434 	p(UDP_STAT_IPACKETS, "\t%llu datagram%s received\n");
435 	ps(UDP_STAT_HDROPS, "\t%llu with incomplete header\n");
436 	ps(UDP_STAT_BADLEN, "\t%llu with bad data length field\n");
437 	ps(UDP_STAT_BADSUM, "\t%llu with bad checksum\n");
438 	ps(UDP_STAT_NOPORT, "\t%llu dropped due to no socket\n");
439 	p(UDP_STAT_NOPORTBCAST,
440 	  "\t%llu broadcast/multicast datagram%s dropped due to no socket\n");
441 	ps(UDP_STAT_FULLSOCK, "\t%llu 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%llu delivered\n", (unsigned long long)delivered);
451 	p3(UDP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n");
452 	p(UDP_STAT_OPACKETS, "\t%llu 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, 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, (unsigned long long)ipstat[f])
482 #define	p(f, m) if (ipstat[f] || sflag <= 1) \
483     printf(m, (unsigned long long)ipstat[f], plural(ipstat[f]))
484 
485 	p(IP_STAT_TOTAL, "\t%llu total packet%s received\n");
486 	p(IP_STAT_BADSUM, "\t%llu bad header checksum%s\n");
487 	ps(IP_STAT_TOOSMALL, "\t%llu with size smaller than minimum\n");
488 	ps(IP_STAT_TOOSHORT, "\t%llu with data size < data length\n");
489 	ps(IP_STAT_TOOLONG, "\t%llu with length > max ip packet size\n");
490 	ps(IP_STAT_BADHLEN, "\t%llu with header length < data size\n");
491 	ps(IP_STAT_BADLEN, "\t%llu with data length < header length\n");
492 	ps(IP_STAT_BADOPTIONS, "\t%llu with bad options\n");
493 	ps(IP_STAT_BADVERS, "\t%llu with incorrect version number\n");
494 	p(IP_STAT_FRAGMENTS, "\t%llu fragment%s received\n");
495 	p(IP_STAT_FRAGDROPPED, "\t%llu fragment%s dropped (dup or out of space)\n");
496 	p(IP_STAT_RCVMEMDROP, "\t%llu fragment%s dropped (out of ipqent)\n");
497 	p(IP_STAT_BADFRAGS, "\t%llu malformed fragment%s dropped\n");
498 	p(IP_STAT_FRAGTIMEOUT, "\t%llu fragment%s dropped after timeout\n");
499 	p(IP_STAT_REASSEMBLED, "\t%llu packet%s reassembled ok\n");
500 	p(IP_STAT_DELIVERED, "\t%llu packet%s for this host\n");
501 	p(IP_STAT_NOPROTO, "\t%llu packet%s for unknown/unsupported protocol\n");
502 	p(IP_STAT_FORWARD, "\t%llu packet%s forwarded");
503 	p(IP_STAT_FASTFORWARD, " (%llu packet%s fast forwarded)");
504 	if (ipstat[IP_STAT_FORWARD] || sflag <= 1)
505 		putchar('\n');
506 	p(IP_STAT_CANTFORWARD, "\t%llu packet%s not forwardable\n");
507 	p(IP_STAT_REDIRECTSENT, "\t%llu redirect%s sent\n");
508 	p(IP_STAT_NOGIF, "\t%llu packet%s no matching gif found\n");
509 	p(IP_STAT_LOCALOUT, "\t%llu packet%s sent from this host\n");
510 	p(IP_STAT_RAWOUT, "\t%llu packet%s sent with fabricated ip header\n");
511 	p(IP_STAT_ODROPPED, "\t%llu output packet%s dropped due to no bufs, etc.\n");
512 	p(IP_STAT_NOROUTE, "\t%llu output packet%s discarded due to no route\n");
513 	p(IP_STAT_FRAGMENTED, "\t%llu output datagram%s fragmented\n");
514 	p(IP_STAT_OFRAGMENTS, "\t%llu fragment%s created\n");
515 	p(IP_STAT_CANTFRAG, "\t%llu datagram%s that can't be fragmented\n");
516 	p(IP_STAT_BADADDR, "\t%llu 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, 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, (unsigned long long)icmpstat[f], plural(icmpstat[f]))
567 
568 	p(ICMP_STAT_ERROR, "\t%llu call%s to icmp_error\n");
569 	p(ICMP_STAT_OLDICMP,
570 	    "\t%llu 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: %llu\n", icmpnames[i],
578 			   (unsigned long long)icmpstat[ICMP_STAT_OUTHIST + i]);
579 		}
580 	p(ICMP_STAT_BADCODE, "\t%llu message%s with bad code fields\n");
581 	p(ICMP_STAT_TOOSHORT, "\t%llu message%s < minimum length\n");
582 	p(ICMP_STAT_CHECKSUM, "\t%llu bad checksum%s\n");
583 	p(ICMP_STAT_BADLEN, "\t%llu message%s with bad length\n");
584 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
585 		if (icmpstat[ICMP_STAT_INHIST + i] != 0) {
586 			if (first) {
587 				printf("\tInput histogram:\n");
588 				first = 0;
589 			}
590 			printf("\t\t%s: %llu\n", icmpnames[i],
591 			    (unsigned long long)icmpstat[ICMP_STAT_INHIST + i]);
592 		}
593 	p(ICMP_STAT_REFLECT, "\t%llu message response%s generated\n");
594 	p(ICMP_STAT_PMTUCHG, "\t%llu path MTU change%s\n");
595 #undef p
596 }
597 
598 /*
599  * Dump IGMP statistics structure.
600  */
601 void
602 igmp_stats(u_long off, char *name)
603 {
604 	uint64_t igmpstat[IGMP_NSTATS];
605 
606 	if (use_sysctl) {
607 		size_t size = sizeof(igmpstat);
608 
609 		if (sysctlbyname("net.inet.igmp.stats", igmpstat, &size,
610 				 NULL, 0) == -1)
611 			return;
612 	} else {
613 		warnx("%s stats not available via KVM.", name);
614 		return;
615 	}
616 
617 	printf("%s:\n", name);
618 
619 #define	p(f, m) if (igmpstat[f] || sflag <= 1) \
620     printf(m, (unsigned long long)igmpstat[f], plural(igmpstat[f]))
621 #define	py(f, m) if (igmpstat[f] || sflag <= 1) \
622     printf(m, (unsigned long long)igmpstat[f], igmpstat[f] != 1 ? "ies" : "y")
623 	p(IGMP_STAT_RCV_TOTAL, "\t%llu message%s received\n");
624         p(IGMP_STAT_RCV_TOOSHORT, "\t%llu message%s received with too few bytes\n");
625         p(IGMP_STAT_RCV_BADSUM, "\t%llu message%s received with bad checksum\n");
626         py(IGMP_STAT_RCV_QUERIES, "\t%llu membership quer%s received\n");
627         py(IGMP_STAT_RCV_BADQUERIES, "\t%llu membership quer%s received with invalid field(s)\n");
628         p(IGMP_STAT_RCV_REPORTS, "\t%llu membership report%s received\n");
629         p(IGMP_STAT_RCV_BADREPORTS, "\t%llu membership report%s received with invalid field(s)\n");
630         p(IGMP_STAT_RCV_OURREPORTS, "\t%llu membership report%s received for groups to which we belong\n");
631         p(IGMP_STAT_SND_REPORTS, "\t%llu membership report%s sent\n");
632 #undef p
633 #undef py
634 }
635 
636 /*
637  * Dump CARP statistics structure.
638  */
639 void
640 carp_stats(u_long off, char *name)
641 {
642 	uint64_t carpstat[CARP_NSTATS];
643 
644 	if (use_sysctl) {
645 		size_t size = sizeof(carpstat);
646 
647 		if (sysctlbyname("net.inet.carp.stats", carpstat, &size,
648 				 NULL, 0) == -1)
649 			return;
650 	} else {
651 		warnx("%s stats not available via KVM.", name);
652 		return;
653 	}
654 
655 	printf("%s:\n", name);
656 
657 #define p(f, m) if (carpstat[f] || sflag <= 1) \
658 	printf(m, carpstat[f], plural(carpstat[f]))
659 #define p2(f, m) if (carpstat[f] || sflag <= 1) \
660 	printf(m, carpstat[f])
661 
662 	p(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n");
663 	p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n");
664 	p(CARP_STAT_BADIF,
665 	    "\t\t%" PRIu64 " packet%s discarded for bad interface\n");
666 	p(CARP_STAT_BADTTL,
667 	    "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n");
668 	p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n");
669 	p(CARP_STAT_BADSUM, "\t\t%" PRIu64
670 		" packet%s discarded for bad checksum\n");
671 	p(CARP_STAT_BADVER,
672 	    "\t\t%" PRIu64 " packet%s discarded with a bad version\n");
673 	p2(CARP_STAT_BADLEN,
674 	    "\t\t%" PRIu64 " discarded because packet was too short\n");
675 	p(CARP_STAT_BADAUTH,
676 	    "\t\t%" PRIu64 " packet%s discarded for bad authentication\n");
677 	p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n");
678 	p(CARP_STAT_BADADDRS, "\t\t%" PRIu64
679 		" packet%s discarded because of a bad address list\n");
680 	p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n");
681 	p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n");
682 	p2(CARP_STAT_ONOMEM,
683 	    "\t\t%" PRIu64 " send failed due to mbuf memory error\n");
684 #undef p
685 #undef p2
686 }
687 
688 /*
689  * Dump PIM statistics structure.
690  */
691 void
692 pim_stats(u_long off, char *name)
693 {
694 	struct pimstat pimstat;
695 
696 	if (off == 0)
697 		return;
698 	if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) {
699 		/* XXX: PIM is probably not enabled in the kernel */
700 		return;
701 	}
702 
703 	printf("%s:\n", name);
704 
705 #define	p(f, m) if (pimstat.f || sflag <= 1) \
706 	printf(m, (unsigned long long)pimstat.f, plural(pimstat.f))
707 
708 	p(pims_rcv_total_msgs, "\t%llu message%s received\n");
709 	p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
710 	p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
711         p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
712 	p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
713 	p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
714 	p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
715 	p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
716 	p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
717 	p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
718 	p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
719 #undef p
720 }
721 
722 /*
723  * Dump the ARP statistics structure.
724  */
725 void
726 arp_stats(u_long off, char *name)
727 {
728 	uint64_t arpstat[ARP_NSTATS];
729 
730 	if (use_sysctl) {
731 		size_t size = sizeof(arpstat);
732 
733 		if (sysctlbyname("net.inet.arp.stats", arpstat, &size,
734 				 NULL, 0) == -1)
735 			return;
736 	} else {
737 		warnx("%s stats not available via KVM.", name);
738 		return;
739 	}
740 
741 	printf("%s:\n", name);
742 
743 #define	ps(f, m) if (arpstat[f] || sflag <= 1) \
744     printf(m, (unsigned long long)arpstat[f])
745 #define	p(f, m) if (arpstat[f] || sflag <= 1) \
746     printf(m, (unsigned long long)arpstat[f], plural(arpstat[f]))
747 
748 	p(ARP_STAT_SNDTOTAL, "\t%llu packet%s sent\n");
749 	p(ARP_STAT_SNDREPLY, "\t\t%llu reply packet%s\n");
750 	p(ARP_STAT_SENDREQUEST, "\t\t%llu request packet%s\n");
751 
752 	p(ARP_STAT_RCVTOTAL, "\t%llu packet%s received\n");
753 	p(ARP_STAT_RCVREPLY, "\t\t%llu reply packet%s\n");
754 	p(ARP_STAT_RCVREQUEST, "\t\t%llu valid request packet%s\n");
755 	p(ARP_STAT_RCVMCAST, "\t\t%llu broadcast/multicast packet%s\n");
756 	p(ARP_STAT_RCVBADPROTO, "\t\t%llu packet%s with unknown protocol type\n");
757 	p(ARP_STAT_RCVBADLEN, "\t\t%llu packet%s with bad (short) length\n");
758 	p(ARP_STAT_RCVZEROTPA, "\t\t%llu packet%s with null target IP address\n");
759 	p(ARP_STAT_RCVZEROSPA, "\t\t%llu packet%s with null source IP address\n");
760 	ps(ARP_STAT_RCVNOINT, "\t\t%llu could not be mapped to an interface\n");
761 	p(ARP_STAT_RCVLOCALSHA, "\t\t%llu packet%s sourced from a local hardware "
762 	    "address\n");
763 	p(ARP_STAT_RCVBCASTSHA, "\t\t%llu packet%s with a broadcast "
764 	    "source hardware address\n");
765 	p(ARP_STAT_RCVLOCALSPA, "\t\t%llu duplicate%s for a local IP address\n");
766 	p(ARP_STAT_RCVOVERPERM, "\t\t%llu attempt%s to overwrite a static entry\n");
767 	p(ARP_STAT_RCVOVERINT, "\t\t%llu packet%s received on wrong interface\n");
768 	p(ARP_STAT_RCVOVER, "\t\t%llu entry%s overwritten\n");
769 	p(ARP_STAT_RCVLENCHG, "\t\t%llu change%s in hardware address length\n");
770 
771 	p(ARP_STAT_DFRTOTAL, "\t%llu packet%s deferred pending ARP resolution\n");
772 	ps(ARP_STAT_DFRSENT, "\t\t%llu sent\n");
773 	ps(ARP_STAT_DFRDROPPED, "\t\t%llu dropped\n");
774 
775 	p(ARP_STAT_ALLOCFAIL, "\t%llu failure%s to allocate llinfo\n");
776 
777 #undef ps
778 #undef p
779 }
780 
781 /*
782  * Pretty print an Internet address (net address + port).
783  * Take numeric_addr and numeric_port into consideration.
784  */
785 void
786 inetprint(struct in_addr *in, uint16_t port, const char *proto,
787 	  int numeric_port)
788 {
789 	struct servent *sp = 0;
790 	char line[80], *cp;
791 	size_t space;
792 
793 	(void)snprintf(line, sizeof line, "%.*s.",
794 	    (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
795 	cp = strchr(line, '\0');
796 	if (!numeric_port && port)
797 		sp = getservbyport((int)port, proto);
798 	space = sizeof line - (cp-line);
799 	if (sp || port == 0)
800 		(void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
801 	else
802 		(void)snprintf(cp, space, "%u", ntohs(port));
803 	(void)printf(" %-*.*s", width, width, line);
804 }
805 
806 /*
807  * Construct an Internet address representation.
808  * If numeric_addr has been supplied, give
809  * numeric value, otherwise try for symbolic name.
810  */
811 char *
812 inetname(struct in_addr *inp)
813 {
814 	char *cp;
815 	static char line[50];
816 	struct hostent *hp;
817 	struct netent *np;
818 	static char domain[MAXHOSTNAMELEN + 1];
819 	static int first = 1;
820 
821 	if (first && !numeric_addr) {
822 		first = 0;
823 		if (gethostname(domain, sizeof domain) == 0) {
824 			domain[sizeof(domain) - 1] = '\0';
825 			if ((cp = strchr(domain, '.')))
826 				(void) strlcpy(domain, cp + 1, sizeof(domain));
827 			else
828 				domain[0] = 0;
829 		} else
830 			domain[0] = 0;
831 	}
832 	cp = 0;
833 	if (!numeric_addr && inp->s_addr != INADDR_ANY) {
834 		int net = inet_netof(*inp);
835 		int lna = inet_lnaof(*inp);
836 
837 		if (lna == INADDR_ANY) {
838 			np = getnetbyaddr(net, AF_INET);
839 			if (np)
840 				cp = np->n_name;
841 		}
842 		if (cp == 0) {
843 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
844 			if (hp) {
845 				if ((cp = strchr(hp->h_name, '.')) &&
846 				    !strcmp(cp + 1, domain))
847 					*cp = 0;
848 				cp = hp->h_name;
849 			}
850 		}
851 	}
852 	if (inp->s_addr == INADDR_ANY)
853 		strlcpy(line, "*", sizeof line);
854 	else if (cp)
855 		strlcpy(line, cp, sizeof line);
856 	else {
857 		inp->s_addr = ntohl(inp->s_addr);
858 #define C(x)	((x) & 0xff)
859 		(void)snprintf(line, sizeof line, "%u.%u.%u.%u",
860 		    C(inp->s_addr >> 24), C(inp->s_addr >> 16),
861 		    C(inp->s_addr >> 8), C(inp->s_addr));
862 #undef C
863 	}
864 	return (line);
865 }
866 
867 /*
868  * Dump the contents of a TCP PCB.
869  */
870 void
871 tcp_dump(u_long pcbaddr)
872 {
873 	callout_impl_t *ci;
874 	struct tcpcb tcpcb;
875 	int i, hardticks;
876 
877 	kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
878 	hardticks = get_hardticks();
879 
880 	printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
881 
882 	printf("Timers:\n");
883 	for (i = 0; i < TCPT_NTIMERS; i++) {
884 		ci = (callout_impl_t *)&tcpcb.t_timer[i];
885 		printf("\t%s: %d", tcptimers[i],
886 		    (ci->c_flags & CALLOUT_PENDING) ?
887 		    ci->c_time - hardticks : 0);
888 	}
889 	printf("\n\n");
890 
891 	if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
892 		printf("State: %d", tcpcb.t_state);
893 	else
894 		printf("State: %s", tcpstates[tcpcb.t_state]);
895 	printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
896 	    (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
897 
898 	printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
899 	    tcpcb.t_rxtcur, tcpcb.t_dupacks);
900 	printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
901 	    tcpcb.t_ourmss, tcpcb.t_segsz);
902 
903 	printf("snd_una %u, snd_nxt %u, snd_up %u\n",
904 	    tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
905 	printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
906 	    tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
907 
908 	printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
909 	    tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
910 
911 	printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
912 	    tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
913 
914 	printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
915 	    "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
916 	    tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
917 	    tcpcb.max_sndwnd);
918 
919 	printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
920 	    tcpcb.t_iobc, tcpcb.t_softerror);
921 
922 	printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
923 	    tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
924 	    tcpcb.requested_s_scale);
925 	printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
926 	    tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
927 }
928