]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/netstat/inet6.c
Add UPDATING entry and bump version
[FreeBSD/FreeBSD.git] / usr.bin / netstat / inet6.c
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
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         strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
624         if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
625                 if (errno != EPFNOSUPPORT)
626                         xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
627                 goto end;
628         }
629
630         xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
631
632         xo_open_instance("ip6-interface-statistics");
633         xo_emit("{ke:name/%s}", ifr.ifr_name);
634
635         p(ifs6_in_receive, "\t{:received-packets/%ju} "
636             "{N:/total input datagram%s}\n");
637         p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
638             "{N:/datagram%s with invalid header received}\n");
639         p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
640             "{N:/datagram%s exceeded MTU received}\n");
641         p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
642             "{N:/datagram%s with no route received}\n");
643         p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
644             "{N:/datagram%s with invalid dst received}\n");
645         p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
646             "{N:/datagram%s with unknown proto received}\n");
647         p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
648             "{N:/truncated datagram%s received}\n");
649         p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
650             "{N:/input datagram%s discarded}\n");
651         p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
652             "{N:/datagram%s delivered to an upper layer protocol}\n");
653         p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
654             "{N:/datagram%s forwarded to this interface}\n");
655         p(ifs6_out_request, "\t{:sent-packets/%ju} "
656             "{N:/datagram%s sent from an upper layer protocol}\n");
657         p(ifs6_out_discard, "\t{:discard-packets/%ju} "
658             "{N:/total discarded output datagram%s}\n");
659         p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
660             "{N:/output datagram%s fragmented}\n");
661         p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
662             "{N:/output datagram%s failed on fragment}\n");
663         p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
664             "{N:/output datagram%s succeeded on fragment}\n");
665         p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
666             "{N:/incoming datagram%s fragmented}\n");
667         p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
668             "{N:/datagram%s reassembled}\n");
669         p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
670             "{N:/datagram%s failed on reassembly}\n");
671         p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
672             "{N:/multicast datagram%s received}\n");
673         p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
674             "{N:/multicast datagram%s sent}\n");
675
676  end:
677         xo_close_instance("ip6-interface-statistics");
678         close(s);
679
680 #undef p
681 }
682
683 static  const char *icmp6names[] = {
684         "#0",
685         "unreach",
686         "packet too big",
687         "time exceed",
688         "parameter problem",
689         "#5",
690         "#6",
691         "#7",
692         "#8",
693         "#9",
694         "#10",
695         "#11",
696         "#12",
697         "#13",
698         "#14",
699         "#15",
700         "#16",
701         "#17",
702         "#18",
703         "#19",
704         "#20",
705         "#21",
706         "#22",
707         "#23",
708         "#24",
709         "#25",
710         "#26",
711         "#27",
712         "#28",
713         "#29",
714         "#30",
715         "#31",
716         "#32",
717         "#33",
718         "#34",
719         "#35",
720         "#36",
721         "#37",
722         "#38",
723         "#39",
724         "#40",
725         "#41",
726         "#42",
727         "#43",
728         "#44",
729         "#45",
730         "#46",
731         "#47",
732         "#48",
733         "#49",
734         "#50",
735         "#51",
736         "#52",
737         "#53",
738         "#54",
739         "#55",
740         "#56",
741         "#57",
742         "#58",
743         "#59",
744         "#60",
745         "#61",
746         "#62",
747         "#63",
748         "#64",
749         "#65",
750         "#66",
751         "#67",
752         "#68",
753         "#69",
754         "#70",
755         "#71",
756         "#72",
757         "#73",
758         "#74",
759         "#75",
760         "#76",
761         "#77",
762         "#78",
763         "#79",
764         "#80",
765         "#81",
766         "#82",
767         "#83",
768         "#84",
769         "#85",
770         "#86",
771         "#87",
772         "#88",
773         "#89",
774         "#80",
775         "#91",
776         "#92",
777         "#93",
778         "#94",
779         "#95",
780         "#96",
781         "#97",
782         "#98",
783         "#99",
784         "#100",
785         "#101",
786         "#102",
787         "#103",
788         "#104",
789         "#105",
790         "#106",
791         "#107",
792         "#108",
793         "#109",
794         "#110",
795         "#111",
796         "#112",
797         "#113",
798         "#114",
799         "#115",
800         "#116",
801         "#117",
802         "#118",
803         "#119",
804         "#120",
805         "#121",
806         "#122",
807         "#123",
808         "#124",
809         "#125",
810         "#126",
811         "#127",
812         "echo",
813         "echo reply",
814         "multicast listener query",
815         "MLDv1 listener report",
816         "MLDv1 listener done",
817         "router solicitation",
818         "router advertisement",
819         "neighbor solicitation",
820         "neighbor advertisement",
821         "redirect",
822         "router renumbering",
823         "node information request",
824         "node information reply",
825         "inverse neighbor solicitation",
826         "inverse neighbor advertisement",
827         "MLDv2 listener report",
828         "#144",
829         "#145",
830         "#146",
831         "#147",
832         "#148",
833         "#149",
834         "#150",
835         "#151",
836         "#152",
837         "#153",
838         "#154",
839         "#155",
840         "#156",
841         "#157",
842         "#158",
843         "#159",
844         "#160",
845         "#161",
846         "#162",
847         "#163",
848         "#164",
849         "#165",
850         "#166",
851         "#167",
852         "#168",
853         "#169",
854         "#170",
855         "#171",
856         "#172",
857         "#173",
858         "#174",
859         "#175",
860         "#176",
861         "#177",
862         "#178",
863         "#179",
864         "#180",
865         "#181",
866         "#182",
867         "#183",
868         "#184",
869         "#185",
870         "#186",
871         "#187",
872         "#188",
873         "#189",
874         "#180",
875         "#191",
876         "#192",
877         "#193",
878         "#194",
879         "#195",
880         "#196",
881         "#197",
882         "#198",
883         "#199",
884         "#200",
885         "#201",
886         "#202",
887         "#203",
888         "#204",
889         "#205",
890         "#206",
891         "#207",
892         "#208",
893         "#209",
894         "#210",
895         "#211",
896         "#212",
897         "#213",
898         "#214",
899         "#215",
900         "#216",
901         "#217",
902         "#218",
903         "#219",
904         "#220",
905         "#221",
906         "#222",
907         "#223",
908         "#224",
909         "#225",
910         "#226",
911         "#227",
912         "#228",
913         "#229",
914         "#230",
915         "#231",
916         "#232",
917         "#233",
918         "#234",
919         "#235",
920         "#236",
921         "#237",
922         "#238",
923         "#239",
924         "#240",
925         "#241",
926         "#242",
927         "#243",
928         "#244",
929         "#245",
930         "#246",
931         "#247",
932         "#248",
933         "#249",
934         "#250",
935         "#251",
936         "#252",
937         "#253",
938         "#254",
939         "#255",
940 };
941
942 /*
943  * Dump ICMP6 statistics.
944  */
945 void
946 icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
947 {
948         struct icmp6stat icmp6stat;
949         int i, first;
950
951         if (fetch_stats("net.inet6.icmp6.stats", off, &icmp6stat,
952             sizeof(icmp6stat), kread_counters) != 0)
953                 return;
954
955         xo_emit("{T:/%s}:\n", name);
956         xo_open_container(name);
957
958 #define p(f, m) if (icmp6stat.f || sflag <= 1) \
959         xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
960 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
961         xo_emit(m, (uintmax_t)icmp6stat.f)
962
963         p(icp6s_error, "\t{:icmp6-calls/%ju} "
964             "{N:/call%s to icmp6_error}\n");
965         p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
966             "{N:/error%s not generated in response to an icmp6 message}\n");
967         p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
968             "{N:/error%s not generated because of rate limitation}\n");
969 #define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
970         for (first = 1, i = 0; i < NELEM; i++)
971                 if (icmp6stat.icp6s_outhist[i] != 0) {
972                         if (first) {
973                                 xo_open_list("output-histogram");
974                                 xo_emit("\t{T:Output histogram}:\n");
975                                 first = 0;
976                         }
977                         xo_open_instance("output-histogram");
978                         xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
979                             icmp6names[i],
980                             (uintmax_t)icmp6stat.icp6s_outhist[i]);
981                         xo_close_instance("output-histogram");
982                 }
983         if (!first)
984                 xo_close_list("output-histogram");
985 #undef NELEM
986
987         p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
988             "{N:/message%s with bad code fields}\n");
989         p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
990             "{N:/message%s < minimum length}\n");
991         p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
992             "{N:/bad checksum%s}\n");
993         p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
994             "{N:/message%s with bad length}\n");
995 #define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
996         for (first = 1, i = 0; i < NELEM; i++)
997                 if (icmp6stat.icp6s_inhist[i] != 0) {
998                         if (first) {
999                                 xo_open_list("input-histogram");
1000                                 xo_emit("\t{T:Input histogram}:\n");
1001                                 first = 0;
1002                         }
1003                         xo_open_instance("input-histogram");
1004                         xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1005                             icmp6names[i],
1006                             (uintmax_t)icmp6stat.icp6s_inhist[i]);
1007                         xo_close_instance("input-histogram");
1008                 }
1009         if (!first)
1010                 xo_close_list("input-histogram");
1011 #undef NELEM
1012         xo_emit("\t{T:Histogram of error messages to be generated}:\n");
1013         xo_open_container("errors");
1014         p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
1015             "{N:/no route}\n");
1016         p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
1017             "{N:/administratively prohibited}\n");
1018         p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
1019             "{N:/beyond scope}\n");
1020         p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
1021             "{N:/address unreachable}\n");
1022         p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
1023             "{N:/port unreachable}\n");
1024         p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
1025             "{N:/packet too big}\n");
1026         p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
1027             "{N:/time exceed transit}\n");
1028         p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
1029             "{N:/time exceed reassembly}\n");
1030         p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
1031             "{N:/erroneous header field}\n");
1032         p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
1033             "{N:/unrecognized next header}\n");
1034         p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
1035             "{N:/unrecognized option}\n");
1036         p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
1037             "{N:/redirect}\n");
1038         p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
1039
1040         p(icp6s_reflect, "\t{:reflect/%ju} "
1041             "{N:/message response%s generated}\n");
1042         p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
1043             "{N:/message%s with too many ND options}\n");
1044         p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
1045             "{N:/message%s with bad ND options}\n");
1046         p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
1047             "{N:/bad neighbor solicitation message%s}\n");
1048         p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
1049             "{N:/bad neighbor advertisement message%s}\n");
1050         p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
1051             "{N:/bad router solicitation message%s}\n");
1052         p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
1053             "{N:/bad router advertisement message%s}\n");
1054         p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
1055             "{N:/bad redirect message%s}\n");
1056         xo_close_container("errors");
1057         p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
1058 #undef p
1059 #undef p_5
1060         xo_close_container(name);
1061 }
1062
1063 /*
1064  * Dump ICMPv6 per-interface statistics based on RFC 2466.
1065  */
1066 void
1067 icmp6_ifstats(char *ifname)
1068 {
1069         struct in6_ifreq ifr;
1070         int s;
1071
1072 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1)        \
1073         xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f,            \
1074             plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1075 #define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1)       \
1076         xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f,            \
1077             pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
1078
1079         if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1080                 xo_warn("Warning: socket(AF_INET6)");
1081                 return;
1082         }
1083
1084         strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1085         if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1086                 if (errno != EPFNOSUPPORT)
1087                         xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1088                 goto end;
1089         }
1090
1091         xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
1092
1093         xo_open_instance("icmp6-interface-statistics");
1094         xo_emit("{ke:name/%s}", ifr.ifr_name);
1095         p(ifs6_in_msg, "\t{:received-packets/%ju} "
1096             "{N:/total input message%s}\n");
1097         p(ifs6_in_error, "\t{:received-errors/%ju} "
1098             "{N:/total input error message%s}\n");
1099         p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
1100             "{N:/input destination unreachable error%s}\n");
1101         p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
1102             "{N:/input administratively prohibited error%s}\n");
1103         p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
1104             "{N:/input time exceeded error%s}\n");
1105         p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
1106             "{N:/input parameter problem error%s}\n");
1107         p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
1108             "{N:/input packet too big error%s}\n");
1109         p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
1110             "{N:/input echo request%s}\n");
1111         p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
1112             "{N:/input echo repl%s}\n");
1113         p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
1114             "{N:/input router solicitation%s}\n");
1115         p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
1116             "{N:/input router advertisement%s}\n");
1117         p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
1118             "{N:/input neighbor solicitation%s}\n");
1119         p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
1120             "{N:/input neighbor advertisement%s}\n");
1121         p(ifs6_in_redirect, "\t{received-redirects/%ju} "
1122             "{N:/input redirect%s}\n");
1123         p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
1124             "{N:/input MLD quer%s}\n");
1125         p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
1126             "{N:/input MLD report%s}\n");
1127         p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
1128             "{N:/input MLD done%s}\n");
1129
1130         p(ifs6_out_msg, "\t{:sent-packets/%ju} "
1131             "{N:/total output message%s}\n");
1132         p(ifs6_out_error, "\t{:sent-errors/%ju} "
1133             "{N:/total output error message%s}\n");
1134         p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
1135             "{N:/output destination unreachable error%s}\n");
1136         p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
1137             "{N:/output administratively prohibited error%s}\n");
1138         p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
1139             "{N:/output time exceeded error%s}\n");
1140         p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
1141             "{N:/output parameter problem error%s}\n");
1142         p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
1143             "{N:/output packet too big error%s}\n");
1144         p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
1145             "{N:/output echo request%s}\n");
1146         p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
1147             "{N:/output echo repl%s}\n");
1148         p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
1149             "{N:/output router solicitation%s}\n");
1150         p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
1151             "{N:/output router advertisement%s}\n");
1152         p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
1153             "{N:/output neighbor solicitation%s}\n");
1154         p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
1155             "{N:/output neighbor advertisement%s}\n");
1156         p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
1157             "{N:/output redirect%s}\n");
1158         p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
1159             "{N:/output MLD quer%s}\n");
1160         p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
1161             "{N:/output MLD report%s}\n");
1162         p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
1163             "{N:/output MLD done%s}\n");
1164
1165 end:
1166         xo_close_instance("icmp6-interface-statistics");
1167         close(s);
1168 #undef p
1169 }
1170
1171 /*
1172  * Dump PIM statistics structure.
1173  */
1174 void
1175 pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1176 {
1177         struct pim6stat pim6stat;
1178
1179         if (fetch_stats("net.inet6.pim.stats", off, &pim6stat,
1180             sizeof(pim6stat), kread) != 0)
1181                 return;
1182
1183         xo_emit("{T:/%s}:\n", name);
1184         xo_open_container(name);
1185
1186 #define p(f, m) if (pim6stat.f || sflag <= 1) \
1187         xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1188
1189         p(pim6s_rcv_total, "\t{:received-packets/%ju} "
1190             "{N:/message%s received}\n");
1191         p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
1192             "{N:/message%s received with too few bytes}\n");
1193         p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
1194             "{N:/message%s received with bad checksum}\n");
1195         p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
1196             "{N:/message%s received with bad version}\n");
1197         p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
1198             "{N:/register%s received}\n");
1199         p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
1200             "{N:/bad register%s received}\n");
1201         p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
1202             "{N:/register%s sent}\n");
1203 #undef p
1204         xo_close_container(name);
1205 }
1206
1207 /*
1208  * Dump raw ip6 statistics structure.
1209  */
1210 void
1211 rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1212 {
1213         struct rip6stat rip6stat;
1214         u_quad_t delivered;
1215
1216         if (fetch_stats("net.inet6.ip6.rip6stats", off, &rip6stat,
1217             sizeof(rip6stat), kread_counters) != 0)
1218                 return;
1219
1220         xo_emit("{T:/%s}:\n", name);
1221         xo_open_container(name);
1222
1223 #define p(f, m) if (rip6stat.f || sflag <= 1) \
1224         xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1225
1226         p(rip6s_ipackets, "\t{:received-packets/%ju} "
1227             "{N:/message%s received}\n");
1228         p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
1229             "{N:/checksum calculation%s on inbound}\n");
1230         p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
1231             "{N:/message%s with bad checksum}\n");
1232         p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
1233             "{N:/message%s dropped due to no socket}\n");
1234         p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
1235             "{N:/multicast message%s dropped due to no socket}\n");
1236         p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
1237             "{N:/message%s dropped due to full socket buffers}\n");
1238         delivered = rip6stat.rip6s_ipackets -
1239                     rip6stat.rip6s_badsum -
1240                     rip6stat.rip6s_nosock -
1241                     rip6stat.rip6s_nosockmcast -
1242                     rip6stat.rip6s_fullsock;
1243         if (delivered || sflag <= 1)
1244                 xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
1245                     (uintmax_t)delivered);
1246         p(rip6s_opackets, "\t{:sent-packets/%ju} "
1247             "{N:/datagram%s output}\n");
1248 #undef p
1249         xo_close_container(name);
1250 }
1251
1252 /*
1253  * Pretty print an Internet address (net address + port).
1254  * Take numeric_addr and numeric_port into consideration.
1255  */
1256 #define GETSERVBYPORT6(port, proto, ret)\
1257 {\
1258         if (strcmp((proto), "tcp6") == 0)\
1259                 (ret) = getservbyport((int)(port), "tcp");\
1260         else if (strcmp((proto), "udp6") == 0)\
1261                 (ret) = getservbyport((int)(port), "udp");\
1262         else\
1263                 (ret) = getservbyport((int)(port), (proto));\
1264 };
1265
1266 void
1267 inet6print(const char *container, struct in6_addr *in6, int port,
1268     const char *proto, int numeric)
1269 {
1270         struct servent *sp = 0;
1271         char line[80], *cp;
1272         int width;
1273         size_t alen, plen;
1274
1275         if (container)
1276                 xo_open_container(container);
1277
1278         snprintf(line, sizeof(line), "%.*s.",
1279             Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
1280             inet6name(in6));
1281         alen = strlen(line);
1282         cp = line + alen;
1283         if (!numeric && port)
1284                 GETSERVBYPORT6(port, proto, sp);
1285         if (sp || port == 0)
1286                 snprintf(cp, sizeof(line) - alen,
1287                     "%.15s", sp ? sp->s_name : "*");
1288         else
1289                 snprintf(cp, sizeof(line) - alen,
1290                     "%d", ntohs((u_short)port));
1291         width = Wflag ? 45 : Aflag ? 18 : 22;
1292
1293         xo_emit("{d:target/%-*.*s} ", width, width, line);
1294
1295         plen = strlen(cp);
1296         alen--;
1297         xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
1298             plen, cp);
1299
1300         if (container)
1301                 xo_close_container(container);
1302 }
1303
1304 /*
1305  * Construct an Internet address representation.
1306  * If the numeric_addr has been supplied, give
1307  * numeric value, otherwise try for symbolic name.
1308  */
1309
1310 char *
1311 inet6name(struct in6_addr *in6p)
1312 {
1313         struct sockaddr_in6 sin6;
1314         char hbuf[NI_MAXHOST], *cp;
1315         static char line[NI_MAXHOST];
1316         static char domain[MAXHOSTNAMELEN];
1317         static int first = 1;
1318         int flags, error;
1319
1320         if (IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1321                 strcpy(line, "*");
1322                 return (line);
1323         }
1324         if (first && !numeric_addr) {
1325                 first = 0;
1326                 if (gethostname(domain, sizeof(domain)) == 0 &&
1327                     (cp = strchr(domain, '.')))
1328                         strlcpy(domain, cp + 1, sizeof(domain));
1329                 else
1330                         domain[0] = 0;
1331         }
1332         memset(&sin6, 0, sizeof(sin6));
1333         memcpy(&sin6.sin6_addr, in6p, sizeof(*in6p));
1334         sin6.sin6_family = AF_INET6;
1335         /* XXX: in6p.s6_addr[2] can contain scopeid. */
1336         in6_fillscopeid(&sin6);
1337         flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1338         error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1339             sizeof(hbuf), NULL, 0, flags);
1340         if (error == 0) {
1341                 if ((flags & NI_NUMERICHOST) == 0 &&
1342                     (cp = strchr(hbuf, '.')) &&
1343                     !strcmp(cp + 1, domain))
1344                         *cp = 0;
1345                 strlcpy(line, hbuf, sizeof(line));
1346         } else {
1347                 /* XXX: this should not happen. */
1348                 snprintf(line, sizeof(line), "%s",
1349                         inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,
1350                                 sizeof(ntop_buf)));
1351         }
1352         return (line);
1353 }
1354 #endif /*INET6*/