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