]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/netstat/inet6.c
Merge branch 'releng/11.3' into releng-CDN/11.3
[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  * 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         strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
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         strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
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*/