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