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