GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/netstat/inet6.c Lines: 0 226 0.0 %
Date: 2017-11-07 Branches: 0 353 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: inet6.c,v 1.52 2017/01/21 11:32:04 guenther Exp $	*/
2
/*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
3
/*
4
 * Copyright (c) 1983, 1988, 1993
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 * 3. Neither the name of the University nor the names of its contributors
16
 *    may be used to endorse or promote products derived from this software
17
 *    without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
#include <sys/types.h>
33
#include <sys/socket.h>
34
#include <sys/socketvar.h>
35
#include <sys/ioctl.h>
36
#include <sys/protosw.h>
37
#include <sys/sysctl.h>
38
39
#include <net/route.h>
40
#include <net/if.h>
41
#include <netinet/in.h>
42
#include <netinet/ip6.h>
43
#include <netinet/icmp6.h>
44
#include <netinet/ip.h>
45
#include <netinet/ip_var.h>
46
#include <netinet6/ip6_var.h>
47
#include <netinet6/in6_var.h>
48
#include <netinet6/raw_ip6.h>
49
#include <netinet6/ip6_divert.h>
50
51
#include <arpa/inet.h>
52
#include <netdb.h>
53
54
#include <err.h>
55
#include <errno.h>
56
#include <stdio.h>
57
#include <string.h>
58
#include <unistd.h>
59
#include <limits.h>
60
#include "netstat.h"
61
62
struct	socket sockb;
63
64
char	*inet6name(struct in6_addr *);
65
66
static	char *ip6nh[] = {
67
	"hop by hop",
68
	"ICMP",
69
	"IGMP",
70
	"#3",
71
	"IP",
72
	"#5",
73
	"TCP",
74
	"#7",
75
	"#8",
76
	"#9",
77
	"#10",
78
	"#11",
79
	"#12",
80
	"#13",
81
	"#14",
82
	"#15",
83
	"#16",
84
	"UDP",
85
	"#18",
86
	"#19",
87
	"#20",
88
	"#21",
89
	"IDP",
90
	"#23",
91
	"#24",
92
	"#25",
93
	"#26",
94
	"#27",
95
	"#28",
96
	"TP",
97
	"#30",
98
	"#31",
99
	"#32",
100
	"#33",
101
	"#34",
102
	"#35",
103
	"#36",
104
	"#37",
105
	"#38",
106
	"#39",
107
	"#40",
108
	"IP6",
109
	"#42",
110
	"routing",
111
	"fragment",
112
	"#45",
113
	"#46",
114
	"#47",
115
	"#48",
116
	"#49",
117
	"ESP",
118
	"AH",
119
	"#52",
120
	"#53",
121
	"#54",
122
	"#55",
123
	"#56",
124
	"#57",
125
	"ICMP6",
126
	"no next header",
127
	"destination option",
128
	"#61",
129
	"#62",
130
	"#63",
131
	"#64",
132
	"#65",
133
	"#66",
134
	"#67",
135
	"#68",
136
	"#69",
137
	"#70",
138
	"#71",
139
	"#72",
140
	"#73",
141
	"#74",
142
	"#75",
143
	"#76",
144
	"#77",
145
	"#78",
146
	"#79",
147
	"ISOIP",
148
	"#81",
149
	"#82",
150
	"#83",
151
	"#84",
152
	"#85",
153
	"#86",
154
	"#87",
155
	"#88",
156
	"OSPF",
157
	"#80",
158
	"#91",
159
	"#92",
160
	"#93",
161
	"#94",
162
	"#95",
163
	"#96",
164
	"Ethernet",
165
	"#98",
166
	"#99",
167
	"#100",
168
	"#101",
169
	"#102",
170
	"#103",
171
	"#104",
172
	"#105",
173
	"#106",
174
	"#107",
175
	"#108",
176
	"#109",
177
	"#110",
178
	"#111",
179
	"#112",
180
	"#113",
181
	"#114",
182
	"#115",
183
	"#116",
184
	"#117",
185
	"#118",
186
	"#119",
187
	"#120",
188
	"#121",
189
	"#122",
190
	"#123",
191
	"#124",
192
	"#125",
193
	"#126",
194
	"#127",
195
	"#128",
196
	"#129",
197
	"#130",
198
	"#131",
199
	"#132",
200
	"#133",
201
	"#134",
202
	"#135",
203
	"#136",
204
	"#137",
205
	"#138",
206
	"#139",
207
	"#140",
208
	"#141",
209
	"#142",
210
	"#143",
211
	"#144",
212
	"#145",
213
	"#146",
214
	"#147",
215
	"#148",
216
	"#149",
217
	"#150",
218
	"#151",
219
	"#152",
220
	"#153",
221
	"#154",
222
	"#155",
223
	"#156",
224
	"#157",
225
	"#158",
226
	"#159",
227
	"#160",
228
	"#161",
229
	"#162",
230
	"#163",
231
	"#164",
232
	"#165",
233
	"#166",
234
	"#167",
235
	"#168",
236
	"#169",
237
	"#170",
238
	"#171",
239
	"#172",
240
	"#173",
241
	"#174",
242
	"#175",
243
	"#176",
244
	"#177",
245
	"#178",
246
	"#179",
247
	"#180",
248
	"#181",
249
	"#182",
250
	"#183",
251
	"#184",
252
	"#185",
253
	"#186",
254
	"#187",
255
	"#188",
256
	"#189",
257
	"#180",
258
	"#191",
259
	"#192",
260
	"#193",
261
	"#194",
262
	"#195",
263
	"#196",
264
	"#197",
265
	"#198",
266
	"#199",
267
	"#200",
268
	"#201",
269
	"#202",
270
	"#203",
271
	"#204",
272
	"#205",
273
	"#206",
274
	"#207",
275
	"#208",
276
	"#209",
277
	"#210",
278
	"#211",
279
	"#212",
280
	"#213",
281
	"#214",
282
	"#215",
283
	"#216",
284
	"#217",
285
	"#218",
286
	"#219",
287
	"#220",
288
	"#221",
289
	"#222",
290
	"#223",
291
	"#224",
292
	"#225",
293
	"#226",
294
	"#227",
295
	"#228",
296
	"#229",
297
	"#230",
298
	"#231",
299
	"#232",
300
	"#233",
301
	"#234",
302
	"#235",
303
	"#236",
304
	"#237",
305
	"#238",
306
	"#239",
307
	"#240",
308
	"#241",
309
	"#242",
310
	"#243",
311
	"#244",
312
	"#245",
313
	"#246",
314
	"#247",
315
	"#248",
316
	"#249",
317
	"#250",
318
	"#251",
319
	"#252",
320
	"#253",
321
	"#254",
322
	"#255",
323
};
324
325
/*
326
 * Dump IP6 statistics structure.
327
 */
328
void
329
ip6_stats(char *name)
330
{
331
	struct ip6stat ip6stat;
332
	int first, i;
333
	struct protoent *ep;
334
	const char *n;
335
	int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_STATS };
336
	size_t len = sizeof(ip6stat);
337
338
	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
339
	    &ip6stat, &len, NULL, 0) == -1) {
340
		if (errno != ENOPROTOOPT)
341
			warn("%s", name);
342
		return;
343
	}
344
345
	printf("%s:\n", name);
346
#define	p(f, m) if (ip6stat.f || sflag <= 1) \
347
	printf(m, (unsigned long long)ip6stat.f, plural(ip6stat.f))
348
#define	p1(f, m) if (ip6stat.f || sflag <= 1) \
349
	printf(m, (unsigned long long)ip6stat.f)
350
351
	p(ip6s_total, "\t%llu total packet%s received\n");
352
	p1(ip6s_toosmall, "\t%llu with size smaller than minimum\n");
353
	p1(ip6s_tooshort, "\t%llu with data size < data length\n");
354
	p1(ip6s_badoptions, "\t%llu with bad options\n");
355
	p1(ip6s_badvers, "\t%llu with incorrect version number\n");
356
	p(ip6s_fragments, "\t%llu fragment%s received\n");
357
	p(ip6s_fragdropped,
358
	    "\t%llu fragment%s dropped (duplicates or out of space)\n");
359
	p(ip6s_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
360
	p(ip6s_fragoverflow, "\t%llu fragment%s that exceeded limit\n");
361
	p(ip6s_reassembled, "\t%llu packet%s reassembled ok\n");
362
	p(ip6s_delivered, "\t%llu packet%s for this host\n");
363
	p(ip6s_forward, "\t%llu packet%s forwarded\n");
364
	p(ip6s_cantforward, "\t%llu packet%s not forwardable\n");
365
	p(ip6s_redirectsent, "\t%llu redirect%s sent\n");
366
	p(ip6s_localout, "\t%llu packet%s sent from this host\n");
367
	p(ip6s_rawout, "\t%llu packet%s sent with fabricated ip header\n");
368
	p(ip6s_odropped,
369
	    "\t%llu output packet%s dropped due to no bufs, etc.\n");
370
	p(ip6s_noroute, "\t%llu output packet%s discarded due to no route\n");
371
	p(ip6s_fragmented, "\t%llu output datagram%s fragmented\n");
372
	p(ip6s_ofragments, "\t%llu fragment%s created\n");
373
	p(ip6s_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
374
	p(ip6s_badscope, "\t%llu packet%s that violated scope rules\n");
375
	p(ip6s_notmember, "\t%llu multicast packet%s which we don't join\n");
376
	for (first = 1, i = 0; i < 256; i++)
377
		if (ip6stat.ip6s_nxthist[i] != 0) {
378
			if (first) {
379
				printf("\tInput packet histogram:\n");
380
				first = 0;
381
			}
382
			n = NULL;
383
			if (ip6nh[i])
384
				n = ip6nh[i];
385
			else if ((ep = getprotobynumber(i)) != NULL)
386
				n = ep->p_name;
387
			if (n)
388
				printf("\t\t%s: %llu\n", n,
389
				    (unsigned long long)ip6stat.ip6s_nxthist[i]);
390
			else
391
				printf("\t\t#%d: %llu\n", i,
392
				    (unsigned long long)ip6stat.ip6s_nxthist[i]);
393
		}
394
	printf("\tMbuf statistics:\n");
395
	p(ip6s_m1, "\t\t%llu one mbuf%s\n");
396
	for (first = 1, i = 0; i < 32; i++) {
397
		char ifbuf[IFNAMSIZ];
398
		if (ip6stat.ip6s_m2m[i] != 0) {
399
			if (first) {
400
				printf("\t\ttwo or more mbuf:\n");
401
				first = 0;
402
			}
403
			printf("\t\t\t%s = %llu\n",
404
			    if_indextoname(i, ifbuf),
405
			    (unsigned long long)ip6stat.ip6s_m2m[i]);
406
		}
407
	}
408
	p(ip6s_mext1, "\t\t%llu one ext mbuf%s\n");
409
	p(ip6s_mext2m, "\t\t%llu two or more ext mbuf%s\n");
410
	p(ip6s_nogif, "\t%llu tunneling packet%s that can't find gif\n");
411
	p(ip6s_toomanyhdr,
412
	    "\t%llu packet%s discarded due to too many headers\n");
413
414
	/* for debugging source address selection */
415
#define PRINT_SCOPESTAT(s,i) do {\
416
		switch(i) { /* XXX hardcoding in each case */\
417
		case 1:\
418
			p(s, "\t\t%llu node-local%s\n");\
419
			break;\
420
		case 2:\
421
			p(s, "\t\t%llu link-local%s\n");\
422
			break;\
423
		case 5:\
424
			p(s, "\t\t%llu site-local%s\n");\
425
			break;\
426
		case 14:\
427
			p(s, "\t\t%llu global%s\n");\
428
			break;\
429
		default:\
430
			printf("\t\t%llu addresses scope=%x\n",\
431
			    (unsigned long long)ip6stat.s, i);\
432
		}\
433
	} while(0);
434
435
	p(ip6s_sources_none,
436
	    "\t%llu failure%s of source address selection\n");
437
	for (first = 1, i = 0; i < 16; i++) {
438
		if (ip6stat.ip6s_sources_sameif[i]) {
439
			if (first) {
440
				printf("\tsource addresses on an outgoing I/F\n");
441
				first = 0;
442
			}
443
			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
444
		}
445
	}
446
	for (first = 1, i = 0; i < 16; i++) {
447
		if (ip6stat.ip6s_sources_otherif[i]) {
448
			if (first) {
449
				printf("\tsource addresses on a non-outgoing I/F\n");
450
				first = 0;
451
			}
452
			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
453
		}
454
	}
455
	for (first = 1, i = 0; i < 16; i++) {
456
		if (ip6stat.ip6s_sources_samescope[i]) {
457
			if (first) {
458
				printf("\tsource addresses of same scope\n");
459
				first = 0;
460
			}
461
			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
462
		}
463
	}
464
	for (first = 1, i = 0; i < 16; i++) {
465
		if (ip6stat.ip6s_sources_otherscope[i]) {
466
			if (first) {
467
				printf("\tsource addresses of a different scope\n");
468
				first = 0;
469
			}
470
			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
471
		}
472
	}
473
	for (first = 1, i = 0; i < 16; i++) {
474
		if (ip6stat.ip6s_sources_deprecated[i]) {
475
			if (first) {
476
				printf("\tdeprecated source addresses\n");
477
				first = 0;
478
			}
479
			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
480
		}
481
	}
482
483
	p1(ip6s_forward_cachehit, "\t%llu forward cache hit\n");
484
	p1(ip6s_forward_cachemiss, "\t%llu forward cache miss\n");
485
#undef p
486
#undef p1
487
}
488
489
static	char *icmp6names[] = {
490
	"#0",
491
	"unreach",
492
	"packet too big",
493
	"time exceed",
494
	"parameter problem",
495
	"#5",
496
	"#6",
497
	"#7",
498
	"#8",
499
	"#9",
500
	"#10",
501
	"#11",
502
	"#12",
503
	"#13",
504
	"#14",
505
	"#15",
506
	"#16",
507
	"#17",
508
	"#18",
509
	"#19",
510
	"#20",
511
	"#21",
512
	"#22",
513
	"#23",
514
	"#24",
515
	"#25",
516
	"#26",
517
	"#27",
518
	"#28",
519
	"#29",
520
	"#30",
521
	"#31",
522
	"#32",
523
	"#33",
524
	"#34",
525
	"#35",
526
	"#36",
527
	"#37",
528
	"#38",
529
	"#39",
530
	"#40",
531
	"#41",
532
	"#42",
533
	"#43",
534
	"#44",
535
	"#45",
536
	"#46",
537
	"#47",
538
	"#48",
539
	"#49",
540
	"#50",
541
	"#51",
542
	"#52",
543
	"#53",
544
	"#54",
545
	"#55",
546
	"#56",
547
	"#57",
548
	"#58",
549
	"#59",
550
	"#60",
551
	"#61",
552
	"#62",
553
	"#63",
554
	"#64",
555
	"#65",
556
	"#66",
557
	"#67",
558
	"#68",
559
	"#69",
560
	"#70",
561
	"#71",
562
	"#72",
563
	"#73",
564
	"#74",
565
	"#75",
566
	"#76",
567
	"#77",
568
	"#78",
569
	"#79",
570
	"#80",
571
	"#81",
572
	"#82",
573
	"#83",
574
	"#84",
575
	"#85",
576
	"#86",
577
	"#87",
578
	"#88",
579
	"#89",
580
	"#80",
581
	"#91",
582
	"#92",
583
	"#93",
584
	"#94",
585
	"#95",
586
	"#96",
587
	"#97",
588
	"#98",
589
	"#99",
590
	"#100",
591
	"#101",
592
	"#102",
593
	"#103",
594
	"#104",
595
	"#105",
596
	"#106",
597
	"#107",
598
	"#108",
599
	"#109",
600
	"#110",
601
	"#111",
602
	"#112",
603
	"#113",
604
	"#114",
605
	"#115",
606
	"#116",
607
	"#117",
608
	"#118",
609
	"#119",
610
	"#120",
611
	"#121",
612
	"#122",
613
	"#123",
614
	"#124",
615
	"#125",
616
	"#126",
617
	"#127",
618
	"echo",
619
	"echo reply",
620
	"multicast listener query",
621
	"multicast listener report",
622
	"multicast listener done",
623
	"router solicitation",
624
	"router advertisement",
625
	"neighbor solicitation",
626
	"neighbor advertisement",
627
	"redirect",
628
	"router renumbering",
629
	"node information request",
630
	"node information reply",
631
	"#141",
632
	"#142",
633
	"#143",
634
	"#144",
635
	"#145",
636
	"#146",
637
	"#147",
638
	"#148",
639
	"#149",
640
	"#150",
641
	"#151",
642
	"#152",
643
	"#153",
644
	"#154",
645
	"#155",
646
	"#156",
647
	"#157",
648
	"#158",
649
	"#159",
650
	"#160",
651
	"#161",
652
	"#162",
653
	"#163",
654
	"#164",
655
	"#165",
656
	"#166",
657
	"#167",
658
	"#168",
659
	"#169",
660
	"#170",
661
	"#171",
662
	"#172",
663
	"#173",
664
	"#174",
665
	"#175",
666
	"#176",
667
	"#177",
668
	"#178",
669
	"#179",
670
	"#180",
671
	"#181",
672
	"#182",
673
	"#183",
674
	"#184",
675
	"#185",
676
	"#186",
677
	"#187",
678
	"#188",
679
	"#189",
680
	"#180",
681
	"#191",
682
	"#192",
683
	"#193",
684
	"#194",
685
	"#195",
686
	"#196",
687
	"#197",
688
	"#198",
689
	"#199",
690
	"#200",
691
	"#201",
692
	"#202",
693
	"#203",
694
	"#204",
695
	"#205",
696
	"#206",
697
	"#207",
698
	"#208",
699
	"#209",
700
	"#210",
701
	"#211",
702
	"#212",
703
	"#213",
704
	"#214",
705
	"#215",
706
	"#216",
707
	"#217",
708
	"#218",
709
	"#219",
710
	"#220",
711
	"#221",
712
	"#222",
713
	"#223",
714
	"#224",
715
	"#225",
716
	"#226",
717
	"#227",
718
	"#228",
719
	"#229",
720
	"#230",
721
	"#231",
722
	"#232",
723
	"#233",
724
	"#234",
725
	"#235",
726
	"#236",
727
	"#237",
728
	"#238",
729
	"#239",
730
	"#240",
731
	"#241",
732
	"#242",
733
	"#243",
734
	"#244",
735
	"#245",
736
	"#246",
737
	"#247",
738
	"#248",
739
	"#249",
740
	"#250",
741
	"#251",
742
	"#252",
743
	"#253",
744
	"#254",
745
	"#255",
746
};
747
748
/*
749
 * Dump ICMPv6 statistics.
750
 */
751
void
752
icmp6_stats(char *name)
753
{
754
	struct icmp6stat icmp6stat;
755
	int i, first;
756
	int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_STATS };
757
	size_t len = sizeof(icmp6stat);
758
759
	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
760
	    &icmp6stat, &len, NULL, 0) == -1) {
761
		if (errno != ENOPROTOOPT)
762
			warn("%s", name);
763
		return;
764
	}
765
766
	printf("%s:\n", name);
767
#define	p(f, m) if (icmp6stat.f || sflag <= 1) \
768
	printf(m, (unsigned long long)icmp6stat.f, plural(icmp6stat.f))
769
#define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
770
	printf(m, (unsigned long long)icmp6stat.f)
771
772
	p(icp6s_error, "\t%llu call%s to icmp6_error\n");
773
	p(icp6s_canterror,
774
	    "\t%llu error%s not generated because old message was icmp6 or so\n");
775
	p(icp6s_toofreq,
776
	    "\t%llu error%s not generated because of rate limitation\n");
777
	for (first = 1, i = 0; i < 256; i++)
778
		if (icmp6stat.icp6s_outhist[i] != 0) {
779
			if (first) {
780
				printf("\tOutput packet histogram:\n");
781
				first = 0;
782
			}
783
			printf("\t\t%s: %llu\n", icmp6names[i],
784
			    (unsigned long long)icmp6stat.icp6s_outhist[i]);
785
		}
786
	p(icp6s_badcode, "\t%llu message%s with bad code fields\n");
787
	p(icp6s_tooshort, "\t%llu message%s < minimum length\n");
788
	p(icp6s_checksum, "\t%llu bad checksum%s\n");
789
	p(icp6s_badlen, "\t%llu message%s with bad length\n");
790
	for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
791
		if (icmp6stat.icp6s_inhist[i] != 0) {
792
			if (first) {
793
				printf("\tInput packet histogram:\n");
794
				first = 0;
795
			}
796
			printf("\t\t%s: %llu\n", icmp6names[i],
797
			    (unsigned long long)icmp6stat.icp6s_inhist[i]);
798
		}
799
	printf("\tHistogram of error messages to be generated:\n");
800
	p_5(icp6s_odst_unreach_noroute, "\t\t%llu no route\n");
801
	p_5(icp6s_odst_unreach_admin, "\t\t%llu administratively prohibited\n");
802
	p_5(icp6s_odst_unreach_beyondscope, "\t\t%llu beyond scope\n");
803
	p_5(icp6s_odst_unreach_addr, "\t\t%llu address unreachable\n");
804
	p_5(icp6s_odst_unreach_noport, "\t\t%llu port unreachable\n");
805
	p_5(icp6s_opacket_too_big, "\t\t%llu packet too big\n");
806
	p_5(icp6s_otime_exceed_transit, "\t\t%llu time exceed transit\n");
807
	p_5(icp6s_otime_exceed_reassembly, "\t\t%llu time exceed reassembly\n");
808
	p_5(icp6s_oparamprob_header, "\t\t%llu erroneous header field\n");
809
	p_5(icp6s_oparamprob_nextheader, "\t\t%llu unrecognized next header\n");
810
	p_5(icp6s_oparamprob_option, "\t\t%llu unrecognized option\n");
811
	p_5(icp6s_oredirect, "\t\t%llu redirect\n");
812
	p_5(icp6s_ounknown, "\t\t%llu unknown\n");
813
814
	p(icp6s_reflect, "\t%llu message response%s generated\n");
815
	p(icp6s_nd_toomanyopt, "\t%llu message%s with too many ND options\n");
816
	p(icp6s_nd_badopt, "\t%llu message%s with bad ND options\n");
817
	p(icp6s_badns, "\t%llu bad neighbor solicitation message%s\n");
818
	p(icp6s_badna, "\t%llu bad neighbor advertisement message%s\n");
819
	p(icp6s_badrs, "\t%llu bad router solicitation message%s\n");
820
	p(icp6s_badra, "\t%llu bad router advertisement message%s\n");
821
	p(icp6s_badredirect, "\t%llu bad redirect message%s\n");
822
	p(icp6s_pmtuchg, "\t%llu path MTU change%s\n");
823
#undef p
824
#undef p_5
825
}
826
827
/*
828
 * Dump raw ip6 statistics structure.
829
 */
830
void
831
rip6_stats(char *name)
832
{
833
	struct rip6stat rip6stat;
834
	u_int64_t delivered;
835
	int mib[] = { CTL_NET, PF_INET6, IPPROTO_RAW, RIPV6CTL_STATS };
836
	size_t len = sizeof(rip6stat);
837
838
	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
839
	    &rip6stat, &len, NULL, 0) == -1) {
840
		if (errno != ENOPROTOOPT)
841
			warn("%s", name);
842
		return;
843
	}
844
845
	printf("%s:\n", name);
846
847
#define	p(f, m) if (rip6stat.f || sflag <= 1) \
848
    printf(m, (unsigned long long)rip6stat.f, plural(rip6stat.f))
849
	p(rip6s_ipackets, "\t%llu message%s received\n");
850
	p(rip6s_isum, "\t%llu checksum calculation%s on inbound\n");
851
	p(rip6s_badsum, "\t%llu message%s with bad checksum\n");
852
	p(rip6s_nosock, "\t%llu message%s dropped due to no socket\n");
853
	p(rip6s_nosockmcast,
854
	    "\t%llu multicast message%s dropped due to no socket\n");
855
	p(rip6s_fullsock,
856
	    "\t%llu message%s dropped due to full socket buffers\n");
857
	delivered = rip6stat.rip6s_ipackets -
858
		    rip6stat.rip6s_badsum -
859
		    rip6stat.rip6s_nosock -
860
		    rip6stat.rip6s_nosockmcast -
861
		    rip6stat.rip6s_fullsock;
862
	if (delivered || sflag <= 1)
863
		printf("\t%llu delivered\n", (unsigned long long)delivered);
864
	p(rip6s_opackets, "\t%llu datagram%s output\n");
865
#undef p
866
}
867
868
/*
869
 * Dump divert6 statistics structure.
870
 */
871
void
872
div6_stats(char *name)
873
{
874
	struct div6stat div6stat;
875
	int mib[] = { CTL_NET, PF_INET6, IPPROTO_DIVERT, DIVERT6CTL_STATS };
876
	size_t len = sizeof(div6stat);
877
878
	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
879
	    &div6stat, &len, NULL, 0) == -1) {
880
		if (errno != ENOPROTOOPT)
881
			warn("%s", name);
882
		return;
883
	}
884
885
	printf("%s:\n", name);
886
#define p(f, m) if (div6stat.f || sflag <= 1) \
887
    printf(m, div6stat.f, plural(div6stat.f))
888
#define p1(f, m) if (div6stat.f || sflag <= 1) \
889
    printf(m, div6stat.f)
890
	p(divs_ipackets, "\t%lu total packet%s received\n");
891
	p1(divs_noport, "\t%lu dropped due to no socket\n");
892
	p1(divs_fullsock, "\t%lu dropped due to full socket buffers\n");
893
	p(divs_opackets, "\t%lu packet%s output\n");
894
	p1(divs_errors, "\t%lu errors\n");
895
#undef p
896
#undef p1
897
}
898
899
/*
900
 * Pretty print an Internet address (net address + port).
901
 * If the nflag was specified, use numbers instead of names.
902
 */
903
904
void
905
inet6print(struct in6_addr *in6, int port, const char *proto)
906
{
907
908
#define GETSERVBYPORT6(port, proto, ret) do { \
909
	if (strcmp((proto), "tcp6") == 0) \
910
		(ret) = getservbyport((int)(port), "tcp"); \
911
	else if (strcmp((proto), "udp6") == 0) \
912
		(ret) = getservbyport((int)(port), "udp"); \
913
	else \
914
		(ret) = getservbyport((int)(port), (proto)); \
915
	} while (0)
916
917
	struct servent *sp = 0;
918
	char line[80], *cp;
919
	int width;
920
	int len = sizeof line;
921
922
	width = Aflag ? 12 : 16;
923
	if (vflag && width < strlen(inet6name(in6)))
924
		width = strlen(inet6name(in6));
925
	snprintf(line, len, "%.*s.", width, inet6name(in6));
926
	len -= strlen(line);
927
	if (len <= 0)
928
		goto bail;
929
930
	cp = strchr(line, '\0');
931
	if (!nflag && port)
932
		GETSERVBYPORT6(port, proto, sp);
933
	if (sp || port == 0)
934
		snprintf(cp, len, "%.8s", sp ? sp->s_name : "*");
935
	else
936
		snprintf(cp, len, "%d", ntohs((u_short)port));
937
	width = Aflag ? 18 : 22;
938
	if (vflag && width < strlen(line))
939
		width = strlen(line);
940
bail:
941
	printf(" %-*.*s", width, width, line);
942
}
943
944
/*
945
 * Construct an Internet address representation.
946
 * If the nflag has been supplied, give
947
 * numeric value, otherwise try for symbolic name.
948
 */
949
950
char *
951
inet6name(struct in6_addr *in6p)
952
{
953
	char *cp;
954
	static char line[NI_MAXHOST];
955
	struct hostent *hp;
956
	static char domain[HOST_NAME_MAX+1];
957
	static int first = 1;
958
	char hbuf[NI_MAXHOST];
959
	struct sockaddr_in6 sin6;
960
	const int niflag = NI_NUMERICHOST;
961
962
	if (first && !nflag) {
963
		first = 0;
964
		if (gethostname(domain, sizeof(domain)) == 0 &&
965
		    (cp = strchr(domain, '.')))
966
			(void) strlcpy(domain, cp + 1, sizeof domain);
967
		else
968
			domain[0] = '\0';
969
	}
970
	cp = 0;
971
	if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
972
		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
973
		if (hp) {
974
			if ((cp = strchr(hp->h_name, '.')) &&
975
			    !strcmp(cp + 1, domain))
976
				*cp = 0;
977
			cp = hp->h_name;
978
		}
979
	}
980
	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
981
		strlcpy(line, "*", sizeof(line));
982
	else if (cp)
983
		strlcpy(line, cp, sizeof(line));
984
	else {
985
		memset(&sin6, 0, sizeof(sin6));
986
		sin6.sin6_family = AF_INET6;
987
		sin6.sin6_addr = *in6p;
988
#ifdef __KAME__
989
		if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
990
		    IN6_IS_ADDR_MC_LINKLOCAL(in6p) ||
991
		    IN6_IS_ADDR_MC_INTFACELOCAL(in6p)) {
992
			sin6.sin6_scope_id =
993
			    ntohs(*(u_int16_t *)&in6p->s6_addr[2]);
994
			sin6.sin6_addr.s6_addr[2] = 0;
995
			sin6.sin6_addr.s6_addr[3] = 0;
996
		}
997
#endif
998
		if (getnameinfo((struct sockaddr *)&sin6, sizeof(sin6),
999
		    hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
1000
			strlcpy(hbuf, "?", sizeof hbuf);
1001
		strlcpy(line, hbuf, sizeof(line));
1002
	}
1003
	return (line);
1004
}