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