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