1 /* $OpenBSD: inet6.c,v 1.50 2016/03/28 07:30:28 jca 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/types.h> 33 #include <sys/socket.h> 34 #include <sys/socketvar.h> 35 #include <sys/ioctl.h> 36 #include <sys/protosw.h> 37 #include <sys/sysctl.h> 38 39 #include <net/route.h> 40 #include <net/if.h> 41 #include <netinet/in.h> 42 #include <netinet/ip6.h> 43 #include <netinet/icmp6.h> 44 #include <netinet/ip.h> 45 #include <netinet/ip_var.h> 46 #include <netinet6/ip6_var.h> 47 #include <netinet6/in6_var.h> 48 #include <netinet6/pim6_var.h> 49 #include <netinet6/raw_ip6.h> 50 #include <netinet6/ip6_divert.h> 51 52 #include <arpa/inet.h> 53 #include <netdb.h> 54 55 #include <err.h> 56 #include <errno.h> 57 #include <stdio.h> 58 #include <string.h> 59 #include <unistd.h> 60 #include <limits.h> 61 #include "netstat.h" 62 63 struct socket sockb; 64 65 char *inet6name(struct in6_addr *); 66 67 static char *ip6nh[] = { 68 "hop by hop", 69 "ICMP", 70 "IGMP", 71 "#3", 72 "IP", 73 "#5", 74 "TCP", 75 "#7", 76 "#8", 77 "#9", 78 "#10", 79 "#11", 80 "#12", 81 "#13", 82 "#14", 83 "#15", 84 "#16", 85 "UDP", 86 "#18", 87 "#19", 88 "#20", 89 "#21", 90 "IDP", 91 "#23", 92 "#24", 93 "#25", 94 "#26", 95 "#27", 96 "#28", 97 "TP", 98 "#30", 99 "#31", 100 "#32", 101 "#33", 102 "#34", 103 "#35", 104 "#36", 105 "#37", 106 "#38", 107 "#39", 108 "#40", 109 "IP6", 110 "#42", 111 "routing", 112 "fragment", 113 "#45", 114 "#46", 115 "#47", 116 "#48", 117 "#49", 118 "ESP", 119 "AH", 120 "#52", 121 "#53", 122 "#54", 123 "#55", 124 "#56", 125 "#57", 126 "ICMP6", 127 "no next header", 128 "destination option", 129 "#61", 130 "#62", 131 "#63", 132 "#64", 133 "#65", 134 "#66", 135 "#67", 136 "#68", 137 "#69", 138 "#70", 139 "#71", 140 "#72", 141 "#73", 142 "#74", 143 "#75", 144 "#76", 145 "#77", 146 "#78", 147 "#79", 148 "ISOIP", 149 "#81", 150 "#82", 151 "#83", 152 "#84", 153 "#85", 154 "#86", 155 "#87", 156 "#88", 157 "OSPF", 158 "#80", 159 "#91", 160 "#92", 161 "#93", 162 "#94", 163 "#95", 164 "#96", 165 "Ethernet", 166 "#98", 167 "#99", 168 "#100", 169 "#101", 170 "#102", 171 "PIM", 172 "#104", 173 "#105", 174 "#106", 175 "#107", 176 "#108", 177 "#109", 178 "#110", 179 "#111", 180 "#112", 181 "#113", 182 "#114", 183 "#115", 184 "#116", 185 "#117", 186 "#118", 187 "#119", 188 "#120", 189 "#121", 190 "#122", 191 "#123", 192 "#124", 193 "#125", 194 "#126", 195 "#127", 196 "#128", 197 "#129", 198 "#130", 199 "#131", 200 "#132", 201 "#133", 202 "#134", 203 "#135", 204 "#136", 205 "#137", 206 "#138", 207 "#139", 208 "#140", 209 "#141", 210 "#142", 211 "#143", 212 "#144", 213 "#145", 214 "#146", 215 "#147", 216 "#148", 217 "#149", 218 "#150", 219 "#151", 220 "#152", 221 "#153", 222 "#154", 223 "#155", 224 "#156", 225 "#157", 226 "#158", 227 "#159", 228 "#160", 229 "#161", 230 "#162", 231 "#163", 232 "#164", 233 "#165", 234 "#166", 235 "#167", 236 "#168", 237 "#169", 238 "#170", 239 "#171", 240 "#172", 241 "#173", 242 "#174", 243 "#175", 244 "#176", 245 "#177", 246 "#178", 247 "#179", 248 "#180", 249 "#181", 250 "#182", 251 "#183", 252 "#184", 253 "#185", 254 "#186", 255 "#187", 256 "#188", 257 "#189", 258 "#180", 259 "#191", 260 "#192", 261 "#193", 262 "#194", 263 "#195", 264 "#196", 265 "#197", 266 "#198", 267 "#199", 268 "#200", 269 "#201", 270 "#202", 271 "#203", 272 "#204", 273 "#205", 274 "#206", 275 "#207", 276 "#208", 277 "#209", 278 "#210", 279 "#211", 280 "#212", 281 "#213", 282 "#214", 283 "#215", 284 "#216", 285 "#217", 286 "#218", 287 "#219", 288 "#220", 289 "#221", 290 "#222", 291 "#223", 292 "#224", 293 "#225", 294 "#226", 295 "#227", 296 "#228", 297 "#229", 298 "#230", 299 "#231", 300 "#232", 301 "#233", 302 "#234", 303 "#235", 304 "#236", 305 "#237", 306 "#238", 307 "#239", 308 "#240", 309 "#241", 310 "#242", 311 "#243", 312 "#244", 313 "#245", 314 "#246", 315 "#247", 316 "#248", 317 "#249", 318 "#250", 319 "#251", 320 "#252", 321 "#253", 322 "#254", 323 "#255", 324 }; 325 326 /* 327 * Dump IP6 statistics structure. 328 */ 329 void 330 ip6_stats(char *name) 331 { 332 struct ip6stat ip6stat; 333 int first, i; 334 struct protoent *ep; 335 const char *n; 336 int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_STATS }; 337 size_t len = sizeof(ip6stat); 338 339 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 340 &ip6stat, &len, NULL, 0) == -1) { 341 if (errno != ENOPROTOOPT) 342 warn("%s", name); 343 return; 344 } 345 346 printf("%s:\n", name); 347 #define p(f, m) if (ip6stat.f || sflag <= 1) \ 348 printf(m, (unsigned long long)ip6stat.f, plural(ip6stat.f)) 349 #define p1(f, m) if (ip6stat.f || sflag <= 1) \ 350 printf(m, (unsigned long long)ip6stat.f) 351 352 p(ip6s_total, "\t%llu total packet%s received\n"); 353 p1(ip6s_toosmall, "\t%llu with size smaller than minimum\n"); 354 p1(ip6s_tooshort, "\t%llu with data size < data length\n"); 355 p1(ip6s_badoptions, "\t%llu with bad options\n"); 356 p1(ip6s_badvers, "\t%llu with incorrect version number\n"); 357 p(ip6s_fragments, "\t%llu fragment%s received\n"); 358 p(ip6s_fragdropped, 359 "\t%llu fragment%s dropped (duplicates or out of space)\n"); 360 p(ip6s_fragtimeout, "\t%llu fragment%s dropped after timeout\n"); 361 p(ip6s_fragoverflow, "\t%llu fragment%s that exceeded limit\n"); 362 p(ip6s_reassembled, "\t%llu packet%s reassembled ok\n"); 363 p(ip6s_delivered, "\t%llu packet%s for this host\n"); 364 p(ip6s_forward, "\t%llu packet%s forwarded\n"); 365 p(ip6s_cantforward, "\t%llu packet%s not forwardable\n"); 366 p(ip6s_redirectsent, "\t%llu redirect%s sent\n"); 367 p(ip6s_localout, "\t%llu packet%s sent from this host\n"); 368 p(ip6s_rawout, "\t%llu packet%s sent with fabricated ip header\n"); 369 p(ip6s_odropped, 370 "\t%llu output packet%s dropped due to no bufs, etc.\n"); 371 p(ip6s_noroute, "\t%llu output packet%s discarded due to no route\n"); 372 p(ip6s_fragmented, "\t%llu output datagram%s fragmented\n"); 373 p(ip6s_ofragments, "\t%llu fragment%s created\n"); 374 p(ip6s_cantfrag, "\t%llu datagram%s that can't be fragmented\n"); 375 p(ip6s_badscope, "\t%llu packet%s that violated scope rules\n"); 376 p(ip6s_notmember, "\t%llu multicast packet%s which we don't join\n"); 377 for (first = 1, i = 0; i < 256; i++) 378 if (ip6stat.ip6s_nxthist[i] != 0) { 379 if (first) { 380 printf("\tInput packet histogram:\n"); 381 first = 0; 382 } 383 n = NULL; 384 if (ip6nh[i]) 385 n = ip6nh[i]; 386 else if ((ep = getprotobynumber(i)) != NULL) 387 n = ep->p_name; 388 if (n) 389 printf("\t\t%s: %llu\n", n, 390 (unsigned long long)ip6stat.ip6s_nxthist[i]); 391 else 392 printf("\t\t#%d: %llu\n", i, 393 (unsigned long long)ip6stat.ip6s_nxthist[i]); 394 } 395 printf("\tMbuf statistics:\n"); 396 p(ip6s_m1, "\t\t%llu one mbuf%s\n"); 397 for (first = 1, i = 0; i < 32; i++) { 398 char ifbuf[IFNAMSIZ]; 399 if (ip6stat.ip6s_m2m[i] != 0) { 400 if (first) { 401 printf("\t\ttwo or more mbuf:\n"); 402 first = 0; 403 } 404 printf("\t\t\t%s = %llu\n", 405 if_indextoname(i, ifbuf), 406 (unsigned long long)ip6stat.ip6s_m2m[i]); 407 } 408 } 409 p(ip6s_mext1, "\t\t%llu one ext mbuf%s\n"); 410 p(ip6s_mext2m, "\t\t%llu two or more ext mbuf%s\n"); 411 p(ip6s_nogif, "\t%llu tunneling packet%s that can't find gif\n"); 412 p(ip6s_toomanyhdr, 413 "\t%llu packet%s discarded due to too many headers\n"); 414 415 /* for debugging source address selection */ 416 #define PRINT_SCOPESTAT(s,i) do {\ 417 switch(i) { /* XXX hardcoding in each case */\ 418 case 1:\ 419 p(s, "\t\t%llu node-local%s\n");\ 420 break;\ 421 case 2:\ 422 p(s, "\t\t%llu link-local%s\n");\ 423 break;\ 424 case 5:\ 425 p(s, "\t\t%llu site-local%s\n");\ 426 break;\ 427 case 14:\ 428 p(s, "\t\t%llu global%s\n");\ 429 break;\ 430 default:\ 431 printf("\t\t%llu addresses scope=%x\n",\ 432 (unsigned long long)ip6stat.s, i);\ 433 }\ 434 } while(0); 435 436 p(ip6s_sources_none, 437 "\t%llu failure%s of source address selection\n"); 438 for (first = 1, i = 0; i < 16; i++) { 439 if (ip6stat.ip6s_sources_sameif[i]) { 440 if (first) { 441 printf("\tsource addresses on an outgoing I/F\n"); 442 first = 0; 443 } 444 PRINT_SCOPESTAT(ip6s_sources_sameif[i], i); 445 } 446 } 447 for (first = 1, i = 0; i < 16; i++) { 448 if (ip6stat.ip6s_sources_otherif[i]) { 449 if (first) { 450 printf("\tsource addresses on a non-outgoing I/F\n"); 451 first = 0; 452 } 453 PRINT_SCOPESTAT(ip6s_sources_otherif[i], i); 454 } 455 } 456 for (first = 1, i = 0; i < 16; i++) { 457 if (ip6stat.ip6s_sources_samescope[i]) { 458 if (first) { 459 printf("\tsource addresses of same scope\n"); 460 first = 0; 461 } 462 PRINT_SCOPESTAT(ip6s_sources_samescope[i], i); 463 } 464 } 465 for (first = 1, i = 0; i < 16; i++) { 466 if (ip6stat.ip6s_sources_otherscope[i]) { 467 if (first) { 468 printf("\tsource addresses of a different scope\n"); 469 first = 0; 470 } 471 PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i); 472 } 473 } 474 for (first = 1, i = 0; i < 16; i++) { 475 if (ip6stat.ip6s_sources_deprecated[i]) { 476 if (first) { 477 printf("\tdeprecated source addresses\n"); 478 first = 0; 479 } 480 PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i); 481 } 482 } 483 484 p1(ip6s_forward_cachehit, "\t%llu forward cache hit\n"); 485 p1(ip6s_forward_cachemiss, "\t%llu forward cache miss\n"); 486 #undef p 487 #undef p1 488 } 489 490 static char *icmp6names[] = { 491 "#0", 492 "unreach", 493 "packet too big", 494 "time exceed", 495 "parameter problem", 496 "#5", 497 "#6", 498 "#7", 499 "#8", 500 "#9", 501 "#10", 502 "#11", 503 "#12", 504 "#13", 505 "#14", 506 "#15", 507 "#16", 508 "#17", 509 "#18", 510 "#19", 511 "#20", 512 "#21", 513 "#22", 514 "#23", 515 "#24", 516 "#25", 517 "#26", 518 "#27", 519 "#28", 520 "#29", 521 "#30", 522 "#31", 523 "#32", 524 "#33", 525 "#34", 526 "#35", 527 "#36", 528 "#37", 529 "#38", 530 "#39", 531 "#40", 532 "#41", 533 "#42", 534 "#43", 535 "#44", 536 "#45", 537 "#46", 538 "#47", 539 "#48", 540 "#49", 541 "#50", 542 "#51", 543 "#52", 544 "#53", 545 "#54", 546 "#55", 547 "#56", 548 "#57", 549 "#58", 550 "#59", 551 "#60", 552 "#61", 553 "#62", 554 "#63", 555 "#64", 556 "#65", 557 "#66", 558 "#67", 559 "#68", 560 "#69", 561 "#70", 562 "#71", 563 "#72", 564 "#73", 565 "#74", 566 "#75", 567 "#76", 568 "#77", 569 "#78", 570 "#79", 571 "#80", 572 "#81", 573 "#82", 574 "#83", 575 "#84", 576 "#85", 577 "#86", 578 "#87", 579 "#88", 580 "#89", 581 "#80", 582 "#91", 583 "#92", 584 "#93", 585 "#94", 586 "#95", 587 "#96", 588 "#97", 589 "#98", 590 "#99", 591 "#100", 592 "#101", 593 "#102", 594 "#103", 595 "#104", 596 "#105", 597 "#106", 598 "#107", 599 "#108", 600 "#109", 601 "#110", 602 "#111", 603 "#112", 604 "#113", 605 "#114", 606 "#115", 607 "#116", 608 "#117", 609 "#118", 610 "#119", 611 "#120", 612 "#121", 613 "#122", 614 "#123", 615 "#124", 616 "#125", 617 "#126", 618 "#127", 619 "echo", 620 "echo reply", 621 "multicast listener query", 622 "multicast listener report", 623 "multicast listener done", 624 "router solicitation", 625 "router advertisement", 626 "neighbor solicitation", 627 "neighbor advertisement", 628 "redirect", 629 "router renumbering", 630 "node information request", 631 "node information reply", 632 "#141", 633 "#142", 634 "#143", 635 "#144", 636 "#145", 637 "#146", 638 "#147", 639 "#148", 640 "#149", 641 "#150", 642 "#151", 643 "#152", 644 "#153", 645 "#154", 646 "#155", 647 "#156", 648 "#157", 649 "#158", 650 "#159", 651 "#160", 652 "#161", 653 "#162", 654 "#163", 655 "#164", 656 "#165", 657 "#166", 658 "#167", 659 "#168", 660 "#169", 661 "#170", 662 "#171", 663 "#172", 664 "#173", 665 "#174", 666 "#175", 667 "#176", 668 "#177", 669 "#178", 670 "#179", 671 "#180", 672 "#181", 673 "#182", 674 "#183", 675 "#184", 676 "#185", 677 "#186", 678 "#187", 679 "#188", 680 "#189", 681 "#180", 682 "#191", 683 "#192", 684 "#193", 685 "#194", 686 "#195", 687 "#196", 688 "#197", 689 "#198", 690 "#199", 691 "#200", 692 "#201", 693 "#202", 694 "#203", 695 "#204", 696 "#205", 697 "#206", 698 "#207", 699 "#208", 700 "#209", 701 "#210", 702 "#211", 703 "#212", 704 "#213", 705 "#214", 706 "#215", 707 "#216", 708 "#217", 709 "#218", 710 "#219", 711 "#220", 712 "#221", 713 "#222", 714 "#223", 715 "#224", 716 "#225", 717 "#226", 718 "#227", 719 "#228", 720 "#229", 721 "#230", 722 "#231", 723 "#232", 724 "#233", 725 "#234", 726 "#235", 727 "#236", 728 "#237", 729 "#238", 730 "#239", 731 "#240", 732 "#241", 733 "#242", 734 "#243", 735 "#244", 736 "#245", 737 "#246", 738 "#247", 739 "#248", 740 "#249", 741 "#250", 742 "#251", 743 "#252", 744 "#253", 745 "#254", 746 "#255", 747 }; 748 749 /* 750 * Dump ICMPv6 statistics. 751 */ 752 void 753 icmp6_stats(char *name) 754 { 755 struct icmp6stat icmp6stat; 756 int i, first; 757 int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_STATS }; 758 size_t len = sizeof(icmp6stat); 759 760 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 761 &icmp6stat, &len, NULL, 0) == -1) { 762 if (errno != ENOPROTOOPT) 763 warn("%s", name); 764 return; 765 } 766 767 printf("%s:\n", name); 768 #define p(f, m) if (icmp6stat.f || sflag <= 1) \ 769 printf(m, (unsigned long long)icmp6stat.f, plural(icmp6stat.f)) 770 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \ 771 printf(m, (unsigned long long)icmp6stat.f) 772 773 p(icp6s_error, "\t%llu call%s to icmp6_error\n"); 774 p(icp6s_canterror, 775 "\t%llu error%s not generated because old message was icmp6 or so\n"); 776 p(icp6s_toofreq, 777 "\t%llu error%s not generated because of rate limitation\n"); 778 for (first = 1, i = 0; i < 256; i++) 779 if (icmp6stat.icp6s_outhist[i] != 0) { 780 if (first) { 781 printf("\tOutput packet histogram:\n"); 782 first = 0; 783 } 784 printf("\t\t%s: %llu\n", icmp6names[i], 785 (unsigned long long)icmp6stat.icp6s_outhist[i]); 786 } 787 p(icp6s_badcode, "\t%llu message%s with bad code fields\n"); 788 p(icp6s_tooshort, "\t%llu message%s < minimum length\n"); 789 p(icp6s_checksum, "\t%llu bad checksum%s\n"); 790 p(icp6s_badlen, "\t%llu message%s with bad length\n"); 791 for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++) 792 if (icmp6stat.icp6s_inhist[i] != 0) { 793 if (first) { 794 printf("\tInput packet histogram:\n"); 795 first = 0; 796 } 797 printf("\t\t%s: %llu\n", icmp6names[i], 798 (unsigned long long)icmp6stat.icp6s_inhist[i]); 799 } 800 printf("\tHistogram of error messages to be generated:\n"); 801 p_5(icp6s_odst_unreach_noroute, "\t\t%llu no route\n"); 802 p_5(icp6s_odst_unreach_admin, "\t\t%llu administratively prohibited\n"); 803 p_5(icp6s_odst_unreach_beyondscope, "\t\t%llu beyond scope\n"); 804 p_5(icp6s_odst_unreach_addr, "\t\t%llu address unreachable\n"); 805 p_5(icp6s_odst_unreach_noport, "\t\t%llu port unreachable\n"); 806 p_5(icp6s_opacket_too_big, "\t\t%llu packet too big\n"); 807 p_5(icp6s_otime_exceed_transit, "\t\t%llu time exceed transit\n"); 808 p_5(icp6s_otime_exceed_reassembly, "\t\t%llu time exceed reassembly\n"); 809 p_5(icp6s_oparamprob_header, "\t\t%llu erroneous header field\n"); 810 p_5(icp6s_oparamprob_nextheader, "\t\t%llu unrecognized next header\n"); 811 p_5(icp6s_oparamprob_option, "\t\t%llu unrecognized option\n"); 812 p_5(icp6s_oredirect, "\t\t%llu redirect\n"); 813 p_5(icp6s_ounknown, "\t\t%llu unknown\n"); 814 815 p(icp6s_reflect, "\t%llu message response%s generated\n"); 816 p(icp6s_nd_toomanyopt, "\t%llu message%s with too many ND options\n"); 817 p(icp6s_nd_badopt, "\t%llu message%s with bad ND options\n"); 818 p(icp6s_badns, "\t%llu bad neighbor solicitation message%s\n"); 819 p(icp6s_badna, "\t%llu bad neighbor advertisement message%s\n"); 820 p(icp6s_badrs, "\t%llu bad router solicitation message%s\n"); 821 p(icp6s_badra, "\t%llu bad router advertisement message%s\n"); 822 p(icp6s_badredirect, "\t%llu bad redirect message%s\n"); 823 p(icp6s_pmtuchg, "\t%llu path MTU change%s\n"); 824 #undef p 825 #undef p_5 826 } 827 828 /* 829 * Dump PIM statistics structure. 830 */ 831 void 832 pim6_stats(char *name) 833 { 834 struct pim6stat pim6stat; 835 int mib[] = { CTL_NET, PF_INET6, IPPROTO_PIM, PIM6CTL_STATS }; 836 size_t len = sizeof(pim6stat); 837 838 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 839 &pim6stat, &len, NULL, 0) == -1) { 840 if (errno != ENOPROTOOPT) 841 warn("%s", name); 842 return; 843 } 844 845 printf("%s:\n", name); 846 #define p(f, m) if (pim6stat.f || sflag <= 1) \ 847 printf(m, (unsigned long long)pim6stat.f, plural(pim6stat.f)) 848 849 p(pim6s_rcv_total, "\t%llu message%s received\n"); 850 p(pim6s_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); 851 p(pim6s_rcv_badsum, "\t%llu message%s received with bad checksum\n"); 852 p(pim6s_rcv_badversion, "\t%llu message%s received with bad version\n"); 853 p(pim6s_rcv_registers, "\t%llu register%s received\n"); 854 p(pim6s_rcv_badregisters, "\t%llu bad register%s received\n"); 855 p(pim6s_snd_registers, "\t%llu register%s sent\n"); 856 #undef p 857 } 858 859 /* 860 * Dump raw ip6 statistics structure. 861 */ 862 void 863 rip6_stats(char *name) 864 { 865 struct rip6stat rip6stat; 866 u_int64_t delivered; 867 int mib[] = { CTL_NET, PF_INET6, IPPROTO_RAW, RIPV6CTL_STATS }; 868 size_t len = sizeof(rip6stat); 869 870 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 871 &rip6stat, &len, NULL, 0) == -1) { 872 if (errno != ENOPROTOOPT) 873 warn("%s", name); 874 return; 875 } 876 877 printf("%s:\n", name); 878 879 #define p(f, m) if (rip6stat.f || sflag <= 1) \ 880 printf(m, (unsigned long long)rip6stat.f, plural(rip6stat.f)) 881 p(rip6s_ipackets, "\t%llu message%s received\n"); 882 p(rip6s_isum, "\t%llu checksum calculation%s on inbound\n"); 883 p(rip6s_badsum, "\t%llu message%s with bad checksum\n"); 884 p(rip6s_nosock, "\t%llu message%s dropped due to no socket\n"); 885 p(rip6s_nosockmcast, 886 "\t%llu multicast message%s dropped due to no socket\n"); 887 p(rip6s_fullsock, 888 "\t%llu message%s dropped due to full socket buffers\n"); 889 delivered = rip6stat.rip6s_ipackets - 890 rip6stat.rip6s_badsum - 891 rip6stat.rip6s_nosock - 892 rip6stat.rip6s_nosockmcast - 893 rip6stat.rip6s_fullsock; 894 if (delivered || sflag <= 1) 895 printf("\t%llu delivered\n", (unsigned long long)delivered); 896 p(rip6s_opackets, "\t%llu datagram%s output\n"); 897 #undef p 898 } 899 900 /* 901 * Dump divert6 statistics structure. 902 */ 903 void 904 div6_stats(char *name) 905 { 906 struct div6stat div6stat; 907 int mib[] = { CTL_NET, PF_INET6, IPPROTO_DIVERT, DIVERT6CTL_STATS }; 908 size_t len = sizeof(div6stat); 909 910 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 911 &div6stat, &len, NULL, 0) == -1) { 912 if (errno != ENOPROTOOPT) 913 warn("%s", name); 914 return; 915 } 916 917 printf("%s:\n", name); 918 #define p(f, m) if (div6stat.f || sflag <= 1) \ 919 printf(m, div6stat.f, plural(div6stat.f)) 920 #define p1(f, m) if (div6stat.f || sflag <= 1) \ 921 printf(m, div6stat.f) 922 p(divs_ipackets, "\t%lu total packet%s received\n"); 923 p1(divs_noport, "\t%lu dropped due to no socket\n"); 924 p1(divs_fullsock, "\t%lu dropped due to full socket buffers\n"); 925 p(divs_opackets, "\t%lu packet%s output\n"); 926 p1(divs_errors, "\t%lu errors\n"); 927 #undef p 928 #undef p1 929 } 930 931 /* 932 * Pretty print an Internet address (net address + port). 933 * If the nflag was specified, use numbers instead of names. 934 */ 935 936 void 937 inet6print(struct in6_addr *in6, int port, const char *proto) 938 { 939 940 #define GETSERVBYPORT6(port, proto, ret) do { \ 941 if (strcmp((proto), "tcp6") == 0) \ 942 (ret) = getservbyport((int)(port), "tcp"); \ 943 else if (strcmp((proto), "udp6") == 0) \ 944 (ret) = getservbyport((int)(port), "udp"); \ 945 else \ 946 (ret) = getservbyport((int)(port), (proto)); \ 947 } while (0) 948 949 struct servent *sp = 0; 950 char line[80], *cp; 951 int width; 952 int len = sizeof line; 953 954 width = Aflag ? 12 : 16; 955 if (vflag && width < strlen(inet6name(in6))) 956 width = strlen(inet6name(in6)); 957 snprintf(line, len, "%.*s.", width, inet6name(in6)); 958 len -= strlen(line); 959 if (len <= 0) 960 goto bail; 961 962 cp = strchr(line, '\0'); 963 if (!nflag && port) 964 GETSERVBYPORT6(port, proto, sp); 965 if (sp || port == 0) 966 snprintf(cp, len, "%.8s", sp ? sp->s_name : "*"); 967 else 968 snprintf(cp, len, "%d", ntohs((u_short)port)); 969 width = Aflag ? 18 : 22; 970 if (vflag && width < strlen(line)) 971 width = strlen(line); 972 bail: 973 printf(" %-*.*s", width, width, line); 974 } 975 976 /* 977 * Construct an Internet address representation. 978 * If the nflag has been supplied, give 979 * numeric value, otherwise try for symbolic name. 980 */ 981 982 char * 983 inet6name(struct in6_addr *in6p) 984 { 985 char *cp; 986 static char line[NI_MAXHOST]; 987 struct hostent *hp; 988 static char domain[HOST_NAME_MAX+1]; 989 static int first = 1; 990 char hbuf[NI_MAXHOST]; 991 struct sockaddr_in6 sin6; 992 const int niflag = NI_NUMERICHOST; 993 994 if (first && !nflag) { 995 first = 0; 996 if (gethostname(domain, sizeof(domain)) == 0 && 997 (cp = strchr(domain, '.'))) 998 (void) strlcpy(domain, cp + 1, sizeof domain); 999 else 1000 domain[0] = '\0'; 1001 } 1002 cp = 0; 1003 if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) { 1004 hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6); 1005 if (hp) { 1006 if ((cp = strchr(hp->h_name, '.')) && 1007 !strcmp(cp + 1, domain)) 1008 *cp = 0; 1009 cp = hp->h_name; 1010 } 1011 } 1012 if (IN6_IS_ADDR_UNSPECIFIED(in6p)) 1013 strlcpy(line, "*", sizeof(line)); 1014 else if (cp) 1015 strlcpy(line, cp, sizeof(line)); 1016 else { 1017 memset(&sin6, 0, sizeof(sin6)); 1018 sin6.sin6_len = sizeof(sin6); 1019 sin6.sin6_family = AF_INET6; 1020 sin6.sin6_addr = *in6p; 1021 #ifdef __KAME__ 1022 if (IN6_IS_ADDR_LINKLOCAL(in6p) || 1023 IN6_IS_ADDR_MC_LINKLOCAL(in6p) || 1024 IN6_IS_ADDR_MC_INTFACELOCAL(in6p)) { 1025 sin6.sin6_scope_id = 1026 ntohs(*(u_int16_t *)&in6p->s6_addr[2]); 1027 sin6.sin6_addr.s6_addr[2] = 0; 1028 sin6.sin6_addr.s6_addr[3] = 0; 1029 } 1030 #endif 1031 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 1032 hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) 1033 strlcpy(hbuf, "?", sizeof hbuf); 1034 strlcpy(line, hbuf, sizeof(line)); 1035 } 1036 return (line); 1037 } 1038