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