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