inet6.c revision 270349
1178172Simp/*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
2195162Simp/*-
3178172Simp * Copyright (c) 1983, 1988, 1993
4178172Simp *	The Regents of the University of California.  All rights reserved.
5178172Simp *
6178172Simp * Redistribution and use in source and binary forms, with or without
7178172Simp * modification, are permitted provided that the following conditions
8178172Simp * are met:
9178172Simp * 1. Redistributions of source code must retain the above copyright
10178172Simp *    notice, this list of conditions and the following disclaimer.
11178172Simp * 2. Redistributions in binary form must reproduce the above copyright
12178172Simp *    notice, this list of conditions and the following disclaimer in the
13178172Simp *    documentation and/or other materials provided with the distribution.
14178172Simp * 4. Neither the name of the University nor the names of its contributors
15178172Simp *    may be used to endorse or promote products derived from this software
16178172Simp *    without specific prior written permission.
17178172Simp *
18178172Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21178172Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26202046Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28178172Simp * SUCH DAMAGE.
29178172Simp */
30178172Simp
31178172Simp#if 0
32202046Simp#ifndef lint
33202046Simpstatic char sccsid[] = "@(#)inet6.c	8.4 (Berkeley) 4/20/94";
34202046Simp#endif /* not lint */
35202046Simp#endif
36178172Simp
37178172Simp#include <sys/cdefs.h>
38178172Simp__FBSDID("$FreeBSD: head/usr.bin/netstat/inet6.c 270349 2014-08-22 19:23:38Z markj $");
39178172Simp
40289701Sian#ifdef INET6
41178172Simp#include <sys/param.h>
42178172Simp#include <sys/socket.h>
43178172Simp#include <sys/socketvar.h>
44246713Skib#include <sys/ioctl.h>
45178172Simp#include <sys/mbuf.h>
46178172Simp#include <sys/protosw.h>
47178172Simp#include <sys/sysctl.h>
48202046Simp
49246713Skib#include <net/route.h>
50178172Simp#include <net/if.h>
51289701Sian#include <net/if_var.h>
52178172Simp#include <netinet/in.h>
53289701Sian#include <netinet/ip6.h>
54289701Sian#include <netinet/icmp6.h>
55178172Simp#include <netinet/in_systm.h>
56178172Simp#include <netinet6/in6_pcb.h>
57178172Simp#include <netinet6/in6_var.h>
58178172Simp#include <netinet6/ip6_var.h>
59178172Simp#include <netinet6/pim6_var.h>
60178172Simp#include <netinet6/raw_ip6.h>
61178172Simp
62204689Sneel#include <arpa/inet.h>
63202046Simp#include <netdb.h>
64178172Simp
65202046Simp#include <err.h>
66202046Simp#include <stdint.h>
67202046Simp#include <stdio.h>
68202046Simp#include <errno.h>
69202046Simp#include <string.h>
70202046Simp#include <unistd.h>
71178172Simp#include "netstat.h"
72178172Simp
73178172Simpstruct	socket sockb;
74232356Sjhb
75178172Simpchar	*inet6name(struct in6_addr *);
76178172Simp
77178172Simpstatic char ntop_buf[INET6_ADDRSTRLEN];
78178172Simp
79178172Simpstatic	const char *ip6nh[] = {
80178172Simp	"hop by hop",
81178172Simp	"ICMP",
82178172Simp	"IGMP",
83178172Simp	"#3",
84178172Simp	"IP",
85178172Simp	"#5",
86178172Simp	"TCP",
87240177Sjhb	"#7",
88202046Simp	"#8",
89178172Simp	"#9",
90178172Simp	"#10",
91202046Simp	"#11",
92202046Simp	"#12",
93202046Simp	"#13",
94202046Simp	"#14",
95202046Simp	"#15",
96246713Skib	"#16",
97202046Simp	"UDP",
98202046Simp	"#18",
99202046Simp	"#19",
100202046Simp	"#20",
101246713Skib	"#21",
102246713Skib	"IDP",
103246713Skib	"#23",
104246713Skib	"#24",
105246713Skib	"#25",
106246713Skib	"#26",
107202046Simp	"#27",
108202046Simp	"#28",
109202046Simp	"TP",
110202046Simp	"#30",
111202046Simp	"#31",
112202046Simp	"#32",
113202046Simp	"#33",
114202046Simp	"#34",
115202046Simp	"#35",
116202046Simp	"#36",
117202046Simp	"#37",
118202046Simp	"#38",
119202046Simp	"#39",
120202046Simp	"#40",
121202046Simp	"IP6",
122202046Simp	"#42",
123202046Simp	"routing",
124202046Simp	"fragment",
125202046Simp	"#45",
126202046Simp	"#46",
127202046Simp	"#47",
128202046Simp	"#48",
129202046Simp	"#49",
130202046Simp	"ESP",
131202046Simp	"AH",
132227309Sed	"#52",
133202046Simp	"#53",
134202046Simp	"#54",
135202046Simp	"#55",
136289701Sian	"#56",
137289701Sian	"#57",
138202046Simp	"ICMP6",
139178172Simp	"no next header",
140202046Simp	"destination option",
141202046Simp	"#61",
142202046Simp	"mobility",
143212284Sjchandra	"#63",
144246713Skib	"#64",
145178172Simp	"#65",
146178172Simp	"#66",
147178172Simp	"#67",
148178172Simp	"#68",
149202046Simp	"#69",
150202046Simp	"#70",
151212284Sjchandra	"#71",
152246713Skib	"#72",
153246713Skib	"#73",
154178172Simp	"#74",
155178172Simp	"#75",
156202046Simp	"#76",
157202046Simp	"#77",
158202046Simp	"#78",
159202046Simp	"#79",
160202046Simp	"ISOIP",
161202046Simp	"#81",
162202046Simp	"#82",
163202046Simp	"#83",
164202046Simp	"#84",
165246713Skib	"#85",
166246713Skib	"#86",
167202046Simp	"#87",
168202046Simp	"#88",
169202046Simp	"OSPF",
170202046Simp	"#80",
171202046Simp	"#91",
172289701Sian	"#92",
173289701Sian	"#93",
174289701Sian	"#94",
175289701Sian	"#95",
176289701Sian	"#96",
177289701Sian	"Ethernet",
178289701Sian	"#98",
179289701Sian	"#99",
180202046Simp	"#100",
181289701Sian	"#101",
182289701Sian	"#102",
183289701Sian	"PIM",
184289701Sian	"#104",
185289701Sian	"#105",
186289701Sian	"#106",
187289701Sian	"#107",
188289701Sian	"#108",
189289701Sian	"#109",
190289701Sian	"#110",
191289701Sian	"#111",
192289701Sian	"#112",
193289701Sian	"#113",
194289701Sian	"#114",
195289701Sian	"#115",
196289701Sian	"#116",
197289701Sian	"#117",
198289701Sian	"#118",
199289701Sian	"#119",
200289701Sian	"#120",
201289701Sian	"#121",
202289701Sian	"#122",
203289701Sian	"#123",
204289701Sian	"#124",
205289701Sian	"#125",
206289701Sian	"#126",
207289701Sian	"#127",
208289701Sian	"#128",
209289701Sian	"#129",
210289701Sian	"#130",
211289701Sian	"#131",
212289701Sian	"#132",
213289701Sian	"#133",
214289701Sian	"#134",
215289701Sian	"#135",
216289701Sian	"#136",
217289701Sian	"#137",
218289701Sian	"#138",
219289701Sian	"#139",
220289701Sian	"#140",
221289701Sian	"#141",
222289701Sian	"#142",
223289701Sian	"#143",
224289701Sian	"#144",
225289701Sian	"#145",
226289701Sian	"#146",
227289701Sian	"#147",
228289701Sian	"#148",
229289701Sian	"#149",
230289701Sian	"#150",
231289701Sian	"#151",
232289701Sian	"#152",
233289701Sian	"#153",
234289701Sian	"#154",
235289701Sian	"#155",
236289701Sian	"#156",
237289701Sian	"#157",
238289701Sian	"#158",
239289701Sian	"#159",
240289701Sian	"#160",
241289701Sian	"#161",
242289701Sian	"#162",
243289701Sian	"#163",
244289701Sian	"#164",
245289701Sian	"#165",
246289701Sian	"#166",
247202046Simp	"#167",
248202046Simp	"#168",
249202046Simp	"#169",
250202046Simp	"#170",
251202046Simp	"#171",
252202046Simp	"#172",
253202046Simp	"#173",
254202046Simp	"#174",
255202046Simp	"#175",
256202046Simp	"#176",
257202046Simp	"#177",
258202046Simp	"#178",
259202046Simp	"#179",
260202046Simp	"#180",
261202046Simp	"#181",
262202046Simp	"#182",
263202046Simp	"#183",
264202046Simp	"#184",
265202046Simp	"#185",
266202046Simp	"#186",
267202046Simp	"#187",
268202046Simp	"#188",
269202046Simp	"#189",
270202046Simp	"#180",
271202046Simp	"#191",
272202046Simp	"#192",
273178172Simp	"#193",
274178172Simp	"#194",
275178172Simp	"#195",
276178172Simp	"#196",
277178172Simp	"#197",
278202046Simp	"#198",
279202046Simp	"#199",
280202046Simp	"#200",
281202046Simp	"#201",
282202046Simp	"#202",
283202046Simp	"#203",
284202046Simp	"#204",
285202046Simp	"#205",
286202046Simp	"#206",
287202046Simp	"#207",
288202046Simp	"#208",
289202046Simp	"#209",
290178172Simp	"#210",
291178172Simp	"#211",
292178172Simp	"#212",
293178172Simp	"#213",
294178172Simp	"#214",
295178172Simp	"#215",
296178172Simp	"#216",
297178172Simp	"#217",
298178172Simp	"#218",
299178172Simp	"#219",
300178172Simp	"#220",
301178172Simp	"#221",
302178172Simp	"#222",
303178172Simp	"#223",
304178172Simp	"#224",
305178172Simp	"#225",
306178172Simp	"#226",
307178172Simp	"#227",
308178172Simp	"#228",
309178172Simp	"#229",
310178172Simp	"#230",
311178172Simp	"#231",
312178172Simp	"#232",
313178172Simp	"#233",
314178172Simp	"#234",
315178172Simp	"#235",
316178172Simp	"#236",
317178172Simp	"#237",
318178172Simp	"#238",
319178172Simp	"#239",
320178172Simp	"#240",
321178172Simp	"#241",
322178172Simp	"#242",
323178172Simp	"#243",
324178172Simp	"#244",
325178172Simp	"#245",
326178172Simp	"#246",
327178172Simp	"#247",
328178172Simp	"#248",
329178172Simp	"#249",
330178172Simp	"#250",
331246713Skib	"#251",
332178172Simp	"#252",
333246713Skib	"#253",
334178172Simp	"#254",
335178172Simp	"#255",
336289701Sian};
337246713Skib
338246713Skibstatic const char *srcrule_str[] = {
339289701Sian	"first candidate",
340289701Sian	"same address",
341246713Skib	"appropriate scope",
342289701Sian	"deprecated address",
343289708Sian	"home address",
344178172Simp	"outgoing interface",
345178172Simp	"matching label",
346178172Simp	"public/temporary address",
347178172Simp	"alive interface",
348178172Simp	"preferred interface",
349178172Simp	"rule #10",
350289708Sian	"rule #11",
351289708Sian	"rule #12",
352289701Sian	"rule #13",
353178172Simp	"longest match",
354178172Simp	"rule #15",
355202046Simp};
356202046Simp
357202046Simp/*
358202046Simp * Dump IP6 statistics structure.
359202046Simp */
360178172Simpvoid
361178172Simpip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
362232356Sjhb{
363212284Sjchandra	struct ip6stat ip6stat, zerostat;
364212284Sjchandra	int first, i;
365212284Sjchandra	size_t len;
366212284Sjchandra
367178172Simp	len = sizeof ip6stat;
368178172Simp	if (live) {
369178172Simp		memset(&ip6stat, 0, len);
370178172Simp		if (zflag)
371178172Simp			memset(&zerostat, 0, len);
372202046Simp		if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len,
373202046Simp		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
374178172Simp			if (errno != ENOENT)
375289701Sian				warn("sysctl: net.inet6.ip6.stats");
376178172Simp			return;
377178172Simp		}
378178172Simp	} else
379178172Simp		kread_counters(off, &ip6stat, len);
380178172Simp
381178172Simp	printf("%s:\n", name);
382178172Simp
383178172Simp#define	p(f, m) if (ip6stat.f || sflag <= 1) \
384178172Simp    printf(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
385202046Simp#define	p1a(f, m) if (ip6stat.f || sflag <= 1) \
386202046Simp    printf(m, (uintmax_t)ip6stat.f)
387178172Simp
388178172Simp	p(ip6s_total, "\t%ju total packet%s received\n");
389212284Sjchandra	p1a(ip6s_toosmall, "\t%ju with size smaller than minimum\n");
390212284Sjchandra	p1a(ip6s_tooshort, "\t%ju with data size < data length\n");
391178172Simp	p1a(ip6s_badoptions, "\t%ju with bad options\n");
392178172Simp	p1a(ip6s_badvers, "\t%ju with incorrect version number\n");
393204689Sneel	p(ip6s_fragments, "\t%ju fragment%s received\n");
394204689Sneel	p(ip6s_fragdropped, "\t%ju fragment%s dropped (dup or out of space)\n");
395178172Simp	p(ip6s_fragtimeout, "\t%ju fragment%s dropped after timeout\n");
396178172Simp	p(ip6s_fragoverflow, "\t%ju fragment%s that exceeded limit\n");
397178172Simp	p(ip6s_reassembled, "\t%ju packet%s reassembled ok\n");
398178172Simp	p(ip6s_delivered, "\t%ju packet%s for this host\n");
399178172Simp	p(ip6s_forward, "\t%ju packet%s forwarded\n");
400178172Simp	p(ip6s_cantforward, "\t%ju packet%s not forwardable\n");
401178172Simp	p(ip6s_redirectsent, "\t%ju redirect%s sent\n");
402178172Simp	p(ip6s_localout, "\t%ju packet%s sent from this host\n");
403178172Simp	p(ip6s_rawout, "\t%ju packet%s sent with fabricated ip header\n");
404240177Sjhb	p(ip6s_odropped, "\t%ju output packet%s dropped due to no bufs, etc.\n");
405240177Sjhb	p(ip6s_noroute, "\t%ju output packet%s discarded due to no route\n");
406212284Sjchandra	p(ip6s_fragmented, "\t%ju output datagram%s fragmented\n");
407202046Simp	p(ip6s_ofragments, "\t%ju fragment%s created\n");
408202046Simp	p(ip6s_cantfrag, "\t%ju datagram%s that can't be fragmented\n");
409212284Sjchandra	p(ip6s_badscope, "\t%ju packet%s that violated scope rules\n");
410232356Sjhb	p(ip6s_notmember, "\t%ju multicast packet%s which we don't join\n");
411232356Sjhb	for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
412178172Simp		if (ip6stat.ip6s_nxthist[i] != 0) {
413178172Simp			if (first) {
414178172Simp				printf("\tInput histogram:\n");
415212284Sjchandra				first = 0;
416232356Sjhb			}
417202046Simp			printf("\t\t%s: %ju\n", ip6nh[i],
418202046Simp			    (uintmax_t)ip6stat.ip6s_nxthist[i]);
419202046Simp		}
420212284Sjchandra	printf("\tMbuf statistics:\n");
421212284Sjchandra	printf("\t\t%ju one mbuf\n", (uintmax_t)ip6stat.ip6s_m1);
422212284Sjchandra	for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
423212284Sjchandra		char ifbuf[IFNAMSIZ];
424212284Sjchandra		if (ip6stat.ip6s_m2m[i] != 0) {
425212284Sjchandra			if (first) {
426212284Sjchandra				printf("\t\ttwo or more mbuf:\n");
427212284Sjchandra				first = 0;
428178172Simp			}
429178172Simp			printf("\t\t\t%s= %ju\n",
430178172Simp			    if_indextoname(i, ifbuf),
431178172Simp			    (uintmax_t)ip6stat.ip6s_m2m[i]);
432202046Simp		}
433202046Simp	}
434202046Simp	printf("\t\t%ju one ext mbuf\n",
435178172Simp	    (uintmax_t)ip6stat.ip6s_mext1);
436202046Simp	printf("\t\t%ju two or more ext mbuf\n",
437202046Simp	    (uintmax_t)ip6stat.ip6s_mext2m);
438202046Simp	p(ip6s_exthdrtoolong,
439202046Simp	    "\t%ju packet%s whose headers are not contiguous\n");
440202046Simp	p(ip6s_nogif, "\t%ju tunneling packet%s that can't find gif\n");
441202046Simp	p(ip6s_toomanyhdr,
442202046Simp	    "\t%ju packet%s discarded because of too many headers\n");
443289708Sian
444202046Simp	/* for debugging source address selection */
445202046Simp#define	PRINT_SCOPESTAT(s,i) do {\
446202046Simp		switch(i) { /* XXX hardcoding in each case */\
447202046Simp		case 1:\
448202046Simp			p(s, "\t\t%ju interface-local%s\n");\
449202046Simp			break;\
450202046Simp		case 2:\
451202046Simp			p(s,"\t\t%ju link-local%s\n");\
452202046Simp			break;\
453202046Simp		case 5:\
454202046Simp			p(s,"\t\t%ju site-local%s\n");\
455202046Simp			break;\
456202046Simp		case 14:\
457202046Simp			p(s,"\t\t%ju global%s\n");\
458202046Simp			break;\
459202046Simp		default:\
460202046Simp			printf("\t\t%ju addresses scope=%x\n",\
461202046Simp			    (uintmax_t)ip6stat.s, i);\
462289708Sian		}\
463202046Simp	} while (0);
464178172Simp
465178172Simp	p(ip6s_sources_none,
466178172Simp	  "\t%ju failure%s of source address selection\n");
467202046Simp	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
468178172Simp		if (ip6stat.ip6s_sources_sameif[i]) {
469178172Simp			if (first) {
470178172Simp				printf("\tsource addresses on an outgoing I/F\n");
471178172Simp				first = 0;
472178172Simp			}
473178172Simp			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
474178172Simp		}
475178172Simp	}
476178172Simp	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
477178172Simp		if (ip6stat.ip6s_sources_otherif[i]) {
478178172Simp			if (first) {
479212284Sjchandra				printf("\tsource addresses on a non-outgoing I/F\n");
480212284Sjchandra				first = 0;
481178172Simp			}
482212284Sjchandra			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
483212284Sjchandra		}
484178172Simp	}
485212284Sjchandra	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
486212284Sjchandra		if (ip6stat.ip6s_sources_samescope[i]) {
487212284Sjchandra			if (first) {
488240177Sjhb				printf("\tsource addresses of same scope\n");
489289708Sian				first = 0;
490289708Sian			}
491212284Sjchandra			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
492212284Sjchandra		}
493212284Sjchandra	}
494212284Sjchandra	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
495212284Sjchandra		if (ip6stat.ip6s_sources_otherscope[i]) {
496212284Sjchandra			if (first) {
497212284Sjchandra				printf("\tsource addresses of a different scope\n");
498240177Sjhb				first = 0;
499212284Sjchandra			}
500212284Sjchandra			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
501178172Simp		}
502178172Simp	}
503212284Sjchandra	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
504178172Simp		if (ip6stat.ip6s_sources_deprecated[i]) {
505178172Simp			if (first) {
506202046Simp				printf("\tdeprecated source addresses\n");
507178172Simp				first = 0;
508178172Simp			}
509178172Simp			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
510178172Simp		}
511178172Simp	}
512178172Simp
513178172Simp	printf("\tSource addresses selection rule applied:\n");
514178172Simp	for (i = 0; i < IP6S_RULESMAX; i++) {
515178172Simp		if (ip6stat.ip6s_sources_rule[i])
516178172Simp			printf("\t\t%ju %s\n",
517240177Sjhb			       (uintmax_t)ip6stat.ip6s_sources_rule[i],
518240177Sjhb			       srcrule_str[i]);
519289701Sian	}
520240177Sjhb#undef p
521240177Sjhb#undef p1a
522240177Sjhb}
523240177Sjhb
524240177Sjhb/*
525240177Sjhb * Dump IPv6 per-interface statistics based on RFC 2465.
526240177Sjhb */
527240177Sjhbvoid
528246713Skibip6_ifstats(char *ifname)
529178172Simp{
530178172Simp	struct in6_ifreq ifr;
531178172Simp	int s;
532178172Simp#define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
533178172Simp    printf(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f, plural(ifr.ifr_ifru.ifru_stat.f))
534178172Simp#define	p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
535202046Simp    printf(m, (uintmax_t)ip6stat.f)
536202046Simp
537202046Simp	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
538202046Simp		perror("Warning: socket(AF_INET6)");
539202046Simp		return;
540202046Simp	}
541202046Simp
542202046Simp	strcpy(ifr.ifr_name, ifname);
543202046Simp	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
544202046Simp		if (errno != EPFNOSUPPORT)
545202046Simp			perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
546202046Simp		goto end;
547202046Simp	}
548202046Simp
549202046Simp	printf("ip6 on %s:\n", ifr.ifr_name);
550202046Simp	p(ifs6_in_receive, "\t%ju total input datagram%s\n");
551202046Simp	p(ifs6_in_hdrerr, "\t%ju datagram%s with invalid header received\n");
552202046Simp	p(ifs6_in_toobig, "\t%ju datagram%s exceeded MTU received\n");
553202046Simp	p(ifs6_in_noroute, "\t%ju datagram%s with no route received\n");
554202046Simp	p(ifs6_in_addrerr, "\t%ju datagram%s with invalid dst received\n");
555202046Simp	p(ifs6_in_protounknown, "\t%ju datagram%s with unknown proto received\n");
556202046Simp	p(ifs6_in_truncated, "\t%ju truncated datagram%s received\n");
557202046Simp	p(ifs6_in_discard, "\t%ju input datagram%s discarded\n");
558202046Simp	p(ifs6_in_deliver,
559202046Simp	  "\t%ju datagram%s delivered to an upper layer protocol\n");
560202046Simp	p(ifs6_out_forward, "\t%ju datagram%s forwarded to this interface\n");
561202046Simp	p(ifs6_out_request,
562202046Simp	  "\t%ju datagram%s sent from an upper layer protocol\n");
563202046Simp	p(ifs6_out_discard, "\t%ju total discarded output datagram%s\n");
564202046Simp	p(ifs6_out_fragok, "\t%ju output datagram%s fragmented\n");
565202046Simp	p(ifs6_out_fragfail, "\t%ju output datagram%s failed on fragment\n");
566202046Simp	p(ifs6_out_fragcreat, "\t%ju output datagram%s succeeded on fragment\n");
567202046Simp	p(ifs6_reass_reqd, "\t%ju incoming datagram%s fragmented\n");
568202046Simp	p(ifs6_reass_ok, "\t%ju datagram%s reassembled\n");
569202046Simp	p(ifs6_reass_fail, "\t%ju datagram%s failed on reassembly\n");
570202046Simp	p(ifs6_in_mcast, "\t%ju multicast datagram%s received\n");
571202046Simp	p(ifs6_out_mcast, "\t%ju multicast datagram%s sent\n");
572202046Simp
573202046Simp  end:
574202046Simp	close(s);
575202046Simp
576202046Simp#undef p
577202046Simp#undef p_5
578202046Simp}
579202046Simp
580202046Simpstatic	const char *icmp6names[] = {
581202046Simp	"#0",
582202046Simp	"unreach",
583178172Simp	"packet too big",
584178172Simp	"time exceed",
585178172Simp	"parameter problem",
586178172Simp	"#5",
587178172Simp	"#6",
588178172Simp	"#7",
589178172Simp	"#8",
590178172Simp	"#9",
591178172Simp	"#10",
592178172Simp	"#11",
593178172Simp	"#12",
594178172Simp	"#13",
595178172Simp	"#14",
596202046Simp	"#15",
597246713Skib	"#16",
598202046Simp	"#17",
599202046Simp	"#18",
600202046Simp	"#19",
601202046Simp	"#20",
602202046Simp	"#21",
603202046Simp	"#22",
604242465Sadrian	"#23",
605178172Simp	"#24",
606178172Simp	"#25",
607178172Simp	"#26",
608178172Simp	"#27",
609178172Simp	"#28",
610178172Simp	"#29",
611178172Simp	"#30",
612178172Simp	"#31",
613178172Simp	"#32",
614178172Simp	"#33",
615289701Sian	"#34",
616212284Sjchandra	"#35",
617178172Simp	"#36",
618178172Simp	"#37",
619289701Sian	"#38",
620289701Sian	"#39",
621289701Sian	"#40",
622289701Sian	"#41",
623178172Simp	"#42",
624178172Simp	"#43",
625178172Simp	"#44",
626178172Simp	"#45",
627178172Simp	"#46",
628178172Simp	"#47",
629178172Simp	"#48",
630240177Sjhb	"#49",
631240177Sjhb	"#50",
632289701Sian	"#51",
633240177Sjhb	"#52",
634240177Sjhb	"#53",
635240177Sjhb	"#54",
636240177Sjhb	"#55",
637240177Sjhb	"#56",
638240177Sjhb	"#57",
639240177Sjhb	"#58",
640178172Simp	"#59",
641246713Skib	"#60",
642178172Simp	"#61",
643178172Simp	"#62",
644178172Simp	"#63",
645178172Simp	"#64",
646178172Simp	"#65",
647202046Simp	"#66",
648204689Sneel	"#67",
649204689Sneel	"#68",
650204689Sneel	"#69",
651204689Sneel	"#70",
652204689Sneel	"#71",
653204689Sneel	"#72",
654204689Sneel	"#73",
655289701Sian	"#74",
656289701Sian	"#75",
657289701Sian	"#76",
658289701Sian	"#77",
659289701Sian	"#78",
660289701Sian	"#79",
661289701Sian	"#80",
662289701Sian	"#81",
663289701Sian	"#82",
664289701Sian	"#83",
665289701Sian	"#84",
666289701Sian	"#85",
667289701Sian	"#86",
668289701Sian	"#87",
669204689Sneel	"#88",
670289701Sian	"#89",
671289701Sian	"#80",
672289701Sian	"#91",
673204689Sneel	"#92",
674289701Sian	"#93",
675204689Sneel	"#94",
676289701Sian	"#95",
677289701Sian	"#96",
678289701Sian	"#97",
679289701Sian	"#98",
680289701Sian	"#99",
681289701Sian	"#100",
682289701Sian	"#101",
683289701Sian	"#102",
684289701Sian	"#103",
685289701Sian	"#104",
686289701Sian	"#105",
687289701Sian	"#106",
688289701Sian	"#107",
689289701Sian	"#108",
690289701Sian	"#109",
691289701Sian	"#110",
692289701Sian	"#111",
693289701Sian	"#112",
694289701Sian	"#113",
695289701Sian	"#114",
696212284Sjchandra	"#115",
697289701Sian	"#116",
698289701Sian	"#117",
699289701Sian	"#118",
700212284Sjchandra	"#119",
701289701Sian	"#120",
702289701Sian	"#121",
703289701Sian	"#122",
704289701Sian	"#123",
705289701Sian	"#124",
706178172Simp	"#125",
707289701Sian	"#126",
708289701Sian	"#127",
709202046Simp	"echo",
710289701Sian	"echo reply",
711178172Simp	"multicast listener query",
712178172Simp	"MLDv1 listener report",
713178172Simp	"MLDv1 listener done",
714178172Simp	"router solicitation",
715178172Simp	"router advertisement",
716178172Simp	"neighbor solicitation",
717178172Simp	"neighbor advertisement",
718178172Simp	"redirect",
719178172Simp	"router renumbering",
720289701Sian	"node information request",
721289701Sian	"node information reply",
722202046Simp	"inverse neighbor solicitation",
723212283Sjchandra	"inverse neighbor advertisement",
724289701Sian	"MLDv2 listener report",
725212284Sjchandra	"#144",
726289701Sian	"#145",
727202046Simp	"#146",
728289708Sian	"#147",
729289701Sian	"#148",
730289701Sian	"#149",
731289701Sian	"#150",
732289701Sian	"#151",
733289701Sian	"#152",
734289701Sian	"#153",
735289701Sian	"#154",
736289701Sian	"#155",
737289701Sian	"#156",
738178172Simp	"#157",
739202046Simp	"#158",
740178172Simp	"#159",
741246713Skib	"#160",
742246713Skib	"#161",
743246713Skib	"#162",
744246713Skib	"#163",
745246713Skib	"#164",
746246713Skib	"#165",
747246713Skib	"#166",
748246713Skib	"#167",
749246713Skib	"#168",
750246713Skib	"#169",
751246713Skib	"#170",
752246713Skib	"#171",
753246713Skib	"#172",
754246713Skib	"#173",
755246713Skib	"#174",
756246713Skib	"#175",
757246713Skib	"#176",
758246713Skib	"#177",
759246713Skib	"#178",
760246713Skib	"#179",
761246713Skib	"#180",
762246713Skib	"#181",
763246713Skib	"#182",
764246713Skib	"#183",
765246713Skib	"#184",
766246713Skib	"#185",
767246713Skib	"#186",
768246713Skib	"#187",
769246713Skib	"#188",
770246713Skib	"#189",
771246713Skib	"#180",
772202046Simp	"#191",
773202046Simp	"#192",
774202046Simp	"#193",
775202046Simp	"#194",
776202046Simp	"#195",
777202046Simp	"#196",
778202046Simp	"#197",
779202046Simp	"#198",
780202046Simp	"#199",
781202046Simp	"#200",
782202046Simp	"#201",
783202046Simp	"#202",
784202046Simp	"#203",
785202046Simp	"#204",
786202046Simp	"#205",
787202046Simp	"#206",
788206405Snwhitehorn	"#207",
789202046Simp	"#208",
790202046Simp	"#209",
791202046Simp	"#210",
792206405Snwhitehorn	"#211",
793206405Snwhitehorn	"#212",
794202046Simp	"#213",
795206405Snwhitehorn	"#214",
796202046Simp	"#215",
797202046Simp	"#216",
798206405Snwhitehorn	"#217",
799206405Snwhitehorn	"#218",
800202046Simp	"#219",
801206405Snwhitehorn	"#220",
802206405Snwhitehorn	"#221",
803202046Simp	"#222",
804202046Simp	"#223",
805202046Simp	"#224",
806246713Skib	"#225",
807202046Simp	"#226",
808246713Skib	"#227",
809246713Skib	"#228",
810246713Skib	"#229",
811246713Skib	"#230",
812202046Simp	"#231",
813246713Skib	"#232",
814246713Skib	"#233",
815246713Skib	"#234",
816246713Skib	"#235",
817246713Skib	"#236",
818202046Simp	"#237",
819246713Skib	"#238",
820246713Skib	"#239",
821246713Skib	"#240",
822246713Skib	"#241",
823246713Skib	"#242",
824246713Skib	"#243",
825246713Skib	"#244",
826246713Skib	"#245",
827202046Simp	"#246",
828246713Skib	"#247",
829202046Simp	"#248",
830202046Simp	"#249",
831178172Simp	"#250",
832178172Simp	"#251",
833178172Simp	"#252",
834246713Skib	"#253",
835246713Skib	"#254",
836246713Skib	"#255",
837246713Skib};
838246713Skib
839246713Skib/*
840246713Skib * Dump ICMP6 statistics.
841246713Skib */
842246713Skibvoid
843246713Skibicmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
844246713Skib{
845246713Skib	struct icmp6stat icmp6stat, zerostat;
846246713Skib	int i, first;
847246713Skib	size_t len;
848246713Skib
849246713Skib	len = sizeof icmp6stat;
850246713Skib	if (live) {
851246713Skib		memset(&icmp6stat, 0, len);
852246713Skib		if (zflag)
853246713Skib			memset(&zerostat, 0, len);
854246713Skib		if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
855246713Skib		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
856246713Skib			if (errno != ENOENT)
857246713Skib				warn("sysctl: net.inet6.icmp6.stats");
858246713Skib			return;
859246713Skib		}
860246713Skib	} else
861246713Skib		kread_counters(off, &icmp6stat, len);
862246713Skib
863246713Skib	printf("%s:\n", name);
864246713Skib
865246713Skib#define	p(f, m) if (icmp6stat.f || sflag <= 1) \
866246713Skib    printf(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
867246713Skib#define	p_5(f, m) if (icmp6stat.f || sflag <= 1) \
868246713Skib    printf(m, (uintmax_t)icmp6stat.f)
869246713Skib
870246713Skib	p(icp6s_error, "\t%ju call%s to icmp6_error\n");
871246713Skib	p(icp6s_canterror,
872246713Skib	    "\t%ju error%s not generated in response to an icmp6 message\n");
873246713Skib	p(icp6s_toofreq,
874246713Skib	  "\t%ju error%s not generated because of rate limitation\n");
875246713Skib#define	NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
876246713Skib	for (first = 1, i = 0; i < NELEM; i++)
877246713Skib		if (icmp6stat.icp6s_outhist[i] != 0) {
878246713Skib			if (first) {
879246713Skib				printf("\tOutput histogram:\n");
880246713Skib				first = 0;
881246713Skib			}
882246713Skib			printf("\t\t%s: %ju\n", icmp6names[i],
883246713Skib			    (uintmax_t)icmp6stat.icp6s_outhist[i]);
884246713Skib		}
885246713Skib#undef NELEM
886246713Skib	p(icp6s_badcode, "\t%ju message%s with bad code fields\n");
887246713Skib	p(icp6s_tooshort, "\t%ju message%s < minimum length\n");
888246713Skib	p(icp6s_checksum, "\t%ju bad checksum%s\n");
889246713Skib	p(icp6s_badlen, "\t%ju message%s with bad length\n");
890246713Skib#define	NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
891246713Skib	for (first = 1, i = 0; i < NELEM; i++)
892246713Skib		if (icmp6stat.icp6s_inhist[i] != 0) {
893246713Skib			if (first) {
894246713Skib				printf("\tInput histogram:\n");
895246713Skib				first = 0;
896246713Skib			}
897246713Skib			printf("\t\t%s: %ju\n", icmp6names[i],
898246713Skib			    (uintmax_t)icmp6stat.icp6s_inhist[i]);
899246713Skib		}
900246713Skib#undef NELEM
901246713Skib	printf("\tHistogram of error messages to be generated:\n");
902246713Skib	p_5(icp6s_odst_unreach_noroute, "\t\t%ju no route\n");
903246713Skib	p_5(icp6s_odst_unreach_admin, "\t\t%ju administratively prohibited\n");
904246713Skib	p_5(icp6s_odst_unreach_beyondscope, "\t\t%ju beyond scope\n");
905246713Skib	p_5(icp6s_odst_unreach_addr, "\t\t%ju address unreachable\n");
906246713Skib	p_5(icp6s_odst_unreach_noport, "\t\t%ju port unreachable\n");
907246713Skib	p_5(icp6s_opacket_too_big, "\t\t%ju packet too big\n");
908246713Skib	p_5(icp6s_otime_exceed_transit, "\t\t%ju time exceed transit\n");
909246713Skib	p_5(icp6s_otime_exceed_reassembly, "\t\t%ju time exceed reassembly\n");
910246713Skib	p_5(icp6s_oparamprob_header, "\t\t%ju erroneous header field\n");
911246713Skib	p_5(icp6s_oparamprob_nextheader, "\t\t%ju unrecognized next header\n");
912246713Skib	p_5(icp6s_oparamprob_option, "\t\t%ju unrecognized option\n");
913246713Skib	p_5(icp6s_oredirect, "\t\t%ju redirect\n");
914246713Skib	p_5(icp6s_ounknown, "\t\t%ju unknown\n");
915246713Skib
916246713Skib	p(icp6s_reflect, "\t%ju message response%s generated\n");
917246713Skib	p(icp6s_nd_toomanyopt, "\t%ju message%s with too many ND options\n");
918246713Skib	p(icp6s_nd_badopt, "\t%ju message%s with bad ND options\n");
919246713Skib	p(icp6s_badns, "\t%ju bad neighbor solicitation message%s\n");
920246713Skib	p(icp6s_badna, "\t%ju bad neighbor advertisement message%s\n");
921246713Skib	p(icp6s_badrs, "\t%ju bad router solicitation message%s\n");
922246713Skib	p(icp6s_badra, "\t%ju bad router advertisement message%s\n");
923246713Skib	p(icp6s_badredirect, "\t%ju bad redirect message%s\n");
924246713Skib	p(icp6s_pmtuchg, "\t%ju path MTU change%s\n");
925257228Skib#undef p
926257228Skib#undef p_5
927257228Skib}
928257228Skib
929257228Skib/*
930257228Skib * Dump ICMPv6 per-interface statistics based on RFC 2466.
931257228Skib */
932257228Skibvoid
933257228Skibicmp6_ifstats(char *ifname)
934257228Skib{
935246713Skib	struct in6_ifreq ifr;
936246713Skib	int s;
937178172Simp#define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
938178172Simp    printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
939178172Simp#define	p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
940246713Skib    printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
941246713Skib
942246713Skib	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
943246713Skib		perror("Warning: socket(AF_INET6)");
944178172Simp		return;
945178172Simp	}
946246713Skib
947246713Skib	strcpy(ifr.ifr_name, ifname);
948178172Simp	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
949178172Simp		if (errno != EPFNOSUPPORT)
950178172Simp			perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
951178172Simp		goto end;
952246713Skib	}
953246713Skib
954289716Sian	printf("icmp6 on %s:\n", ifr.ifr_name);
955289716Sian	p(ifs6_in_msg, "\t%ju total input message%s\n");
956246713Skib	p(ifs6_in_error, "\t%ju total input error message%s\n");
957202046Simp	p(ifs6_in_dstunreach, "\t%ju input destination unreachable error%s\n");
958246713Skib	p(ifs6_in_adminprohib, "\t%ju input administratively prohibited error%s\n");
959246713Skib	p(ifs6_in_timeexceed, "\t%ju input time exceeded error%s\n");
960246713Skib	p(ifs6_in_paramprob, "\t%ju input parameter problem error%s\n");
961246713Skib	p(ifs6_in_pkttoobig, "\t%ju input packet too big error%s\n");
962246713Skib	p(ifs6_in_echo, "\t%ju input echo request%s\n");
963246713Skib	p2(ifs6_in_echoreply, "\t%ju input echo repl%s\n");
964202046Simp	p(ifs6_in_routersolicit, "\t%ju input router solicitation%s\n");
965202046Simp	p(ifs6_in_routeradvert, "\t%ju input router advertisement%s\n");
966202046Simp	p(ifs6_in_neighborsolicit, "\t%ju input neighbor solicitation%s\n");
967202046Simp	p(ifs6_in_neighboradvert, "\t%ju input neighbor advertisement%s\n");
968246713Skib	p(ifs6_in_redirect, "\t%ju input redirect%s\n");
969178172Simp	p2(ifs6_in_mldquery, "\t%ju input MLD quer%s\n");
970178172Simp	p(ifs6_in_mldreport, "\t%ju input MLD report%s\n");
971202046Simp	p(ifs6_in_mlddone, "\t%ju input MLD done%s\n");
972202046Simp
973202046Simp	p(ifs6_out_msg, "\t%ju total output message%s\n");
974178172Simp	p(ifs6_out_error, "\t%ju total output error message%s\n");
975178172Simp	p(ifs6_out_dstunreach, "\t%ju output destination unreachable error%s\n");
976178172Simp	p(ifs6_out_adminprohib, "\t%ju output administratively prohibited error%s\n");
977178172Simp	p(ifs6_out_timeexceed, "\t%ju output time exceeded error%s\n");
978178172Simp	p(ifs6_out_paramprob, "\t%ju output parameter problem error%s\n");
979178172Simp	p(ifs6_out_pkttoobig, "\t%ju output packet too big error%s\n");
980178172Simp	p(ifs6_out_echo, "\t%ju output echo request%s\n");
981178172Simp	p2(ifs6_out_echoreply, "\t%ju output echo repl%s\n");
982202046Simp	p(ifs6_out_routersolicit, "\t%ju output router solicitation%s\n");
983202046Simp	p(ifs6_out_routeradvert, "\t%ju output router advertisement%s\n");
984178172Simp	p(ifs6_out_neighborsolicit, "\t%ju output neighbor solicitation%s\n");
985178172Simp	p(ifs6_out_neighboradvert, "\t%ju output neighbor advertisement%s\n");
986178172Simp	p(ifs6_out_redirect, "\t%ju output redirect%s\n");
987202046Simp	p2(ifs6_out_mldquery, "\t%ju output MLD quer%s\n");
988202046Simp	p(ifs6_out_mldreport, "\t%ju output MLD report%s\n");
989246713Skib	p(ifs6_out_mlddone, "\t%ju output MLD done%s\n");
990246713Skib
991178172Simp  end:
992246713Skib	close(s);
993246713Skib#undef p
994246713Skib}
995246713Skib
996246713Skib/*
997246713Skib * Dump PIM statistics structure.
998246713Skib */
999246713Skibvoid
1000246713Skibpim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1001246713Skib{
1002246713Skib	struct pim6stat pim6stat, zerostat;
1003178172Simp	size_t len = sizeof pim6stat;
1004246713Skib
1005246713Skib	if (live) {
1006246713Skib		if (zflag)
1007178172Simp			memset(&zerostat, 0, len);
1008178172Simp		if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
1009178172Simp		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1010178172Simp			if (errno != ENOENT)
1011178172Simp				warn("sysctl: net.inet6.pim.stats");
1012246713Skib			return;
1013178172Simp		}
1014178172Simp	} else {
1015178172Simp		if (off == 0)
1016246713Skib			return;
1017246713Skib		kread(off, &pim6stat, len);
1018202046Simp	}
1019246713Skib
1020202046Simp	printf("%s:\n", name);
1021178172Simp
1022178172Simp#define	p(f, m) if (pim6stat.f || sflag <= 1) \
1023246713Skib    printf(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1024246713Skib	p(pim6s_rcv_total, "\t%ju message%s received\n");
1025246713Skib	p(pim6s_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
1026178172Simp	p(pim6s_rcv_badsum, "\t%ju message%s received with bad checksum\n");
1027178172Simp	p(pim6s_rcv_badversion, "\t%ju message%s received with bad version\n");
1028178172Simp	p(pim6s_rcv_registers, "\t%ju register%s received\n");
1029178172Simp	p(pim6s_rcv_badregisters, "\t%ju bad register%s received\n");
1030246713Skib	p(pim6s_snd_registers, "\t%ju register%s sent\n");
1031202046Simp#undef p
1032202046Simp}
1033178172Simp
1034178172Simp/*
1035246713Skib * Dump raw ip6 statistics structure.
1036246713Skib */
1037246713Skibvoid
1038178172Simprip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1039178172Simp{
1040246713Skib	struct rip6stat rip6stat, zerostat;
1041246713Skib	u_quad_t delivered;
1042246713Skib	size_t len;
1043178172Simp
1044178172Simp	len = sizeof(rip6stat);
1045178172Simp	if (live) {
1046178172Simp		if (zflag)
1047178172Simp			memset(&zerostat, 0, len);
1048178172Simp		if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
1049178172Simp		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1050178172Simp			if (errno != ENOENT)
1051202046Simp				warn("sysctl: net.inet6.ip6.rip6stats");
1052178172Simp			return;
1053202046Simp		}
1054202046Simp	} else
1055202046Simp		kread_counters(off, &rip6stat, len);
1056202046Simp
1057246713Skib	printf("%s:\n", name);
1058178172Simp
1059178172Simp#define	p(f, m) if (rip6stat.f || sflag <= 1) \
1060178172Simp    printf(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1061202046Simp	p(rip6s_ipackets, "\t%ju message%s received\n");
1062289701Sian	p(rip6s_isum, "\t%ju checksum calculation%s on inbound\n");
1063178172Simp	p(rip6s_badsum, "\t%ju message%s with bad checksum\n");
1064202046Simp	p(rip6s_nosock, "\t%ju message%s dropped due to no socket\n");
1065202046Simp	p(rip6s_nosockmcast,
1066202046Simp	    "\t%ju multicast message%s dropped due to no socket\n");
1067202046Simp	p(rip6s_fullsock,
1068178172Simp	    "\t%ju message%s dropped due to full socket buffers\n");
1069202046Simp	delivered = rip6stat.rip6s_ipackets -
1070202046Simp		    rip6stat.rip6s_badsum -
1071202046Simp		    rip6stat.rip6s_nosock -
1072202046Simp		    rip6stat.rip6s_nosockmcast -
1073202046Simp		    rip6stat.rip6s_fullsock;
1074289701Sian	if (delivered || sflag <= 1)
1075289701Sian		printf("\t%ju delivered\n", (uintmax_t)delivered);
1076289716Sian	p(rip6s_opackets, "\t%ju datagram%s output\n");
1077289716Sian#undef p
1078289716Sian}
1079289716Sian
1080289716Sian/*
1081289716Sian * Pretty print an Internet address (net address + port).
1082289716Sian * Take numeric_addr and numeric_port into consideration.
1083289716Sian */
1084289716Sian#define	GETSERVBYPORT6(port, proto, ret)\
1085289716Sian{\
1086202046Simp	if (strcmp((proto), "tcp6") == 0)\
1087289701Sian		(ret) = getservbyport((int)(port), "tcp");\
1088289701Sian	else if (strcmp((proto), "udp6") == 0)\
1089289701Sian		(ret) = getservbyport((int)(port), "udp");\
1090289701Sian	else\
1091289701Sian		(ret) = getservbyport((int)(port), (proto));\
1092289701Sian};
1093289701Sian
1094289701Sianvoid
1095289701Sianinet6print(struct in6_addr *in6, int port, const char *proto, int numeric)
1096289701Sian{
1097202046Simp	struct servent *sp = 0;
1098178172Simp	char line[80], *cp;
1099202046Simp	int width;
1100202046Simp
1101202046Simp	sprintf(line, "%.*s.", Wflag ? 39 :
1102202046Simp		(Aflag && !numeric) ? 12 : 16, inet6name(in6));
1103202046Simp	cp = strchr(line, '\0');
1104202046Simp	if (!numeric && port)
1105202046Simp		GETSERVBYPORT6(port, proto, sp);
1106202046Simp	if (sp || port == 0)
1107202046Simp		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
1108202046Simp	else
1109246713Skib		sprintf(cp, "%d", ntohs((u_short)port));
1110202046Simp	width = Wflag ? 45 : Aflag ? 18 : 22;
1111202046Simp	printf("%-*.*s ", width, width, line);
1112202046Simp}
1113202046Simp
1114202046Simp/*
1115202046Simp * Construct an Internet address representation.
1116202046Simp * If the numeric_addr has been supplied, give
1117203080Skan * numeric value, otherwise try for symbolic name.
1118203080Skan */
1119203080Skan
1120203080Skanchar *
1121203080Skaninet6name(struct in6_addr *in6p)
1122203080Skan{
1123203080Skan	struct sockaddr_in6 sin6;
1124246713Skib	char hbuf[NI_MAXHOST], *cp;
1125203080Skan	static char line[50];
1126203080Skan	static char domain[MAXHOSTNAMELEN];
1127246713Skib	static int first = 1;
1128202046Simp	int flags, error;
1129202046Simp
1130178172Simp	if (IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1131290082Sadrian		strcpy(line, "*");
1132178172Simp		return (line);
1133178172Simp	}
1134178172Simp	if (first && !numeric_addr) {
1135202046Simp		first = 0;
1136202046Simp		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1137202046Simp		    (cp = strchr(domain, '.')))
1138202046Simp			(void) strcpy(domain, cp + 1);
1139202046Simp		else
1140202046Simp			domain[0] = 0;
1141202046Simp	}
1142246713Skib	memset(&sin6, 0, sizeof(sin6));
1143202046Simp	memcpy(&sin6.sin6_addr, in6p, sizeof(*in6p));
1144202046Simp	sin6.sin6_family = AF_INET6;
1145202046Simp	/* XXX: in6p.s6_addr[2] can contain scopeid. */
1146202046Simp	in6_fillscopeid(&sin6);
1147202046Simp	flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1148202046Simp	error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1149202046Simp	    sizeof(hbuf), NULL, 0, flags);
1150203080Skan	if (error == 0) {
1151203080Skan		if ((flags & NI_NUMERICHOST) == 0 &&
1152203080Skan		    (cp = strchr(hbuf, '.')) &&
1153203080Skan		    !strcmp(cp + 1, domain))
1154203080Skan			*cp = 0;
1155203080Skan		strcpy(line, hbuf);
1156203080Skan	} else {
1157246713Skib		/* XXX: this should not happen. */
1158203080Skan		sprintf(line, "%s",
1159203080Skan			inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,
1160246713Skib				sizeof(ntop_buf)));
1161178172Simp	}
1162178172Simp	return (line);
1163178172Simp}
1164246713Skib#endif /*INET6*/
1165178172Simp