1 /* $OpenBSD: inet6.c,v 1.36 2007/12/19 01:47:00 deraadt 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 #ifndef TCP6 47 #include <netinet/ip.h> 48 #include <netinet/ip_var.h> 49 #endif 50 #include <netinet6/ip6_var.h> 51 #include <netinet6/in6_var.h> 52 #include <netinet6/pim6_var.h> 53 #include <netinet6/raw_ip6.h> 54 55 #include <arpa/inet.h> 56 #if 0 57 #include "gethostbyname2.h" 58 #endif 59 #include <netdb.h> 60 61 #include <stdio.h> 62 #include <string.h> 63 #include <unistd.h> 64 #include <errno.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_exthdrtoolong, 417 "\t%llu packet%s whose headers are not continuous\n"); 418 p(ip6s_nogif, "\t%llu tunneling packet%s that can't find gif\n"); 419 p(ip6s_toomanyhdr, 420 "\t%llu packet%s discarded due to too many headers\n"); 421 422 /* for debugging source address selection */ 423 #define PRINT_SCOPESTAT(s,i) do {\ 424 switch(i) { /* XXX hardcoding in each case */\ 425 case 1:\ 426 p(s, "\t\t%llu node-local%s\n");\ 427 break;\ 428 case 2:\ 429 p(s, "\t\t%llu link-local%s\n");\ 430 break;\ 431 case 5:\ 432 p(s, "\t\t%llu site-local%s\n");\ 433 break;\ 434 case 14:\ 435 p(s, "\t\t%llu global%s\n");\ 436 break;\ 437 default:\ 438 printf("\t\t%llu addresses scope=%x\n",\ 439 (unsigned long long)ip6stat.s, i);\ 440 }\ 441 } while(0); 442 443 p(ip6s_sources_none, 444 "\t%llu failure%s of source address selection\n"); 445 for (first = 1, i = 0; i < 16; i++) { 446 if (ip6stat.ip6s_sources_sameif[i]) { 447 if (first) { 448 printf("\tsource addresses on an outgoing I/F\n"); 449 first = 0; 450 } 451 PRINT_SCOPESTAT(ip6s_sources_sameif[i], i); 452 } 453 } 454 for (first = 1, i = 0; i < 16; i++) { 455 if (ip6stat.ip6s_sources_otherif[i]) { 456 if (first) { 457 printf("\tsource addresses on a non-outgoing I/F\n"); 458 first = 0; 459 } 460 PRINT_SCOPESTAT(ip6s_sources_otherif[i], i); 461 } 462 } 463 for (first = 1, i = 0; i < 16; i++) { 464 if (ip6stat.ip6s_sources_samescope[i]) { 465 if (first) { 466 printf("\tsource addresses of same scope\n"); 467 first = 0; 468 } 469 PRINT_SCOPESTAT(ip6s_sources_samescope[i], i); 470 } 471 } 472 for (first = 1, i = 0; i < 16; i++) { 473 if (ip6stat.ip6s_sources_otherscope[i]) { 474 if (first) { 475 printf("\tsource addresses of a different scope\n"); 476 first = 0; 477 } 478 PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i); 479 } 480 } 481 for (first = 1, i = 0; i < 16; i++) { 482 if (ip6stat.ip6s_sources_deprecated[i]) { 483 if (first) { 484 printf("\tdeprecated source addresses\n"); 485 first = 0; 486 } 487 PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i); 488 } 489 } 490 491 p1(ip6s_forward_cachehit, "\t%llu forward cache hit\n"); 492 p1(ip6s_forward_cachemiss, "\t%llu forward cache miss\n"); 493 #undef p 494 #undef p1 495 } 496 497 /* 498 * Dump IPv6 per-interface statistics based on RFC 2465. 499 */ 500 void 501 ip6_ifstats(char *ifname) 502 { 503 struct in6_ifreq ifr; 504 int s; 505 506 #define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \ 507 printf(m, (unsigned long long)ifr.ifr_ifru.ifru_stat.f, \ 508 plural(ifr.ifr_ifru.ifru_stat.f)) 509 #define p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \ 510 printf(m, (unsigned long long)ip6stat.f) 511 512 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 513 perror("Warning: socket(AF_INET6)"); 514 return; 515 } 516 517 strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name); 518 printf("ip6 on %s:\n", ifr.ifr_name); 519 520 if (ioctl(s, SIOCGIFSTAT_IN6, &ifr) < 0) { 521 perror("Warning: ioctl(SIOCGIFSTAT_IN6)"); 522 goto end; 523 } 524 525 p(ifs6_in_receive, "\t%llu total input datagram%s\n"); 526 p(ifs6_in_hdrerr, "\t%llu datagram%s with invalid header received\n"); 527 p(ifs6_in_toobig, "\t%llu datagram%s exceeded MTU received\n"); 528 p(ifs6_in_noroute, "\t%llu datagram%s with no route received\n"); 529 p(ifs6_in_addrerr, "\t%llu datagram%s with invalid dst received\n"); 530 p(ifs6_in_truncated, "\t%llu truncated datagram%s received\n"); 531 p(ifs6_in_protounknown, "\t%llu datagram%s with unknown proto received\n"); 532 p(ifs6_in_discard, "\t%llu input datagram%s discarded\n"); 533 p(ifs6_in_deliver, 534 "\t%llu datagram%s delivered to an upper layer protocol\n"); 535 p(ifs6_out_forward, "\t%llu datagram%s forwarded to this interface\n"); 536 p(ifs6_out_request, 537 "\t%llu datagram%s sent from an upper layer protocol\n"); 538 p(ifs6_out_discard, "\t%llu total discarded output datagram%s\n"); 539 p(ifs6_out_fragok, "\t%llu output datagram%s fragmented\n"); 540 p(ifs6_out_fragfail, "\t%llu output datagram%s failed on fragment\n"); 541 p(ifs6_out_fragcreat, "\t%llu output datagram%s succeeded on fragment\n"); 542 p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n"); 543 p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n"); 544 p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembling\n"); 545 p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n"); 546 p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n"); 547 548 end: 549 close(s); 550 551 #undef p 552 #undef p_5 553 } 554 555 static char *icmp6names[] = { 556 "#0", 557 "unreach", 558 "packet too big", 559 "time exceed", 560 "parameter problem", 561 "#5", 562 "#6", 563 "#7", 564 "#8", 565 "#9", 566 "#10", 567 "#11", 568 "#12", 569 "#13", 570 "#14", 571 "#15", 572 "#16", 573 "#17", 574 "#18", 575 "#19", 576 "#20", 577 "#21", 578 "#22", 579 "#23", 580 "#24", 581 "#25", 582 "#26", 583 "#27", 584 "#28", 585 "#29", 586 "#30", 587 "#31", 588 "#32", 589 "#33", 590 "#34", 591 "#35", 592 "#36", 593 "#37", 594 "#38", 595 "#39", 596 "#40", 597 "#41", 598 "#42", 599 "#43", 600 "#44", 601 "#45", 602 "#46", 603 "#47", 604 "#48", 605 "#49", 606 "#50", 607 "#51", 608 "#52", 609 "#53", 610 "#54", 611 "#55", 612 "#56", 613 "#57", 614 "#58", 615 "#59", 616 "#60", 617 "#61", 618 "#62", 619 "#63", 620 "#64", 621 "#65", 622 "#66", 623 "#67", 624 "#68", 625 "#69", 626 "#70", 627 "#71", 628 "#72", 629 "#73", 630 "#74", 631 "#75", 632 "#76", 633 "#77", 634 "#78", 635 "#79", 636 "#80", 637 "#81", 638 "#82", 639 "#83", 640 "#84", 641 "#85", 642 "#86", 643 "#87", 644 "#88", 645 "#89", 646 "#80", 647 "#91", 648 "#92", 649 "#93", 650 "#94", 651 "#95", 652 "#96", 653 "#97", 654 "#98", 655 "#99", 656 "#100", 657 "#101", 658 "#102", 659 "#103", 660 "#104", 661 "#105", 662 "#106", 663 "#107", 664 "#108", 665 "#109", 666 "#110", 667 "#111", 668 "#112", 669 "#113", 670 "#114", 671 "#115", 672 "#116", 673 "#117", 674 "#118", 675 "#119", 676 "#120", 677 "#121", 678 "#122", 679 "#123", 680 "#124", 681 "#125", 682 "#126", 683 "#127", 684 "echo", 685 "echo reply", 686 "multicast listener query", 687 "multicast listener report", 688 "multicast listener done", 689 "router solicitation", 690 "router advertisement", 691 "neighbor solicitation", 692 "neighbor advertisement", 693 "redirect", 694 "router renumbering", 695 "node information request", 696 "node information reply", 697 "#141", 698 "#142", 699 "#143", 700 "#144", 701 "#145", 702 "#146", 703 "#147", 704 "#148", 705 "#149", 706 "#150", 707 "#151", 708 "#152", 709 "#153", 710 "#154", 711 "#155", 712 "#156", 713 "#157", 714 "#158", 715 "#159", 716 "#160", 717 "#161", 718 "#162", 719 "#163", 720 "#164", 721 "#165", 722 "#166", 723 "#167", 724 "#168", 725 "#169", 726 "#170", 727 "#171", 728 "#172", 729 "#173", 730 "#174", 731 "#175", 732 "#176", 733 "#177", 734 "#178", 735 "#179", 736 "#180", 737 "#181", 738 "#182", 739 "#183", 740 "#184", 741 "#185", 742 "#186", 743 "#187", 744 "#188", 745 "#189", 746 "#180", 747 "#191", 748 "#192", 749 "#193", 750 "#194", 751 "#195", 752 "#196", 753 "#197", 754 "#198", 755 "#199", 756 "#200", 757 "#201", 758 "#202", 759 "#203", 760 "#204", 761 "#205", 762 "#206", 763 "#207", 764 "#208", 765 "#209", 766 "#210", 767 "#211", 768 "#212", 769 "#213", 770 "#214", 771 "#215", 772 "#216", 773 "#217", 774 "#218", 775 "#219", 776 "#220", 777 "#221", 778 "#222", 779 "#223", 780 "#224", 781 "#225", 782 "#226", 783 "#227", 784 "#228", 785 "#229", 786 "#230", 787 "#231", 788 "#232", 789 "#233", 790 "#234", 791 "#235", 792 "#236", 793 "#237", 794 "#238", 795 "#239", 796 "#240", 797 "#241", 798 "#242", 799 "#243", 800 "#244", 801 "#245", 802 "#246", 803 "#247", 804 "#248", 805 "#249", 806 "#250", 807 "#251", 808 "#252", 809 "#253", 810 "#254", 811 "#255", 812 }; 813 814 /* 815 * Dump ICMPv6 statistics. 816 */ 817 void 818 icmp6_stats(char *name) 819 { 820 struct icmp6stat icmp6stat; 821 int i, first; 822 int mib[] = { CTL_NET, AF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_STATS }; 823 size_t len = sizeof(icmp6stat); 824 825 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 826 &icmp6stat, &len, NULL, 0) == -1) { 827 if (errno != ENOPROTOOPT) 828 warn(name); 829 return; 830 } 831 832 printf("%s:\n", name); 833 #define p(f, m) if (icmp6stat.f || sflag <= 1) \ 834 printf(m, (unsigned long long)icmp6stat.f, plural(icmp6stat.f)) 835 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \ 836 printf(m, (unsigned long long)icmp6stat.f) 837 838 p(icp6s_error, "\t%llu call%s to icmp6_error\n"); 839 p(icp6s_canterror, 840 "\t%llu error%s not generated because old message was icmp6 or so\n"); 841 p(icp6s_toofreq, 842 "\t%llu error%s not generated because of rate limitation\n"); 843 for (first = 1, i = 0; i < 256; i++) 844 if (icmp6stat.icp6s_outhist[i] != 0) { 845 if (first) { 846 printf("\tOutput packet histogram:\n"); 847 first = 0; 848 } 849 printf("\t\t%s: %llu\n", icmp6names[i], 850 (unsigned long long)icmp6stat.icp6s_outhist[i]); 851 } 852 p(icp6s_badcode, "\t%llu message%s with bad code fields\n"); 853 p(icp6s_tooshort, "\t%llu message%s < minimum length\n"); 854 p(icp6s_checksum, "\t%llu bad checksum%s\n"); 855 p(icp6s_badlen, "\t%llu message%s with bad length\n"); 856 for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++) 857 if (icmp6stat.icp6s_inhist[i] != 0) { 858 if (first) { 859 printf("\tInput packet histogram:\n"); 860 first = 0; 861 } 862 printf("\t\t%s: %llu\n", icmp6names[i], 863 (unsigned long long)icmp6stat.icp6s_inhist[i]); 864 } 865 printf("\tHistogram of error messages to be generated:\n"); 866 p_5(icp6s_odst_unreach_noroute, "\t\t%llu no route\n"); 867 p_5(icp6s_odst_unreach_admin, "\t\t%llu administratively prohibited\n"); 868 p_5(icp6s_odst_unreach_beyondscope, "\t\t%llu beyond scope\n"); 869 p_5(icp6s_odst_unreach_addr, "\t\t%llu address unreachable\n"); 870 p_5(icp6s_odst_unreach_noport, "\t\t%llu port unreachable\n"); 871 p_5(icp6s_opacket_too_big, "\t\t%llu packet too big\n"); 872 p_5(icp6s_otime_exceed_transit, "\t\t%llu time exceed transit\n"); 873 p_5(icp6s_otime_exceed_reassembly, "\t\t%llu time exceed reassembly\n"); 874 p_5(icp6s_oparamprob_header, "\t\t%llu erroneous header field\n"); 875 p_5(icp6s_oparamprob_nextheader, "\t\t%llu unrecognized next header\n"); 876 p_5(icp6s_oparamprob_option, "\t\t%llu unrecognized option\n"); 877 p_5(icp6s_oredirect, "\t\t%llu redirect\n"); 878 p_5(icp6s_ounknown, "\t\t%llu unknown\n"); 879 880 p(icp6s_reflect, "\t%llu message response%s generated\n"); 881 p(icp6s_nd_toomanyopt, "\t%llu message%s with too many ND options\n"); 882 p(icp6s_nd_badopt, "\t%llu message%s with bad ND options\n"); 883 p(icp6s_badns, "\t%llu bad neighbor solicitation message%s\n"); 884 p(icp6s_badna, "\t%llu bad neighbor advertisement message%s\n"); 885 p(icp6s_badrs, "\t%llu bad router solicitation message%s\n"); 886 p(icp6s_badra, "\t%llu bad router advertisement message%s\n"); 887 p(icp6s_badredirect, "\t%llu bad redirect message%s\n"); 888 p(icp6s_pmtuchg, "\t%llu path MTU change%s\n"); 889 #undef p 890 #undef p_5 891 } 892 893 /* 894 * Dump ICMPv6 per-interface statistics based on RFC 2466. 895 */ 896 void 897 icmp6_ifstats(char *ifname) 898 { 899 struct in6_ifreq ifr; 900 int s; 901 902 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \ 903 printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, \ 904 plural(ifr.ifr_ifru.ifru_icmp6stat.f)) 905 906 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 907 perror("Warning: socket(AF_INET6)"); 908 return; 909 } 910 911 strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name); 912 printf("icmp6 on %s:\n", ifr.ifr_name); 913 914 if (ioctl(s, SIOCGIFSTAT_ICMP6, &ifr) < 0) { 915 perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)"); 916 goto end; 917 } 918 919 p(ifs6_in_msg, "\t%llu total input message%s\n"); 920 p(ifs6_in_error, "\t%llu total input error message%s\n"); 921 p(ifs6_in_dstunreach, "\t%llu input destination unreachable error%s\n"); 922 p(ifs6_in_adminprohib, "\t%llu input administratively prohibited error%s\n"); 923 p(ifs6_in_timeexceed, "\t%llu input time exceeded error%s\n"); 924 p(ifs6_in_paramprob, "\t%llu input parameter problem error%s\n"); 925 p(ifs6_in_pkttoobig, "\t%llu input packet too big error%s\n"); 926 p(ifs6_in_echo, "\t%llu input echo request%s\n"); 927 p(ifs6_in_echoreply, "\t%llu input echo reply%s\n"); 928 p(ifs6_in_routersolicit, "\t%llu input router solicitation%s\n"); 929 p(ifs6_in_routeradvert, "\t%llu input router advertisement%s\n"); 930 p(ifs6_in_neighborsolicit, "\t%llu input neighbor solicitation%s\n"); 931 p(ifs6_in_neighboradvert, "\t%llu input neighbor advertisement%s\n"); 932 p(ifs6_in_redirect, "\t%llu input redirect%s\n"); 933 p(ifs6_in_mldquery, "\t%llu input MLD query%s\n"); 934 p(ifs6_in_mldreport, "\t%llu input MLD report%s\n"); 935 p(ifs6_in_mlddone, "\t%llu input MLD done%s\n"); 936 937 p(ifs6_out_msg, "\t%llu total output message%s\n"); 938 p(ifs6_out_error, "\t%llu total output error message%s\n"); 939 p(ifs6_out_dstunreach, "\t%llu output destination unreachable error%s\n"); 940 p(ifs6_out_adminprohib, "\t%llu output administratively prohibited error%s\n"); 941 p(ifs6_out_timeexceed, "\t%llu output time exceeded error%s\n"); 942 p(ifs6_out_paramprob, "\t%llu output parameter problem error%s\n"); 943 p(ifs6_out_pkttoobig, "\t%llu output packet too big error%s\n"); 944 p(ifs6_out_echo, "\t%llu output echo request%s\n"); 945 p(ifs6_out_echoreply, "\t%llu output echo reply%s\n"); 946 p(ifs6_out_routersolicit, "\t%llu output router solicitation%s\n"); 947 p(ifs6_out_routeradvert, "\t%llu output router advertisement%s\n"); 948 p(ifs6_out_neighborsolicit, "\t%llu output neighbor solicitation%s\n"); 949 p(ifs6_out_neighboradvert, "\t%llu output neighbor advertisement%s\n"); 950 p(ifs6_out_redirect, "\t%llu output redirect%s\n"); 951 p(ifs6_out_mldquery, "\t%llu output MLD query%s\n"); 952 p(ifs6_out_mldreport, "\t%llu output MLD report%s\n"); 953 p(ifs6_out_mlddone, "\t%llu output MLD done%s\n"); 954 955 end: 956 close(s); 957 #undef p 958 } 959 960 /* 961 * Dump PIM statistics structure. 962 */ 963 void 964 pim6_stats(char *name) 965 { 966 struct pim6stat pim6stat; 967 int mib[] = { CTL_NET, AF_INET6, IPPROTO_PIM, PIM6CTL_STATS }; 968 size_t len = sizeof(pim6stat); 969 970 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 971 &pim6stat, &len, NULL, 0) == -1) { 972 if (errno != ENOPROTOOPT) 973 warn(name); 974 return; 975 } 976 977 printf("%s:\n", name); 978 #define p(f, m) if (pim6stat.f || sflag <= 1) \ 979 printf(m, (unsigned long long)pim6stat.f, plural(pim6stat.f)) 980 981 p(pim6s_rcv_total, "\t%llu message%s received\n"); 982 p(pim6s_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); 983 p(pim6s_rcv_badsum, "\t%llu message%s received with bad checksum\n"); 984 p(pim6s_rcv_badversion, "\t%llu message%s received with bad version\n"); 985 p(pim6s_rcv_registers, "\t%llu register%s received\n"); 986 p(pim6s_rcv_badregisters, "\t%llu bad register%s received\n"); 987 p(pim6s_snd_registers, "\t%llu register%s sent\n"); 988 #undef p 989 } 990 991 /* 992 * Dump raw ip6 statistics structure. 993 */ 994 void 995 rip6_stats(char *name) 996 { 997 struct rip6stat rip6stat; 998 u_int64_t delivered; 999 int mib[] = { CTL_NET, AF_INET6, IPPROTO_RAW, RIPV6CTL_STATS }; 1000 size_t len = sizeof(rip6stat); 1001 1002 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 1003 &rip6stat, &len, NULL, 0) == -1) { 1004 if (errno != ENOPROTOOPT) 1005 warn(name); 1006 return; 1007 } 1008 1009 printf("%s:\n", name); 1010 1011 #define p(f, m) if (rip6stat.f || sflag <= 1) \ 1012 printf(m, (unsigned long long)rip6stat.f, plural(rip6stat.f)) 1013 p(rip6s_ipackets, "\t%llu message%s received\n"); 1014 p(rip6s_isum, "\t%llu checksum calculation%s on inbound\n"); 1015 p(rip6s_badsum, "\t%llu message%s with bad checksum\n"); 1016 p(rip6s_nosock, "\t%llu message%s dropped due to no socket\n"); 1017 p(rip6s_nosockmcast, 1018 "\t%llu multicast message%s dropped due to no socket\n"); 1019 p(rip6s_fullsock, 1020 "\t%llu message%s dropped due to full socket buffers\n"); 1021 delivered = rip6stat.rip6s_ipackets - 1022 rip6stat.rip6s_badsum - 1023 rip6stat.rip6s_nosock - 1024 rip6stat.rip6s_nosockmcast - 1025 rip6stat.rip6s_fullsock; 1026 if (delivered || sflag <= 1) 1027 printf("\t%llu delivered\n", (unsigned long long)delivered); 1028 p(rip6s_opackets, "\t%llu datagram%s output\n"); 1029 #undef p 1030 } 1031 1032 /* 1033 * Pretty print an Internet address (net address + port). 1034 * If the nflag was specified, use numbers instead of names. 1035 */ 1036 1037 void 1038 inet6print(struct in6_addr *in6, int port, char *proto) 1039 { 1040 1041 #define GETSERVBYPORT6(port, proto, ret) do { \ 1042 if (strcmp((proto), "tcp6") == 0) \ 1043 (ret) = getservbyport((int)(port), "tcp"); \ 1044 else if (strcmp((proto), "udp6") == 0) \ 1045 (ret) = getservbyport((int)(port), "udp"); \ 1046 else \ 1047 (ret) = getservbyport((int)(port), (proto)); \ 1048 } while (0) 1049 1050 struct servent *sp = 0; 1051 char line[80], *cp; 1052 int width; 1053 int len = sizeof line; 1054 1055 width = Aflag ? 12 : 16; 1056 if (vflag && width < strlen(inet6name(in6))) 1057 width = strlen(inet6name(in6)); 1058 snprintf(line, len, "%.*s.", width, inet6name(in6)); 1059 len -= strlen(line); 1060 if (len <= 0) 1061 goto bail; 1062 1063 cp = strchr(line, '\0'); 1064 if (!nflag && port) 1065 GETSERVBYPORT6(port, proto, sp); 1066 if (sp || port == 0) 1067 snprintf(cp, len, "%.8s", sp ? sp->s_name : "*"); 1068 else 1069 snprintf(cp, len, "%d", ntohs((u_short)port)); 1070 width = Aflag ? 18 : 22; 1071 if (vflag && width < strlen(line)) 1072 width = strlen(line); 1073 bail: 1074 printf(" %-*.*s", width, width, line); 1075 } 1076 1077 /* 1078 * Construct an Internet address representation. 1079 * If the nflag has been supplied, give 1080 * numeric value, otherwise try for symbolic name. 1081 */ 1082 1083 char * 1084 inet6name(struct in6_addr *in6p) 1085 { 1086 char *cp; 1087 static char line[NI_MAXHOST]; 1088 struct hostent *hp; 1089 static char domain[MAXHOSTNAMELEN]; 1090 static int first = 1; 1091 char hbuf[NI_MAXHOST]; 1092 struct sockaddr_in6 sin6; 1093 const int niflag = NI_NUMERICHOST; 1094 1095 if (first && !nflag) { 1096 first = 0; 1097 if (gethostname(domain, sizeof(domain)) == 0 && 1098 (cp = strchr(domain, '.'))) 1099 (void) strlcpy(domain, cp + 1, sizeof domain); 1100 else 1101 domain[0] = '\0'; 1102 } 1103 cp = 0; 1104 if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) { 1105 hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6); 1106 if (hp) { 1107 if ((cp = strchr(hp->h_name, '.')) && 1108 !strcmp(cp + 1, domain)) 1109 *cp = 0; 1110 cp = hp->h_name; 1111 } 1112 } 1113 if (IN6_IS_ADDR_UNSPECIFIED(in6p)) 1114 strlcpy(line, "*", sizeof(line)); 1115 else if (cp) 1116 strlcpy(line, cp, sizeof(line)); 1117 else { 1118 memset(&sin6, 0, sizeof(sin6)); 1119 sin6.sin6_len = sizeof(sin6); 1120 sin6.sin6_family = AF_INET6; 1121 sin6.sin6_addr = *in6p; 1122 #ifdef __KAME__ 1123 if (IN6_IS_ADDR_LINKLOCAL(in6p) || 1124 IN6_IS_ADDR_MC_LINKLOCAL(in6p) || 1125 IN6_IS_ADDR_MC_INTFACELOCAL(in6p)) { 1126 sin6.sin6_scope_id = 1127 ntohs(*(u_int16_t *)&in6p->s6_addr[2]); 1128 sin6.sin6_addr.s6_addr[2] = 0; 1129 sin6.sin6_addr.s6_addr[3] = 0; 1130 } 1131 #endif 1132 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 1133 hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) 1134 strlcpy(hbuf, "?", sizeof hbuf); 1135 strlcpy(line, hbuf, sizeof(line)); 1136 } 1137 return (line); 1138 } 1139 1140 #ifdef TCP6 1141 /* 1142 * Dump the contents of a TCP6 PCB. 1143 */ 1144 void 1145 tcp6_dump(u_long pcbaddr) 1146 { 1147 struct tcp6cb tcp6cb; 1148 int i; 1149 1150 kread(pcbaddr, &tcp6cb, sizeof(tcp6cb)); 1151 1152 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr); 1153 1154 printf("Timers:\n"); 1155 for (i = 0; i < TCP6T_NTIMERS; i++) 1156 printf("\t%s: %u", tcp6timers[i], tcp6cb.t_timer[i]); 1157 printf("\n\n"); 1158 1159 if (tcp6cb.t_state < 0 || tcp6cb.t_state >= TCP6_NSTATES) 1160 printf("State: %d", tcp6cb.t_state); 1161 else 1162 printf("State: %s", tcp6states[tcp6cb.t_state]); 1163 printf(", flags 0x%x, in6pcb 0x%lx\n\n", tcp6cb.t_flags, 1164 (u_long)tcp6cb.t_in6pcb); 1165 1166 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcp6cb.t_rxtshift, 1167 tcp6cb.t_rxtcur, tcp6cb.t_dupacks); 1168 printf("peermaxseg %u, maxseg %u, force %d\n\n", tcp6cb.t_peermaxseg, 1169 tcp6cb.t_maxseg, tcp6cb.t_force); 1170 1171 printf("snd_una %u, snd_nxt %u, snd_up %u\n", 1172 tcp6cb.snd_una, tcp6cb.snd_nxt, tcp6cb.snd_up); 1173 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n", 1174 tcp6cb.snd_wl1, tcp6cb.snd_wl2, tcp6cb.iss, tcp6cb.snd_wnd); 1175 1176 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n", 1177 tcp6cb.rcv_wnd, tcp6cb.rcv_nxt, tcp6cb.rcv_up, tcp6cb.irs); 1178 1179 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n", 1180 tcp6cb.rcv_adv, tcp6cb.snd_max, tcp6cb.snd_cwnd, tcp6cb.snd_ssthresh); 1181 1182 printf("idle %d, rtt %d, rtseq %u, srtt %d, rttvar %d, rttmin %d, " 1183 "max_sndwnd %lu\n\n", tcp6cb.t_idle, tcp6cb.t_rtt, tcp6cb.t_rtseq, 1184 tcp6cb.t_srtt, tcp6cb.t_rttvar, tcp6cb.t_rttmin, tcp6cb.max_sndwnd); 1185 1186 printf("oobflags %d, iobc %d, softerror %d\n\n", tcp6cb.t_oobflags, 1187 tcp6cb.t_iobc, tcp6cb.t_softerror); 1188 1189 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n", 1190 tcp6cb.snd_scale, tcp6cb.rcv_scale, tcp6cb.request_r_scale, 1191 tcp6cb.requested_s_scale); 1192 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n", 1193 tcp6cb.ts_recent, tcp6cb.ts_recent_age, tcp6cb.last_ack_sent); 1194 } 1195 #endif 1196