xref: /openbsd-src/usr.bin/netstat/inet.c (revision 5738bc6274bbfbba95d07e5dc8d380a26b687449)
1 /*	$OpenBSD: inet.c,v 1.88 2004/09/09 10:30:23 otto 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 #ifndef lint
34 #if 0
35 static char sccsid[] = "from: @(#)inet.c	8.4 (Berkeley) 4/20/94";
36 #else
37 static const char *rcsid = "$OpenBSD: inet.c,v 1.88 2004/09/09 10:30:23 otto Exp $";
38 #endif
39 #endif /* not lint */
40 
41 #include <sys/param.h>
42 #include <sys/queue.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/mbuf.h>
46 #include <sys/protosw.h>
47 
48 #include <net/route.h>
49 #include <netinet/in.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/ip.h>
52 #include <netinet/in_pcb.h>
53 #include <netinet/ip_icmp.h>
54 #include <netinet/icmp_var.h>
55 #include <netinet/igmp_var.h>
56 #include <netinet/ip_var.h>
57 #include <netinet/tcp.h>
58 #include <netinet/tcpip.h>
59 #include <netinet/tcp_seq.h>
60 #define TCPSTATES
61 #include <netinet/tcp_fsm.h>
62 #include <netinet/tcp_timer.h>
63 #include <netinet/tcp_var.h>
64 #include <netinet/tcp_debug.h>
65 #include <netinet/udp.h>
66 #include <netinet/udp_var.h>
67 #include <netinet/ip_ipsp.h>
68 #include <netinet/ip_ah.h>
69 #include <netinet/ip_esp.h>
70 #include <netinet/ip_ipip.h>
71 #include <netinet/ip_ipcomp.h>
72 #include <netinet/ip_ether.h>
73 #include <netinet/ip_carp.h>
74 #include <net/if.h>
75 #include <net/pfvar.h>
76 #include <net/if_pfsync.h>
77 
78 #include <arpa/inet.h>
79 #include <limits.h>
80 #include <netdb.h>
81 #include <stdio.h>
82 #include <string.h>
83 #include <unistd.h>
84 #include <stdlib.h>
85 #include "netstat.h"
86 
87 #include <rpc/rpc.h>
88 #include <rpc/pmap_prot.h>
89 #include <rpc/pmap_clnt.h>
90 
91 struct	inpcb inpcb;
92 struct	tcpcb tcpcb;
93 struct	socket sockb;
94 
95 static void protopr0(u_long, char *, int);
96 
97 char	*inetname(struct in_addr *);
98 void	inetprint(struct in_addr *, in_port_t, char *, int);
99 #ifdef INET6
100 char	*inet6name(struct in6_addr *);
101 void	inet6print(struct in6_addr *, int, char *, int);
102 #endif
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)
112 {
113 	protopr0(off, name, AF_INET);
114 }
115 
116 #ifdef INET6
117 void
118 ip6protopr(u_long off, char *name)
119 {
120 	protopr0(off, name, AF_INET6);
121 }
122 #endif
123 
124 static void
125 protopr0(u_long off, char *name, int af)
126 {
127 	struct inpcbtable table;
128 	struct inpcb *head, *next, *prev;
129 	struct inpcb inpcb;
130 	int istcp, israw;
131 	int first = 1;
132 	char *name0;
133 	char namebuf[20];
134 
135 	name0 = name;
136 	if (off == 0)
137 		return;
138 	istcp = strcmp(name, "tcp") == 0;
139 	israw = strncmp(name, "ip", 2) == 0;
140 	kread(off, (char *)&table, sizeof table);
141 	prev = head =
142 	    (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
143 	next = table.inpt_queue.cqh_first;
144 
145 	while (next != head) {
146 		kread((u_long)next, (char *)&inpcb, sizeof inpcb);
147 		if (inpcb.inp_queue.cqe_prev != prev) {
148 			printf("???\n");
149 			break;
150 		}
151 		prev = next;
152 		next = inpcb.inp_queue.cqe_next;
153 
154 		switch (af) {
155 		case AF_INET:
156 			if ((inpcb.inp_flags & INP_IPV6) != 0)
157 				continue;
158 			break;
159 		case AF_INET6:
160 			if ((inpcb.inp_flags & INP_IPV6) == 0)
161 				continue;
162 			break;
163 		default:
164 			break;
165 		}
166 
167 		if (!aflag &&
168 		    inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
169 			continue;
170 		kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
171 		if (istcp) {
172 			kread((u_long)inpcb.inp_ppcb,
173 			    (char *)&tcpcb, sizeof (tcpcb));
174 		}
175 		if (first) {
176 			printf("Active Internet connections");
177 			if (aflag)
178 				printf(" (including servers)");
179 			putchar('\n');
180 			if (Aflag)
181 				printf("%-*.*s %-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n",
182 				    PLEN, PLEN, "PCB", "Proto", "Recv-Q",
183 				    "Send-Q", "Local Address",
184 				    "Foreign Address", "(state)");
185 			else
186 				printf("%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
187 				    "Proto", "Recv-Q", "Send-Q",
188 				    "Local Address", "Foreign Address",
189 				    "(state)");
190 			first = 0;
191 		}
192 		if (Aflag) {
193 			if (istcp)
194 				printf("%*p ", PLEN, inpcb.inp_ppcb);
195 			else
196 				printf("%*p ", PLEN, prev);
197 		}
198 #ifdef INET6
199 		if (inpcb.inp_flags & INP_IPV6 && !israw) {
200 			strlcpy(namebuf, name0, sizeof namebuf);
201 			strlcat(namebuf, "6", sizeof namebuf);
202 			name = namebuf;
203 		} else
204 			name = name0;
205 #endif
206 		printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
207 		    sockb.so_snd.sb_cc);
208 #ifdef INET6
209 		if (inpcb.inp_flags & INP_IPV6) {
210 			inet6print(&inpcb.inp_laddr6, (int)inpcb.inp_lport,
211 			    name, 1);
212 			inet6print(&inpcb.inp_faddr6, (int)inpcb.inp_fport,
213 			    name, 0);
214 		} else
215 #endif
216 		{
217 			inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport,
218 			    name, 1);
219 			inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport,
220 			    name, 0);
221 		}
222 		if (istcp) {
223 			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
224 				printf(" %d", tcpcb.t_state);
225 			else
226 				printf(" %s", tcpstates[tcpcb.t_state]);
227 		} else if (israw) {
228 			u_int8_t proto;
229 #ifdef INET6
230 			if (inpcb.inp_flags & INP_IPV6)
231 				proto = inpcb.inp_ipv6.ip6_nxt;
232 			else
233 #endif
234 				proto = inpcb.inp_ip.ip_p;
235 			printf(" %u", proto);
236 		}
237 		putchar('\n');
238 	}
239 }
240 
241 /*
242  * Dump TCP statistics structure.
243  */
244 void
245 tcp_stats(u_long off, char *name)
246 {
247 	struct tcpstat tcpstat;
248 
249 	if (off == 0)
250 		return;
251 	printf("%s:\n", name);
252 	kread(off, (char *)&tcpstat, sizeof (tcpstat));
253 
254 #define	p(f, m) if (tcpstat.f || sflag <= 1) \
255 	printf(m, tcpstat.f, plural(tcpstat.f))
256 #define	p1(f, m) if (tcpstat.f || sflag <= 1) \
257 	printf(m, tcpstat.f)
258 #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
259 	printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
260 #define	p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
261 	printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
262 #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
263 	printf(m, tcpstat.f, plurales(tcpstat.f))
264 
265 	p(tcps_sndtotal, "\t%u packet%s sent\n");
266 	p2(tcps_sndpack,tcps_sndbyte,
267 	    "\t\t%u data packet%s (%qd byte%s)\n");
268 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
269 	    "\t\t%u data packet%s (%qd byte%s) retransmitted\n");
270 	p(tcps_sndrexmitfast, "\t\t%qd fast retransmitted packet%s\n");
271 	p2a(tcps_sndacks, tcps_delack,
272 	    "\t\t%u ack-only packet%s (%u delayed)\n");
273 	p(tcps_sndurg, "\t\t%u URG only packet%s\n");
274 	p(tcps_sndprobe, "\t\t%u window probe packet%s\n");
275 	p(tcps_sndwinup, "\t\t%u window update packet%s\n");
276 	p(tcps_sndctrl, "\t\t%u control packet%s\n");
277 	p(tcps_outhwcsum, "\t\t%u packet%s hardware-checksummed\n");
278 	p(tcps_rcvtotal, "\t%u packet%s received\n");
279 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%u ack%s (for %qd byte%s)\n");
280 	p(tcps_rcvdupack, "\t\t%u duplicate ack%s\n");
281 	p(tcps_rcvacktoomuch, "\t\t%u ack%s for unsent data\n");
282 	p(tcps_rcvacktooold, "\t\t%u ack%s for old data\n");
283 	p2(tcps_rcvpack, tcps_rcvbyte,
284 	    "\t\t%u packet%s (%qu byte%s) received in-sequence\n");
285 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
286 	    "\t\t%u completely duplicate packet%s (%qd byte%s)\n");
287 	p(tcps_pawsdrop, "\t\t%u old duplicate packet%s\n");
288 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
289 	    "\t\t%u packet%s with some duplicate data (%qd byte%s duplicated)\n");
290 	p2(tcps_rcvoopack, tcps_rcvoobyte,
291 	    "\t\t%u out-of-order packet%s (%qd byte%s)\n");
292 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
293 	    "\t\t%u packet%s (%qd byte%s) of data after window\n");
294 	p(tcps_rcvwinprobe, "\t\t%u window probe%s\n");
295 	p(tcps_rcvwinupd, "\t\t%u window update packet%s\n");
296 	p(tcps_rcvafterclose, "\t\t%u packet%s received after close\n");
297 	p(tcps_rcvbadsum, "\t\t%u discarded for bad checksum%s\n");
298 	p(tcps_rcvbadoff, "\t\t%u discarded for bad header offset field%s\n");
299 	p1(tcps_rcvshort, "\t\t%u discarded because packet too short\n");
300 	p1(tcps_rcvnosec, "\t\t%u discarded for missing IPsec protection\n");
301 	p1(tcps_rcvmemdrop, "\t\t%u discarded due to memory shortage\n");
302 	p(tcps_inhwcsum, "\t\t%u packet%s hardware-checksummed\n");
303 	p(tcps_rcvbadsig, "\t\t%u bad/missing md5 checksum%s\n");
304 	p(tcps_rcvgoodsig, "\t\t%qd good md5 checksum%s\n");
305 	p(tcps_connattempt, "\t%u connection request%s\n");
306 	p(tcps_accepts, "\t%u connection accept%s\n");
307 	p(tcps_connects, "\t%u connection%s established (including accepts)\n");
308 	p2(tcps_closed, tcps_drops,
309 	    "\t%u connection%s closed (including %u drop%s)\n");
310 	p(tcps_conndrained, "\t%qd connection%s drained\n");
311 	p(tcps_conndrops, "\t%u embryonic connection%s dropped\n");
312 	p2(tcps_rttupdated, tcps_segstimed,
313 	    "\t%u segment%s updated rtt (of %u attempt%s)\n");
314 	p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n");
315 	p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n");
316 	p(tcps_persisttimeo, "\t%u persist timeout%s\n");
317 	p(tcps_keeptimeo, "\t%u keepalive timeout%s\n");
318 	p(tcps_keepprobe, "\t\t%u keepalive probe%s sent\n");
319 	p(tcps_keepdrops, "\t\t%u connection%s dropped by keepalive\n");
320 	p(tcps_predack, "\t%u correct ACK header prediction%s\n");
321 	p(tcps_preddat, "\t%u correct data packet header prediction%s\n");
322 	p3(tcps_pcbhashmiss, "\t%u PCB cache miss%s\n");
323 
324 	p(tcps_ecn_accepts, "\t%u ECN connection%s accepted\n");
325 	p(tcps_ecn_rcvece, "\t\t%u ECE packet%s received\n");
326 	p(tcps_ecn_rcvcwr, "\t\t%u CWR packet%s received\n");
327 	p(tcps_ecn_rcvce, "\t\t%u CE packet%s received\n");
328 	p(tcps_ecn_sndect, "\t\t%u ECT packet%s sent\n");
329 	p(tcps_ecn_sndece, "\t\t%u ECE packet%s sent\n");
330 	p(tcps_ecn_sndcwr, "\t\t%u CWR packet%s sent\n");
331 	p1(tcps_cwr_frecovery, "\t\t\tcwr by fastrecovery: %u\n");
332 	p1(tcps_cwr_timeout, "\t\t\tcwr by timeout: %u\n");
333 	p1(tcps_cwr_ecn, "\t\t\tcwr by ecn: %u\n");
334 
335 	p(tcps_badsyn, "\t%u bad connection attempt%s\n");
336 	p1(tcps_sc_added, "\t%qd SYN cache entries added\n");
337 	p(tcps_sc_collisions, "\t\t%qd hash collision%s\n");
338 	p1(tcps_sc_completed, "\t\t%qd completed\n");
339 	p1(tcps_sc_aborted, "\t\t%qd aborted (no space to build PCB)\n");
340 	p1(tcps_sc_timed_out, "\t\t%qd timed out\n");
341 	p1(tcps_sc_overflowed, "\t\t%qd dropped due to overflow\n");
342 	p1(tcps_sc_bucketoverflow, "\t\t%qd dropped due to bucket overflow\n");
343 	p1(tcps_sc_reset, "\t\t%qd dropped due to RST\n");
344 	p1(tcps_sc_unreach, "\t\t%qd dropped due to ICMP unreachable\n");
345 	p(tcps_sc_retransmitted, "\t%qd SYN,ACK%s retransmitted\n");
346 	p(tcps_sc_dupesyn, "\t%qd duplicate SYN%s received for entries "
347 		"already in the cache\n");
348 	p(tcps_sc_dropped, "\t%qd SYN%s dropped (no route or no space)\n");
349 
350 #undef p
351 #undef p1
352 #undef p2
353 #undef p2a
354 #undef p3
355 }
356 
357 /*
358  * Dump UDP statistics structure.
359  */
360 void
361 udp_stats(u_long off, char *name)
362 {
363 	struct udpstat udpstat;
364 	u_long delivered;
365 
366 	if (off == 0)
367 		return;
368 	kread(off, (char *)&udpstat, sizeof (udpstat));
369 	printf("%s:\n", name);
370 #define	p(f, m) if (udpstat.f || sflag <= 1) \
371 	printf(m, udpstat.f, plural(udpstat.f))
372 #define	p1(f, m) if (udpstat.f || sflag <= 1) \
373 	printf(m, udpstat.f)
374 
375 	p(udps_ipackets, "\t%lu datagram%s received\n");
376 	p1(udps_hdrops, "\t%lu with incomplete header\n");
377 	p1(udps_badlen, "\t%lu with bad data length field\n");
378 	p1(udps_badsum, "\t%lu with bad checksum\n");
379 	p1(udps_nosum, "\t%lu with no checksum\n");
380 	p(udps_inhwcsum, "\t%lu input packet%s hardware-checksummed\n");
381 	p(udps_outhwcsum, "\t%lu output packet%s hardware-checksummed\n");
382 	p1(udps_noport, "\t%lu dropped due to no socket\n");
383 	p(udps_noportbcast, "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
384 	p1(udps_nosec, "\t%lu dropped due to missing IPsec protection\n");
385 	p1(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
386 	delivered = udpstat.udps_ipackets - udpstat.udps_hdrops -
387 	    udpstat.udps_badlen - udpstat.udps_badsum -
388 	    udpstat.udps_noport - udpstat.udps_noportbcast -
389 	    udpstat.udps_fullsock;
390 	if (delivered || sflag <= 1)
391 		printf("\t%lu delivered\n", delivered);
392 	p(udps_opackets, "\t%lu datagram%s output\n");
393 	p1(udps_pcbhashmiss, "\t%lu missed PCB cache\n");
394 #undef p
395 #undef p1
396 }
397 
398 /*
399  * Dump IP statistics structure.
400  */
401 void
402 ip_stats(u_long off, char *name)
403 {
404 	struct ipstat ipstat;
405 
406 	if (off == 0)
407 		return;
408 	kread(off, (char *)&ipstat, sizeof (ipstat));
409 	printf("%s:\n", name);
410 
411 #define	p(f, m) if (ipstat.f || sflag <= 1) \
412 	printf(m, ipstat.f, plural(ipstat.f))
413 #define	p1(f, m) if (ipstat.f || sflag <= 1) \
414 	printf(m, ipstat.f)
415 
416 	p(ips_total, "\t%lu total packet%s received\n");
417 	p(ips_badsum, "\t%lu bad header checksum%s\n");
418 	p1(ips_toosmall, "\t%lu with size smaller than minimum\n");
419 	p1(ips_tooshort, "\t%lu with data size < data length\n");
420 	p1(ips_badhlen, "\t%lu with header length < data size\n");
421 	p1(ips_badlen, "\t%lu with data length < header length\n");
422 	p1(ips_badoptions, "\t%lu with bad options\n");
423 	p1(ips_badvers, "\t%lu with incorrect version number\n");
424 	p(ips_fragments, "\t%lu fragment%s received\n");
425 	p(ips_fragdropped, "\t%lu fragment%s dropped (duplicates or out of space)\n");
426 	p(ips_badfrags, "\t%lu malformed fragment%s dropped\n");
427 	p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
428 	p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
429 	p(ips_delivered, "\t%lu packet%s for this host\n");
430 	p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
431 	p(ips_forward, "\t%lu packet%s forwarded\n");
432 	p(ips_cantforward, "\t%lu packet%s not forwardable\n");
433 	p(ips_redirectsent, "\t%lu redirect%s sent\n");
434 	p(ips_localout, "\t%lu packet%s sent from this host\n");
435 	p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
436 	p(ips_odropped, "\t%lu output packet%s dropped due to no bufs, etc.\n");
437 	p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
438 	p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
439 	p(ips_ofragments, "\t%lu fragment%s created\n");
440 	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
441 	p1(ips_rcvmemdrop, "\t%lu fragment floods\n");
442 	p(ips_toolong, "\t%lu packet%s with ip length > max ip packet size\n");
443 	p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
444 	p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
445 	p(ips_inhwcsum, "\t%lu input datagram%s checksum-processed by hardware\n");
446 	p(ips_outhwcsum, "\t%lu output datagram%s checksum-processed by hardware\n");
447 #undef p
448 #undef p1
449 }
450 
451 static	char *icmpnames[ICMP_MAXTYPE + 1] = {
452 	"echo reply",
453 	"#1",
454 	"#2",
455 	"destination unreachable",
456 	"source quench",
457 	"routing redirect",
458 	"#6",
459 	"#7",
460 	"echo",
461 	"router advertisement",
462 	"router solicitation",
463 	"time exceeded",
464 	"parameter problem",
465 	"time stamp",
466 	"time stamp reply",
467 	"information request",
468 	"information request reply",
469 	"address mask request",
470 	"address mask reply",
471 	"#19",
472 	"#20",
473 	"#21",
474 	"#22",
475 	"#23",
476 	"#24",
477 	"#25",
478 	"#26",
479 	"#27",
480 	"#28",
481 	"#29",
482 	"traceroute",
483 	"data conversion error",
484 	"mobile host redirect",
485 	"IPv6 where-are-you",
486 	"IPv6 i-am-here",
487 	"mobile registration request",
488 	"mobile registration reply",
489 	"#37",
490 	"#38",
491 	"SKIP",
492 	"Photuris",
493 };
494 
495 /*
496  * Dump ICMP statistics.
497  */
498 void
499 icmp_stats(u_long off, char *name)
500 {
501 	struct icmpstat icmpstat;
502 	int i, first;
503 
504 	if (off == 0)
505 		return;
506 	kread(off, (char *)&icmpstat, sizeof (icmpstat));
507 	printf("%s:\n", name);
508 
509 #define	p(f, m) if (icmpstat.f || sflag <= 1) \
510 	printf(m, icmpstat.f, plural(icmpstat.f))
511 
512 	p(icps_error, "\t%lu call%s to icmp_error\n");
513 	p(icps_oldicmp,
514 	    "\t%lu error%s not generated because old message was icmp\n");
515 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
516 		if (icmpstat.icps_outhist[i] != 0) {
517 			if (first) {
518 				printf("\tOutput packet histogram:\n");
519 				first = 0;
520 			}
521 			if (icmpnames[i])
522 				printf("\t\t%s:", icmpnames[i]);
523 			else
524 				printf("\t\t#%d:", i);
525 			printf(" %lu\n", icmpstat.icps_outhist[i]);
526 		}
527 	p(icps_badcode, "\t%lu message%s with bad code fields\n");
528 	p(icps_tooshort, "\t%lu message%s < minimum length\n");
529 	p(icps_checksum, "\t%lu bad checksum%s\n");
530 	p(icps_badlen, "\t%lu message%s with bad length\n");
531 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
532 		if (icmpstat.icps_inhist[i] != 0) {
533 			if (first) {
534 				printf("\tInput packet histogram:\n");
535 				first = 0;
536 			}
537 			if (icmpnames[i])
538 				printf("\t\t%s:", icmpnames[i]);
539 			else
540 				printf("\t\t#%d:", i);
541 			printf(" %lu\n", icmpstat.icps_inhist[i]);
542 		}
543 	p(icps_reflect, "\t%lu message response%s generated\n");
544 #undef p
545 }
546 
547 /*
548  * Dump IGMP statistics structure.
549  */
550 void
551 igmp_stats(u_long off, char *name)
552 {
553 	struct igmpstat igmpstat;
554 
555 	if (off == 0)
556 		return;
557 	kread(off, (char *)&igmpstat, sizeof (igmpstat));
558 	printf("%s:\n", name);
559 
560 #define	p(f, m) if (igmpstat.f || sflag <= 1) \
561 	printf(m, igmpstat.f, plural(igmpstat.f))
562 #define	py(f, m) if (igmpstat.f || sflag <= 1) \
563 	printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
564 
565 	p(igps_rcv_total, "\t%lu message%s received\n");
566 	p(igps_rcv_tooshort, "\t%lu message%s received with too few bytes\n");
567 	p(igps_rcv_badsum, "\t%lu message%s received with bad checksum\n");
568 	py(igps_rcv_queries, "\t%lu membership quer%s received\n");
569 	py(igps_rcv_badqueries, "\t%lu membership quer%s received with invalid field(s)\n");
570 	p(igps_rcv_reports, "\t%lu membership report%s received\n");
571 	p(igps_rcv_badreports, "\t%lu membership report%s received with invalid field(s)\n");
572 	p(igps_rcv_ourreports, "\t%lu membership report%s received for groups to which we belong\n");
573 	p(igps_snd_reports, "\t%lu membership report%s sent\n");
574 #undef p
575 #undef py
576 }
577 
578 struct rpcnams {
579 	struct rpcnams *next;
580 	in_port_t port;
581 	int	  proto;
582 	char	*rpcname;
583 };
584 
585 static char *
586 getrpcportnam(in_port_t port, int proto)
587 {
588 	struct sockaddr_in server_addr;
589 	struct hostent *hp;
590 	static struct pmaplist *head;
591 	int socket = RPC_ANYSOCK;
592 	struct timeval minutetimeout;
593 	CLIENT *client;
594 	struct rpcent *rpc;
595 	static int first;
596 	static struct rpcnams *rpcn;
597 	struct rpcnams *n;
598 	char num[20];
599 
600 	if (first == 0) {
601 		first = 1;
602 		memset((char *)&server_addr, 0, sizeof server_addr);
603 		server_addr.sin_family = AF_INET;
604 		if ((hp = gethostbyname("localhost")) != NULL)
605 			memmove((caddr_t)&server_addr.sin_addr, hp->h_addr,
606 			    hp->h_length);
607 		else
608 			(void) inet_aton("0.0.0.0", &server_addr.sin_addr);
609 
610 		minutetimeout.tv_sec = 60;
611 		minutetimeout.tv_usec = 0;
612 		server_addr.sin_port = htons(PMAPPORT);
613 		if ((client = clnttcp_create(&server_addr, PMAPPROG,
614 		    PMAPVERS, &socket, 50, 500)) == NULL)
615 			return (NULL);
616 		if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
617 		    xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
618 			clnt_destroy(client);
619 			return (NULL);
620 		}
621 		for (; head != NULL; head = head->pml_next) {
622 			n = (struct rpcnams *)malloc(sizeof(struct rpcnams));
623 			if (n == NULL)
624 				continue;
625 			n->next = rpcn;
626 			rpcn = n;
627 			n->port = head->pml_map.pm_port;
628 			n->proto = head->pml_map.pm_prot;
629 
630 			rpc = getrpcbynumber(head->pml_map.pm_prog);
631 			if (rpc)
632 				n->rpcname = strdup(rpc->r_name);
633 			else {
634 				snprintf(num, sizeof num, "%ld",
635 				    head->pml_map.pm_prog);
636 				n->rpcname = strdup(num);
637 			}
638 		}
639 		clnt_destroy(client);
640 	}
641 
642 	for (n = rpcn; n; n = n->next)
643 		if (n->port == port && n->proto == proto)
644 			return (n->rpcname);
645 	return (NULL);
646 }
647 
648 /*
649  * Pretty print an Internet address (net address + port).
650  * If the nflag was specified, use numbers instead of names.
651  */
652 void
653 inetprint(struct in_addr *in, in_port_t port, char *proto, int local)
654 {
655 	struct servent *sp = 0;
656 	char line[80], *cp, *nam;
657 	int width;
658 
659 	snprintf(line, sizeof line, "%.*s.", (Aflag && !nflag) ? 12 : 16,
660 	    inetname(in));
661 	cp = strchr(line, '\0');
662 	if (!nflag && port)
663 		sp = getservbyport((int)port, proto);
664 	if (sp || port == 0)
665 		snprintf(cp, line + sizeof line - cp, "%.8s",
666 		    sp ? sp->s_name : "*");
667 	else if (local && !nflag && (nam = getrpcportnam(ntohs(port),
668 	    (strcmp(proto, "tcp") == 0 ? IPPROTO_TCP : IPPROTO_UDP))))
669 		snprintf(cp, line + sizeof line - cp, "%d[%.8s]",
670 		    ntohs(port), nam);
671 	else
672 		snprintf(cp, line + sizeof line - cp, "%d", ntohs(port));
673 	width = Aflag ? 18 : 22;
674 	printf(" %-*.*s", width, width, line);
675 }
676 
677 /*
678  * Construct an Internet address representation.
679  * If the nflag has been supplied, give
680  * numeric value, otherwise try for symbolic name.
681  */
682 char *
683 inetname(struct in_addr *inp)
684 {
685 	char *cp;
686 	static char line[50];
687 	struct hostent *hp;
688 	struct netent *np;
689 	static char domain[MAXHOSTNAMELEN];
690 	static int first = 1;
691 
692 	if (first && !nflag) {
693 		first = 0;
694 		if (gethostname(domain, sizeof(domain)) == 0 &&
695 		    (cp = strchr(domain, '.')))
696 			(void) strlcpy(domain, cp + 1, sizeof domain);
697 		else
698 			domain[0] = '\0';
699 	}
700 	cp = NULL;
701 	if (!nflag && inp->s_addr != INADDR_ANY) {
702 		int net = inet_netof(*inp);
703 		int lna = inet_lnaof(*inp);
704 
705 		if (lna == INADDR_ANY) {
706 			np = getnetbyaddr(net, AF_INET);
707 			if (np)
708 				cp = np->n_name;
709 		}
710 		if (cp == NULL) {
711 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
712 			if (hp) {
713 				if ((cp = strchr(hp->h_name, '.')) &&
714 				    !strcmp(cp + 1, domain))
715 					*cp = '\0';
716 				cp = hp->h_name;
717 			}
718 		}
719 	}
720 	if (inp->s_addr == INADDR_ANY)
721 		snprintf(line, sizeof line, "*");
722 	else if (cp)
723 		snprintf(line, sizeof line, "%s", cp);
724 	else {
725 		inp->s_addr = ntohl(inp->s_addr);
726 #define C(x)	((x) & 0xff)
727 		snprintf(line, sizeof line, "%u.%u.%u.%u",
728 		    C(inp->s_addr >> 24), C(inp->s_addr >> 16),
729 		    C(inp->s_addr >> 8), C(inp->s_addr));
730 	}
731 	return (line);
732 }
733 
734 /*
735  * Dump AH statistics structure.
736  */
737 void
738 ah_stats(u_long off, char *name)
739 {
740 	struct ahstat ahstat;
741 
742 	if (off == 0)
743 		return;
744 	kread(off, (char *)&ahstat, sizeof (ahstat));
745 	printf("%s:\n", name);
746 
747 #define p(f, m) if (ahstat.f || sflag <= 1) \
748 	printf(m, ahstat.f, plural(ahstat.f))
749 #define p1(f, m) if (ahstat.f || sflag <= 1) \
750 	printf(m, ahstat.f)
751 
752 	p1(ahs_input, "\t%u input AH packets\n");
753 	p1(ahs_output, "\t%u output AH packets\n");
754 	p(ahs_nopf, "\t%u packet%s from unsupported protocol families\n");
755 	p(ahs_hdrops, "\t%u packet%s shorter than header shows\n");
756 	p(ahs_pdrops, "\t%u packet%s dropped due to policy\n");
757 	p(ahs_notdb, "\t%u packet%s for which no TDB was found\n");
758 	p(ahs_badkcr, "\t%u input packet%s that failed to be processed\n");
759 	p(ahs_badauth, "\t%u packet%s that failed verification received\n");
760 	p(ahs_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
761 	p(ahs_qfull, "\t%u packet%s were dropped due to full output queue\n");
762 	p(ahs_wrap, "\t%u packet%s where counter wrapping was detected\n");
763 	p(ahs_replay, "\t%u possibly replayed packet%s received\n");
764 	p(ahs_badauthl, "\t%u packet%s with bad authenticator length received\n");
765 	p(ahs_invalid, "\t%u packet%s attempted to use an invalid TDB\n");
766 	p(ahs_toobig, "\t%u packet%s got larger than max IP packet size\n");
767 	p(ahs_crypto, "\t%u packet%s that failed crypto processing\n");
768 	p(ahs_ibytes, "\t%qu input byte%s\n");
769 	p(ahs_obytes, "\t%qu output byte%s\n");
770 
771 #undef p
772 #undef p1
773 }
774 
775 /*
776  * Dump etherip statistics structure.
777  */
778 void
779 etherip_stats(u_long off, char *name)
780 {
781 	struct etheripstat etheripstat;
782 
783 	if (off == 0)
784 		return;
785 	kread(off, (char *)&etheripstat, sizeof (etheripstat));
786 	printf("%s:\n", name);
787 
788 #define p(f, m) if (etheripstat.f || sflag <= 1) \
789 	printf(m, etheripstat.f, plural(etheripstat.f))
790 
791 	p(etherip_hdrops, "\t%u packet%s shorter than header shows\n");
792 	p(etherip_qfull, "\t%u packet%s were dropped due to full output queue\n");
793 	p(etherip_noifdrops, "\t%u packet%s were dropped because of no interface/bridge information\n");
794 	p(etherip_pdrops, "\t%u packet%s dropped due to policy\n");
795 	p(etherip_adrops, "\t%u packet%s dropped for other reasons\n");
796 	p(etherip_ipackets, "\t%u input ethernet-in-IP packet%s\n");
797 	p(etherip_opackets, "\t%u output ethernet-in-IP packet%s\n");
798 	p(etherip_ibytes, "\t%qu input byte%s\n");
799 	p(etherip_obytes, "\t%qu output byte%s\n");
800 #undef p
801 }
802 
803 /*
804  * Dump ESP statistics structure.
805  */
806 void
807 esp_stats(u_long off, char *name)
808 {
809 	struct espstat espstat;
810 
811 	if (off == 0)
812 		return;
813 	kread(off, (char *)&espstat, sizeof (espstat));
814 	printf("%s:\n", name);
815 
816 #define p(f, m) if (espstat.f || sflag <= 1) \
817 	printf(m, espstat.f, plural(espstat.f))
818 
819 	p(esps_input, "\t%u input ESP packet%s\n");
820 	p(esps_output, "\t%u output ESP packet%s\n");
821 	p(esps_nopf, "\t%u packet%s from unsupported protocol families\n");
822 	p(esps_hdrops, "\t%u packet%s shorter than header shows\n");
823 	p(esps_pdrops, "\t%u packet%s dropped due to policy\n");
824 	p(esps_notdb, "\t%u packet%s for which no TDB was found\n");
825 	p(esps_badkcr, "\t%u input packet%s that failed to be processed\n");
826 	p(esps_badenc, "\t%u packet%s with bad encryption received\n");
827 	p(esps_badauth, "\t%u packet%s that failed verification received\n");
828 	p(esps_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
829 	p(esps_qfull, "\t%u packet%s were dropped due to full output queue\n");
830 	p(esps_wrap, "\t%u packet%s where counter wrapping was detected\n");
831 	p(esps_replay, "\t%u possibly replayed packet%s received\n");
832 	p(esps_badilen, "\t%u packet%s with bad payload size or padding received\n");
833 	p(esps_invalid, "\t%u packet%s attempted to use an invalid TDB\n");
834 	p(esps_toobig, "\t%u packet%s got larger than max IP packet size\n");
835 	p(esps_crypto, "\t%u packet%s that failed crypto processing\n");
836 	p(esps_udpencin, "\t%u input UDP encapsulated ESP packet%s\n");
837 	p(esps_udpencout, "\t%u output UDP encapsulated ESP packet%s\n");
838 	p(esps_udpinval, "\t%u UDP packet%s for non-encapsulating TDB received\n");
839 	p(esps_ibytes, "\t%qu input byte%s\n");
840 	p(esps_obytes, "\t%qu output byte%s\n");
841 
842 #undef p
843 }
844 
845 /*
846  * Dump IP-in-IP statistics structure.
847  */
848 void
849 ipip_stats(u_long off, char *name)
850 {
851 	struct ipipstat ipipstat;
852 
853 	if (off == 0)
854 		return;
855 	kread(off, (char *)&ipipstat, sizeof (ipipstat));
856 	printf("%s:\n", name);
857 
858 #define p(f, m) if (ipipstat.f || sflag <= 1) \
859 	printf(m, ipipstat.f, plural(ipipstat.f))
860 
861 	p(ipips_ipackets, "\t%u total input packet%s\n");
862 	p(ipips_opackets, "\t%u total output packet%s\n");
863 	p(ipips_hdrops, "\t%u packet%s shorter than header shows\n");
864 	p(ipips_pdrops, "\t%u packet%s dropped due to policy\n");
865 	p(ipips_spoof, "\t%u packet%s with possibly spoofed local addresses\n");
866 	p(ipips_qfull, "\t%u packet%s were dropped due to full output queue\n");
867 	p(ipips_ibytes, "\t%qu input byte%s\n");
868 	p(ipips_obytes, "\t%qu output byte%s\n");
869 	p(ipips_family, "\t%u protocol family mismatche%s\n");
870 	p(ipips_unspec, "\t%u attempt%s to use tunnel with unspecified endpoint(s)\n");
871 #undef p
872 }
873 
874 /*
875  * Dump CARP statistics structure.
876  */
877 void
878 carp_stats(u_long off, char *name)
879 {
880 	struct carpstats carpstat;
881 
882 	if (off == 0)
883 		return;
884 	kread(off, (char *)&carpstat, sizeof(carpstat));
885 	printf("%s:\n", name);
886 
887 #define p(f, m) if (carpstat.f || sflag <= 1) \
888 	printf(m, carpstat.f, plural(carpstat.f))
889 #define p2(f, m) if (carpstat.f || sflag <= 1) \
890 	printf(m, carpstat.f)
891 
892 	p(carps_ipackets, "\t%llu packet%s received (IPv4)\n");
893 	p(carps_ipackets6, "\t%llu packet%s received (IPv6)\n");
894 	p(carps_badif, "\t\t%llu packet%s discarded for bad interface\n");
895 	p(carps_hdrops, "\t\t%llu packet%s shorter than header\n");
896 	p(carps_badsum, "\t\t%llu discarded for bad checksum%s\n");
897 	p(carps_badver,	"\t\t%llu discarded packet%s with a bad version\n");
898 	p2(carps_badlen, "\t\t%llu discarded because packet too short\n");
899 	p2(carps_badauth, "\t\t%llu discarded for bad authentication\n");
900 	p2(carps_badvhid, "\t\t%llu discarded for bad vhid\n");
901 	p2(carps_badaddrs, "\t\t%llu discarded because of a bad address list\n");
902 	p(carps_opackets, "\t%llu packet%s sent (IPv4)\n");
903 	p(carps_opackets6, "\t%llu packet%s sent (IPv6)\n");
904 #undef p
905 #undef p2
906 }
907 
908 /*
909  * Dump pfsync statistics structure.
910  */
911 void
912 pfsync_stats(u_long off, char *name)
913 {
914 	struct pfsyncstats pfsyncstat;
915 
916 	if (off == 0)
917 		return;
918 	kread(off, (char *)&pfsyncstat, sizeof(pfsyncstat));
919 	printf("%s:\n", name);
920 
921 #define p(f, m) if (pfsyncstat.f || sflag <= 1) \
922 	printf(m, pfsyncstat.f, plural(pfsyncstat.f))
923 #define p2(f, m) if (pfsyncstat.f || sflag <= 1) \
924 	printf(m, pfsyncstat.f)
925 
926 	p(pfsyncs_ipackets, "\t%llu packet%s received (IPv4)\n");
927 	p(pfsyncs_ipackets6, "\t%llu packet%s received (IPv6)\n");
928 	p(pfsyncs_badif, "\t\t%llu packet%s discarded for bad interface\n");
929 	p(pfsyncs_badttl, "\t\t%llu packet%s discarded for bad ttl\n");
930 	p(pfsyncs_hdrops, "\t\t%llu packet%s shorter than header\n");
931 	p(pfsyncs_badver, "\t\t%llu packet%s discarded for bad version\n");
932 	p(pfsyncs_badauth, "\t\t%llu packet%s discarded for bad HMAC\n");
933 	p(pfsyncs_badact,"\t\t%llu packet%s discarded for bad action\n");
934 	p(pfsyncs_badlen, "\t\t%llu packet%s discarded for short packet\n");
935 	p(pfsyncs_badval, "\t\t%llu state%s discarded for bad values\n");
936 	p(pfsyncs_stale, "\t\t%llu stale state%s\n");
937 	p(pfsyncs_badstate, "\t\t%llu failed state lookup/insert%s\n");
938 	p(pfsyncs_opackets, "\t%llu packet%s sent (IPv4)\n");
939 	p(pfsyncs_opackets6, "\t%llu packet%s sent (IPv6)\n");
940 	p2(pfsyncs_onomem, "\t\t%llu send failed due to mbuf memory error\n");
941 	p2(pfsyncs_oerrors, "\t\t%llu send error\n");
942 #undef p
943 #undef p2
944 }
945 
946 /*
947  * Dump IPCOMP statistics structure.
948  */
949 void
950 ipcomp_stats(u_long off, char *name)
951 {
952 	struct ipcompstat ipcompstat;
953 
954 	if (off == 0)
955 		return;
956 	kread(off, (char *)&ipcompstat, sizeof (ipcompstat));
957 	printf("%s:\n", name);
958 
959 #define p(f, m) if (ipcompstat.f || sflag <= 1) \
960 	printf(m, ipcompstat.f, plural(ipcompstat.f))
961 
962 	p(ipcomps_input, "\t%u input IPCOMP packet%s\n");
963 	p(ipcomps_output, "\t%u output IPCOMP packet%s\n");
964 	p(ipcomps_nopf, "\t%u packet%s from unsupported protocol families\n");
965 	p(ipcomps_hdrops, "\t%u packet%s shorter than header shows\n");
966 	p(ipcomps_pdrops, "\t%u packet%s dropped due to policy\n");
967 	p(ipcomps_notdb, "\t%u packet%s for which no TDB was found\n");
968 	p(ipcomps_badkcr, "\t%u input packet%s that failed to be processed\n");
969 	p(ipcomps_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
970 	p(ipcomps_qfull, "\t%u packet%s were dropped due to full output queue\n");
971 	p(ipcomps_wrap, "\t%u packet%s where counter wrapping was detected\n");
972 	p(ipcomps_invalid, "\t%u packet%s attempted to use an invalid TDB\n");
973 	p(ipcomps_toobig, "\t%u packet%s got larger than max IP packet size\n");
974 	p(ipcomps_crypto, "\t%u packet%s that failed (de)compression processing\n");
975 	p(ipcomps_minlen, "\t%u packet%s less than minimum compression length\n");
976 	p(ipcomps_ibytes, "\t%qu input byte%s\n");
977 	p(ipcomps_obytes, "\t%qu output byte%s\n");
978 
979 #undef p
980 }
981