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