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