xref: /netbsd-src/usr.bin/netstat/inet6.c (revision 3b435a73967be44dfb4a27315acd72bfacde430c)
1 /*	$NetBSD: inet6.c,v 1.3 1999/07/30 10:31:22 itojun Exp $	*/
2 
3 /*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
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 #include <sys/cdefs.h>
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)inet.c	8.4 (Berkeley) 4/20/94";
41 #else
42 __RCSID("$NetBSD: inet6.c,v 1.3 1999/07/30 10:31:22 itojun Exp $");
43 #endif
44 #endif /* not lint */
45 
46 #include <sys/param.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 <net/if.h>
54 #include <netinet/in.h>
55 #include <netinet/ip6.h>
56 #include <netinet/icmp6.h>
57 #include <netinet/in_systm.h>
58 #ifndef TCP6
59 #include <netinet/ip.h>
60 #include <netinet/ip_var.h>
61 #endif
62 #include <netinet6/in6_pcb.h>
63 #include <netinet6/ip6_var.h>
64 #ifdef TCP6
65 #include <netinet6/tcp6.h>
66 #include <netinet6/tcp6_seq.h>
67 #define TCP6STATES
68 #include <netinet6/tcp6_fsm.h>
69 #define TCP6TIMERS
70 #include <netinet6/tcp6_timer.h>
71 #include <netinet6/tcp6_var.h>
72 #include <netinet6/tcp6_debug.h>
73 #else
74 #include <netinet/tcp.h>
75 #include <netinet/tcpip.h>
76 #include <netinet/tcp_seq.h>
77 /*#define TCPSTATES*/
78 #include <netinet/tcp_fsm.h>
79 extern char *tcpstates[];
80 /*#define	TCPTIMERS*/
81 #include <netinet/tcp_timer.h>
82 #include <netinet/tcp_var.h>
83 #include <netinet/tcp_debug.h>
84 #endif /*TCP6*/
85 #include <netinet6/udp6.h>
86 #include <netinet6/udp6_var.h>
87 #include <netinet6/pim6_var.h>
88 
89 #include <arpa/inet.h>
90 #if 0
91 #include "gethostbyname2.h"
92 #endif
93 #include <netdb.h>
94 
95 #include <stdio.h>
96 #include <string.h>
97 #include <unistd.h>
98 #include "netstat.h"
99 
100 #ifdef INET6
101 
102 struct	in6pcb in6pcb;
103 #ifdef TCP6
104 struct	tcp6cb tcp6cb;
105 #else
106 struct	tcpcb tcpcb;
107 #endif
108 struct	socket sockb;
109 
110 char	*inet6name __P((struct in6_addr *));
111 void	inet6print __P((struct in6_addr *, int, char *));
112 
113 static char ntop_buf[INET6_ADDRSTRLEN];
114 
115 /*
116  * Print a summary of connections related to an Internet
117  * protocol.  For TCP, also give state of connection.
118  * Listening processes (aflag) are suppressed unless the
119  * -a (all) flag is specified.
120  */
121 void
122 ip6protopr(off, name)
123 	u_long off;
124 	char *name;
125 {
126 	struct in6pcb cb;
127 	register struct in6pcb *prev, *next;
128 	int istcp;
129 	static int first = 1;
130 
131 	if (off == 0)
132 		return;
133 	istcp = strcmp(name, "tcp6") == 0;
134 	kread(off, (char *)&cb, sizeof (struct in6pcb));
135 	in6pcb = cb;
136 	prev = (struct in6pcb *)off;
137 	if (in6pcb.in6p_next == (struct in6pcb *)off)
138 		return;
139 	while (in6pcb.in6p_next != (struct in6pcb *)off) {
140 		next = in6pcb.in6p_next;
141 		kread((u_long)next, (char *)&in6pcb, sizeof (in6pcb));
142 		if (in6pcb.in6p_prev != prev) {
143 			printf("???\n");
144 			break;
145 		}
146 		if (!aflag && IN6_IS_ADDR_ANY(&in6pcb.in6p_laddr)) {
147 			prev = next;
148 			continue;
149 		}
150 		kread((u_long)in6pcb.in6p_socket, (char *)&sockb, sizeof (sockb));
151 		if (istcp) {
152 #ifdef TCP6
153 			kread((u_long)in6pcb.in6p_ppcb,
154 			    (char *)&tcp6cb, sizeof (tcp6cb));
155 #else
156 			kread((u_long)in6pcb.in6p_ppcb,
157 			    (char *)&tcpcb, sizeof (tcpcb));
158 #endif
159 		}
160 		if (first) {
161 			printf("Active Internet6 connections");
162 			if (aflag)
163 				printf(" (including servers)");
164 			putchar('\n');
165 			if (Aflag)
166 				printf("%-8.8s ", "PCB");
167 			printf(Aflag ?
168 				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
169 				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
170 				"Proto", "Recv-Q", "Send-Q",
171 				"Local Address", "Foreign Address", "(state)");
172 			first = 0;
173 		}
174 		if (Aflag) {
175 			if (istcp)
176 				printf("%8p ", in6pcb.in6p_ppcb);
177 			else
178 				printf("%8p ", next);
179 		}
180 		printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
181 			sockb.so_snd.sb_cc);
182 		/* xxx */
183 		inet6print(&in6pcb.in6p_laddr, (int)in6pcb.in6p_lport, name);
184 		inet6print(&in6pcb.in6p_faddr, (int)in6pcb.in6p_fport, name);
185 		if (istcp) {
186 #ifdef TCP6
187 			if (tcp6cb.t_state < 0 || tcp6cb.t_state >= TCP6_NSTATES)
188 				printf(" %d", tcp6cb.t_state);
189 			else
190 				printf(" %s", tcp6states[tcp6cb.t_state]);
191 #else
192 			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
193 				printf(" %d", tcpcb.t_state);
194 			else
195 				printf(" %s", tcpstates[tcpcb.t_state]);
196 #endif
197 		}
198 		putchar('\n');
199 		prev = next;
200 	}
201 }
202 
203 #ifdef TCP6
204 /*
205  * Dump TCP6 statistics structure.
206  */
207 void
208 tcp6_stats(off, name)
209 	u_long off;
210 	char *name;
211 {
212 	struct tcp6stat tcp6stat;
213 
214 	if (off == 0)
215 		return;
216 	printf ("%s:\n", name);
217 	kread(off, (char *)&tcp6stat, sizeof (tcp6stat));
218 
219 #define	p(f, m) if (tcp6stat.f || sflag <= 1) \
220     printf(m, tcp6stat.f, plural(tcp6stat.f))
221 #define	p2(f1, f2, m) if (tcp6stat.f1 || tcp6stat.f2 || sflag <= 1) \
222     printf(m, tcp6stat.f1, plural(tcp6stat.f1), tcp6stat.f2, plural(tcp6stat.f2))
223 #define	p3(f, m) if (tcp6stat.f || sflag <= 1) \
224     printf(m, tcp6stat.f, plurales(tcp6stat.f))
225 
226 	p(tcp6s_sndtotal, "\t%ld packet%s sent\n");
227 	p2(tcp6s_sndpack,tcp6s_sndbyte,
228 		"\t\t%ld data packet%s (%ld byte%s)\n");
229 	p2(tcp6s_sndrexmitpack, tcp6s_sndrexmitbyte,
230 		"\t\t%ld data packet%s (%ld byte%s) retransmitted\n");
231 	p2(tcp6s_sndacks, tcp6s_delack,
232 		"\t\t%ld ack-only packet%s (%ld packet%s delayed)\n");
233 	p(tcp6s_sndurg, "\t\t%ld URG only packet%s\n");
234 	p(tcp6s_sndprobe, "\t\t%ld window probe packet%s\n");
235 	p(tcp6s_sndwinup, "\t\t%ld window update packet%s\n");
236 	p(tcp6s_sndctrl, "\t\t%ld control packet%s\n");
237 	p(tcp6s_rcvtotal, "\t%ld packet%s received\n");
238 	p2(tcp6s_rcvackpack, tcp6s_rcvackbyte, "\t\t%ld ack%s (for %ld byte%s)\n");
239 	p(tcp6s_rcvdupack, "\t\t%ld duplicate ack%s\n");
240 	p(tcp6s_rcvacktoomuch, "\t\t%ld ack%s for unsent data\n");
241 	p2(tcp6s_rcvpack, tcp6s_rcvbyte,
242 		"\t\t%ld packet%s (%ld byte%s) received in-sequence\n");
243 	p2(tcp6s_rcvduppack, tcp6s_rcvdupbyte,
244 		"\t\t%ld completely duplicate packet%s (%ld byte%s)\n");
245 	p(tcp6s_pawsdrop, "\t\t%ld old duplicate packet%s\n");
246 	p2(tcp6s_rcvpartduppack, tcp6s_rcvpartdupbyte,
247 		"\t\t%ld packet%s with some dup. data (%ld byte%s duped)\n");
248 	p2(tcp6s_rcvoopack, tcp6s_rcvoobyte,
249 		"\t\t%ld out-of-order packet%s (%ld byte%s)\n");
250 	p2(tcp6s_rcvpackafterwin, tcp6s_rcvbyteafterwin,
251 		"\t\t%ld packet%s (%ld byte%s) of data after window\n");
252 	p(tcp6s_rcvwinprobe, "\t\t%ld window probe%s\n");
253 	p(tcp6s_rcvwinupd, "\t\t%ld window update packet%s\n");
254 	p(tcp6s_rcvafterclose, "\t\t%ld packet%s received after close\n");
255 	p(tcp6s_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n");
256 	p(tcp6s_rcvbadoff, "\t\t%ld discarded for bad header offset field%s\n");
257 	p(tcp6s_rcvshort, "\t\t%ld discarded because packet%s too short\n");
258 	p(tcp6s_connattempt, "\t%ld connection request%s\n");
259 	p(tcp6s_accepts, "\t%ld connection accept%s\n");
260 	p(tcp6s_badsyn, "\t%ld bad connection attempt%s\n");
261 	p(tcp6s_connects, "\t%ld connection%s established (including accepts)\n");
262 	p2(tcp6s_closed, tcp6s_drops,
263 		"\t%ld connection%s closed (including %ld drop%s)\n");
264 	p(tcp6s_conndrops, "\t%ld embryonic connection%s dropped\n");
265 	p2(tcp6s_rttupdated, tcp6s_segstimed,
266 		"\t%ld segment%s updated rtt (of %ld attempt%s)\n");
267 	p(tcp6s_rexmttimeo, "\t%ld retransmit timeout%s\n");
268 	p(tcp6s_timeoutdrop, "\t\t%ld connection%s dropped by rexmit timeout\n");
269 	p(tcp6s_persisttimeo, "\t%ld persist timeout%s\n");
270 	p(tcp6s_persistdrop, "\t%ld connection%s timed out in persist\n");
271 	p(tcp6s_keeptimeo, "\t%ld keepalive timeout%s\n");
272 	p(tcp6s_keepprobe, "\t\t%ld keepalive probe%s sent\n");
273 	p(tcp6s_keepdrops, "\t\t%ld connection%s dropped by keepalive\n");
274 	p(tcp6s_predack, "\t%ld correct ACK header prediction%s\n");
275 	p(tcp6s_preddat, "\t%ld correct data packet header prediction%s\n");
276 	p3(tcp6s_pcbcachemiss, "\t%ld PCB cache miss%s\n");
277 #undef p
278 #undef p2
279 #undef p3
280 }
281 #endif
282 
283 /*
284  * Dump UDP6 statistics structure.
285  */
286 void
287 udp6_stats(off, name)
288 	u_long off;
289 	char *name;
290 {
291 	struct udp6stat udp6stat;
292 	u_long delivered;
293 
294 	if (off == 0)
295 		return;
296 	kread(off, (char *)&udp6stat, sizeof (udp6stat));
297 	printf("%s:\n", name);
298 #define	p(f, m) if (udp6stat.f || sflag <= 1) \
299     printf(m, udp6stat.f, plural(udp6stat.f))
300 #define	p1(f, m) if (udp6stat.f || sflag <= 1) \
301     printf(m, udp6stat.f)
302 	p(udp6s_ipackets, "\t%lu datagram%s received\n");
303 	p1(udp6s_hdrops, "\t%lu with incomplete header\n");
304 	p1(udp6s_badlen, "\t%lu with bad data length field\n");
305 	p1(udp6s_badsum, "\t%lu with bad checksum\n");
306 	p1(udp6s_nosum, "\t%lu with no checksum\n");
307 	p1(udp6s_noport, "\t%lu dropped due to no socket\n");
308 	p(udp6s_noportmcast, "\t%lu multicast datagram%s dropped due to no socket\n");
309 	p1(udp6s_fullsock, "\t%lu dropped due to full socket buffers\n");
310 	delivered = udp6stat.udp6s_ipackets -
311 		    udp6stat.udp6s_hdrops -
312 		    udp6stat.udp6s_badlen -
313 		    udp6stat.udp6s_badsum -
314 		    udp6stat.udp6s_noport -
315 		    udp6stat.udp6s_noportmcast -
316 		    udp6stat.udp6s_fullsock;
317 	if (delivered || sflag <= 1)
318 		printf("\t%lu delivered\n", delivered);
319 	p(udp6s_opackets, "\t%lu datagram%s output\n");
320 #undef p
321 #undef p1
322 }
323 
324 static	char *ip6nh[] = {
325 	"hop by hop",
326 	"ICMP",
327 	"IGMP",
328 	"#3",
329 	"IP",
330 	"#5",
331 	"TCP",
332 	"#7",
333 	"#8",
334 	"#9",
335 	"#10",
336 	"#11",
337 	"#12",
338 	"#13",
339 	"#14",
340 	"#15",
341 	"#16",
342 	"UDP",
343 	"#18",
344 	"#19",
345 	"#20",
346 	"#21",
347 	"IDP",
348 	"#23",
349 	"#24",
350 	"#25",
351 	"#26",
352 	"#27",
353 	"#28",
354 	"TP",
355 	"#30",
356 	"#31",
357 	"#32",
358 	"#33",
359 	"#34",
360 	"#35",
361 	"#36",
362 	"#37",
363 	"#38",
364 	"#39",
365 	"#40",
366 	"IP6",
367 	"#42",
368 	"routing",
369 	"fragment",
370 	"#45",
371 	"#46",
372 	"#47",
373 	"#48",
374 	"#49",
375 	"ESP",
376 	"AH",
377 	"#52",
378 	"#53",
379 	"#54",
380 	"#55",
381 	"#56",
382 	"#57",
383 	"ICMP6",
384 	"no next header",
385 	"destination option",
386 	"#61",
387 	"#62",
388 	"#63",
389 	"#64",
390 	"#65",
391 	"#66",
392 	"#67",
393 	"#68",
394 	"#69",
395 	"#70",
396 	"#71",
397 	"#72",
398 	"#73",
399 	"#74",
400 	"#75",
401 	"#76",
402 	"#77",
403 	"#78",
404 	"#79",
405 	"ISOIP",
406 	"#81",
407 	"#82",
408 	"#83",
409 	"#84",
410 	"#85",
411 	"#86",
412 	"#87",
413 	"#88",
414 	"#89",
415 	"#80",
416 	"#91",
417 	"#92",
418 	"#93",
419 	"#94",
420 	"#95",
421 	"#96",
422 	"Ethernet",
423 	"#98",
424 	"#99",
425 	"#100",
426 	"#101",
427 	"#102",
428 	"PIM",
429 	"#104",
430 	"#105",
431 	"#106",
432 	"#107",
433 	"#108",
434 	"#109",
435 	"#110",
436 	"#111",
437 	"#112",
438 	"#113",
439 	"#114",
440 	"#115",
441 	"#116",
442 	"#117",
443 	"#118",
444 	"#119",
445 	"#120",
446 	"#121",
447 	"#122",
448 	"#123",
449 	"#124",
450 	"#125",
451 	"#126",
452 	"#127",
453 	"#128",
454 	"#129",
455 	"#130",
456 	"#131",
457 	"#132",
458 	"#133",
459 	"#134",
460 	"#135",
461 	"#136",
462 	"#137",
463 	"#138",
464 	"#139",
465 	"#140",
466 	"#141",
467 	"#142",
468 	"#143",
469 	"#144",
470 	"#145",
471 	"#146",
472 	"#147",
473 	"#148",
474 	"#149",
475 	"#150",
476 	"#151",
477 	"#152",
478 	"#153",
479 	"#154",
480 	"#155",
481 	"#156",
482 	"#157",
483 	"#158",
484 	"#159",
485 	"#160",
486 	"#161",
487 	"#162",
488 	"#163",
489 	"#164",
490 	"#165",
491 	"#166",
492 	"#167",
493 	"#168",
494 	"#169",
495 	"#170",
496 	"#171",
497 	"#172",
498 	"#173",
499 	"#174",
500 	"#175",
501 	"#176",
502 	"#177",
503 	"#178",
504 	"#179",
505 	"#180",
506 	"#181",
507 	"#182",
508 	"#183",
509 	"#184",
510 	"#185",
511 	"#186",
512 	"#187",
513 	"#188",
514 	"#189",
515 	"#180",
516 	"#191",
517 	"#192",
518 	"#193",
519 	"#194",
520 	"#195",
521 	"#196",
522 	"#197",
523 	"#198",
524 	"#199",
525 	"#200",
526 	"#201",
527 	"#202",
528 	"#203",
529 	"#204",
530 	"#205",
531 	"#206",
532 	"#207",
533 	"#208",
534 	"#209",
535 	"#210",
536 	"#211",
537 	"#212",
538 	"#213",
539 	"#214",
540 	"#215",
541 	"#216",
542 	"#217",
543 	"#218",
544 	"#219",
545 	"#220",
546 	"#221",
547 	"#222",
548 	"#223",
549 	"#224",
550 	"#225",
551 	"#226",
552 	"#227",
553 	"#228",
554 	"#229",
555 	"#230",
556 	"#231",
557 	"#232",
558 	"#233",
559 	"#234",
560 	"#235",
561 	"#236",
562 	"#237",
563 	"#238",
564 	"#239",
565 	"#240",
566 	"#241",
567 	"#242",
568 	"#243",
569 	"#244",
570 	"#245",
571 	"#246",
572 	"#247",
573 	"#248",
574 	"#249",
575 	"#250",
576 	"#251",
577 	"#252",
578 	"#253",
579 	"#254",
580 	"#255",
581 };
582 
583 /*
584  * Dump IP6 statistics structure.
585  */
586 void
587 ip6_stats(off, name)
588 	u_long off;
589 	char *name;
590 {
591 	struct ip6stat ip6stat;
592 	int first, i;
593 
594 	if (off == 0)
595 		return;
596 
597 	kread(off, (char *)&ip6stat, sizeof (ip6stat));
598 	printf("%s:\n", name);
599 
600 #define	p(f, m) if (ip6stat.f || sflag <= 1) \
601     printf(m, ip6stat.f, plural(ip6stat.f))
602 #define	p1(f, m) if (ip6stat.f || sflag <= 1) \
603     printf(m, ip6stat.f)
604 
605 	p(ip6s_total, "\t%lu total packet%s received\n");
606 	p1(ip6s_toosmall, "\t%lu with size smaller than minimum\n");
607 	p1(ip6s_tooshort, "\t%lu with data size < data length\n");
608 	p1(ip6s_badoptions, "\t%lu with bad options\n");
609 	p1(ip6s_badvers, "\t%lu with incorrect version number\n");
610 	p(ip6s_fragments, "\t%lu fragment%s received\n");
611 	p(ip6s_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
612 	p(ip6s_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
613 	p(ip6s_fragoverflow, "\t%lu fragment%s that exceeded limit\n");
614 	p(ip6s_reassembled, "\t%lu packet%s reassembled ok\n");
615 	p(ip6s_delivered, "\t%lu packet%s for this host\n");
616 	p(ip6s_forward, "\t%lu packet%s forwarded\n");
617 	p(ip6s_cantforward, "\t%lu packet%s not forwardable\n");
618 	p(ip6s_redirectsent, "\t%lu redirect%s sent\n");
619 	p(ip6s_localout, "\t%lu packet%s sent from this host\n");
620 	p(ip6s_rawout, "\t%lu packet%s sent with fabricated ip header\n");
621 	p(ip6s_odropped, "\t%lu output packet%s dropped due to no bufs, etc.\n");
622 	p(ip6s_noroute, "\t%lu output packet%s discarded due to no route\n");
623 	p(ip6s_fragmented, "\t%lu output datagram%s fragmented\n");
624 	p(ip6s_ofragments, "\t%lu fragment%s created\n");
625 	p(ip6s_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
626 	p(ip6s_badscope, "\t%lu packet%s that violated scope rules\n");
627 	p(ip6s_notmember, "\t%lu multicast packet%s which we don't join\n");
628 	for (first = 1, i = 0; i < 256; i++)
629 		if (ip6stat.ip6s_nxthist[i] != 0) {
630 			if (first) {
631 				printf("\tInput histogram:\n");
632 				first = 0;
633 			}
634 			printf("\t\t%s: %lu\n", ip6nh[i],
635 			       ip6stat.ip6s_nxthist[i]);
636 		}
637 	printf("\tMbuf statics:\n");
638 	printf("\t\t%lu one mbuf\n", ip6stat.ip6s_m1);
639 	for (first = 1, i = 0; i < 32; i++) {
640 		char ifbuf[IFNAMSIZ];
641 		if (ip6stat.ip6s_m2m[i] != 0) {
642 			if (first) {
643 				printf("\t\ttwo or more mbuf:\n");
644 				first = 0;
645 			}
646 			printf("\t\t\t%s = %ld\n",
647 			       if_indextoname(i, ifbuf),
648 			       ip6stat.ip6s_m2m[i]);
649 		}
650 	}
651 	printf("\t\t%lu one ext mbuf\n", ip6stat.ip6s_mext1);
652 	printf("\t\t%lu two or more ext mbuf\n", ip6stat.ip6s_mext2m);
653 	p(ip6s_exthdrtoolong, "\t%lu packet%s whose headers are not continuous\n");
654 	p(ip6s_nogif, "\t%lu tunneling packet%s that can't find gif\n");
655 #undef p
656 #undef p1
657 }
658 
659 static	char *icmp6names[] = {
660 	"#0",
661 	"unreach",
662 	"packet too big",
663 	"time exceed",
664 	"parameter problem",
665 	"#5",
666 	"#6",
667 	"#7",
668 	"#8",
669 	"#9",
670 	"#10",
671 	"#11",
672 	"#12",
673 	"#13",
674 	"#14",
675 	"#15",
676 	"#16",
677 	"#17",
678 	"#18",
679 	"#19",
680 	"#20",
681 	"#21",
682 	"#22",
683 	"#23",
684 	"#24",
685 	"#25",
686 	"#26",
687 	"#27",
688 	"#28",
689 	"#29",
690 	"#30",
691 	"#31",
692 	"#32",
693 	"#33",
694 	"#34",
695 	"#35",
696 	"#36",
697 	"#37",
698 	"#38",
699 	"#39",
700 	"#40",
701 	"#41",
702 	"#42",
703 	"#43",
704 	"#44",
705 	"#45",
706 	"#46",
707 	"#47",
708 	"#48",
709 	"#49",
710 	"#50",
711 	"#51",
712 	"#52",
713 	"#53",
714 	"#54",
715 	"#55",
716 	"#56",
717 	"#57",
718 	"#58",
719 	"#59",
720 	"#60",
721 	"#61",
722 	"#62",
723 	"#63",
724 	"#64",
725 	"#65",
726 	"#66",
727 	"#67",
728 	"#68",
729 	"#69",
730 	"#70",
731 	"#71",
732 	"#72",
733 	"#73",
734 	"#74",
735 	"#75",
736 	"#76",
737 	"#77",
738 	"#78",
739 	"#79",
740 	"#80",
741 	"#81",
742 	"#82",
743 	"#83",
744 	"#84",
745 	"#85",
746 	"#86",
747 	"#87",
748 	"#88",
749 	"#89",
750 	"#80",
751 	"#91",
752 	"#92",
753 	"#93",
754 	"#94",
755 	"#95",
756 	"#96",
757 	"#97",
758 	"#98",
759 	"#99",
760 	"#100",
761 	"#101",
762 	"#102",
763 	"#103",
764 	"#104",
765 	"#105",
766 	"#106",
767 	"#107",
768 	"#108",
769 	"#109",
770 	"#110",
771 	"#111",
772 	"#112",
773 	"#113",
774 	"#114",
775 	"#115",
776 	"#116",
777 	"#117",
778 	"#118",
779 	"#119",
780 	"#120",
781 	"#121",
782 	"#122",
783 	"#123",
784 	"#124",
785 	"#125",
786 	"#126",
787 	"#127",
788 	"echo",
789 	"echo reply",
790 	"group member query",
791 	"group member report",
792 	"group member termination",
793 	"router solicitation",
794 	"router advertisment",
795 	"neighbor solicitation",
796 	"neighbor advertisment",
797 	"redirect",
798 	"router renumbering",
799 	"node information request",
800 	"node information reply",
801 	"#141",
802 	"#142",
803 	"#143",
804 	"#144",
805 	"#145",
806 	"#146",
807 	"#147",
808 	"#148",
809 	"#149",
810 	"#150",
811 	"#151",
812 	"#152",
813 	"#153",
814 	"#154",
815 	"#155",
816 	"#156",
817 	"#157",
818 	"#158",
819 	"#159",
820 	"#160",
821 	"#161",
822 	"#162",
823 	"#163",
824 	"#164",
825 	"#165",
826 	"#166",
827 	"#167",
828 	"#168",
829 	"#169",
830 	"#170",
831 	"#171",
832 	"#172",
833 	"#173",
834 	"#174",
835 	"#175",
836 	"#176",
837 	"#177",
838 	"#178",
839 	"#179",
840 	"#180",
841 	"#181",
842 	"#182",
843 	"#183",
844 	"#184",
845 	"#185",
846 	"#186",
847 	"#187",
848 	"#188",
849 	"#189",
850 	"#180",
851 	"#191",
852 	"#192",
853 	"#193",
854 	"#194",
855 	"#195",
856 	"#196",
857 	"#197",
858 	"#198",
859 	"#199",
860 	"#200",
861 	"#201",
862 	"#202",
863 	"#203",
864 	"#204",
865 	"#205",
866 	"#206",
867 	"#207",
868 	"#208",
869 	"#209",
870 	"#210",
871 	"#211",
872 	"#212",
873 	"#213",
874 	"#214",
875 	"#215",
876 	"#216",
877 	"#217",
878 	"#218",
879 	"#219",
880 	"#220",
881 	"#221",
882 	"#222",
883 	"#223",
884 	"#224",
885 	"#225",
886 	"#226",
887 	"#227",
888 	"#228",
889 	"#229",
890 	"#230",
891 	"#231",
892 	"#232",
893 	"#233",
894 	"#234",
895 	"#235",
896 	"#236",
897 	"#237",
898 	"#238",
899 	"#239",
900 	"#240",
901 	"#241",
902 	"#242",
903 	"#243",
904 	"#244",
905 	"#245",
906 	"#246",
907 	"#247",
908 	"#248",
909 	"#249",
910 	"#250",
911 	"#251",
912 	"#252",
913 	"#253",
914 	"#254",
915 	"#255",
916 };
917 
918 /*
919  * Dump ICMP6 statistics.
920  */
921 void
922 icmp6_stats(off, name)
923 	u_long off;
924 	char *name;
925 {
926 	struct icmp6stat icmp6stat;
927 	register int i, first;
928 
929 	if (off == 0)
930 		return;
931 	kread(off, (char *)&icmp6stat, sizeof (icmp6stat));
932 	printf("%s:\n", name);
933 
934 #define	p(f, m) if (icmp6stat.f || sflag <= 1) \
935     printf(m, icmp6stat.f, plural(icmp6stat.f))
936 
937 	p(icp6s_error, "\t%lu call%s to icmp_error\n");
938 	p(icp6s_canterror,
939 	    "\t%lu error%s not generated because old message was icmp or so\n");
940 	for (first = 1, i = 0; i < 256; i++)
941 		if (icmp6stat.icp6s_outhist[i] != 0) {
942 			if (first) {
943 				printf("\tOutput histogram:\n");
944 				first = 0;
945 			}
946 			printf("\t\t%s: %lu\n", icmp6names[i],
947 				icmp6stat.icp6s_outhist[i]);
948 		}
949 	p(icp6s_badcode, "\t%lu message%s with bad code fields\n");
950 	p(icp6s_tooshort, "\t%lu message%s < minimum length\n");
951 	p(icp6s_checksum, "\t%lu bad checksum%s\n");
952 	p(icp6s_badlen, "\t%lu message%s with bad length\n");
953 	for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
954 		if (icmp6stat.icp6s_inhist[i] != 0) {
955 			if (first) {
956 				printf("\tInput histogram:\n");
957 				first = 0;
958 			}
959 			printf("\t\t%s: %lu\n", icmp6names[i],
960 				icmp6stat.icp6s_inhist[i]);
961 		}
962 	p(icp6s_reflect, "\t%lu message response%s generated\n");
963 #undef p
964 }
965 
966 /*
967  * Dump PIM statistics structure.
968  */
969 void
970 pim6_stats(off, name)
971 	u_long off;
972 	char *name;
973 {
974 	struct pim6stat pim6stat;
975 
976 	if (off == 0)
977 		return;
978 	kread(off, (char *)&pim6stat, sizeof(pim6stat));
979 	printf("%s:\n", name);
980 
981 #define	p(f, m) if (pim6stat.f || sflag <= 1) \
982     printf(m, pim6stat.f, plural(pim6stat.f))
983 	p(pim6s_rcv_total, "\t%u message%s received\n");
984 	p(pim6s_rcv_tooshort, "\t%u message%s received with too few bytes\n");
985 	p(pim6s_rcv_badsum, "\t%u message%s received with bad checksum\n");
986 	p(pim6s_rcv_badversion, "\t%u message%s received with bad version\n");
987 	p(pim6s_rcv_registers, "\t%u register%s received\n");
988 	p(pim6s_rcv_badregisters, "\t%u bad register%s received\n");
989 	p(pim6s_snd_registers, "\t%u register%s sent\n");
990 #undef p
991 }
992 
993 /*
994  * Pretty print an Internet address (net address + port).
995  * If the nflag was specified, use numbers instead of names.
996  */
997 
998 void
999 inet6print(in6, port, proto)
1000 	register struct in6_addr *in6;
1001 	int port;
1002 	char *proto;
1003 {
1004 #define GETSERVBYPORT6(port, proto, ret)\
1005 {\
1006 	if (strcmp((proto), "tcp6") == 0)\
1007 		(ret) = getservbyport((int)(port), "tcp");\
1008 	else if (strcmp((proto), "udp6") == 0)\
1009 		(ret) = getservbyport((int)(port), "udp");\
1010 	else\
1011 		(ret) = getservbyport((int)(port), (proto));\
1012 };
1013 	struct servent *sp = 0;
1014 	char line[80], *cp;
1015 	int width;
1016 
1017 	sprintf(line, "%.*s.", (Aflag && !nflag) ? 12 : 16, inet6name(in6));
1018 	cp = index(line, '\0');
1019 	if (!nflag && port)
1020 		GETSERVBYPORT6(port, proto, sp);
1021 	if (sp || port == 0)
1022 		sprintf(cp, "%.8s", sp ? sp->s_name : "*");
1023 	else
1024 		sprintf(cp, "%d", ntohs((u_short)port));
1025 	width = Aflag ? 18 : 22;
1026 	printf(" %-*.*s", width, width, line);
1027 }
1028 
1029 /*
1030  * Construct an Internet address representation.
1031  * If the nflag has been supplied, give
1032  * numeric value, otherwise try for symbolic name.
1033  */
1034 
1035 char *
1036 inet6name(in6p)
1037 	struct in6_addr *in6p;
1038 {
1039 	register char *cp;
1040 	static char line[50];
1041 	struct hostent *hp;
1042 	static char domain[MAXHOSTNAMELEN + 1];
1043 	static int first = 1;
1044 
1045 	if (first && !nflag) {
1046 		first = 0;
1047 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1048 		    (cp = index(domain, '.')))
1049 			(void) strcpy(domain, cp + 1);
1050 		else
1051 			domain[0] = 0;
1052 	}
1053 	cp = 0;
1054 	if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1055 		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
1056 		if (hp) {
1057 			if ((cp = index(hp->h_name, '.')) &&
1058 			    !strcmp(cp + 1, domain))
1059 				*cp = 0;
1060 			cp = hp->h_name;
1061 		}
1062 	}
1063 	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1064 		strcpy(line, "*");
1065 	else if (cp)
1066 		strcpy(line, cp);
1067 	else
1068 		sprintf(line, "%s",
1069 			inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
1070 				sizeof(ntop_buf)));
1071 	return (line);
1072 }
1073 
1074 #ifdef TCP6
1075 /*
1076  * Dump the contents of a TCP6 PCB.
1077  */
1078 void
1079 tcp6_dump(pcbaddr)
1080 	u_long pcbaddr;
1081 {
1082 	struct tcp6cb tcp6cb;
1083 	int i;
1084 
1085 	kread(pcbaddr, (char *)&tcp6cb, sizeof(tcp6cb));
1086 
1087 	printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
1088 
1089 	printf("Timers:\n");
1090 	for (i = 0; i < TCP6T_NTIMERS; i++)
1091 		printf("\t%s: %u", tcp6timers[i], tcp6cb.t_timer[i]);
1092 	printf("\n\n");
1093 
1094 	if (tcp6cb.t_state < 0 || tcp6cb.t_state >= TCP6_NSTATES)
1095 		printf("State: %d", tcp6cb.t_state);
1096 	else
1097 		printf("State: %s", tcp6states[tcp6cb.t_state]);
1098 	printf(", flags 0x%x, in6pcb 0x%lx\n\n", tcp6cb.t_flags,
1099 	    (u_long)tcp6cb.t_in6pcb);
1100 
1101 	printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcp6cb.t_rxtshift,
1102 	    tcp6cb.t_rxtcur, tcp6cb.t_dupacks);
1103 	printf("peermaxseg %u, maxseg %u, force %d\n\n", tcp6cb.t_peermaxseg,
1104 	    tcp6cb.t_maxseg, tcp6cb.t_force);
1105 
1106 	printf("snd_una %u, snd_nxt %u, snd_up %u\n",
1107 	    tcp6cb.snd_una, tcp6cb.snd_nxt, tcp6cb.snd_up);
1108 	printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
1109 	    tcp6cb.snd_wl1, tcp6cb.snd_wl2, tcp6cb.iss, tcp6cb.snd_wnd);
1110 
1111 	printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
1112 	    tcp6cb.rcv_wnd, tcp6cb.rcv_nxt, tcp6cb.rcv_up, tcp6cb.irs);
1113 
1114 	printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
1115 	    tcp6cb.rcv_adv, tcp6cb.snd_max, tcp6cb.snd_cwnd, tcp6cb.snd_ssthresh);
1116 
1117 	printf("idle %d, rtt %d, rtseq %u, srtt %d, rttvar %d, rttmin %d, "
1118 	    "max_sndwnd %lu\n\n", tcp6cb.t_idle, tcp6cb.t_rtt, tcp6cb.t_rtseq,
1119 	    tcp6cb.t_srtt, tcp6cb.t_rttvar, tcp6cb.t_rttmin, tcp6cb.max_sndwnd);
1120 
1121 	printf("oobflags %d, iobc %d, softerror %d\n\n", tcp6cb.t_oobflags,
1122 	    tcp6cb.t_iobc, tcp6cb.t_softerror);
1123 
1124 	printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
1125 	    tcp6cb.snd_scale, tcp6cb.rcv_scale, tcp6cb.request_r_scale,
1126 	    tcp6cb.requested_s_scale);
1127 	printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
1128 	    tcp6cb.ts_recent, tcp6cb.ts_recent_age, tcp6cb.last_ack_sent);
1129 }
1130 #endif
1131 
1132 #endif /*INET6*/
1133