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