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