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