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