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