GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/netstat/inet6.c Lines: 0 225 0.0 %
Date: 2016-12-06 Branches: 0 581 0.0 %

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