1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1980, 1992, 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
33
34/* From:
35	"Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp"
36*/
37
38#ifdef INET6
39#include <sys/param.h>
40#include <sys/types.h>
41#include <sys/socket.h>
42#include <sys/sysctl.h>
43
44#include <netinet/in.h>
45#include <netinet/icmp6.h>
46
47#include <inttypes.h>
48#include <stdlib.h>
49#include <string.h>
50#include <paths.h>
51#include "systat.h"
52#include "extern.h"
53#include "mode.h"
54
55static struct icmp6stat icmp6stat, initstat, oldstat;
56
57/*-
58--0         1         2         3         4         5         6         7
59--0123456789012345678901234567890123456789012345678901234567890123456789012345
6000          ICMPv6 Input                       ICMPv6 Output
6101999999999 total messages           999999999 total messages
6202999999999 with bad code            999999999 errors generated
6303999999999 with bad length          999999999 suppressed - original too short
6404999999999 with bad checksum        999999999 suppressed - original was ICMP
6505999999999 with insufficient data   999999999 responses sent
6606
6707          Input Histogram                    Output Histogram
6808999999999 echo response            999999999 echo response
6909999999999 echo request             999999999 echo request
7010999999999 destination unreachable  999999999 destination unreachable
7111999999999 redirect                 999999999 redirect
7212999999999 time-to-live exceeded    999999999 time-to-line exceeded
7313999999999 parameter problem        999999999 parameter problem
7414999999999 neighbor solicitation    999999999 neighbor solicitation
7515999999999 neighbor advertisement   999999999 neighbor advertisement
7616999999999 router advertisement     999999999 router solicitation
7717
7818
79--0123456789012345678901234567890123456789012345678901234567890123456789012345
80--0         1         2         3         4         5         6         7
81*/
82
83WINDOW *
84openicmp6(void)
85{
86	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
87}
88
89void
90closeicmp6(WINDOW *w)
91{
92	if (w == NULL)
93		return;
94	wclear(w);
95	wrefresh(w);
96	delwin(w);
97}
98
99void
100labelicmp6(void)
101{
102	wmove(wnd, 0, 0); wclrtoeol(wnd);
103#define L(row, str) mvwprintw(wnd, row, 10, str)
104#define R(row, str) mvwprintw(wnd, row, 45, str);
105	L(0, "ICMPv6 Input");		R(0, "ICMPv6 Output");
106	L(1, "total messages");		R(1, "total messages");
107	L(2, "with bad code");		R(2, "errors generated");
108	L(3, "with bad length");	R(3, "suppressed - original too short");
109	L(4, "with bad checksum");	R(4, "suppressed - original was ICMP");
110	L(5, "with insufficient data");	R(5, "responses sent");
111
112	L(7, "Input Histogram");	R(7, "Output Histogram");
113#define B(row, str) L(row, str); R(row, str)
114	B(8, "echo response");
115	B(9, "echo request");
116	B(10, "destination unreachable");
117	B(11, "redirect");
118	B(12, "time-to-live exceeded");
119	B(13, "parameter problem");
120	B(14, "neighbor solicitation");
121	B(15, "neighbor advertisement");
122	L(16, "router advertisement");	R(16, "router solicitation");
123#undef L
124#undef R
125#undef B
126}
127
128static void
129domode(struct icmp6stat *ret)
130{
131	const struct icmp6stat *sub;
132	int i, divisor = 1;
133
134	switch(currentmode) {
135	case display_RATE:
136		sub = &oldstat;
137		divisor = (delay > 1000000) ? delay / 1000000 : 1;
138		break;
139	case display_DELTA:
140		sub = &oldstat;
141		break;
142	case display_SINCE:
143		sub = &initstat;
144		break;
145	default:
146		*ret = icmp6stat;
147		return;
148	}
149#define DO(stat) ret->stat = (icmp6stat.stat - sub->stat) / divisor
150	DO(icp6s_error);
151	DO(icp6s_tooshort);
152	DO(icp6s_canterror);
153	for (i = 0; i <= ICMP6_MAXTYPE; i++) {
154		DO(icp6s_outhist[i]);
155	}
156	DO(icp6s_badcode);
157	DO(icp6s_tooshort);
158	DO(icp6s_checksum);
159	DO(icp6s_badlen);
160	DO(icp6s_reflect);
161	for (i = 0; i <= ICMP6_MAXTYPE; i++) {
162		DO(icp6s_inhist[i]);
163	}
164#undef DO
165}
166
167void
168showicmp6(void)
169{
170	struct icmp6stat stats;
171	uint64_t totalin, totalout;
172	int i;
173
174	memset(&stats, 0, sizeof stats);
175	domode(&stats);
176	for (i = totalin = totalout = 0; i <= ICMP6_MAXTYPE; i++) {
177		totalin += stats.icp6s_inhist[i];
178		totalout += stats.icp6s_outhist[i];
179	}
180	totalin += stats.icp6s_badcode + stats.icp6s_badlen +
181		stats.icp6s_checksum + stats.icp6s_tooshort;
182	mvwprintw(wnd, 1, 0, "%9"PRIu64, totalin);
183	mvwprintw(wnd, 1, 35, "%9"PRIu64, totalout);
184
185#define DO(stat, row, col) \
186	mvwprintw(wnd, row, col, "%9"PRIu64, stats.stat)
187
188	DO(icp6s_badcode, 2, 0);
189	DO(icp6s_badlen, 3, 0);
190	DO(icp6s_checksum, 4, 0);
191	DO(icp6s_tooshort, 5, 0);
192	DO(icp6s_error, 2, 35);
193	DO(icp6s_tooshort, 3, 35);
194	DO(icp6s_canterror, 4, 35);
195	DO(icp6s_reflect, 5, 35);
196#define DO2(type, row) DO(icp6s_inhist[type], row, 0); DO(icp6s_outhist[type], \
197							 row, 35)
198	DO2(ICMP6_ECHO_REPLY, 8);
199	DO2(ICMP6_ECHO_REQUEST, 9);
200	DO2(ICMP6_DST_UNREACH, 10);
201	DO2(ND_REDIRECT, 11);
202	DO2(ICMP6_TIME_EXCEEDED, 12);
203	DO2(ICMP6_PARAM_PROB, 13);
204	DO2(ND_NEIGHBOR_SOLICIT, 14);
205	DO2(ND_NEIGHBOR_ADVERT, 15);
206	DO(icp6s_inhist[ND_ROUTER_SOLICIT], 16, 0);
207	DO(icp6s_outhist[ND_ROUTER_ADVERT], 16, 35);
208#undef DO
209#undef DO2
210}
211
212int
213initicmp6(void)
214{
215	size_t len;
216	int name[4];
217
218	name[0] = CTL_NET;
219	name[1] = PF_INET6;
220	name[2] = IPPROTO_ICMPV6;
221	name[3] = ICMPV6CTL_STATS;
222
223	len = 0;
224	if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
225		error("sysctl getting icmp6stat size failed");
226		return 0;
227	}
228	if (len > sizeof icmp6stat) {
229		error("icmp6stat structure has grown--recompile systat!");
230		return 0;
231	}
232	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
233		error("sysctl getting icmp6stat size failed");
234		return 0;
235	}
236	oldstat = initstat;
237	return 1;
238}
239
240void
241reseticmp6(void)
242{
243	size_t len;
244	int name[4];
245
246	name[0] = CTL_NET;
247	name[1] = PF_INET6;
248	name[2] = IPPROTO_ICMPV6;
249	name[3] = ICMPV6CTL_STATS;
250
251	len = sizeof initstat;
252	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
253		error("sysctl getting icmp6stat size failed");
254	}
255	oldstat = initstat;
256}
257
258void
259fetchicmp6(void)
260{
261	int name[4];
262	size_t len;
263
264	oldstat = icmp6stat;
265	name[0] = CTL_NET;
266	name[1] = PF_INET6;
267	name[2] = IPPROTO_ICMPV6;
268	name[3] = ICMPV6CTL_STATS;
269	len = sizeof icmp6stat;
270
271	if (sysctl(name, 4, &icmp6stat, &len, 0, 0) < 0)
272		return;
273}
274
275#endif
276