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