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