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