xref: /openbsd-src/usr.bin/netstat/inet.c (revision ac9b4aacc1da35008afea06a5d23c2f2dea9b93e)
1 /*	$OpenBSD: inet.c,v 1.119 2011/11/01 00:00:01 mikeb Exp $	*/
2 /*	$NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $	*/
3 
4 /*
5  * Copyright (c) 1983, 1988, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/queue.h>
35 #include <sys/socket.h>
36 #include <sys/socketvar.h>
37 #include <sys/mbuf.h>
38 #include <sys/domain.h>
39 #include <sys/protosw.h>
40 #include <sys/sysctl.h>
41 
42 #include <net/route.h>
43 #include <netinet/in.h>
44 #include <netinet/in_systm.h>
45 #include <netinet/ip.h>
46 #include <netinet/in_pcb.h>
47 #include <netinet/ip_icmp.h>
48 #include <netinet/icmp_var.h>
49 #include <netinet/igmp_var.h>
50 #include <netinet/ip_var.h>
51 #include <netinet/pim_var.h>
52 #include <netinet/tcp.h>
53 #include <netinet/tcpip.h>
54 #include <netinet/tcp_seq.h>
55 #define TCPSTATES
56 #include <netinet/tcp_fsm.h>
57 #include <netinet/tcp_timer.h>
58 #include <netinet/tcp_var.h>
59 #include <netinet/tcp_debug.h>
60 #include <netinet/udp.h>
61 #include <netinet/udp_var.h>
62 #include <netinet/ip_ipsp.h>
63 #include <netinet/ip_ah.h>
64 #include <netinet/ip_esp.h>
65 #include <netinet/ip_ipip.h>
66 #include <netinet/ip_ipcomp.h>
67 #include <netinet/ip_ether.h>
68 #include <netinet/ip_carp.h>
69 #include <netinet/ip_divert.h>
70 #include <net/if.h>
71 #include <net/pfvar.h>
72 #include <net/if_pfsync.h>
73 #include <net/if_pflow.h>
74 
75 #include <rpc/rpc.h>
76 #include <rpc/pmap_prot.h>
77 #include <rpc/pmap_clnt.h>
78 
79 #include <arpa/inet.h>
80 #include <err.h>
81 #include <limits.h>
82 #include <netdb.h>
83 #include <stdio.h>
84 #include <string.h>
85 #include <unistd.h>
86 #include <stdlib.h>
87 #include <errno.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 *, in_port_t, char *, int);
96 char	*inet6name(struct in6_addr *);
97 void	inet6print(struct in6_addr *, int, char *);
98 void	sockbuf_dump(struct sockbuf *, const char *);
99 void	protosw_dump(u_long, u_long);
100 void	domain_dump(u_long, u_long, short);
101 void	inpcb_dump(u_long, short, int);
102 void	tcpcb_dump(u_long);
103 
104 /*
105  * Print a summary of connections related to an Internet
106  * protocol.  For TCP, also give state of connection.
107  * Listening processes (aflag) are suppressed unless the
108  * -a (all) flag is specified.
109  */
110 void
111 protopr(u_long off, char *name, int af, u_int tableid, u_long pcbaddr)
112 {
113 	struct inpcbtable table;
114 	struct inpcb *head, *next, *prev;
115 	struct inpcb inpcb;
116 	int istcp, israw, isany;
117 	int addrlen = 22;
118 	int first = 1;
119 	char *name0;
120 	char namebuf[20];
121 
122 	name0 = name;
123 	if (off == 0)
124 		return;
125 	istcp = strcmp(name, "tcp") == 0;
126 	israw = strncmp(name, "ip", 2) == 0;
127 	kread(off, &table, sizeof table);
128 	prev = head =
129 	    (struct inpcb *)&CIRCLEQ_FIRST(&((struct inpcbtable *)off)->inpt_queue);
130 	next = CIRCLEQ_FIRST(&table.inpt_queue);
131 
132 	while (next != head) {
133 		kread((u_long)next, &inpcb, sizeof inpcb);
134 		if (CIRCLEQ_PREV(&inpcb, inp_queue) != prev) {
135 			printf("???\n");
136 			break;
137 		}
138 		prev = next;
139 		next = CIRCLEQ_NEXT(&inpcb, inp_queue);
140 
141 		switch (af) {
142 		case AF_INET:
143 			if ((inpcb.inp_flags & INP_IPV6) != 0)
144 				continue;
145 			isany = inet_lnaof(inpcb.inp_faddr) == INADDR_ANY;
146 			break;
147 		case AF_INET6:
148 			if ((inpcb.inp_flags & INP_IPV6) == 0)
149 				continue;
150 			isany = IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_faddr6);
151 			break;
152 		default:
153 			isany = 0;
154 			break;
155 		}
156 
157 		if (Pflag) {
158 			if (istcp && pcbaddr == (u_long)inpcb.inp_ppcb) {
159 				if (vflag)
160 					socket_dump((u_long)inpcb.inp_socket);
161 				else
162 					tcpcb_dump(pcbaddr);
163 			} else if (pcbaddr == (u_long)prev) {
164 				if (vflag)
165 					socket_dump((u_long)inpcb.inp_socket);
166 				else
167 					inpcb_dump(pcbaddr, 0, af);
168 			}
169 			continue;
170 		}
171 
172 		if (inpcb.inp_rtableid != tableid)
173 			continue;
174 
175 		kread((u_long)inpcb.inp_socket, &sockb, sizeof (sockb));
176 		if (istcp) {
177 			kread((u_long)inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
178 			if (!aflag && tcpcb.t_state <= TCPS_LISTEN)
179 				continue;
180 		} else if (!aflag && isany)
181 			continue;
182 		if (first) {
183 			printf("Active Internet connections");
184 			if (aflag)
185 				printf(" (including servers)");
186 			putchar('\n');
187 			if (Aflag) {
188 				addrlen = 18;
189 				printf("%-*.*s ", PLEN, PLEN, "PCB");
190 			}
191 			printf("%-7.7s %-6.6s %-6.6s ",
192 			    "Proto", "Recv-Q", "Send-Q");
193 			if (Bflag && istcp)
194 				printf("%-6.6s %-6.6s %-6.6s ",
195 				    "Recv-W", "Send-W", "Cgst-W");
196 			printf(" %-*.*s %-*.*s %s\n",
197 			    addrlen, addrlen, "Local Address",
198 			    addrlen, addrlen, "Foreign Address", "(state)");
199 			first = 0;
200 		}
201 		if (Aflag) {
202 			if (istcp)
203 				printf("%*p ", PLEN, inpcb.inp_ppcb);
204 			else
205 				printf("%*p ", PLEN, prev);
206 		}
207 		if (inpcb.inp_flags & INP_IPV6 && !israw) {
208 			strlcpy(namebuf, name0, sizeof namebuf);
209 			strlcat(namebuf, "6", sizeof namebuf);
210 			name = namebuf;
211 		} else
212 			name = name0;
213 		printf("%-7.7s %6lu %6lu ",
214 		    name, sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
215 		if (Bflag && istcp)
216 			printf("%6lu %6lu %6lu ", tcpcb.rcv_wnd, tcpcb.snd_wnd,
217 			    (tcpcb.t_state == TCPS_ESTABLISHED) ?
218 			    tcpcb.snd_cwnd : 0);
219 
220 		if (inpcb.inp_flags & INP_IPV6) {
221 			inet6print(&inpcb.inp_laddr6, (int)inpcb.inp_lport,
222 			    name);
223 			inet6print(&inpcb.inp_faddr6, (int)inpcb.inp_fport,
224 			    name);
225 		} else {
226 			inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport,
227 			    name, 1);
228 			inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport,
229 			    name, 0);
230 		}
231 		if (istcp) {
232 			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
233 				printf(" %d", tcpcb.t_state);
234 			else
235 				printf(" %s", tcpstates[tcpcb.t_state]);
236 		} else if (israw) {
237 			u_int8_t proto;
238 
239 			if (inpcb.inp_flags & INP_IPV6)
240 				proto = inpcb.inp_ipv6.ip6_nxt;
241 			else
242 				proto = inpcb.inp_ip.ip_p;
243 			printf(" %u", proto);
244 		}
245 		putchar('\n');
246 	}
247 }
248 
249 /*
250  * Dump TCP statistics structure.
251  */
252 void
253 tcp_stats(char *name)
254 {
255 	struct tcpstat tcpstat;
256 	int mib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
257 	size_t len = sizeof(tcpstat);
258 
259 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
260 	    &tcpstat, &len, NULL, 0) == -1) {
261 		if (errno != ENOPROTOOPT)
262 			warn(name);
263 		return;
264 	}
265 
266 	printf("%s:\n", name);
267 #define	p(f, m) if (tcpstat.f || sflag <= 1) \
268 	printf(m, tcpstat.f, plural(tcpstat.f))
269 #define	p1(f, m) if (tcpstat.f || sflag <= 1) \
270 	printf(m, tcpstat.f)
271 #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
272 	printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
273 #define	p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
274 	printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
275 #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
276 	printf(m, tcpstat.f, plurales(tcpstat.f))
277 
278 	p(tcps_sndtotal, "\t%u packet%s sent\n");
279 	p2(tcps_sndpack,tcps_sndbyte,
280 	    "\t\t%u data packet%s (%qd byte%s)\n");
281 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
282 	    "\t\t%u data packet%s (%qd byte%s) retransmitted\n");
283 	p(tcps_sndrexmitfast, "\t\t%qd fast retransmitted packet%s\n");
284 	p2a(tcps_sndacks, tcps_delack,
285 	    "\t\t%u ack-only packet%s (%u delayed)\n");
286 	p(tcps_sndurg, "\t\t%u URG only packet%s\n");
287 	p(tcps_sndprobe, "\t\t%u window probe packet%s\n");
288 	p(tcps_sndwinup, "\t\t%u window update packet%s\n");
289 	p(tcps_sndctrl, "\t\t%u control packet%s\n");
290 	p(tcps_outhwcsum, "\t\t%u packet%s hardware-checksummed\n");
291 	p(tcps_rcvtotal, "\t%u packet%s received\n");
292 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%u ack%s (for %qd byte%s)\n");
293 	p(tcps_rcvdupack, "\t\t%u duplicate ack%s\n");
294 	p(tcps_rcvacktoomuch, "\t\t%u ack%s for unsent data\n");
295 	p(tcps_rcvacktooold, "\t\t%u ack%s for old data\n");
296 	p2(tcps_rcvpack, tcps_rcvbyte,
297 	    "\t\t%u packet%s (%qu byte%s) received in-sequence\n");
298 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
299 	    "\t\t%u completely duplicate packet%s (%qd byte%s)\n");
300 	p(tcps_pawsdrop, "\t\t%u old duplicate packet%s\n");
301 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
302 	    "\t\t%u packet%s with some duplicate data (%qd byte%s duplicated)\n");
303 	p2(tcps_rcvoopack, tcps_rcvoobyte,
304 	    "\t\t%u out-of-order packet%s (%qd byte%s)\n");
305 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
306 	    "\t\t%u packet%s (%qd byte%s) of data after window\n");
307 	p(tcps_rcvwinprobe, "\t\t%u window probe%s\n");
308 	p(tcps_rcvwinupd, "\t\t%u window update packet%s\n");
309 	p(tcps_rcvafterclose, "\t\t%u packet%s received after close\n");
310 	p(tcps_rcvbadsum, "\t\t%u discarded for bad checksum%s\n");
311 	p(tcps_rcvbadoff, "\t\t%u discarded for bad header offset field%s\n");
312 	p1(tcps_rcvshort, "\t\t%u discarded because packet too short\n");
313 	p1(tcps_rcvnosec, "\t\t%u discarded for missing IPsec protection\n");
314 	p1(tcps_rcvmemdrop, "\t\t%u discarded due to memory shortage\n");
315 	p(tcps_inhwcsum, "\t\t%u packet%s hardware-checksummed\n");
316 	p(tcps_rcvbadsig, "\t\t%u bad/missing md5 checksum%s\n");
317 	p(tcps_rcvgoodsig, "\t\t%qd good md5 checksum%s\n");
318 	p(tcps_connattempt, "\t%u connection request%s\n");
319 	p(tcps_accepts, "\t%u connection accept%s\n");
320 	p(tcps_connects, "\t%u connection%s established (including accepts)\n");
321 	p2(tcps_closed, tcps_drops,
322 	    "\t%u connection%s closed (including %u drop%s)\n");
323 	p(tcps_conndrained, "\t%qd connection%s drained\n");
324 	p(tcps_conndrops, "\t%u embryonic connection%s dropped\n");
325 	p2(tcps_rttupdated, tcps_segstimed,
326 	    "\t%u segment%s updated rtt (of %u attempt%s)\n");
327 	p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n");
328 	p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n");
329 	p(tcps_persisttimeo, "\t%u persist timeout%s\n");
330 	p(tcps_keeptimeo, "\t%u keepalive timeout%s\n");
331 	p(tcps_keepprobe, "\t\t%u keepalive probe%s sent\n");
332 	p(tcps_keepdrops, "\t\t%u connection%s dropped by keepalive\n");
333 	p(tcps_predack, "\t%u correct ACK header prediction%s\n");
334 	p(tcps_preddat, "\t%u correct data packet header prediction%s\n");
335 	p3(tcps_pcbhashmiss, "\t%u PCB cache miss%s\n");
336 
337 	p(tcps_ecn_accepts, "\t%u ECN connection%s accepted\n");
338 	p(tcps_ecn_rcvece, "\t\t%u ECE packet%s received\n");
339 	p(tcps_ecn_rcvcwr, "\t\t%u CWR packet%s received\n");
340 	p(tcps_ecn_rcvce, "\t\t%u CE packet%s received\n");
341 	p(tcps_ecn_sndect, "\t\t%u ECT packet%s sent\n");
342 	p(tcps_ecn_sndece, "\t\t%u ECE packet%s sent\n");
343 	p(tcps_ecn_sndcwr, "\t\t%u CWR packet%s sent\n");
344 	p1(tcps_cwr_frecovery, "\t\t\tcwr by fastrecovery: %u\n");
345 	p1(tcps_cwr_timeout, "\t\t\tcwr by timeout: %u\n");
346 	p1(tcps_cwr_ecn, "\t\t\tcwr by ecn: %u\n");
347 
348 	p(tcps_badsyn, "\t%u bad connection attempt%s\n");
349 	p1(tcps_sc_added, "\t%qd SYN cache entries added\n");
350 	p(tcps_sc_collisions, "\t\t%qd hash collision%s\n");
351 	p1(tcps_sc_completed, "\t\t%qd completed\n");
352 	p1(tcps_sc_aborted, "\t\t%qd aborted (no space to build PCB)\n");
353 	p1(tcps_sc_timed_out, "\t\t%qd timed out\n");
354 	p1(tcps_sc_overflowed, "\t\t%qd dropped due to overflow\n");
355 	p1(tcps_sc_bucketoverflow, "\t\t%qd dropped due to bucket overflow\n");
356 	p1(tcps_sc_reset, "\t\t%qd dropped due to RST\n");
357 	p1(tcps_sc_unreach, "\t\t%qd dropped due to ICMP unreachable\n");
358 	p(tcps_sc_retransmitted, "\t%qd SYN,ACK%s retransmitted\n");
359 	p(tcps_sc_dupesyn, "\t%qd duplicate SYN%s received for entries "
360 		"already in the cache\n");
361 	p(tcps_sc_dropped, "\t%qd SYN%s dropped (no route or no space)\n");
362 
363 	p(tcps_sack_recovery_episode, "\t%qd SACK recovery episode%s\n");
364 	p(tcps_sack_rexmits,
365 		"\t\t%qd segment rexmit%s in SACK recovery episodes\n");
366 	p(tcps_sack_rexmit_bytes,
367 		"\t\t%qd byte rexmit%s in SACK recovery episodes\n");
368 	p(tcps_sack_rcv_opts,
369 		"\t%qd SACK option%s received\n");
370 	p(tcps_sack_snd_opts, "\t%qd SACK option%s sent\n");
371 
372 #undef p
373 #undef p1
374 #undef p2
375 #undef p2a
376 #undef p3
377 }
378 
379 /*
380  * Dump UDP statistics structure.
381  */
382 void
383 udp_stats(char *name)
384 {
385 	struct udpstat udpstat;
386 	u_long delivered;
387 	int mib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
388 	size_t len = sizeof(udpstat);
389 
390 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
391 	    &udpstat, &len, NULL, 0) == -1) {
392 		if (errno != ENOPROTOOPT)
393 			warn(name);
394 		return;
395 	}
396 
397 	printf("%s:\n", name);
398 #define	p(f, m) if (udpstat.f || sflag <= 1) \
399 	printf(m, udpstat.f, plural(udpstat.f))
400 #define	p1(f, m) if (udpstat.f || sflag <= 1) \
401 	printf(m, udpstat.f)
402 
403 	p(udps_ipackets, "\t%lu datagram%s received\n");
404 	p1(udps_hdrops, "\t%lu with incomplete header\n");
405 	p1(udps_badlen, "\t%lu with bad data length field\n");
406 	p1(udps_badsum, "\t%lu with bad checksum\n");
407 	p1(udps_nosum, "\t%lu with no checksum\n");
408 	p(udps_inhwcsum, "\t%lu input packet%s hardware-checksummed\n");
409 	p(udps_outhwcsum, "\t%lu output packet%s hardware-checksummed\n");
410 	p1(udps_noport, "\t%lu dropped due to no socket\n");
411 	p(udps_noportbcast, "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
412 	p1(udps_nosec, "\t%lu dropped due to missing IPsec protection\n");
413 	p1(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
414 	delivered = udpstat.udps_ipackets - udpstat.udps_hdrops -
415 	    udpstat.udps_badlen - udpstat.udps_badsum -
416 	    udpstat.udps_noport - udpstat.udps_noportbcast -
417 	    udpstat.udps_fullsock;
418 	if (delivered || sflag <= 1)
419 		printf("\t%lu delivered\n", delivered);
420 	p(udps_opackets, "\t%lu datagram%s output\n");
421 	p1(udps_pcbhashmiss, "\t%lu missed PCB cache\n");
422 #undef p
423 #undef p1
424 }
425 
426 /*
427  * Dump IP statistics structure.
428  */
429 void
430 ip_stats(char *name)
431 {
432 	struct ipstat ipstat;
433 	int mib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
434 	size_t len = sizeof(ipstat);
435 
436 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
437 	    &ipstat, &len, NULL, 0) == -1) {
438 		if (errno != ENOPROTOOPT)
439 			warn(name);
440 		return;
441 	}
442 
443 	printf("%s:\n", name);
444 #define	p(f, m) if (ipstat.f || sflag <= 1) \
445 	printf(m, ipstat.f, plural(ipstat.f))
446 #define	p1(f, m) if (ipstat.f || sflag <= 1) \
447 	printf(m, ipstat.f)
448 
449 	p(ips_total, "\t%lu total packet%s received\n");
450 	p(ips_badsum, "\t%lu bad header checksum%s\n");
451 	p1(ips_toosmall, "\t%lu with size smaller than minimum\n");
452 	p1(ips_tooshort, "\t%lu with data size < data length\n");
453 	p1(ips_badhlen, "\t%lu with header length < data size\n");
454 	p1(ips_badlen, "\t%lu with data length < header length\n");
455 	p1(ips_badoptions, "\t%lu with bad options\n");
456 	p1(ips_badvers, "\t%lu with incorrect version number\n");
457 	p(ips_fragments, "\t%lu fragment%s received\n");
458 	p(ips_fragdropped, "\t%lu fragment%s dropped (duplicates or out of space)\n");
459 	p(ips_badfrags, "\t%lu malformed fragment%s dropped\n");
460 	p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
461 	p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
462 	p(ips_delivered, "\t%lu packet%s for this host\n");
463 	p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
464 	p(ips_forward, "\t%lu packet%s forwarded\n");
465 	p(ips_cantforward, "\t%lu packet%s not forwardable\n");
466 	p(ips_redirectsent, "\t%lu redirect%s sent\n");
467 	p(ips_localout, "\t%lu packet%s sent from this host\n");
468 	p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
469 	p(ips_odropped, "\t%lu output packet%s dropped due to no bufs, etc.\n");
470 	p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
471 	p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
472 	p(ips_ofragments, "\t%lu fragment%s created\n");
473 	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
474 	p1(ips_rcvmemdrop, "\t%lu fragment floods\n");
475 	p(ips_toolong, "\t%lu packet%s with ip length > max ip packet size\n");
476 	p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
477 	p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
478 	p(ips_inhwcsum, "\t%lu input datagram%s checksum-processed by hardware\n");
479 	p(ips_outhwcsum, "\t%lu output datagram%s checksum-processed by hardware\n");
480 	p(ips_notmember, "\t%lu multicast packet%s which we don't join\n");
481 #undef p
482 #undef p1
483 }
484 
485 /*
486  * Dump DIVERT statistics structure.
487  */
488 void
489 div_stats(char *name)
490 {
491 	struct divstat divstat;
492 	int mib[] = { CTL_NET, AF_INET, IPPROTO_DIVERT, DIVERTCTL_STATS };
493 	size_t len = sizeof(divstat);
494 
495 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
496 	    &divstat, &len, NULL, 0) == -1) {
497 		if (errno != ENOPROTOOPT)
498 			warn(name);
499 		return;
500 	}
501 
502 	printf("%s:\n", name);
503 #define	p(f, m) if (divstat.f || sflag <= 1) \
504 	printf(m, divstat.f, plural(divstat.f))
505 #define	p1(f, m) if (divstat.f || sflag <= 1) \
506 	printf(m, divstat.f)
507 	p(divs_ipackets, "\t%lu total packet%s received\n");
508 	p1(divs_noport, "\t%lu dropped due to no socket\n");
509 	p1(divs_fullsock, "\t%lu dropped due to full socket buffers\n");
510 	p(divs_opackets, "\t%lu packet%s output\n");
511 	p1(divs_errors, "\t%lu errors\n");
512 #undef p
513 #undef p1
514 }
515 
516 static	char *icmpnames[ICMP_MAXTYPE + 1] = {
517 	"echo reply",
518 	"#1",
519 	"#2",
520 	"destination unreachable",
521 	"source quench",
522 	"routing redirect",
523 	"#6",
524 	"#7",
525 	"echo",
526 	"router advertisement",
527 	"router solicitation",
528 	"time exceeded",
529 	"parameter problem",
530 	"time stamp",
531 	"time stamp reply",
532 	"information request",
533 	"information request reply",
534 	"address mask request",
535 	"address mask reply",
536 	"#19",
537 	"#20",
538 	"#21",
539 	"#22",
540 	"#23",
541 	"#24",
542 	"#25",
543 	"#26",
544 	"#27",
545 	"#28",
546 	"#29",
547 	"traceroute",
548 	"data conversion error",
549 	"mobile host redirect",
550 	"IPv6 where-are-you",
551 	"IPv6 i-am-here",
552 	"mobile registration request",
553 	"mobile registration reply",
554 	"#37",
555 	"#38",
556 	"SKIP",
557 	"Photuris",
558 };
559 
560 /*
561  * Dump ICMP statistics.
562  */
563 void
564 icmp_stats(char *name)
565 {
566 	struct icmpstat icmpstat;
567 	int i, first;
568 	int mib[] = { CTL_NET, AF_INET, IPPROTO_ICMP, ICMPCTL_STATS };
569 	size_t len = sizeof(icmpstat);
570 
571 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
572 	    &icmpstat, &len, NULL, 0) == -1) {
573 		if (errno != ENOPROTOOPT)
574 			warn(name);
575 		return;
576 	}
577 
578 	printf("%s:\n", name);
579 #define	p(f, m) if (icmpstat.f || sflag <= 1) \
580 	printf(m, icmpstat.f, plural(icmpstat.f))
581 
582 	p(icps_error, "\t%lu call%s to icmp_error\n");
583 	p(icps_oldicmp,
584 	    "\t%lu error%s not generated because old message was icmp\n");
585 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
586 		if (icmpstat.icps_outhist[i] != 0) {
587 			if (first) {
588 				printf("\tOutput packet histogram:\n");
589 				first = 0;
590 			}
591 			if (icmpnames[i])
592 				printf("\t\t%s:", icmpnames[i]);
593 			else
594 				printf("\t\t#%d:", i);
595 			printf(" %lu\n", icmpstat.icps_outhist[i]);
596 		}
597 	p(icps_badcode, "\t%lu message%s with bad code fields\n");
598 	p(icps_tooshort, "\t%lu message%s < minimum length\n");
599 	p(icps_checksum, "\t%lu bad checksum%s\n");
600 	p(icps_badlen, "\t%lu message%s with bad length\n");
601 	p(icps_bmcastecho, "\t%lu echo request%s to broadcast/multicast "
602 	    "rejected\n");
603 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
604 		if (icmpstat.icps_inhist[i] != 0) {
605 			if (first) {
606 				printf("\tInput packet histogram:\n");
607 				first = 0;
608 			}
609 			if (icmpnames[i])
610 				printf("\t\t%s:", icmpnames[i]);
611 			else
612 				printf("\t\t#%d:", i);
613 			printf(" %lu\n", icmpstat.icps_inhist[i]);
614 		}
615 	p(icps_reflect, "\t%lu message response%s generated\n");
616 #undef p
617 }
618 
619 /*
620  * Dump IGMP statistics structure.
621  */
622 void
623 igmp_stats(char *name)
624 {
625 	struct igmpstat igmpstat;
626 	int mib[] = { CTL_NET, AF_INET, IPPROTO_IGMP, IGMPCTL_STATS };
627 	size_t len = sizeof(igmpstat);
628 
629 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
630 	    &igmpstat, &len, NULL, 0) == -1) {
631 		if (errno != ENOPROTOOPT)
632 			warn(name);
633 		return;
634 	}
635 
636 	printf("%s:\n", name);
637 #define	p(f, m) if (igmpstat.f || sflag <= 1) \
638 	printf(m, igmpstat.f, plural(igmpstat.f))
639 #define	py(f, m) if (igmpstat.f || sflag <= 1) \
640 	printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
641 
642 	p(igps_rcv_total, "\t%lu message%s received\n");
643 	p(igps_rcv_tooshort, "\t%lu message%s received with too few bytes\n");
644 	p(igps_rcv_badsum, "\t%lu message%s received with bad checksum\n");
645 	py(igps_rcv_queries, "\t%lu membership quer%s received\n");
646 	py(igps_rcv_badqueries, "\t%lu membership quer%s received with invalid field(s)\n");
647 	p(igps_rcv_reports, "\t%lu membership report%s received\n");
648 	p(igps_rcv_badreports, "\t%lu membership report%s received with invalid field(s)\n");
649 	p(igps_rcv_ourreports, "\t%lu membership report%s received for groups to which we belong\n");
650 	p(igps_snd_reports, "\t%lu membership report%s sent\n");
651 #undef p
652 #undef py
653 }
654 
655 /*
656  * Dump PIM statistics structure.
657  */
658 void
659 pim_stats(char *name)
660 {
661 	struct pimstat pimstat;
662 	int mib[] = { CTL_NET, AF_INET, IPPROTO_PIM, PIMCTL_STATS };
663 	size_t len = sizeof(pimstat);
664 
665 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
666 	    &pimstat, &len, NULL, 0) == -1) {
667 		if (errno != ENOPROTOOPT)
668 			warn(name);
669 		return;
670 	}
671 
672 	printf("%s:\n", name);
673 #define	p(f, m) if (pimstat.f || sflag <= 1) \
674 	printf(m, pimstat.f, plural(pimstat.f))
675 #define	py(f, m) if (pimstat.f || sflag <= 1) \
676 	printf(m, pimstat.f, pimstat.f != 1 ? "ies" : "y")
677 
678 	p(pims_rcv_total_msgs, "\t%llu message%s received\n");
679 	p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
680 	p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
681 	p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
682 	p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
683 	p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
684 	p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
685 	p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
686 	p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
687 	p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
688 	p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
689 #undef p
690 #undef py
691 }
692 
693 struct rpcnams {
694 	struct rpcnams *next;
695 	in_port_t port;
696 	int	  proto;
697 	char	*rpcname;
698 };
699 
700 static char *
701 getrpcportnam(in_port_t port, int proto)
702 {
703 	struct sockaddr_in server_addr;
704 	struct hostent *hp;
705 	static struct pmaplist *head;
706 	int socket = RPC_ANYSOCK;
707 	struct timeval minutetimeout;
708 	CLIENT *client;
709 	struct rpcent *rpc;
710 	static int first;
711 	static struct rpcnams *rpcn;
712 	struct rpcnams *n;
713 	char num[20];
714 
715 	if (first == 0) {
716 		first = 1;
717 		memset(&server_addr, 0, sizeof server_addr);
718 		server_addr.sin_family = AF_INET;
719 		if ((hp = gethostbyname("localhost")) != NULL)
720 			memmove((caddr_t)&server_addr.sin_addr, hp->h_addr,
721 			    hp->h_length);
722 		else
723 			(void) inet_aton("0.0.0.0", &server_addr.sin_addr);
724 
725 		minutetimeout.tv_sec = 60;
726 		minutetimeout.tv_usec = 0;
727 		server_addr.sin_port = htons(PMAPPORT);
728 		if ((client = clnttcp_create(&server_addr, PMAPPROG,
729 		    PMAPVERS, &socket, 50, 500)) == NULL)
730 			return (NULL);
731 		if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
732 		    xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
733 			clnt_destroy(client);
734 			return (NULL);
735 		}
736 		for (; head != NULL; head = head->pml_next) {
737 			n = (struct rpcnams *)malloc(sizeof(struct rpcnams));
738 			if (n == NULL)
739 				continue;
740 			n->next = rpcn;
741 			rpcn = n;
742 			n->port = head->pml_map.pm_port;
743 			n->proto = head->pml_map.pm_prot;
744 
745 			rpc = getrpcbynumber(head->pml_map.pm_prog);
746 			if (rpc)
747 				n->rpcname = strdup(rpc->r_name);
748 			else {
749 				snprintf(num, sizeof num, "%ld",
750 				    head->pml_map.pm_prog);
751 				n->rpcname = strdup(num);
752 			}
753 		}
754 		clnt_destroy(client);
755 	}
756 
757 	for (n = rpcn; n; n = n->next)
758 		if (n->port == port && n->proto == proto)
759 			return (n->rpcname);
760 	return (NULL);
761 }
762 
763 /*
764  * Pretty print an Internet address (net address + port).
765  * If the nflag was specified, use numbers instead of names.
766  */
767 void
768 inetprint(struct in_addr *in, in_port_t port, char *proto, int local)
769 {
770 	struct servent *sp = 0;
771 	char line[80], *cp, *nam;
772 	int width;
773 
774 	snprintf(line, sizeof line, "%.*s.", (Aflag && !nflag) ? 12 : 16,
775 	    inetname(in));
776 	cp = strchr(line, '\0');
777 	if (!nflag && port)
778 		sp = getservbyport((int)port, proto);
779 	if (sp || port == 0)
780 		snprintf(cp, line + sizeof line - cp, "%.8s",
781 		    sp ? sp->s_name : "*");
782 	else if (local && !nflag && (nam = getrpcportnam(ntohs(port),
783 	    (strcmp(proto, "tcp") == 0 ? IPPROTO_TCP : IPPROTO_UDP))))
784 		snprintf(cp, line + sizeof line - cp, "%d[%.8s]",
785 		    ntohs(port), nam);
786 	else
787 		snprintf(cp, line + sizeof line - cp, "%d", ntohs(port));
788 	width = Aflag ? 18 : 22;
789 	printf(" %-*.*s", width, width, line);
790 }
791 
792 /*
793  * Construct an Internet address representation.
794  * If the nflag has been supplied, give
795  * numeric value, otherwise try for symbolic name.
796  */
797 char *
798 inetname(struct in_addr *inp)
799 {
800 	char *cp;
801 	static char line[50];
802 	struct hostent *hp;
803 	struct netent *np;
804 	static char domain[MAXHOSTNAMELEN];
805 	static int first = 1;
806 
807 	if (first && !nflag) {
808 		first = 0;
809 		if (gethostname(domain, sizeof(domain)) == 0 &&
810 		    (cp = strchr(domain, '.')))
811 			(void) strlcpy(domain, cp + 1, sizeof domain);
812 		else
813 			domain[0] = '\0';
814 	}
815 	cp = NULL;
816 	if (!nflag && inp->s_addr != INADDR_ANY) {
817 		int net = inet_netof(*inp);
818 		int lna = inet_lnaof(*inp);
819 
820 		if (lna == INADDR_ANY) {
821 			np = getnetbyaddr(net, AF_INET);
822 			if (np)
823 				cp = np->n_name;
824 		}
825 		if (cp == NULL) {
826 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
827 			if (hp) {
828 				if ((cp = strchr(hp->h_name, '.')) &&
829 				    !strcmp(cp + 1, domain))
830 					*cp = '\0';
831 				cp = hp->h_name;
832 			}
833 		}
834 	}
835 	if (inp->s_addr == INADDR_ANY)
836 		snprintf(line, sizeof line, "*");
837 	else if (cp)
838 		snprintf(line, sizeof line, "%s", cp);
839 	else {
840 		inp->s_addr = ntohl(inp->s_addr);
841 #define C(x)	((x) & 0xff)
842 		snprintf(line, sizeof line, "%u.%u.%u.%u",
843 		    C(inp->s_addr >> 24), C(inp->s_addr >> 16),
844 		    C(inp->s_addr >> 8), C(inp->s_addr));
845 	}
846 	return (line);
847 }
848 
849 /*
850  * Dump AH statistics structure.
851  */
852 void
853 ah_stats(char *name)
854 {
855 	struct ahstat ahstat;
856 	int mib[] = { CTL_NET, AF_INET, IPPROTO_AH, AHCTL_STATS };
857 	size_t len = sizeof(ahstat);
858 
859 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
860 	    &ahstat, &len, NULL, 0) == -1) {
861 		if (errno != ENOPROTOOPT)
862 			warn(name);
863 		return;
864 	}
865 
866 	printf("%s:\n", name);
867 #define p(f, m) if (ahstat.f || sflag <= 1) \
868 	printf(m, ahstat.f, plural(ahstat.f))
869 #define p1(f, m) if (ahstat.f || sflag <= 1) \
870 	printf(m, ahstat.f)
871 
872 	p1(ahs_input, "\t%u input AH packets\n");
873 	p1(ahs_output, "\t%u output AH packets\n");
874 	p(ahs_nopf, "\t%u packet%s from unsupported protocol families\n");
875 	p(ahs_hdrops, "\t%u packet%s shorter than header shows\n");
876 	p(ahs_pdrops, "\t%u packet%s dropped due to policy\n");
877 	p(ahs_notdb, "\t%u packet%s for which no TDB was found\n");
878 	p(ahs_badkcr, "\t%u input packet%s that failed to be processed\n");
879 	p(ahs_badauth, "\t%u packet%s that failed verification received\n");
880 	p(ahs_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
881 	p(ahs_qfull, "\t%u packet%s were dropped due to full output queue\n");
882 	p(ahs_wrap, "\t%u packet%s where counter wrapping was detected\n");
883 	p(ahs_replay, "\t%u possibly replayed packet%s received\n");
884 	p(ahs_badauthl, "\t%u packet%s with bad authenticator length received\n");
885 	p(ahs_invalid, "\t%u packet%s attempted to use an invalid TDB\n");
886 	p(ahs_toobig, "\t%u packet%s got larger than max IP packet size\n");
887 	p(ahs_crypto, "\t%u packet%s that failed crypto processing\n");
888 	p(ahs_ibytes, "\t%qu input byte%s\n");
889 	p(ahs_obytes, "\t%qu output byte%s\n");
890 
891 #undef p
892 #undef p1
893 }
894 
895 /*
896  * Dump etherip statistics structure.
897  */
898 void
899 etherip_stats(char *name)
900 {
901 	struct etheripstat etheripstat;
902 	int mib[] = { CTL_NET, AF_INET, IPPROTO_ETHERIP, ETHERIPCTL_STATS };
903 	size_t len = sizeof(etheripstat);
904 
905 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
906 	    &etheripstat, &len, NULL, 0) == -1) {
907 		if (errno != ENOPROTOOPT)
908 			warn(name);
909 		return;
910 	}
911 
912 	printf("%s:\n", name);
913 #define p(f, m) if (etheripstat.f || sflag <= 1) \
914 	printf(m, etheripstat.f, plural(etheripstat.f))
915 
916 	p(etherip_hdrops, "\t%u packet%s shorter than header shows\n");
917 	p(etherip_qfull, "\t%u packet%s were dropped due to full output queue\n");
918 	p(etherip_noifdrops, "\t%u packet%s were dropped because of no interface/bridge information\n");
919 	p(etherip_pdrops, "\t%u packet%s dropped due to policy\n");
920 	p(etherip_adrops, "\t%u packet%s dropped for other reasons\n");
921 	p(etherip_ipackets, "\t%u input ethernet-in-IP packet%s\n");
922 	p(etherip_opackets, "\t%u output ethernet-in-IP packet%s\n");
923 	p(etherip_ibytes, "\t%qu input byte%s\n");
924 	p(etherip_obytes, "\t%qu output byte%s\n");
925 #undef p
926 }
927 
928 /*
929  * Dump ESP statistics structure.
930  */
931 void
932 esp_stats(char *name)
933 {
934 	struct espstat espstat;
935 	int mib[] = { CTL_NET, AF_INET, IPPROTO_ESP, ESPCTL_STATS };
936 	size_t len = sizeof(espstat);
937 
938 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
939 	    &espstat, &len, NULL, 0) == -1) {
940 		if (errno != ENOPROTOOPT)
941 			warn(name);
942 		return;
943 	}
944 
945 	printf("%s:\n", name);
946 #define p(f, m) if (espstat.f || sflag <= 1) \
947 	printf(m, espstat.f, plural(espstat.f))
948 
949 	p(esps_input, "\t%u input ESP packet%s\n");
950 	p(esps_output, "\t%u output ESP packet%s\n");
951 	p(esps_nopf, "\t%u packet%s from unsupported protocol families\n");
952 	p(esps_hdrops, "\t%u packet%s shorter than header shows\n");
953 	p(esps_pdrops, "\t%u packet%s dropped due to policy\n");
954 	p(esps_notdb, "\t%u packet%s for which no TDB was found\n");
955 	p(esps_badkcr, "\t%u input packet%s that failed to be processed\n");
956 	p(esps_badenc, "\t%u packet%s with bad encryption received\n");
957 	p(esps_badauth, "\t%u packet%s that failed verification received\n");
958 	p(esps_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
959 	p(esps_qfull, "\t%u packet%s were dropped due to full output queue\n");
960 	p(esps_wrap, "\t%u packet%s where counter wrapping was detected\n");
961 	p(esps_replay, "\t%u possibly replayed packet%s received\n");
962 	p(esps_badilen, "\t%u packet%s with bad payload size or padding received\n");
963 	p(esps_invalid, "\t%u packet%s attempted to use an invalid TDB\n");
964 	p(esps_toobig, "\t%u packet%s got larger than max IP packet size\n");
965 	p(esps_crypto, "\t%u packet%s that failed crypto processing\n");
966 	p(esps_udpencin, "\t%u input UDP encapsulated ESP packet%s\n");
967 	p(esps_udpencout, "\t%u output UDP encapsulated ESP packet%s\n");
968 	p(esps_udpinval, "\t%u UDP packet%s for non-encapsulating TDB received\n");
969 	p(esps_ibytes, "\t%qu input byte%s\n");
970 	p(esps_obytes, "\t%qu output byte%s\n");
971 
972 #undef p
973 }
974 
975 /*
976  * Dump IP-in-IP statistics structure.
977  */
978 void
979 ipip_stats(char *name)
980 {
981 	struct ipipstat ipipstat;
982 	int mib[] = { CTL_NET, AF_INET, IPPROTO_IPIP, IPIPCTL_STATS };
983 	size_t len = sizeof(ipipstat);
984 
985 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
986 	    &ipipstat, &len, NULL, 0) == -1) {
987 		if (errno != ENOPROTOOPT)
988 			warn(name);
989 		return;
990 	}
991 
992 	printf("%s:\n", name);
993 #define p(f, m) if (ipipstat.f || sflag <= 1) \
994 	printf(m, ipipstat.f, plural(ipipstat.f))
995 
996 	p(ipips_ipackets, "\t%u total input packet%s\n");
997 	p(ipips_opackets, "\t%u total output packet%s\n");
998 	p(ipips_hdrops, "\t%u packet%s shorter than header shows\n");
999 	p(ipips_pdrops, "\t%u packet%s dropped due to policy\n");
1000 	p(ipips_spoof, "\t%u packet%s with possibly spoofed local addresses\n");
1001 	p(ipips_qfull, "\t%u packet%s were dropped due to full output queue\n");
1002 	p(ipips_ibytes, "\t%qu input byte%s\n");
1003 	p(ipips_obytes, "\t%qu output byte%s\n");
1004 	p(ipips_family, "\t%u protocol family mismatche%s\n");
1005 	p(ipips_unspec, "\t%u attempt%s to use tunnel with unspecified endpoint(s)\n");
1006 #undef p
1007 }
1008 
1009 /*
1010  * Dump CARP statistics structure.
1011  */
1012 void
1013 carp_stats(char *name)
1014 {
1015 	struct carpstats carpstat;
1016 	int mib[] = { CTL_NET, AF_INET, IPPROTO_CARP, CARPCTL_STATS };
1017 	size_t len = sizeof(carpstat);
1018 
1019 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
1020 	    &carpstat, &len, NULL, 0) == -1) {
1021 		if (errno != ENOPROTOOPT)
1022 			warn(name);
1023 		return;
1024 	}
1025 
1026 	printf("%s:\n", name);
1027 #define p(f, m) if (carpstat.f || sflag <= 1) \
1028 	printf(m, carpstat.f, plural(carpstat.f))
1029 #define p2(f, m) if (carpstat.f || sflag <= 1) \
1030 	printf(m, carpstat.f)
1031 
1032 	p(carps_ipackets, "\t%llu packet%s received (IPv4)\n");
1033 	p(carps_ipackets6, "\t%llu packet%s received (IPv6)\n");
1034 	p(carps_badif, "\t\t%llu packet%s discarded for bad interface\n");
1035 	p(carps_badttl, "\t\t%llu packet%s discarded for wrong TTL\n");
1036 	p(carps_hdrops, "\t\t%llu packet%s shorter than header\n");
1037 	p(carps_badsum, "\t\t%llu discarded for bad checksum%s\n");
1038 	p(carps_badver,	"\t\t%llu discarded packet%s with a bad version\n");
1039 	p2(carps_badlen, "\t\t%llu discarded because packet too short\n");
1040 	p2(carps_badauth, "\t\t%llu discarded for bad authentication\n");
1041 	p2(carps_badvhid, "\t\t%llu discarded for unknown vhid\n");
1042 	p2(carps_badaddrs, "\t\t%llu discarded because of a bad address list\n");
1043 	p(carps_opackets, "\t%llu packet%s sent (IPv4)\n");
1044 	p(carps_opackets6, "\t%llu packet%s sent (IPv6)\n");
1045 	p2(carps_onomem, "\t\t%llu send failed due to mbuf memory error\n");
1046 	p(carps_preempt, "\t%llu transition%s to master\n");
1047 #undef p
1048 #undef p2
1049 }
1050 
1051 /*
1052  * Dump pfsync statistics structure.
1053  */
1054 void
1055 pfsync_stats(char *name)
1056 {
1057 	struct pfsyncstats pfsyncstat;
1058 	int mib[] = { CTL_NET, AF_INET, IPPROTO_PFSYNC, PFSYNCCTL_STATS };
1059 	size_t len = sizeof(pfsyncstat);
1060 
1061 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
1062 	    &pfsyncstat, &len, NULL, 0) == -1) {
1063 		if (errno != ENOPROTOOPT)
1064 			warn(name);
1065 		return;
1066 	}
1067 
1068 	printf("%s:\n", name);
1069 #define p(f, m) if (pfsyncstat.f || sflag <= 1) \
1070 	printf(m, pfsyncstat.f, plural(pfsyncstat.f))
1071 #define p2(f, m) if (pfsyncstat.f || sflag <= 1) \
1072 	printf(m, pfsyncstat.f)
1073 
1074 	p(pfsyncs_ipackets, "\t%llu packet%s received (IPv4)\n");
1075 	p(pfsyncs_ipackets6, "\t%llu packet%s received (IPv6)\n");
1076 	p(pfsyncs_badif, "\t\t%llu packet%s discarded for bad interface\n");
1077 	p(pfsyncs_badttl, "\t\t%llu packet%s discarded for bad ttl\n");
1078 	p(pfsyncs_hdrops, "\t\t%llu packet%s shorter than header\n");
1079 	p(pfsyncs_badver, "\t\t%llu packet%s discarded for bad version\n");
1080 	p(pfsyncs_badauth, "\t\t%llu packet%s discarded for bad HMAC\n");
1081 	p(pfsyncs_badact,"\t\t%llu packet%s discarded for bad action\n");
1082 	p(pfsyncs_badlen, "\t\t%llu packet%s discarded for short packet\n");
1083 	p(pfsyncs_badval, "\t\t%llu state%s discarded for bad values\n");
1084 	p(pfsyncs_stale, "\t\t%llu stale state%s\n");
1085 	p(pfsyncs_badstate, "\t\t%llu failed state lookup/insert%s\n");
1086 	p(pfsyncs_opackets, "\t%llu packet%s sent (IPv4)\n");
1087 	p(pfsyncs_opackets6, "\t%llu packet%s sent (IPv6)\n");
1088 	p2(pfsyncs_onomem, "\t\t%llu send failed due to mbuf memory error\n");
1089 	p2(pfsyncs_oerrors, "\t\t%llu send error\n");
1090 #undef p
1091 #undef p2
1092 }
1093 
1094 /*
1095  * Dump pflow statistics structure.
1096  */
1097 void
1098 pflow_stats(char *name)
1099 {
1100 	struct pflowstats flowstats;
1101 	int mib[] = { CTL_NET, PF_PFLOW, NET_PFLOW_STATS };
1102 	size_t len = sizeof(struct pflowstats);
1103 
1104 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &flowstats, &len,
1105 	    NULL, 0) == -1) {
1106 		if (errno != ENOPROTOOPT)
1107 			warn(name);
1108 		return;
1109 	}
1110 
1111 	printf("%s:\n", name);
1112 #define p(f, m) if (flowstats.f || sflag <= 1) \
1113 	printf(m, flowstats.f, plural(flowstats.f))
1114 #define p2(f, m) if (flowstats.f || sflag <= 1) \
1115 	printf(m, flowstats.f)
1116 
1117 	p(pflow_flows, "\t%llu flow%s sent\n");
1118 	p(pflow_packets, "\t%llu packet%s sent\n");
1119 	p2(pflow_onomem, "\t\t%llu send failed due to mbuf memory error\n");
1120 	p2(pflow_oerrors, "\t\t%llu send error\n");
1121 #undef p
1122 #undef p2
1123 }
1124 
1125 /*
1126  * Dump IPCOMP statistics structure.
1127  */
1128 void
1129 ipcomp_stats(char *name)
1130 {
1131 	struct ipcompstat ipcompstat;
1132 	int mib[] = { CTL_NET, AF_INET, IPPROTO_IPCOMP, IPCOMPCTL_STATS };
1133 	size_t len = sizeof(ipcompstat);
1134 
1135 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
1136 	    &ipcompstat, &len, NULL, 0) == -1) {
1137 		if (errno != ENOPROTOOPT)
1138 			warn(name);
1139 		return;
1140 	}
1141 
1142 	printf("%s:\n", name);
1143 #define p(f, m) if (ipcompstat.f || sflag <= 1) \
1144 	printf(m, ipcompstat.f, plural(ipcompstat.f))
1145 
1146 	p(ipcomps_input, "\t%u input IPCOMP packet%s\n");
1147 	p(ipcomps_output, "\t%u output IPCOMP packet%s\n");
1148 	p(ipcomps_nopf, "\t%u packet%s from unsupported protocol families\n");
1149 	p(ipcomps_hdrops, "\t%u packet%s shorter than header shows\n");
1150 	p(ipcomps_pdrops, "\t%u packet%s dropped due to policy\n");
1151 	p(ipcomps_notdb, "\t%u packet%s for which no TDB was found\n");
1152 	p(ipcomps_badkcr, "\t%u input packet%s that failed to be processed\n");
1153 	p(ipcomps_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
1154 	p(ipcomps_qfull, "\t%u packet%s were dropped due to full output queue\n");
1155 	p(ipcomps_wrap, "\t%u packet%s where counter wrapping was detected\n");
1156 	p(ipcomps_invalid, "\t%u packet%s attempted to use an invalid TDB\n");
1157 	p(ipcomps_toobig, "\t%u packet%s got larger than max IP packet size\n");
1158 	p(ipcomps_crypto, "\t%u packet%s that failed (de)compression processing\n");
1159 	p(ipcomps_minlen, "\t%u packet%s less than minimum compression length\n");
1160 	p(ipcomps_ibytes, "\t%qu input byte%s\n");
1161 	p(ipcomps_obytes, "\t%qu output byte%s\n");
1162 
1163 #undef p
1164 }
1165 
1166 /*
1167  * Dump the contents of a socket structure
1168  */
1169 void
1170 socket_dump(u_long off)
1171 {
1172 	struct socket so;
1173 
1174 	if (off == 0)
1175 		return;
1176 	kread(off, &so, sizeof(so));
1177 
1178 #define	p(fmt, v, sep) printf(#v " " fmt sep, so.v);
1179 	printf("socket %#lx\n ", off);
1180 	p("%#0.4x", so_type, "\n ");
1181 	p("%#0.4x", so_options, "\n ");
1182 	p("%d", so_linger, "\n ");
1183 	p("%#0.4x", so_state, "\n ");
1184 	p("%p", so_pcb, ", ");
1185 	p("%p", so_proto, ", ");
1186 	p("%p", so_head, "\n ");
1187 	p("%d", so_q0len, ", ");
1188 	p("%d", so_qlen, ", ");
1189 	p("%d", so_qlimit, "\n ");
1190 	p("%d", so_timeo, "\n ");
1191 	p("%u", so_error, "\n ");
1192 	p("%d", so_pgid, ", ");
1193 	p("%u", so_siguid, ", ");
1194 	p("%u", so_sigeuid, "\n ");
1195 	p("%lu", so_oobmark, "\n ");
1196 	p("%p", so_splice, ", ");
1197 	p("%p", so_spliceback, "\n ");
1198 	p("%lld", so_splicelen, ", ");
1199 	p("%lld", so_splicemax, ", ");
1200 	p("%ld", so_idletv.tv_sec, ", ");
1201 	p("%ld", so_idletv.tv_usec, "\n ");
1202 	sockbuf_dump(&so.so_rcv, "so_rcv");
1203 	sockbuf_dump(&so.so_snd, "so_snd");
1204 	p("%u", so_euid, ", ");
1205 	p("%u", so_ruid, ", ");
1206 	p("%u", so_egid, ", ");
1207 	p("%u", so_rgid, "\n ");
1208 	p("%d", so_cpid, "\n");
1209 #undef	p
1210 
1211 	if (!vflag)
1212 		return;
1213 	protosw_dump((u_long)so.so_proto, (u_long)so.so_pcb);
1214 }
1215 
1216 /*
1217  * Dump the contents of a socket buffer
1218  */
1219 void
1220 sockbuf_dump(struct sockbuf *sb, const char *name)
1221 {
1222 #define	p(fmt, v, sep) printf(#v " " fmt sep, sb->v);
1223 	printf("%s ", name);
1224 	p("%lu", sb_cc, ", ");
1225 	p("%lu", sb_datacc, ", ");
1226 	p("%lu", sb_hiwat, ", ");
1227 	p("%lu", sb_wat, "\n ");
1228 	printf("%s ", name);
1229 	p("%lu", sb_mbcnt, ", ");
1230 	p("%lu", sb_mbmax, ", ");
1231 	p("%ld", sb_lowat, "\n ");
1232 	printf("%s ", name);
1233 	p("%#0.4x", sb_flags, ", ");
1234 	p("%u", sb_timeo, "\n ");
1235 #undef	p
1236 }
1237 
1238 /*
1239  * Dump the contents of a protosw structure
1240  */
1241 void
1242 protosw_dump(u_long off, u_long pcb)
1243 {
1244 	struct protosw proto;
1245 
1246 	if (off == 0)
1247 		return;
1248 	kread(off, &proto, sizeof(proto));
1249 
1250 #define	p(fmt, v, sep) printf(#v " " fmt sep, proto.v);
1251 	printf("protosw %#lx\n ", off);
1252 	p("%#0.4x", pr_type, "\n ");
1253 	p("%p", pr_domain, "\n ");
1254 	p("%d", pr_protocol, "\n ");
1255 	p("%#0.4x", pr_flags, "\n");
1256 #undef	p
1257 
1258 	domain_dump((u_long)proto.pr_domain, pcb, proto.pr_protocol);
1259 }
1260 
1261 /*
1262  * Dump the contents of a domain structure
1263  */
1264 void
1265 domain_dump(u_long off, u_long pcb, short protocol)
1266 {
1267 	struct domain dom;
1268 	char name[256];
1269 
1270 	if (off == 0)
1271 		return;
1272 	kread(off, &dom, sizeof(dom));
1273 	kread((u_long)dom.dom_name, name, sizeof(name));
1274 
1275 #define	p(fmt, v, sep) printf(#v " " fmt sep, dom.v);
1276 	printf("domain %#lx\n ", off);
1277 	p("%d", dom_family, "\n ");
1278 	printf("dom_name %.*s\n", sizeof(name), name);
1279 #undef	p
1280 
1281 	switch (dom.dom_family) {
1282 	case AF_INET:
1283 	case AF_INET6:
1284 		inpcb_dump(pcb, protocol, dom.dom_family);
1285 		break;
1286 	case AF_UNIX:
1287 		unpcb_dump(pcb);
1288 		break;
1289 	}
1290 }
1291 
1292 /*
1293  * Dump the contents of a internet PCB
1294  */
1295 void
1296 inpcb_dump(u_long off, short protocol, int af)
1297 {
1298 	struct inpcb inp;
1299 	char faddr[256], laddr[256];
1300 
1301 	if (off == 0)
1302 		return;
1303 	kread(off, &inp, sizeof(inp));
1304 	switch (af) {
1305 	case AF_INET:
1306 		inet_ntop(af, &inp.inp_faddr, faddr, sizeof(faddr));
1307 		inet_ntop(af, &inp.inp_laddr, laddr, sizeof(laddr));
1308 		break;
1309 	case AF_INET6:
1310 		inet_ntop(af, &inp.inp_faddr6, faddr, sizeof(faddr));
1311 		inet_ntop(af, &inp.inp_laddr6, laddr, sizeof(laddr));
1312 		break;
1313 	default:
1314 		faddr[0] = laddr[0] = '\0';
1315 	}
1316 
1317 #define	p(fmt, v, sep) printf(#v " " fmt sep, inp.v);
1318 	printf("inpcb %#lx\n ", off);
1319 	p("%p", inp_table, "\n ");
1320 	printf("inp_faddru %s, inp_laddru %s\n ", faddr, laddr);
1321 	HTONS(inp.inp_fport);
1322 	HTONS(inp.inp_lport);
1323 	p("%u", inp_fport, ", ");
1324 	p("%u", inp_lport, "\n ");
1325 	p("%p", inp_socket, ", ");
1326 	p("%p", inp_ppcb, "\n ");
1327 	p("%#0.8x", inp_flags, "\n ");
1328 	p("%d", inp_hops, "\n ");
1329 	p("%u", inp_seclevel[0], ", ");
1330 	p("%u", inp_seclevel[1], ", ");
1331 	p("%u", inp_seclevel[2], ", ");
1332 	p("%u", inp_seclevel[3], "\n ");
1333 	p("%#x", inp_secrequire, ", ");
1334 	p("%#x", inp_secresult, "\n ");
1335 	p("%u", inp_ip_minttl, "\n ");
1336 	p("%p", inp_tdb_in, ", ");
1337 	p("%p", inp_tdb_out, ", ");
1338 	p("%p", inp_ipo, "\n ");
1339 	p("%p", inp_ipsec_remotecred, ", ");
1340 	p("%p", inp_ipsec_remoteauth, "\n ");
1341 	p("%d", in6p_cksum, "\n ");
1342 	p("%p", inp_icmp6filt, "\n ");
1343 	p("%p", inp_pf_sk, "\n ");
1344 	p("%u", inp_rtableid, "\n ");
1345 	p("%d", inp_pipex, "\n");
1346 #undef	p
1347 
1348 	switch (protocol) {
1349 	case IPPROTO_TCP:
1350 		tcpcb_dump((u_long)inp.inp_ppcb);
1351 		break;
1352 	}
1353 }
1354 
1355 /*
1356  * Dump the contents of a TCP PCB
1357  */
1358 void
1359 tcpcb_dump(u_long off)
1360 {
1361 	struct tcpcb tcpcb;
1362 
1363 	if (off == 0)
1364 		return;
1365 	kread(off, (char *)&tcpcb, sizeof (tcpcb));
1366 
1367 #define	p(fmt, v, sep) printf(#v " " fmt sep, tcpcb.v);
1368 	printf("tcpcb %#lx\n ", off);
1369 	p("%p", t_inpcb, "\n ");
1370 	p("%d", t_state, "");
1371 	if (tcpcb.t_state >= 0 && tcpcb.t_state < TCP_NSTATES)
1372 		printf(" (%s)", tcpstates[tcpcb.t_state]);
1373 	printf("\n ");
1374 	p("%d", t_rxtshift, ", ");
1375 	p("%d", t_rxtcur, ", ");
1376 	p("%d", t_dupacks, "\n ");
1377 	p("%u", t_maxseg, ", ");
1378 	p("%u", t_maxopd, ", ");
1379 	p("%u", t_peermss, "\n ");
1380 	p("0x%x", t_flags, ", ");
1381 	p("%u", t_force, "\n ");
1382 	p("%u", iss, "\n ");
1383 	p("%u", snd_una, ", ");
1384 	p("%u", snd_nxt, ", ");
1385 	p("%u", snd_up, "\n ");
1386 	p("%u", snd_wl1, ", ");
1387 	p("%u", snd_wl2, ", ");
1388 	p("%lu", snd_wnd, "\n ");
1389 	p("%d", sack_enable, ", ");
1390 	p("%d", snd_numholes, ", ");
1391 	p("%u", snd_fack, ", ");
1392 	p("%lu",snd_awnd, "\n ");
1393 	p("%u", retran_data, ", ");
1394 	p("%u", snd_last, "\n ");
1395 	p("%u", irs, "\n ");
1396 	p("%u", rcv_nxt, ", ");
1397 	p("%u", rcv_up, ", ");
1398 	p("%lu", rcv_wnd, "\n ");
1399 	p("%u", rcv_lastsack, "\n ");
1400 	p("%d", rcv_numsacks, "\n ");
1401 	p("%u", rcv_adv, ", ");
1402 	p("%u", snd_max, "\n ");
1403 	p("%lu", snd_cwnd, ", ");
1404 	p("%lu", snd_ssthresh, ", ");
1405 	p("%lu", max_sndwnd, "\n ");
1406 	p("%u", t_rcvtime, ", ");
1407 	p("%u", t_rtttime, ", ");
1408 	p("%u", t_rtseq, "\n ");
1409 	p("%u", t_srtt, ", ");
1410 	p("%u", t_rttvar, ", ");
1411 	p("%u", t_rttmin, "\n ");
1412 	p("%u", t_oobflags, ", ");
1413 	p("%u", t_iobc, "\n ");
1414 	p("%u", t_softerror, "\n ");
1415 	p("%u", snd_scale, ", ");
1416 	p("%u", rcv_scale, ", ");
1417 	p("%u", request_r_scale, ", ");
1418 	p("%u", requested_s_scale, "\n ");
1419 	p("%u", ts_recent, ", ");
1420 	p("%u", ts_recent_age, "\n ");
1421 	p("%u", last_ack_sent, "\n ");
1422 	HTONS(tcpcb.t_pmtud_ip_len);
1423 	HTONS(tcpcb.t_pmtud_nextmtu);
1424 	p("%u", t_pmtud_mss_acked, ", ");
1425 	p("%u", t_pmtud_mtu_sent, "\n ");
1426 	p("%u", t_pmtud_nextmtu, ", ");
1427 	p("%u", t_pmtud_ip_len, ", ");
1428 	p("%u", t_pmtud_ip_hl, "\n ");
1429 	p("%u", t_pmtud_th_seq, "\n ");
1430 	p("%u", pf, "\n");
1431 #undef	p
1432 }
1433