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