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