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