xref: /openbsd-src/usr.bin/netstat/inet.c (revision 8445c53715e7030056b779e8ab40efb7820981f2)
1 /*	$OpenBSD: inet.c,v 1.53 2001/08/26 09:42:04 brian 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. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "from: @(#)inet.c	8.4 (Berkeley) 4/20/94";
40 #else
41 static char *rcsid = "$OpenBSD: inet.c,v 1.53 2001/08/26 09:42:04 brian Exp $";
42 #endif
43 #endif /* not lint */
44 
45 #include <sys/param.h>
46 #include <sys/queue.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/mbuf.h>
50 #include <sys/protosw.h>
51 
52 #include <net/route.h>
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #include <netinet/in_pcb.h>
57 #include <netinet/ip_icmp.h>
58 #include <netinet/icmp_var.h>
59 #include <netinet/igmp_var.h>
60 #include <netinet/ip_var.h>
61 #include <netinet/tcp.h>
62 #include <netinet/tcpip.h>
63 #include <netinet/tcp_seq.h>
64 #define TCPSTATES
65 #include <netinet/tcp_fsm.h>
66 #include <netinet/tcp_timer.h>
67 #include <netinet/tcp_var.h>
68 #include <netinet/tcp_debug.h>
69 #include <netinet/udp.h>
70 #include <netinet/udp_var.h>
71 #include <netinet/ip_ipsp.h>
72 #include <netinet/ip_ah.h>
73 #include <netinet/ip_esp.h>
74 #include <netinet/ip_ipip.h>
75 #include <netinet/ip_ipcomp.h>
76 #include <netinet/ip_ether.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 __P((u_long, char *, int));
96 
97 char	*inetname __P((struct in_addr *));
98 void	inetprint __P((struct in_addr *, int, char *, int));
99 #ifdef INET6
100 char	*inet6name __P((struct in6_addr *));
101 void	inet6print __P((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(off, name)
112 	u_long off;
113 	char *name;
114 {
115 	protopr0(off, name, AF_INET);
116 }
117 
118 #ifdef INET6
119 void
120 ip6protopr(off, name)
121 	u_long off;
122 	char *name;
123 {
124 	protopr0(off, name, AF_INET6);
125 }
126 #endif
127 
128 static void
129 protopr0(off, name, af)
130 	u_long off;
131 	char *name;
132 	int af;
133 {
134 	struct inpcbtable table;
135 	register struct inpcb *head, *next, *prev;
136 	struct inpcb inpcb;
137 	int istcp;
138 	static int first = 1;
139 	char *name0;
140 	char namebuf[20];
141 
142 	name0 = name;
143 	if (off == 0)
144 		return;
145 	istcp = strcmp(name, "tcp") == 0;
146 	kread(off, (char *)&table, sizeof table);
147 	prev = head =
148 	    (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
149 	next = table.inpt_queue.cqh_first;
150 
151 	while (next != head) {
152 		kread((u_long)next, (char *)&inpcb, sizeof inpcb);
153 		if (inpcb.inp_queue.cqe_prev != prev) {
154 			printf("???\n");
155 			break;
156 		}
157 		prev = next;
158 		next = inpcb.inp_queue.cqe_next;
159 
160 		switch (af) {
161 		case AF_INET:
162 			if ((inpcb.inp_flags & INP_IPV6) != 0)
163 				continue;
164 			break;
165 		case AF_INET6:
166 			if ((inpcb.inp_flags & INP_IPV6) == 0)
167 				continue;
168 			break;
169 		default:
170 			break;
171 		}
172 
173 		if (!aflag &&
174 		    inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
175 			continue;
176 		kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
177 		if (istcp) {
178 			kread((u_long)inpcb.inp_ppcb,
179 			    (char *)&tcpcb, sizeof (tcpcb));
180 		}
181 		if (first) {
182 			printf("Active Internet connections");
183 			if (aflag)
184 				printf(" (including servers)");
185 			putchar('\n');
186 			if (Aflag)
187 				printf("%-*.*s %-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n",
188 				    PLEN, PLEN, "PCB", "Proto", "Recv-Q",
189 				    "Send-Q", "Local Address",
190 				    "Foreign Address", "(state)");
191 			else
192 				printf("%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
193 				    "Proto", "Recv-Q", "Send-Q",
194 				    "Local Address", "Foreign Address",
195 				    "(state)");
196 			first = 0;
197 		}
198 		if (Aflag) {
199 			if (istcp)
200 				printf("%*p ", PLEN, inpcb.inp_ppcb);
201 			else
202 				printf("%*p ", PLEN, prev);
203 		}
204 #ifdef INET6
205 		if (inpcb.inp_flags & INP_IPV6) {
206 			strcpy(namebuf, name0);
207 			strcat(namebuf, "6");
208 			name = namebuf;
209 		} else
210 			name = name0;
211 #endif
212 		printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
213 			sockb.so_snd.sb_cc);
214 #ifdef INET6
215 		if (inpcb.inp_flags & INP_IPV6) {
216 			inet6print(&inpcb.inp_laddr6, (int)inpcb.inp_lport,
217 				name, 1);
218 			inet6print(&inpcb.inp_faddr6, (int)inpcb.inp_fport,
219 				name, 0);
220 		} else
221 #endif
222 		{
223 			inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport,
224 				name, 1);
225 			inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport,
226 				name, 0);
227 		}
228 		if (istcp) {
229 			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
230 				printf(" %d", tcpcb.t_state);
231 			else
232 				printf(" %s", tcpstates[tcpcb.t_state]);
233 		}
234 		putchar('\n');
235 	}
236 }
237 
238 /*
239  * Dump TCP statistics structure.
240  */
241 void
242 tcp_stats(off, name)
243 	u_long off;
244 	char *name;
245 {
246 	struct tcpstat tcpstat;
247 
248 	if (off == 0)
249 		return;
250 	printf ("%s:\n", name);
251 	kread(off, (char *)&tcpstat, sizeof (tcpstat));
252 
253 #define	p(f, m) if (tcpstat.f || sflag <= 1) \
254     printf(m, tcpstat.f, plural(tcpstat.f))
255 #define	p1(f, m) if (tcpstat.f || sflag <= 1) \
256     printf(m, tcpstat.f)
257 #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
258     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
259 #define	p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
260     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
261 #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
262     printf(m, tcpstat.f, plurales(tcpstat.f))
263 
264 	p(tcps_sndtotal, "\t%u packet%s sent\n");
265 	p2(tcps_sndpack,tcps_sndbyte,
266 		"\t\t%u data packet%s (%qd byte%s)\n");
267 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
268 		"\t\t%u data packet%s (%qd byte%s) retransmitted\n");
269 	p(tcps_sndrexmitfast, "\t\t%qd fast retransmitted packet%s\n");
270 	p2a(tcps_sndacks, tcps_delack,
271 		"\t\t%u ack-only packet%s (%u delayed)\n");
272 	p(tcps_sndurg, "\t\t%u URG only packet%s\n");
273 	p(tcps_sndprobe, "\t\t%u window probe packet%s\n");
274 	p(tcps_sndwinup, "\t\t%u window update packet%s\n");
275 	p(tcps_sndctrl, "\t\t%u control packet%s\n");
276 	p(tcps_outhwcsum, "\t\t%u packet%s hardware-checksummed\n");
277 	p(tcps_rcvtotal, "\t%u packet%s received\n");
278 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%u ack%s (for %qd byte%s)\n");
279 	p(tcps_rcvdupack, "\t\t%u duplicate ack%s\n");
280 	p(tcps_rcvacktoomuch, "\t\t%u ack%s for unsent data\n");
281 	p2(tcps_rcvpack, tcps_rcvbyte,
282 		"\t\t%u packet%s (%qu byte%s) received in-sequence\n");
283 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
284 		"\t\t%u completely duplicate packet%s (%qd byte%s)\n");
285 	p(tcps_pawsdrop, "\t\t%u old duplicate packet%s\n");
286 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
287 		"\t\t%u packet%s with some dup. data (%qd byte%s duped)\n");
288 	p2(tcps_rcvoopack, tcps_rcvoobyte,
289 		"\t\t%u out-of-order packet%s (%qd byte%s)\n");
290 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
291 		"\t\t%u packet%s (%qd byte%s) of data after window\n");
292 	p(tcps_rcvwinprobe, "\t\t%u window probe%s\n");
293 	p(tcps_rcvwinupd, "\t\t%u window update packet%s\n");
294 	p(tcps_rcvafterclose, "\t\t%u packet%s received after close\n");
295 	p(tcps_rcvbadsum, "\t\t%u discarded for bad checksum%s\n");
296 	p(tcps_rcvbadoff, "\t\t%u discarded for bad header offset field%s\n");
297 	p1(tcps_rcvshort, "\t\t%u discarded because packet too short\n");
298 	p1(tcps_rcvnosec, "\t\t%u discarded for missing IPSec protection\n");
299 	p(tcps_inhwcsum, "\t\t%u packet%s hardware-checksummed\n");
300 	p(tcps_connattempt, "\t%u connection request%s\n");
301 	p(tcps_accepts, "\t%u connection accept%s\n");
302 	p(tcps_connects, "\t%u connection%s established (including accepts)\n");
303 	p2(tcps_closed, tcps_drops,
304 		"\t%u connection%s closed (including %u drop%s)\n");
305 	p(tcps_conndrops, "\t%u embryonic connection%s dropped\n");
306 	p2(tcps_rttupdated, tcps_segstimed,
307 		"\t%u segment%s updated rtt (of %u attempt%s)\n");
308 	p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n");
309 	p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n");
310 	p(tcps_persisttimeo, "\t%u persist timeout%s\n");
311 	p(tcps_keeptimeo, "\t%u keepalive timeout%s\n");
312 	p(tcps_keepprobe, "\t\t%u keepalive probe%s sent\n");
313 	p(tcps_keepdrops, "\t\t%u connection%s dropped by keepalive\n");
314 	p(tcps_predack, "\t%u correct ACK header prediction%s\n");
315 	p(tcps_preddat, "\t%u correct data packet header prediction%s\n");
316 	p3(tcps_pcbhashmiss, "\t%u PCB cache miss%s\n");
317 	p(tcps_badsyn, "\t%u SYN packet%s received with same src/dst address/port\n");
318 #undef p
319 #undef p1
320 #undef p2
321 #undef p2a
322 #undef p3
323 }
324 
325 /*
326  * Dump UDP statistics structure.
327  */
328 void
329 udp_stats(off, name)
330 	u_long off;
331 	char *name;
332 {
333 	struct udpstat udpstat;
334 	u_long delivered;
335 
336 	if (off == 0)
337 		return;
338 	kread(off, (char *)&udpstat, sizeof (udpstat));
339 	printf("%s:\n", name);
340 #define	p(f, m) if (udpstat.f || sflag <= 1) \
341     printf(m, udpstat.f, plural(udpstat.f))
342 #define	p1(f, m) if (udpstat.f || sflag <= 1) \
343     printf(m, udpstat.f)
344 	p(udps_ipackets, "\t%lu datagram%s received\n");
345 	p1(udps_hdrops, "\t%lu with incomplete header\n");
346 	p1(udps_badlen, "\t%lu with bad data length field\n");
347 	p1(udps_badsum, "\t%lu with bad checksum\n");
348 	p1(udps_nosum, "\t%lu with no checksum\n");
349 	p(udps_inhwcsum, "\t%lu input packet%s hardware-checksummed\n");
350 	p(udps_outhwcsum, "\t%lu output packet%s hardware-checksummed\n");
351 	p1(udps_noport, "\t%lu dropped due to no socket\n");
352 	p(udps_noportbcast, "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
353 	p1(udps_nosec, "\t%lu dropped due to missing IPSec protection\n");
354 	p1(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
355 	delivered = udpstat.udps_ipackets -
356 		    udpstat.udps_hdrops -
357 		    udpstat.udps_badlen -
358 		    udpstat.udps_badsum -
359 		    udpstat.udps_noport -
360 		    udpstat.udps_noportbcast -
361 		    udpstat.udps_fullsock;
362 	if (delivered || sflag <= 1)
363 		printf("\t%lu delivered\n", delivered);
364 	p(udps_opackets, "\t%lu datagram%s output\n");
365 	p1(udps_pcbhashmiss, "\t%lu missed PCB cache\n");
366 #undef p
367 #undef p1
368 }
369 
370 /*
371  * Dump IP statistics structure.
372  */
373 void
374 ip_stats(off, name)
375 	u_long off;
376 	char *name;
377 {
378 	struct ipstat ipstat;
379 
380 	if (off == 0)
381 		return;
382 	kread(off, (char *)&ipstat, sizeof (ipstat));
383 	printf("%s:\n", name);
384 
385 #define	p(f, m) if (ipstat.f || sflag <= 1) \
386     printf(m, ipstat.f, plural(ipstat.f))
387 #define	p1(f, m) if (ipstat.f || sflag <= 1) \
388     printf(m, ipstat.f)
389 
390 	p(ips_total, "\t%lu total packet%s received\n");
391 	p(ips_badsum, "\t%lu bad header checksum%s\n");
392 	p1(ips_toosmall, "\t%lu with size smaller than minimum\n");
393 	p1(ips_tooshort, "\t%lu with data size < data length\n");
394 	p1(ips_badhlen, "\t%lu with header length < data size\n");
395 	p1(ips_badlen, "\t%lu with data length < header length\n");
396 	p1(ips_badoptions, "\t%lu with bad options\n");
397 	p1(ips_badvers, "\t%lu with incorrect version number\n");
398 	p(ips_fragments, "\t%lu fragment%s received\n");
399 	p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
400 	p(ips_badfrags, "\t%lu malformed fragment%s dropped\n");
401 	p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
402 	p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
403 	p(ips_delivered, "\t%lu packet%s for this host\n");
404 	p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
405 	p(ips_forward, "\t%lu packet%s forwarded\n");
406 	p(ips_cantforward, "\t%lu packet%s not forwardable\n");
407 	p(ips_redirectsent, "\t%lu redirect%s sent\n");
408 	p(ips_localout, "\t%lu packet%s sent from this host\n");
409 	p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
410 	p(ips_odropped, "\t%lu output packet%s dropped due to no bufs, etc.\n");
411 	p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
412 	p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
413 	p(ips_ofragments, "\t%lu fragment%s created\n");
414 	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
415 	p1(ips_rcvmemdrop, "\t%lu fragment floods\n");
416 	p(ips_toolong, "\t%lu packet%s with ip length > max ip packet size\n");
417 	p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
418 	p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
419 	p(ips_inhwcsum, "\t%lu input datagram%s checksum-processed by hardware\n");
420 	p(ips_outhwcsum, "\t%lu output datagram%s checksum-processed by hardware\n");
421 #undef p
422 #undef p1
423 }
424 
425 static	char *icmpnames[] = {
426 	"echo reply",
427 	"#1",
428 	"#2",
429 	"destination unreachable",
430 	"source quench",
431 	"routing redirect",
432 	"#6",
433 	"#7",
434 	"echo",
435 	"router advertisement",
436 	"router solicitation",
437 	"time exceeded",
438 	"parameter problem",
439 	"time stamp",
440 	"time stamp reply",
441 	"information request",
442 	"information request reply",
443 	"address mask request",
444 	"address mask reply",
445 };
446 
447 /*
448  * Dump ICMP statistics.
449  */
450 void
451 icmp_stats(off, name)
452 	u_long off;
453 	char *name;
454 {
455 	struct icmpstat icmpstat;
456 	register int i, first;
457 
458 	if (off == 0)
459 		return;
460 	kread(off, (char *)&icmpstat, sizeof (icmpstat));
461 	printf("%s:\n", name);
462 
463 #define	p(f, m) if (icmpstat.f || sflag <= 1) \
464     printf(m, icmpstat.f, plural(icmpstat.f))
465 
466 	p(icps_error, "\t%lu call%s to icmp_error\n");
467 	p(icps_oldicmp,
468 	    "\t%lu error%s not generated 'cuz old message was icmp\n");
469 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
470 		if (icmpstat.icps_outhist[i] != 0) {
471 			if (first) {
472 				printf("\tOutput packet histogram:\n");
473 				first = 0;
474 			}
475 			printf("\t\t%s: %lu\n", icmpnames[i],
476 				icmpstat.icps_outhist[i]);
477 		}
478 	p(icps_badcode, "\t%lu message%s with bad code fields\n");
479 	p(icps_tooshort, "\t%lu message%s < minimum length\n");
480 	p(icps_checksum, "\t%lu bad checksum%s\n");
481 	p(icps_badlen, "\t%lu message%s with bad length\n");
482 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
483 		if (icmpstat.icps_inhist[i] != 0) {
484 			if (first) {
485 				printf("\tInput packet histogram:\n");
486 				first = 0;
487 			}
488 			printf("\t\t%s: %lu\n", icmpnames[i],
489 				icmpstat.icps_inhist[i]);
490 		}
491 	p(icps_reflect, "\t%lu message response%s generated\n");
492 #undef p
493 }
494 
495 /*
496  * Dump IGMP statistics structure.
497  */
498 void
499 igmp_stats(off, name)
500 	u_long off;
501 	char *name;
502 {
503 	struct igmpstat igmpstat;
504 
505 	if (off == 0)
506 		return;
507 	kread(off, (char *)&igmpstat, sizeof (igmpstat));
508 	printf("%s:\n", name);
509 
510 #define	p(f, m) if (igmpstat.f || sflag <= 1) \
511     printf(m, igmpstat.f, plural(igmpstat.f))
512 #define	py(f, m) if (igmpstat.f || sflag <= 1) \
513     printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
514 	p(igps_rcv_total, "\t%lu message%s received\n");
515         p(igps_rcv_tooshort, "\t%lu message%s received with too few bytes\n");
516         p(igps_rcv_badsum, "\t%lu message%s received with bad checksum\n");
517         py(igps_rcv_queries, "\t%lu membership quer%s received\n");
518         py(igps_rcv_badqueries, "\t%lu membership quer%s received with invalid field(s)\n");
519         p(igps_rcv_reports, "\t%lu membership report%s received\n");
520         p(igps_rcv_badreports, "\t%lu membership report%s received with invalid field(s)\n");
521         p(igps_rcv_ourreports, "\t%lu membership report%s received for groups to which we belong\n");
522         p(igps_snd_reports, "\t%lu membership report%s sent\n");
523 #undef p
524 #undef py
525 }
526 
527 struct rpcnams {
528 	struct rpcnams *next;
529 	in_port_t port;
530 	int	  proto;
531 	char	*rpcname;
532 };
533 
534 char *
535 getrpcportnam(port, proto)
536 	in_port_t port;
537 	int proto;
538 {
539 	struct sockaddr_in server_addr;
540 	register struct hostent *hp;
541 	static struct pmaplist *head;
542 	int socket = RPC_ANYSOCK;
543 	struct timeval minutetimeout;
544 	register CLIENT *client;
545 	struct rpcent *rpc;
546 	static int first;
547 	static struct rpcnams *rpcn;
548 	struct rpcnams *n;
549 	char num[20];
550 
551 	if (first == 0) {
552 		first = 1;
553 		memset((char *)&server_addr, 0, sizeof server_addr);
554 		server_addr.sin_family = AF_INET;
555 		if ((hp = gethostbyname("localhost")) != NULL)
556 			memmove((caddr_t)&server_addr.sin_addr, hp->h_addr,
557 			    hp->h_length);
558 		else
559 			(void) inet_aton("0.0.0.0", &server_addr.sin_addr);
560 
561 		minutetimeout.tv_sec = 60;
562 		minutetimeout.tv_usec = 0;
563 		server_addr.sin_port = htons(PMAPPORT);
564 		if ((client = clnttcp_create(&server_addr, PMAPPROG,
565 		    PMAPVERS, &socket, 50, 500)) == NULL)
566 			return (NULL);
567 		if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
568 		    xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
569 			clnt_destroy(client);
570 			return (NULL);
571 		}
572 		for (; head != NULL; head = head->pml_next) {
573 			n = (struct rpcnams *)malloc(sizeof(struct rpcnams));
574 			if (n == NULL)
575 				continue;
576 			n->next = rpcn;
577 			rpcn = n;
578 			n->port = head->pml_map.pm_port;
579 			n->proto = head->pml_map.pm_prot;
580 
581 			rpc = getrpcbynumber(head->pml_map.pm_prog);
582 			if (rpc)
583 				n->rpcname = strdup(rpc->r_name);
584 			else {
585 				snprintf(num, sizeof num, "%ld",
586 				    head->pml_map.pm_prog);
587 				n->rpcname = strdup(num);
588 			}
589 		}
590 		clnt_destroy(client);
591 	}
592 
593 	for (n = rpcn; n; n = n->next)
594 		if (n->port == port && n->proto == proto)
595 			return (n->rpcname);
596 	return (NULL);
597 }
598 
599 /*
600  * Pretty print an Internet address (net address + port).
601  * If the nflag was specified, use numbers instead of names.
602  */
603 void
604 inetprint(in, port, proto, local)
605 	register struct in_addr *in;
606 	in_port_t port;
607 	char *proto;
608 	int local;
609 {
610 	struct servent *sp = 0;
611 	char line[80], *cp, *nam;
612 	int width;
613 
614 	snprintf(line, sizeof line, "%.*s.", (Aflag && !nflag) ? 12 : 16,
615 	    inetname(in));
616 	cp = strchr(line, '\0');
617 	if (!nflag && port)
618 		sp = getservbyport((int)port, proto);
619 	if (sp || port == 0)
620 		snprintf(cp, line + sizeof line - cp, "%.8s",
621 		    sp ? sp->s_name : "*");
622 	else if (local && !nflag && (nam = getrpcportnam(ntohs(port),
623 	    (strcmp(proto, "tcp") == 0 ? IPPROTO_TCP : IPPROTO_UDP))))
624 		snprintf(cp, line + sizeof line - cp, "%d[%.8s]",
625 		    ntohs(port), nam);
626 	else
627 		snprintf(cp, line + sizeof line - cp, "%d", ntohs(port));
628 	width = Aflag ? 18 : 22;
629 	printf(" %-*.*s", width, width, line);
630 }
631 
632 /*
633  * Construct an Internet address representation.
634  * If the nflag has been supplied, give
635  * numeric value, otherwise try for symbolic name.
636  */
637 char *
638 inetname(inp)
639 	struct in_addr *inp;
640 {
641 	register char *cp;
642 	static char line[50];
643 	struct hostent *hp;
644 	struct netent *np;
645 	static char domain[MAXHOSTNAMELEN + 1];
646 	static int first = 1;
647 
648 	if (first && !nflag) {
649 		first = 0;
650 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
651 		    (cp = strchr(domain, '.')))
652 			(void) strcpy(domain, cp + 1);
653 		else
654 			domain[0] = 0;
655 	}
656 	cp = 0;
657 	if (!nflag && inp->s_addr != INADDR_ANY) {
658 		int net = inet_netof(*inp);
659 		int lna = inet_lnaof(*inp);
660 
661 		if (lna == INADDR_ANY) {
662 			np = getnetbyaddr(net, AF_INET);
663 			if (np)
664 				cp = np->n_name;
665 		}
666 		if (cp == 0) {
667 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
668 			if (hp) {
669 				if ((cp = strchr(hp->h_name, '.')) &&
670 				    !strcmp(cp + 1, domain))
671 					*cp = 0;
672 				cp = hp->h_name;
673 			}
674 		}
675 	}
676 	if (inp->s_addr == INADDR_ANY)
677 		snprintf(line, sizeof line, "*");
678 	else if (cp)
679 		snprintf(line, sizeof line, "%s", cp);
680 	else {
681 		inp->s_addr = ntohl(inp->s_addr);
682 #define C(x)	((x) & 0xff)
683 		snprintf(line, sizeof line, "%u.%u.%u.%u",
684 		    C(inp->s_addr >> 24), C(inp->s_addr >> 16),
685 		    C(inp->s_addr >> 8), C(inp->s_addr));
686 	}
687 	return (line);
688 }
689 
690 /*
691  * Dump AH statistics structure.
692  */
693 void
694 ah_stats(off, name)
695         u_long off;
696         char *name;
697 {
698         struct ahstat ahstat;
699 
700         if (off == 0)
701                 return;
702         kread(off, (char *)&ahstat, sizeof (ahstat));
703         printf("%s:\n", name);
704 
705 #define p(f, m) if (ahstat.f || sflag <= 1) \
706     printf(m, ahstat.f, plural(ahstat.f))
707 #define p1(f, m) if (ahstat.f || sflag <= 1) \
708     printf(m, ahstat.f)
709 
710 	p1(ahs_input, "\t%u input AH packets\n");
711 	p1(ahs_output, "\t%u output AH packets\n");
712         p(ahs_nopf, "\t%u packet%s from unsupported protocol families\n");
713         p(ahs_hdrops, "\t%u packet%s shorter than header shows\n");
714         p(ahs_pdrops, "\t%u packet%s dropped due to policy\n");
715         p(ahs_notdb, "\t%u packet%s for which no TDB was found\n");
716         p(ahs_badkcr, "\t%u input packet%s that failed to be processed\n");
717         p(ahs_badauth, "\t%u packet%s that failed verification received\n");
718         p(ahs_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
719         p(ahs_qfull, "\t%u packet%s were dropped due to full output queue\n");
720         p(ahs_wrap, "\t%u packet%s where counter wrapping was detected\n");
721         p(ahs_replay, "\t%u possibly replayed packet%s received\n");
722         p(ahs_badauthl, "\t%u packet%s with bad authenticator length received\n");
723 	p(ahs_invalid, "\t%u packet%s attempted to use an invalid tdb\n");
724 	p(ahs_toobig, "\t%u packet%s got larger than max IP packet size\n");
725 	p(ahs_crypto, "\t%u packet%s that failed crypto processing\n");
726 	p(ahs_ibytes, "\t%qu input byte%s\n");
727 	p(ahs_obytes, "\t%qu output byte%s\n");
728 
729 #undef p
730 #undef p1
731 }
732 
733 /*
734  * Dump etherip statistics structure.
735  */
736 void
737 etherip_stats(off, name)
738 	u_long off;
739 	char *name;
740 {
741         struct etheripstat etheripstat;
742 
743 
744         if (off == 0)
745                 return;
746         kread(off, (char *)&etheripstat, sizeof (etheripstat));
747         printf("%s:\n", name);
748 
749 #define p(f, m) if (etheripstat.f || sflag <= 1) \
750     printf(m, etheripstat.f, plural(etheripstat.f))
751 
752 
753 	p(etherip_hdrops, "\t%u packet%s shorter than header shows\n");
754 	p(etherip_qfull, "\t%u packet%s were dropped due to full output queue\n");
755 	p(etherip_noifdrops, "\t%u packet%s were dropped because of no interface/bridge information\n");
756 	p(etherip_pdrops, "\t%u packet%s dropped due to policy\n");
757 	p(etherip_adrops, "\t%u packet%s dropped for other reasons\n");
758 	p(etherip_ipackets, "\t%u input ethernet-in-IP packet%s\n");
759 	p(etherip_opackets, "\t%u output ethernet-in-IP packet%s\n");
760 	p(etherip_ibytes, "\t%qu input byte%s\n");
761 	p(etherip_obytes, "\t%qu output byte%s\n");
762 #undef p
763 }
764 
765 /*
766  * Dump ESP statistics structure.
767  */
768 void
769 esp_stats(off, name)
770         u_long off;
771         char *name;
772 {
773         struct espstat espstat;
774 
775 
776         if (off == 0)
777                 return;
778         kread(off, (char *)&espstat, sizeof (espstat));
779         printf("%s:\n", name);
780 
781 #define p(f, m) if (espstat.f || sflag <= 1) \
782     printf(m, espstat.f, plural(espstat.f))
783 
784 	p(esps_input, "\t%u input ESP packet%s\n");
785 	p(esps_output, "\t%u output ESP packet%s\n");
786         p(esps_nopf, "\t%u packet%s from unsupported protocol families\n");
787         p(esps_hdrops, "\t%u packet%s shorter than header shows\n");
788         p(esps_pdrops, "\t%u packet%s dropped due to policy\n");
789         p(esps_notdb, "\t%u packet%s for which no TDB was found\n");
790         p(esps_badkcr, "\t%u input packet%s that failed to be processed\n");
791         p(esps_badenc, "\t%u packet%s with bad encryption received\n");
792         p(esps_badauth, "\t%u packet%s that failed verification received\n");
793         p(esps_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
794         p(esps_qfull, "\t%u packet%s were dropped due to full output queue\n");
795         p(esps_wrap, "\t%u packet%s where counter wrapping was detected\n");
796         p(esps_replay, "\t%u possibly replayed packet%s received\n");
797         p(esps_badilen, "\t%u packet%s with bad payload size or padding received\n");
798 	p(esps_invalid, "\t%u packet%s attempted to use an invalid tdb\n");
799 	p(esps_toobig, "\t%u packet%s got larger than max IP packet size\n");
800 	p(esps_crypto, "\t%u packet%s that failed crypto processing\n");
801 	p(esps_ibytes, "\t%qu input byte%s\n");
802 	p(esps_obytes, "\t%qu output byte%s\n");
803 
804 #undef p
805 }
806 
807 /*
808  * Dump ESP statistics structure.
809  */
810 void
811 ipip_stats(off, name)
812         u_long off;
813         char *name;
814 {
815         struct ipipstat ipipstat;
816 
817         if (off == 0)
818                 return;
819         kread(off, (char *)&ipipstat, sizeof (ipipstat));
820         printf("%s:\n", name);
821 
822 #define p(f, m) if (ipipstat.f || sflag <= 1) \
823     printf(m, ipipstat.f, plural(ipipstat.f))
824 
825         p(ipips_ipackets, "\t%u total input packet%s\n");
826         p(ipips_opackets, "\t%u total output packet%s\n");
827         p(ipips_hdrops, "\t%u packet%s shorter than header shows\n");
828         p(ipips_pdrops, "\t%u packet%s dropped due to policy\n");
829         p(ipips_spoof, "\t%u packet%s with possibly spoofed local addresses\n");
830         p(ipips_qfull, "\t%u packet%s were dropped due to full output queue\n");
831 	p(ipips_ibytes, "\t%qu input byte%s\n");
832 	p(ipips_obytes, "\t%qu output byte%s\n");
833 	p(ipips_family, "\t%u protocol family mismatches\n");
834 	p(ipips_unspec, "\t%u attempts to use tunnel with unspecified endpoint(s)\n");
835 #undef p
836 }
837 
838 /*
839  * Dump IPCOMP statistics structure.
840  */
841 void
842 ipcomp_stats(off, name)
843 	u_long off;
844 	char *name;
845 {
846 	struct ipcompstat ipcompstat;
847 
848 
849 	if (off == 0)
850 		return;
851 	kread(off, (char *)&ipcompstat, sizeof (ipcompstat));
852 	printf("%s:\n", name);
853 
854 #define p(f, m) if (ipcompstat.f || sflag <= 1) \
855     printf(m, ipcompstat.f, plural(ipcompstat.f))
856 
857 	p(ipcomps_input, "\t%u input IPCOMP packet%s\n");
858 	p(ipcomps_output, "\t%u output IPCOMP packet%s\n");
859 	p(ipcomps_nopf, "\t%u packet%s from unsupported protocol families\n");
860 	p(ipcomps_hdrops, "\t%u packet%s shorter than header shows\n");
861 	p(ipcomps_pdrops, "\t%u packet%s dropped due to policy\n");
862 	p(ipcomps_notdb, "\t%u packet%s for which no TDB was found\n");
863 	p(ipcomps_badkcr, "\t%u input packet%s that failed to be processed\n");
864 	p(ipcomps_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n");
865 	p(ipcomps_qfull, "\t%u packet%s were dropped due to full output queue\n");
866 	p(ipcomps_wrap, "\t%u packet%s where counter wrapping was detected\n");
867 	p(ipcomps_invalid, "\t%u packet%s attempted to use an invalid tdb\n");
868 	p(ipcomps_toobig, "\t%u packet%s got larger than max IP packet size\n");
869 	p(ipcomps_crypto, "\t%u packet%s that failed (de)compression processing\n");
870 	p(ipcomps_ibytes, "\t%qu input byte%s\n");
871 	p(ipcomps_obytes, "\t%qu output byte%s\n");
872 
873 #undef p
874 }
875