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