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