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