xref: /netbsd-src/usr.bin/netstat/inet6.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: inet6.c,v 1.31 2003/11/06 06:11:48 itojun Exp $	*/
2 /*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6  * 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 project 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 PROJECT 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 PROJECT 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 /*
34  * Copyright (c) 1983, 1988, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. Neither the name of the University nor the names of its contributors
46  *    may be used to endorse or promote products derived from this software
47  *    without specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  */
61 
62 #include <sys/cdefs.h>
63 #ifndef lint
64 #if 0
65 static char sccsid[] = "@(#)inet.c	8.4 (Berkeley) 4/20/94";
66 #else
67 __RCSID("$NetBSD: inet6.c,v 1.31 2003/11/06 06:11:48 itojun Exp $");
68 #endif
69 #endif /* not lint */
70 
71 #include <sys/param.h>
72 #include <sys/socket.h>
73 #include <sys/socketvar.h>
74 #include <sys/ioctl.h>
75 #include <sys/mbuf.h>
76 #include <sys/protosw.h>
77 
78 #include <net/route.h>
79 #include <net/if.h>
80 #include <netinet/in.h>
81 #include <netinet/ip6.h>
82 #include <netinet/icmp6.h>
83 #include <netinet/in_systm.h>
84 #ifndef TCP6
85 #include <netinet/ip.h>
86 #include <netinet/ip_var.h>
87 #endif
88 #include <netinet6/ip6_var.h>
89 #include <netinet6/in6_pcb.h>
90 #include <netinet6/in6_var.h>
91 #include <netinet6/ip6_var.h>
92 #ifdef TCP6
93 #include <netinet6/tcp6.h>
94 #include <netinet6/tcp6_seq.h>
95 #define TCP6STATES
96 #include <netinet6/tcp6_fsm.h>
97 #define TCP6TIMERS
98 #include <netinet6/tcp6_timer.h>
99 #include <netinet6/tcp6_var.h>
100 #include <netinet6/tcp6_debug.h>
101 #else
102 #include <netinet/tcp.h>
103 #include <netinet/tcpip.h>
104 #include <netinet/tcp_seq.h>
105 /*#define TCPSTATES*/
106 #include <netinet/tcp_fsm.h>
107 extern char *tcpstates[];
108 /*#define	TCPTIMERS*/
109 #include <netinet/tcp_timer.h>
110 #include <netinet/tcp_var.h>
111 #include <netinet/tcp_debug.h>
112 #endif /*TCP6*/
113 #include <netinet6/udp6.h>
114 #include <netinet6/udp6_var.h>
115 #include <netinet6/pim6_var.h>
116 #include <netinet6/raw_ip6.h>
117 
118 #include <arpa/inet.h>
119 #if 0
120 #include "gethostbyname2.h"
121 #endif
122 #include <netdb.h>
123 
124 #include <stdio.h>
125 #include <string.h>
126 #include <unistd.h>
127 #include "netstat.h"
128 
129 #ifdef INET6
130 
131 struct	in6pcb in6pcb;
132 #ifdef TCP6
133 struct	tcp6cb tcp6cb;
134 #else
135 struct	tcpcb tcpcb;
136 #endif
137 struct	socket sockb;
138 
139 char	*inet6name __P((struct in6_addr *));
140 void	inet6print __P((struct in6_addr *, int, char *));
141 
142 /*
143  * Print a summary of connections related to an Internet
144  * protocol.  For TCP, also give state of connection.
145  * Listening processes (aflag) are suppressed unless the
146  * -a (all) flag is specified.
147  */
148 void
149 ip6protopr(off, name)
150 	u_long off;
151 	char *name;
152 {
153 	struct inpcbtable table;
154 	struct in6pcb *head, *prev, *next;
155 	int istcp;
156 	static int first = 1;
157 	int width = 22;
158 
159 	if (off == 0)
160 		return;
161 	istcp = strcmp(name, "tcp6") == 0;
162 	kread(off, (char *)&table, sizeof (table));
163 	head = prev =
164 	    (struct in6pcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
165 	next = (struct in6pcb *)table.inpt_queue.cqh_first;
166 	while (next != head) {
167 		kread((u_long)next, (char *)&in6pcb, sizeof in6pcb);
168 		if ((struct in6pcb *)in6pcb.in6p_queue.cqe_prev != prev) {
169 			printf("???\n");
170 			break;
171 		}
172 		prev = next;
173 		next = (struct in6pcb *)in6pcb.in6p_queue.cqe_next;
174 
175 		if (in6pcb.in6p_af != AF_INET6)
176 			continue;
177 
178 		if (!aflag && IN6_IS_ADDR_UNSPECIFIED(&in6pcb.in6p_laddr))
179 			continue;
180 		kread((u_long)in6pcb.in6p_socket, (char *)&sockb, sizeof (sockb));
181 		if (istcp) {
182 #ifdef TCP6
183 			kread((u_long)in6pcb.in6p_ppcb,
184 			    (char *)&tcp6cb, sizeof (tcp6cb));
185 #else
186 			kread((u_long)in6pcb.in6p_ppcb,
187 			    (char *)&tcpcb, sizeof (tcpcb));
188 #endif
189 		}
190 		if (first) {
191 			printf("Active Internet6 connections");
192 			if (aflag)
193 				printf(" (including servers)");
194 			putchar('\n');
195 			if (Aflag) {
196 				printf("%-8.8s ", "PCB");
197 				width = 18;
198 			}
199 			printf( "%-5.5s %-6.6s %-6.6s  %*.*s %*.*s %s\n",
200 				"Proto", "Recv-Q", "Send-Q",
201 				-width, width, "Local Address",
202 				-width, width, "Foreign Address",
203 				"(state)");
204 			first = 0;
205 		}
206 		if (Aflag) {
207 			if (istcp)
208 				printf("%8lx ", (u_long) in6pcb.in6p_ppcb);
209 			else
210 				printf("%8lx ", (u_long) next);
211 		}
212 		printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
213 			sockb.so_snd.sb_cc);
214 		/* xxx */
215 		inet6print(&in6pcb.in6p_laddr, (int)in6pcb.in6p_lport, name);
216 		inet6print(&in6pcb.in6p_faddr, (int)in6pcb.in6p_fport, name);
217 		if (istcp) {
218 #ifdef TCP6
219 			if (tcp6cb.t_state < 0 || tcp6cb.t_state >= TCP6_NSTATES)
220 				printf(" %d", tcp6cb.t_state);
221 			else
222 				printf(" %s", tcp6states[tcp6cb.t_state]);
223 #else
224 			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
225 				printf(" %d", tcpcb.t_state);
226 			else
227 				printf(" %s", tcpstates[tcpcb.t_state]);
228 #endif
229 		}
230 		putchar('\n');
231 	}
232 }
233 
234 #ifdef TCP6
235 /*
236  * Dump TCP6 statistics structure.
237  */
238 void
239 tcp6_stats(off, name)
240 	u_long off;
241 	char *name;
242 {
243 	struct tcp6stat tcp6stat;
244 
245 	if (off == 0)
246 		return;
247 	printf ("%s:\n", name);
248 	kread(off, (char *)&tcp6stat, sizeof (tcp6stat));
249 
250 #define	p(f, m) if (tcp6stat.f || sflag <= 1) \
251     printf(m, tcp6stat.f, plural(tcp6stat.f))
252 #define	p2(f1, f2, m) if (tcp6stat.f1 || tcp6stat.f2 || sflag <= 1) \
253     printf(m, tcp6stat.f1, plural(tcp6stat.f1), tcp6stat.f2, plural(tcp6stat.f2))
254 #define	p3(f, m) if (tcp6stat.f || sflag <= 1) \
255     printf(m, tcp6stat.f, plurales(tcp6stat.f))
256 
257 	p(tcp6s_sndtotal, "\t%ld packet%s sent\n");
258 	p2(tcp6s_sndpack,tcp6s_sndbyte,
259 		"\t\t%ld data packet%s (%ld byte%s)\n");
260 	p2(tcp6s_sndrexmitpack, tcp6s_sndrexmitbyte,
261 		"\t\t%ld data packet%s (%ld byte%s) retransmitted\n");
262 	p2(tcp6s_sndacks, tcp6s_delack,
263 		"\t\t%ld ack-only packet%s (%ld packet%s delayed)\n");
264 	p(tcp6s_sndurg, "\t\t%ld URG only packet%s\n");
265 	p(tcp6s_sndprobe, "\t\t%ld window probe packet%s\n");
266 	p(tcp6s_sndwinup, "\t\t%ld window update packet%s\n");
267 	p(tcp6s_sndctrl, "\t\t%ld control packet%s\n");
268 	p(tcp6s_rcvtotal, "\t%ld packet%s received\n");
269 	p2(tcp6s_rcvackpack, tcp6s_rcvackbyte, "\t\t%ld ack%s (for %ld byte%s)\n");
270 	p(tcp6s_rcvdupack, "\t\t%ld duplicate ack%s\n");
271 	p(tcp6s_rcvacktoomuch, "\t\t%ld ack%s for unsent data\n");
272 	p2(tcp6s_rcvpack, tcp6s_rcvbyte,
273 		"\t\t%ld packet%s (%ld byte%s) received in-sequence\n");
274 	p2(tcp6s_rcvduppack, tcp6s_rcvdupbyte,
275 		"\t\t%ld completely duplicate packet%s (%ld byte%s)\n");
276 	p(tcp6s_pawsdrop, "\t\t%ld old duplicate packet%s\n");
277 	p2(tcp6s_rcvpartduppack, tcp6s_rcvpartdupbyte,
278 		"\t\t%ld packet%s with some dup. data (%ld byte%s duped)\n");
279 	p2(tcp6s_rcvoopack, tcp6s_rcvoobyte,
280 		"\t\t%ld out-of-order packet%s (%ld byte%s)\n");
281 	p2(tcp6s_rcvpackafterwin, tcp6s_rcvbyteafterwin,
282 		"\t\t%ld packet%s (%ld byte%s) of data after window\n");
283 	p(tcp6s_rcvwinprobe, "\t\t%ld window probe%s\n");
284 	p(tcp6s_rcvwinupd, "\t\t%ld window update packet%s\n");
285 	p(tcp6s_rcvafterclose, "\t\t%ld packet%s received after close\n");
286 	p(tcp6s_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n");
287 	p(tcp6s_rcvbadoff, "\t\t%ld discarded for bad header offset field%s\n");
288 	p(tcp6s_rcvshort, "\t\t%ld discarded because packet%s too short\n");
289 	p(tcp6s_connattempt, "\t%ld connection request%s\n");
290 	p(tcp6s_accepts, "\t%ld connection accept%s\n");
291 	p(tcp6s_badsyn, "\t%ld bad connection attempt%s\n");
292 	p(tcp6s_connects, "\t%ld connection%s established (including accepts)\n");
293 	p2(tcp6s_closed, tcp6s_drops,
294 		"\t%ld connection%s closed (including %ld drop%s)\n");
295 	p(tcp6s_conndrops, "\t%ld embryonic connection%s dropped\n");
296 	p2(tcp6s_rttupdated, tcp6s_segstimed,
297 		"\t%ld segment%s updated rtt (of %ld attempt%s)\n");
298 	p(tcp6s_rexmttimeo, "\t%ld retransmit timeout%s\n");
299 	p(tcp6s_timeoutdrop, "\t\t%ld connection%s dropped by rexmit timeout\n");
300 	p(tcp6s_persisttimeo, "\t%ld persist timeout%s\n");
301 	p(tcp6s_persistdrop, "\t%ld connection%s timed out in persist\n");
302 	p(tcp6s_keeptimeo, "\t%ld keepalive timeout%s\n");
303 	p(tcp6s_keepprobe, "\t\t%ld keepalive probe%s sent\n");
304 	p(tcp6s_keepdrops, "\t\t%ld connection%s dropped by keepalive\n");
305 	p(tcp6s_predack, "\t%ld correct ACK header prediction%s\n");
306 	p(tcp6s_preddat, "\t%ld correct data packet header prediction%s\n");
307 	p3(tcp6s_pcbcachemiss, "\t%ld PCB cache miss%s\n");
308 #undef p
309 #undef p2
310 #undef p3
311 }
312 #endif
313 
314 /*
315  * Dump UDP6 statistics structure.
316  */
317 void
318 udp6_stats(off, name)
319 	u_long off;
320 	char *name;
321 {
322 	struct udp6stat udp6stat;
323 	u_quad_t delivered;
324 
325 	if (off == 0)
326 		return;
327 	kread(off, (char *)&udp6stat, sizeof (udp6stat));
328 	printf("%s:\n", name);
329 #define	p(f, m) if (udp6stat.f || sflag <= 1) \
330     printf(m, (unsigned long long)udp6stat.f, plural(udp6stat.f))
331 #define	p1(f, m) if (udp6stat.f || sflag <= 1) \
332     printf(m, (unsigned long long)udp6stat.f)
333 	p(udp6s_ipackets, "\t%llu datagram%s received\n");
334 	p1(udp6s_hdrops, "\t%llu with incomplete header\n");
335 	p1(udp6s_badlen, "\t%llu with bad data length field\n");
336 	p1(udp6s_badsum, "\t%llu with bad checksum\n");
337 	p1(udp6s_nosum, "\t%llu with no checksum\n");
338 	p1(udp6s_noport, "\t%llu dropped due to no socket\n");
339 	p(udp6s_noportmcast,
340 	    "\t%llu multicast datagram%s dropped due to no socket\n");
341 	p1(udp6s_fullsock, "\t%llu dropped due to full socket buffers\n");
342 	delivered = udp6stat.udp6s_ipackets -
343 		    udp6stat.udp6s_hdrops -
344 		    udp6stat.udp6s_badlen -
345 		    udp6stat.udp6s_badsum -
346 		    udp6stat.udp6s_noport -
347 		    udp6stat.udp6s_noportmcast -
348 		    udp6stat.udp6s_fullsock;
349 	if (delivered || sflag <= 1)
350 		printf("\t%llu delivered\n", (unsigned long long)delivered);
351 	p(udp6s_opackets, "\t%llu datagram%s output\n");
352 #undef p
353 #undef p1
354 }
355 
356 static	char *ip6nh[] = {
357 /*0*/	"hop by hop",
358 	"ICMP",
359 	"IGMP",
360 	NULL,
361 	"IP",
362 /*5*/	NULL,
363 	"TCP",
364 	NULL,
365 	NULL,
366 	NULL,
367 /*10*/	NULL, NULL, NULL, NULL, NULL,
368 /*15*/	NULL,
369 	NULL,
370 	"UDP",
371 	NULL,
372 	NULL,
373 /*20*/	NULL,
374 	NULL,
375 	"IDP",
376 	NULL,
377 	NULL,
378 /*25*/	NULL,
379 	NULL,
380 	NULL,
381 	NULL,
382 	"TP",
383 /*30*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
384 /*40*/	NULL,
385 	"IP6",
386 	NULL,
387 	"routing",
388 	"fragment",
389 /*45*/	NULL, NULL, NULL, NULL, NULL,
390 /*50*/	"ESP",
391 	"AH",
392 	NULL,
393 	NULL,
394 	NULL,
395 /*55*/	NULL,
396 	NULL,
397 	NULL,
398 	"ICMP6",
399 	"no next header",
400 /*60*/	"destination option",
401 	NULL,
402 	NULL,
403 	NULL,
404 	NULL,
405 /*65*/	NULL, NULL, NULL, NULL, NULL,
406 /*70*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
407 /*80*/	"ISOIP",
408 	NULL,
409 	NULL,
410 	NULL,
411 	NULL,
412 	NULL,
413 	NULL,
414 	NULL,
415 	NULL,
416 	"OSPF",
417 /*90*/	NULL, NULL, NULL, NULL, NULL,
418 /*95*/	NULL,
419 	NULL,
420 	"Ethernet",
421 	NULL,
422 	NULL,
423 /*100*/	NULL,
424 	NULL,
425 	NULL,
426 	"PIM",
427 	NULL,
428 /*105*/	NULL, NULL, NULL, NULL, NULL,
429 /*110*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
430 /*120*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
431 /*130*/	NULL,
432 	NULL,
433 	"SCTP",
434 	NULL,
435 	NULL,
436 /*135*/	NULL, NULL, NULL, NULL, NULL,
437 /*140*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
438 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
439 /*160*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
440 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
441 /*180*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
442 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
443 /*200*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
444 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
445 /*220*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
446 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
447 /*240*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
448 	NULL, NULL, NULL, NULL, NULL, NULL,
449 };
450 
451 /*
452  * Dump IP6 statistics structure.
453  */
454 void
455 ip6_stats(off, name)
456 	u_long off;
457 	char *name;
458 {
459 	struct ip6stat ip6stat;
460 	int first, i;
461 	struct protoent *ep;
462 	const char *n;
463 
464 	if (off == 0)
465 		return;
466 
467 	kread(off, (char *)&ip6stat, sizeof (ip6stat));
468 	printf("%s:\n", name);
469 
470 #define	p(f, m) if (ip6stat.f || sflag <= 1) \
471     printf(m, (unsigned long long)ip6stat.f, plural(ip6stat.f))
472 #define	p1(f, m) if (ip6stat.f || sflag <= 1) \
473     printf(m, (unsigned long long)ip6stat.f)
474 
475 	p(ip6s_total, "\t%llu total packet%s received\n");
476 	p1(ip6s_toosmall, "\t%llu with size smaller than minimum\n");
477 	p1(ip6s_tooshort, "\t%llu with data size < data length\n");
478 	p1(ip6s_badoptions, "\t%llu with bad options\n");
479 	p1(ip6s_badvers, "\t%llu with incorrect version number\n");
480 	p(ip6s_fragments, "\t%llu fragment%s received\n");
481 	p(ip6s_fragdropped,
482 	    "\t%llu fragment%s dropped (dup or out of space)\n");
483 	p(ip6s_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
484 	p(ip6s_fragoverflow, "\t%llu fragment%s that exceeded limit\n");
485 	p(ip6s_reassembled, "\t%llu packet%s reassembled ok\n");
486 	p(ip6s_delivered, "\t%llu packet%s for this host\n");
487 	p(ip6s_forward, "\t%llu packet%s forwarded\n");
488 	p(ip6s_cantforward, "\t%llu packet%s not forwardable\n");
489 	p(ip6s_redirectsent, "\t%llu redirect%s sent\n");
490 	p(ip6s_localout, "\t%llu packet%s sent from this host\n");
491 	p(ip6s_rawout, "\t%llu packet%s sent with fabricated ip header\n");
492 	p(ip6s_odropped,
493 	    "\t%llu output packet%s dropped due to no bufs, etc.\n");
494 	p(ip6s_noroute, "\t%llu output packet%s discarded due to no route\n");
495 	p(ip6s_fragmented, "\t%llu output datagram%s fragmented\n");
496 	p(ip6s_ofragments, "\t%llu fragment%s created\n");
497 	p(ip6s_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
498 	p(ip6s_badscope, "\t%llu packet%s that violated scope rules\n");
499 	p(ip6s_notmember, "\t%llu multicast packet%s which we don't join\n");
500 	for (first = 1, i = 0; i < 256; i++)
501 		if (ip6stat.ip6s_nxthist[i] != 0) {
502 			if (first) {
503 				printf("\tInput packet histogram:\n");
504 				first = 0;
505 			}
506 			n = NULL;
507 			if (ip6nh[i])
508 				n = ip6nh[i];
509 			else if ((ep = getprotobynumber(i)) != NULL)
510 				n = ep->p_name;
511 			if (n)
512 				printf("\t\t%s: %llu\n", n,
513 				    (unsigned long long)ip6stat.ip6s_nxthist[i]);
514 			else
515 				printf("\t\t#%d: %llu\n", i,
516 				    (unsigned long long)ip6stat.ip6s_nxthist[i]);
517 		}
518 	printf("\tMbuf statistics:\n");
519 	p(ip6s_m1, "\t\t%llu one mbuf%s\n");
520 	for (first = 1, i = 0; i < 32; i++) {
521 		char ifbuf[IFNAMSIZ];
522 		if (ip6stat.ip6s_m2m[i] != 0) {
523 			if (first) {
524 				printf("\t\ttwo or more mbuf:\n");
525 				first = 0;
526 			}
527 			printf("\t\t\t%s = %llu\n",
528 			       if_indextoname(i, ifbuf),
529 			       (unsigned long long)ip6stat.ip6s_m2m[i]);
530 		}
531 	}
532 	p(ip6s_mext1, "\t\t%llu one ext mbuf%s\n");
533 	p(ip6s_mext2m, "\t\t%llu two or more ext mbuf%s\n");
534 	p(ip6s_exthdrtoolong,
535 	    "\t%llu packet%s whose headers are not continuous\n");
536 	p(ip6s_nogif, "\t%llu tunneling packet%s that can't find gif\n");
537 	p(ip6s_toomanyhdr,
538 	    "\t%llu packet%s discarded due to too many headers\n");
539 
540 	/* for debugging source address selection */
541 #define PRINT_SCOPESTAT(s,i) do {\
542 		switch(i) { /* XXX hardcoding in each case */\
543 		case 1:\
544 			p(s, "\t\t%llu node-local%s\n");\
545 			break;\
546 		case 2:\
547 			p(s, "\t\t%llu link-local%s\n");\
548 			break;\
549 		case 5:\
550 			p(s, "\t\t%llu site-local%s\n");\
551 			break;\
552 		case 14:\
553 			p(s, "\t\t%llu global%s\n");\
554 			break;\
555 		default:\
556 			printf("\t\t%llu addresses scope=%x\n",\
557 			       (unsigned long long)ip6stat.s, i);\
558 		}\
559 	} while(0);
560 
561 	p(ip6s_sources_none,
562 	  "\t%llu failure%s of source address selection\n");
563 	for (first = 1, i = 0; i < 16; i++) {
564 		if (ip6stat.ip6s_sources_sameif[i]) {
565 			if (first) {
566 				printf("\tsource addresses on an outgoing I/F\n");
567 				first = 0;
568 			}
569 			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
570 		}
571 	}
572 	for (first = 1, i = 0; i < 16; i++) {
573 		if (ip6stat.ip6s_sources_otherif[i]) {
574 			if (first) {
575 				printf("\tsource addresses on a non-outgoing I/F\n");
576 				first = 0;
577 			}
578 			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
579 		}
580 	}
581 	for (first = 1, i = 0; i < 16; i++) {
582 		if (ip6stat.ip6s_sources_samescope[i]) {
583 			if (first) {
584 				printf("\tsource addresses of same scope\n");
585 				first = 0;
586 			}
587 			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
588 		}
589 	}
590 	for (first = 1, i = 0; i < 16; i++) {
591 		if (ip6stat.ip6s_sources_otherscope[i]) {
592 			if (first) {
593 				printf("\tsource addresses of a different scope\n");
594 				first = 0;
595 			}
596 			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
597 		}
598 	}
599 	for (first = 1, i = 0; i < 16; i++) {
600 		if (ip6stat.ip6s_sources_deprecated[i]) {
601 			if (first) {
602 				printf("\tdeprecated source addresses\n");
603 				first = 0;
604 			}
605 			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
606 		}
607 	}
608 
609 	p1(ip6s_forward_cachehit, "\t%llu forward cache hit\n");
610 	p1(ip6s_forward_cachemiss, "\t%llu forward cache miss\n");
611 #undef p
612 #undef p1
613 }
614 
615 /*
616  * Dump IPv6 per-interface statistics based on RFC 2465.
617  */
618 void
619 ip6_ifstats(ifname)
620 	char *ifname;
621 {
622 	struct in6_ifreq ifr;
623 	int s;
624 #define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
625     printf(m, (unsigned long long)ifr.ifr_ifru.ifru_stat.f, \
626 	plural(ifr.ifr_ifru.ifru_stat.f))
627 #define	p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
628     printf(m, (unsigned long long)ip6stat.f)
629 
630 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
631 		perror("Warning: socket(AF_INET6)");
632 		return;
633 	}
634 
635 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
636 	printf("ip6 on %s:\n", ifname);
637 
638 	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
639 		perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
640 		goto end;
641 	}
642 
643 	p(ifs6_in_receive, "\t%llu total input datagram%s\n");
644 	p(ifs6_in_hdrerr, "\t%llu datagram%s with invalid header received\n");
645 	p(ifs6_in_toobig, "\t%llu datagram%s exceeded MTU received\n");
646 	p(ifs6_in_noroute, "\t%llu datagram%s with no route received\n");
647 	p(ifs6_in_addrerr, "\t%llu datagram%s with invalid dst received\n");
648 	p(ifs6_in_truncated, "\t%llu truncated datagram%s received\n");
649 	p(ifs6_in_protounknown, "\t%llu datagram%s with unknown proto received\n");
650 	p(ifs6_in_discard, "\t%llu input datagram%s discarded\n");
651 	p(ifs6_in_deliver,
652 	  "\t%llu datagram%s delivered to an upper layer protocol\n");
653 	p(ifs6_out_forward, "\t%llu datagram%s forwarded to this interface\n");
654 	p(ifs6_out_request,
655 	  "\t%llu datagram%s sent from an upper layer protocol\n");
656 	p(ifs6_out_discard, "\t%llu total discarded output datagram%s\n");
657 	p(ifs6_out_fragok, "\t%llu output datagram%s fragmented\n");
658 	p(ifs6_out_fragfail, "\t%llu output datagram%s failed on fragment\n");
659 	p(ifs6_out_fragcreat, "\t%llu output datagram%s succeeded on fragment\n");
660 	p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n");
661 	p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n");
662 	p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembling\n");
663 	p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n");
664 	p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n");
665 
666   end:
667 	close(s);
668 
669 #undef p
670 #undef p_5
671 }
672 
673 static	char *icmp6names[] = {
674 	"#0",
675 	"unreach",
676 	"packet too big",
677 	"time exceed",
678 	"parameter problem",
679 	"#5",
680 	"#6",
681 	"#7",
682 	"#8",
683 	"#9",
684 	"#10",
685 	"#11",
686 	"#12",
687 	"#13",
688 	"#14",
689 	"#15",
690 	"#16",
691 	"#17",
692 	"#18",
693 	"#19",
694 	"#20",
695 	"#21",
696 	"#22",
697 	"#23",
698 	"#24",
699 	"#25",
700 	"#26",
701 	"#27",
702 	"#28",
703 	"#29",
704 	"#30",
705 	"#31",
706 	"#32",
707 	"#33",
708 	"#34",
709 	"#35",
710 	"#36",
711 	"#37",
712 	"#38",
713 	"#39",
714 	"#40",
715 	"#41",
716 	"#42",
717 	"#43",
718 	"#44",
719 	"#45",
720 	"#46",
721 	"#47",
722 	"#48",
723 	"#49",
724 	"#50",
725 	"#51",
726 	"#52",
727 	"#53",
728 	"#54",
729 	"#55",
730 	"#56",
731 	"#57",
732 	"#58",
733 	"#59",
734 	"#60",
735 	"#61",
736 	"#62",
737 	"#63",
738 	"#64",
739 	"#65",
740 	"#66",
741 	"#67",
742 	"#68",
743 	"#69",
744 	"#70",
745 	"#71",
746 	"#72",
747 	"#73",
748 	"#74",
749 	"#75",
750 	"#76",
751 	"#77",
752 	"#78",
753 	"#79",
754 	"#80",
755 	"#81",
756 	"#82",
757 	"#83",
758 	"#84",
759 	"#85",
760 	"#86",
761 	"#87",
762 	"#88",
763 	"#89",
764 	"#80",
765 	"#91",
766 	"#92",
767 	"#93",
768 	"#94",
769 	"#95",
770 	"#96",
771 	"#97",
772 	"#98",
773 	"#99",
774 	"#100",
775 	"#101",
776 	"#102",
777 	"#103",
778 	"#104",
779 	"#105",
780 	"#106",
781 	"#107",
782 	"#108",
783 	"#109",
784 	"#110",
785 	"#111",
786 	"#112",
787 	"#113",
788 	"#114",
789 	"#115",
790 	"#116",
791 	"#117",
792 	"#118",
793 	"#119",
794 	"#120",
795 	"#121",
796 	"#122",
797 	"#123",
798 	"#124",
799 	"#125",
800 	"#126",
801 	"#127",
802 	"echo",
803 	"echo reply",
804 	"multicast listener query",
805 	"multicast listener report",
806 	"multicast listener done",
807 	"router solicitation",
808 	"router advertisement",
809 	"neighbor solicitation",
810 	"neighbor advertisement",
811 	"redirect",
812 	"router renumbering",
813 	"node information request",
814 	"node information reply",
815 	"#141",
816 	"#142",
817 	"#143",
818 	"#144",
819 	"#145",
820 	"#146",
821 	"#147",
822 	"#148",
823 	"#149",
824 	"#150",
825 	"#151",
826 	"#152",
827 	"#153",
828 	"#154",
829 	"#155",
830 	"#156",
831 	"#157",
832 	"#158",
833 	"#159",
834 	"#160",
835 	"#161",
836 	"#162",
837 	"#163",
838 	"#164",
839 	"#165",
840 	"#166",
841 	"#167",
842 	"#168",
843 	"#169",
844 	"#170",
845 	"#171",
846 	"#172",
847 	"#173",
848 	"#174",
849 	"#175",
850 	"#176",
851 	"#177",
852 	"#178",
853 	"#179",
854 	"#180",
855 	"#181",
856 	"#182",
857 	"#183",
858 	"#184",
859 	"#185",
860 	"#186",
861 	"#187",
862 	"#188",
863 	"#189",
864 	"#180",
865 	"#191",
866 	"#192",
867 	"#193",
868 	"#194",
869 	"#195",
870 	"#196",
871 	"#197",
872 	"#198",
873 	"#199",
874 	"#200",
875 	"#201",
876 	"#202",
877 	"#203",
878 	"#204",
879 	"#205",
880 	"#206",
881 	"#207",
882 	"#208",
883 	"#209",
884 	"#210",
885 	"#211",
886 	"#212",
887 	"#213",
888 	"#214",
889 	"#215",
890 	"#216",
891 	"#217",
892 	"#218",
893 	"#219",
894 	"#220",
895 	"#221",
896 	"#222",
897 	"#223",
898 	"#224",
899 	"#225",
900 	"#226",
901 	"#227",
902 	"#228",
903 	"#229",
904 	"#230",
905 	"#231",
906 	"#232",
907 	"#233",
908 	"#234",
909 	"#235",
910 	"#236",
911 	"#237",
912 	"#238",
913 	"#239",
914 	"#240",
915 	"#241",
916 	"#242",
917 	"#243",
918 	"#244",
919 	"#245",
920 	"#246",
921 	"#247",
922 	"#248",
923 	"#249",
924 	"#250",
925 	"#251",
926 	"#252",
927 	"#253",
928 	"#254",
929 	"#255",
930 };
931 
932 /*
933  * Dump ICMPv6 statistics.
934  */
935 void
936 icmp6_stats(off, name)
937 	u_long off;
938 	char *name;
939 {
940 	struct icmp6stat icmp6stat;
941 	register int i, first;
942 
943 	if (off == 0)
944 		return;
945 	kread(off, (char *)&icmp6stat, sizeof (icmp6stat));
946 	printf("%s:\n", name);
947 
948 #define	p(f, m) if (icmp6stat.f || sflag <= 1) \
949     printf(m, (unsigned long long)icmp6stat.f, plural(icmp6stat.f))
950 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
951     printf(m, (unsigned long long)icmp6stat.f)
952 
953 	p(icp6s_error, "\t%llu call%s to icmp6_error\n");
954 	p(icp6s_canterror,
955 	    "\t%llu error%s not generated because old message was icmp6 or so\n");
956 	p(icp6s_toofreq,
957 	    "\t%llu error%s not generated because of rate limitation\n");
958 	for (first = 1, i = 0; i < 256; i++)
959 		if (icmp6stat.icp6s_outhist[i] != 0) {
960 			if (first) {
961 				printf("\tOutput packet histogram:\n");
962 				first = 0;
963 			}
964 			printf("\t\t%s: %llu\n", icmp6names[i],
965 				(unsigned long long)icmp6stat.icp6s_outhist[i]);
966 		}
967 	p(icp6s_badcode, "\t%llu message%s with bad code fields\n");
968 	p(icp6s_tooshort, "\t%llu message%s < minimum length\n");
969 	p(icp6s_checksum, "\t%llu bad checksum%s\n");
970 	p(icp6s_badlen, "\t%llu message%s with bad length\n");
971 	for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
972 		if (icmp6stat.icp6s_inhist[i] != 0) {
973 			if (first) {
974 				printf("\tInput packet histogram:\n");
975 				first = 0;
976 			}
977 			printf("\t\t%s: %llu\n", icmp6names[i],
978 				(unsigned long long)icmp6stat.icp6s_inhist[i]);
979 		}
980 	printf("\tHistogram of error messages to be generated:\n");
981 	p_5(icp6s_odst_unreach_noroute, "\t\t%llu no route\n");
982 	p_5(icp6s_odst_unreach_admin, "\t\t%llu administratively prohibited\n");
983 	p_5(icp6s_odst_unreach_beyondscope, "\t\t%llu beyond scope\n");
984 	p_5(icp6s_odst_unreach_addr, "\t\t%llu address unreachable\n");
985 	p_5(icp6s_odst_unreach_noport, "\t\t%llu port unreachable\n");
986 	p_5(icp6s_opacket_too_big, "\t\t%llu packet too big\n");
987 	p_5(icp6s_otime_exceed_transit, "\t\t%llu time exceed transit\n");
988 	p_5(icp6s_otime_exceed_reassembly, "\t\t%llu time exceed reassembly\n");
989 	p_5(icp6s_oparamprob_header, "\t\t%llu erroneous header field\n");
990 	p_5(icp6s_oparamprob_nextheader, "\t\t%llu unrecognized next header\n");
991 	p_5(icp6s_oparamprob_option, "\t\t%llu unrecognized option\n");
992 	p_5(icp6s_oredirect, "\t\t%llu redirect\n");
993 	p_5(icp6s_ounknown, "\t\t%llu unknown\n");
994 
995 	p(icp6s_reflect, "\t%llu message response%s generated\n");
996 	p(icp6s_nd_toomanyopt, "\t%llu message%s with too many ND options\n");
997 	p(icp6s_nd_badopt, "\t%llu message%s with bad ND options\n");
998 	p(icp6s_badns, "\t%llu bad neighbor solicitation message%s\n");
999 	p(icp6s_badna, "\t%llu bad neighbor advertisement message%s\n");
1000 	p(icp6s_badrs, "\t%llu bad router solicitation message%s\n");
1001 	p(icp6s_badra, "\t%llu bad router advertisement message%s\n");
1002 	p(icp6s_badredirect, "\t%llu bad redirect message%s\n");
1003 	p(icp6s_pmtuchg, "\t%llu path MTU change%s\n");
1004 #undef p
1005 #undef p_5
1006 }
1007 
1008 /*
1009  * Dump ICMPv6 per-interface statistics based on RFC 2466.
1010  */
1011 void
1012 icmp6_ifstats(ifname)
1013 	char *ifname;
1014 {
1015 	struct in6_ifreq ifr;
1016 	int s;
1017 #define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1018     printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, \
1019 	plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1020 
1021 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1022 		perror("Warning: socket(AF_INET6)");
1023 		return;
1024 	}
1025 
1026 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1027 	printf("icmp6 on %s:\n", ifname);
1028 
1029 	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1030 		perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1031 		goto end;
1032 	}
1033 
1034 	p(ifs6_in_msg, "\t%llu total input message%s\n");
1035 	p(ifs6_in_error, "\t%llu total input error message%s\n");
1036 	p(ifs6_in_dstunreach, "\t%llu input destination unreachable error%s\n");
1037 	p(ifs6_in_adminprohib, "\t%llu input administratively prohibited error%s\n");
1038 	p(ifs6_in_timeexceed, "\t%llu input time exceeded error%s\n");
1039 	p(ifs6_in_paramprob, "\t%llu input parameter problem error%s\n");
1040 	p(ifs6_in_pkttoobig, "\t%llu input packet too big error%s\n");
1041 	p(ifs6_in_echo, "\t%llu input echo request%s\n");
1042 	p(ifs6_in_echoreply, "\t%llu input echo reply%s\n");
1043 	p(ifs6_in_routersolicit, "\t%llu input router solicitation%s\n");
1044 	p(ifs6_in_routeradvert, "\t%llu input router advertisement%s\n");
1045 	p(ifs6_in_neighborsolicit, "\t%llu input neighbor solicitation%s\n");
1046 	p(ifs6_in_neighboradvert, "\t%llu input neighbor advertisement%s\n");
1047 	p(ifs6_in_redirect, "\t%llu input redirect%s\n");
1048 	p(ifs6_in_mldquery, "\t%llu input MLD query%s\n");
1049 	p(ifs6_in_mldreport, "\t%llu input MLD report%s\n");
1050 	p(ifs6_in_mlddone, "\t%llu input MLD done%s\n");
1051 
1052 	p(ifs6_out_msg, "\t%llu total output message%s\n");
1053 	p(ifs6_out_error, "\t%llu total output error message%s\n");
1054 	p(ifs6_out_dstunreach, "\t%llu output destination unreachable error%s\n");
1055 	p(ifs6_out_adminprohib, "\t%llu output administratively prohibited error%s\n");
1056 	p(ifs6_out_timeexceed, "\t%llu output time exceeded error%s\n");
1057 	p(ifs6_out_paramprob, "\t%llu output parameter problem error%s\n");
1058 	p(ifs6_out_pkttoobig, "\t%llu output packet too big error%s\n");
1059 	p(ifs6_out_echo, "\t%llu output echo request%s\n");
1060 	p(ifs6_out_echoreply, "\t%llu output echo reply%s\n");
1061 	p(ifs6_out_routersolicit, "\t%llu output router solicitation%s\n");
1062 	p(ifs6_out_routeradvert, "\t%llu output router advertisement%s\n");
1063 	p(ifs6_out_neighborsolicit, "\t%llu output neighbor solicitation%s\n");
1064 	p(ifs6_out_neighboradvert, "\t%llu output neighbor advertisement%s\n");
1065 	p(ifs6_out_redirect, "\t%llu output redirect%s\n");
1066 	p(ifs6_out_mldquery, "\t%llu output MLD query%s\n");
1067 	p(ifs6_out_mldreport, "\t%llu output MLD report%s\n");
1068 	p(ifs6_out_mlddone, "\t%llu output MLD done%s\n");
1069 
1070   end:
1071 	close(s);
1072 #undef p
1073 }
1074 
1075 /*
1076  * Dump PIM statistics structure.
1077  */
1078 void
1079 pim6_stats(off, name)
1080 	u_long off;
1081 	char *name;
1082 {
1083 	struct pim6stat pim6stat;
1084 
1085 	if (off == 0)
1086 		return;
1087 	kread(off, (char *)&pim6stat, sizeof(pim6stat));
1088 	printf("%s:\n", name);
1089 
1090 #define	p(f, m) if (pim6stat.f || sflag <= 1) \
1091     printf(m, (unsigned long long)pim6stat.f, plural(pim6stat.f))
1092 	p(pim6s_rcv_total, "\t%llu message%s received\n");
1093 	p(pim6s_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
1094 	p(pim6s_rcv_badsum, "\t%llu message%s received with bad checksum\n");
1095 	p(pim6s_rcv_badversion, "\t%llu message%s received with bad version\n");
1096 	p(pim6s_rcv_registers, "\t%llu register%s received\n");
1097 	p(pim6s_rcv_badregisters, "\t%llu bad register%s received\n");
1098 	p(pim6s_snd_registers, "\t%llu register%s sent\n");
1099 #undef p
1100 }
1101 
1102 /*
1103  * Dump raw ip6 statistics structure.
1104  */
1105 void
1106 rip6_stats(off, name)
1107 	u_long off;
1108 	char *name;
1109 {
1110 	struct rip6stat rip6stat;
1111 	u_quad_t delivered;
1112 
1113 	if (off == 0)
1114 		return;
1115 	kread(off, (char *)&rip6stat, sizeof(rip6stat));
1116 	printf("%s:\n", name);
1117 
1118 #define	p(f, m) if (rip6stat.f || sflag <= 1) \
1119     printf(m, (unsigned long long)rip6stat.f, plural(rip6stat.f))
1120 	p(rip6s_ipackets, "\t%llu message%s received\n");
1121 	p(rip6s_isum, "\t%llu checksum calculation%s on inbound\n");
1122 	p(rip6s_badsum, "\t%llu message%s with bad checksum\n");
1123 	p(rip6s_nosock, "\t%llu message%s dropped due to no socket\n");
1124 	p(rip6s_nosockmcast,
1125 	    "\t%llu multicast message%s dropped due to no socket\n");
1126 	p(rip6s_fullsock,
1127 	    "\t%llu message%s dropped due to full socket buffers\n");
1128 	delivered = rip6stat.rip6s_ipackets -
1129 		    rip6stat.rip6s_badsum -
1130 		    rip6stat.rip6s_nosock -
1131 		    rip6stat.rip6s_nosockmcast -
1132 		    rip6stat.rip6s_fullsock;
1133 	if (delivered || sflag <= 1)
1134 		printf("\t%llu delivered\n", (unsigned long long)delivered);
1135 	p(rip6s_opackets, "\t%llu datagram%s output\n");
1136 #undef p
1137 }
1138 
1139 /*
1140  * Pretty print an Internet address (net address + port).
1141  * Take numeric_addr and numeric_port into consideration.
1142  */
1143 void
1144 inet6print(in6, port, proto)
1145 	register struct in6_addr *in6;
1146 	int port;
1147 	char *proto;
1148 {
1149 #define GETSERVBYPORT6(port, proto, ret)\
1150 do {\
1151 	if (strcmp((proto), "tcp6") == 0)\
1152 		(ret) = getservbyport((int)(port), "tcp");\
1153 	else if (strcmp((proto), "udp6") == 0)\
1154 		(ret) = getservbyport((int)(port), "udp");\
1155 	else\
1156 		(ret) = getservbyport((int)(port), (proto));\
1157 } while (0)
1158 	struct servent *sp = 0;
1159 	char line[80], *cp;
1160 	int width;
1161 
1162 	width = Aflag ? 12 : 16;
1163 	if (vflag && width < strlen(inet6name(in6)))
1164 		width = strlen(inet6name(in6));
1165 	snprintf(line, sizeof(line), "%.*s.", width, inet6name(in6));
1166 	cp = strchr(line, '\0');
1167 	if (!numeric_port && port)
1168 		GETSERVBYPORT6(port, proto, sp);
1169 	if (sp || port == 0)
1170 		snprintf(cp, sizeof(line) - (cp - line),
1171 		    "%s", sp ? sp->s_name : "*");
1172 	else
1173 		snprintf(cp, sizeof(line) - (cp - line),
1174 		    "%d", ntohs((u_short)port));
1175 	width = Aflag ? 18 : 22;
1176 	if (vflag && width < strlen(line))
1177 		width = strlen(line);
1178 	printf(" %-*.*s", width, width, line);
1179 }
1180 
1181 /*
1182  * Construct an Internet address representation.
1183  * If the numeric_addr has been supplied, give
1184  * numeric value, otherwise try for symbolic name.
1185  */
1186 
1187 char *
1188 inet6name(in6p)
1189 	struct in6_addr *in6p;
1190 {
1191 	register char *cp;
1192 	static char line[NI_MAXHOST];
1193 	struct hostent *hp;
1194 	static char domain[MAXHOSTNAMELEN + 1];
1195 	static int first = 1;
1196 	char hbuf[NI_MAXHOST];
1197 	struct sockaddr_in6 sin6;
1198 #ifdef NI_WITHSCOPEID
1199 	const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID;
1200 #else
1201 	const int niflag = NI_NUMERICHOST;
1202 #endif
1203 
1204 	if (first && !numeric_addr) {
1205 		first = 0;
1206 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1207 		    (cp = strchr(domain, '.')))
1208 			(void) strlcpy(domain, cp + 1, sizeof(domain));
1209 		else
1210 			domain[0] = 0;
1211 	}
1212 	cp = 0;
1213 	if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1214 		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
1215 		if (hp) {
1216 			if ((cp = strchr(hp->h_name, '.')) &&
1217 			    !strcmp(cp + 1, domain))
1218 				*cp = 0;
1219 			cp = hp->h_name;
1220 		}
1221 	}
1222 	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1223 		strlcpy(line, "*", sizeof(line));
1224 	else if (cp)
1225 		strlcpy(line, cp, sizeof(line));
1226 	else {
1227 		memset(&sin6, 0, sizeof(sin6));
1228 		sin6.sin6_len = sizeof(sin6);
1229 		sin6.sin6_family = AF_INET6;
1230 		sin6.sin6_addr = *in6p;
1231 #ifdef __KAME__
1232 		if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
1233 		    IN6_IS_ADDR_MC_LINKLOCAL(in6p)) {
1234 			sin6.sin6_scope_id =
1235 			    ntohs(*(u_int16_t *)&in6p->s6_addr[2]);
1236 			sin6.sin6_addr.s6_addr[2] = 0;
1237 			sin6.sin6_addr.s6_addr[3] = 0;
1238 		}
1239 #endif
1240 		if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1241 				hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
1242 			strlcpy(hbuf, "?", sizeof(hbuf));
1243 		strlcpy(line, hbuf, sizeof(line));
1244 	}
1245 	return (line);
1246 }
1247 
1248 #ifdef TCP6
1249 /*
1250  * Dump the contents of a TCP6 PCB.
1251  */
1252 void
1253 tcp6_dump(pcbaddr)
1254 	u_long pcbaddr;
1255 {
1256 	struct tcp6cb tcp6cb;
1257 	int i;
1258 
1259 	kread(pcbaddr, (char *)&tcp6cb, sizeof(tcp6cb));
1260 
1261 	printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
1262 
1263 	printf("Timers:\n");
1264 	for (i = 0; i < TCP6T_NTIMERS; i++)
1265 		printf("\t%s: %u", tcp6timers[i], tcp6cb.t_timer[i]);
1266 	printf("\n\n");
1267 
1268 	if (tcp6cb.t_state < 0 || tcp6cb.t_state >= TCP6_NSTATES)
1269 		printf("State: %d", tcp6cb.t_state);
1270 	else
1271 		printf("State: %s", tcp6states[tcp6cb.t_state]);
1272 	printf(", flags 0x%x, in6pcb 0x%lx\n\n", tcp6cb.t_flags,
1273 	    (u_long)tcp6cb.t_in6pcb);
1274 
1275 	printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcp6cb.t_rxtshift,
1276 	    tcp6cb.t_rxtcur, tcp6cb.t_dupacks);
1277 	printf("peermaxseg %u, maxseg %u, force %d\n\n", tcp6cb.t_peermaxseg,
1278 	    tcp6cb.t_maxseg, tcp6cb.t_force);
1279 
1280 	printf("snd_una %u, snd_nxt %u, snd_up %u\n",
1281 	    tcp6cb.snd_una, tcp6cb.snd_nxt, tcp6cb.snd_up);
1282 	printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %llu\n\n",
1283 	    tcp6cb.snd_wl1, tcp6cb.snd_wl2, tcp6cb.iss,
1284 	    (unsigned long long)tcp6cb.snd_wnd);
1285 
1286 	printf("rcv_wnd %llu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
1287 	    (unsigned long long)cp6cb.rcv_wnd, tcp6cb.rcv_nxt,
1288 	    tcp6cb.rcv_up, tcp6cb.irs);
1289 
1290 	printf("rcv_adv %u, snd_max %u, snd_cwnd %llu, snd_ssthresh %llu\n",
1291 	    tcp6cb.rcv_adv, tcp6cb.snd_max, (unsigned long long)tcp6cb.snd_cwnd,
1292 	    (unsigned long long)tcp6cb.snd_ssthresh);
1293 
1294 	printf("idle %d, rtt %d, rtseq %u, srtt %d, rttvar %d, rttmin %d, "
1295 	    "max_sndwnd %llu\n\n", tcp6cb.t_idle, tcp6cb.t_rtt, tcp6cb.t_rtseq,
1296 	    tcp6cb.t_srtt, tcp6cb.t_rttvar, tcp6cb.t_rttmin,
1297 	    (unsigned long long)tcp6cb.max_sndwnd);
1298 
1299 	printf("oobflags %d, iobc %d, softerror %d\n\n", tcp6cb.t_oobflags,
1300 	    tcp6cb.t_iobc, tcp6cb.t_softerror);
1301 
1302 	printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
1303 	    tcp6cb.snd_scale, tcp6cb.rcv_scale, tcp6cb.request_r_scale,
1304 	    tcp6cb.requested_s_scale);
1305 	printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
1306 	    tcp6cb.ts_recent, tcp6cb.ts_recent_age, tcp6cb.last_ack_sent);
1307 }
1308 #endif
1309 
1310 #endif /*INET6*/
1311