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