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