1/*-
2 * Copyright (c) 1980, 1992, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31
32__FBSDID("$FreeBSD$");
33
34#ifdef lint
35static char sccsid[] = "@(#)mbufs.c	8.1 (Berkeley) 6/6/93";
36#endif
37
38/* From:
39	"Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp"
40*/
41
42#ifdef INET6
43#include <sys/param.h>
44#include <sys/types.h>
45#include <sys/socket.h>
46#include <sys/sysctl.h>
47
48#include <netinet/in.h>
49#include <netinet/icmp6.h>
50
51#include <stdlib.h>
52#include <string.h>
53#include <paths.h>
54#include "systat.h"
55#include "extern.h"
56#include "mode.h"
57
58static struct icmp6stat icmp6stat, initstat, oldstat;
59
60/*-
61--0         1         2         3         4         5         6         7
62--0123456789012345678901234567890123456789012345678901234567890123456789012345
6300          ICMPv6 Input                       ICMPv6 Output
6401999999999 total messages           999999999 total messages
6502999999999 with bad code            999999999 errors generated
6603999999999 with bad length          999999999 suppressed - original too short
6704999999999 with bad checksum        999999999 suppressed - original was ICMP
6805999999999 with insufficient data   999999999 responses sent
6906
7007          Input Histogram                    Output Histogram
7108999999999 echo response            999999999 echo response
7209999999999 echo request             999999999 echo request
7310999999999 destination unreachable  999999999 destination unreachable
7411999999999 redirect                 999999999 redirect
7512999999999 time-to-live exceeded    999999999 time-to-line exceeded
7613999999999 parameter problem        999999999 parameter problem
7714999999999 neighbor solicitation    999999999 neighbor solicitation
7815999999999 neighbor advertisment    999999999 neighbor advertisment
7916999999999 router advertisement     999999999 router solicitation
8017
8118
82--0123456789012345678901234567890123456789012345678901234567890123456789012345
83--0         1         2         3         4         5         6         7
84*/
85
86WINDOW *
87openicmp6(void)
88{
89	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
90}
91
92void
93closeicmp6(WINDOW *w)
94{
95	if (w == NULL)
96		return;
97	wclear(w);
98	wrefresh(w);
99	delwin(w);
100}
101
102void
103labelicmp6(void)
104{
105	wmove(wnd, 0, 0); wclrtoeol(wnd);
106#define L(row, str) mvwprintw(wnd, row, 10, str)
107#define R(row, str) mvwprintw(wnd, row, 45, str);
108	L(0, "ICMPv6 Input");		R(0, "ICMPv6 Output");
109	L(1, "total messages");		R(1, "total messages");
110	L(2, "with bad code");		R(2, "errors generated");
111	L(3, "with bad length");	R(3, "suppressed - original too short");
112	L(4, "with bad checksum");	R(4, "suppressed - original was ICMP");
113	L(5, "with insufficient data");	R(5, "responses sent");
114
115	L(7, "Input Histogram");	R(7, "Output Histogram");
116#define B(row, str) L(row, str); R(row, str)
117	B(8, "echo response");
118	B(9, "echo request");
119	B(10, "destination unreachable");
120	B(11, "redirect");
121	B(12, "time-to-live exceeded");
122	B(13, "parameter problem");
123	B(14, "neighbor solicitation");
124	B(15, "neighbor advertisment");
125	L(16, "router advertisement");	R(16, "router solicitation");
126#undef L
127#undef R
128#undef B
129}
130
131static void
132domode(struct icmp6stat *ret)
133{
134	const struct icmp6stat *sub;
135	int i, divisor = 1;
136
137	switch(currentmode) {
138	case display_RATE:
139		sub = &oldstat;
140		divisor = (delay > 1000000) ? delay / 1000000 : 1;
141		break;
142	case display_DELTA:
143		sub = &oldstat;
144		break;
145	case display_SINCE:
146		sub = &initstat;
147		break;
148	default:
149		*ret = icmp6stat;
150		return;
151	}
152#define DO(stat) ret->stat = (icmp6stat.stat - sub->stat) / divisor
153	DO(icp6s_error);
154	DO(icp6s_tooshort);
155	DO(icp6s_canterror);
156	for (i = 0; i <= ICMP6_MAXTYPE; i++) {
157		DO(icp6s_outhist[i]);
158	}
159	DO(icp6s_badcode);
160	DO(icp6s_tooshort);
161	DO(icp6s_checksum);
162	DO(icp6s_badlen);
163	DO(icp6s_reflect);
164	for (i = 0; i <= ICMP6_MAXTYPE; i++) {
165		DO(icp6s_inhist[i]);
166	}
167#undef DO
168}
169
170void
171showicmp6(void)
172{
173	struct icmp6stat stats;
174	u_long totalin, totalout;
175	int i;
176
177	memset(&stats, 0, sizeof stats);
178	domode(&stats);
179	for (i = totalin = totalout = 0; i <= ICMP6_MAXTYPE; i++) {
180		totalin += stats.icp6s_inhist[i];
181		totalout += stats.icp6s_outhist[i];
182	}
183	totalin += stats.icp6s_badcode + stats.icp6s_badlen +
184		stats.icp6s_checksum + stats.icp6s_tooshort;
185	mvwprintw(wnd, 1, 0, "%9lu", totalin);
186	mvwprintw(wnd, 1, 35, "%9lu", totalout);
187
188#define DO(stat, row, col) \
189	mvwprintw(wnd, row, col, "%9lu", stats.stat)
190
191	DO(icp6s_badcode, 2, 0);
192	DO(icp6s_badlen, 3, 0);
193	DO(icp6s_checksum, 4, 0);
194	DO(icp6s_tooshort, 5, 0);
195	DO(icp6s_error, 2, 35);
196	DO(icp6s_tooshort, 3, 35);
197	DO(icp6s_canterror, 4, 35);
198	DO(icp6s_reflect, 5, 35);
199#define DO2(type, row) DO(icp6s_inhist[type], row, 0); DO(icp6s_outhist[type], \
200							 row, 35)
201	DO2(ICMP6_ECHO_REPLY, 8);
202	DO2(ICMP6_ECHO_REQUEST, 9);
203	DO2(ICMP6_DST_UNREACH, 10);
204	DO2(ND_REDIRECT, 11);
205	DO2(ICMP6_TIME_EXCEEDED, 12);
206	DO2(ICMP6_PARAM_PROB, 13);
207	DO2(ND_NEIGHBOR_SOLICIT, 14);
208	DO2(ND_NEIGHBOR_ADVERT, 15);
209	DO(icp6s_inhist[ND_ROUTER_SOLICIT], 16, 0);
210	DO(icp6s_outhist[ND_ROUTER_ADVERT], 16, 35);
211#undef DO
212#undef DO2
213}
214
215int
216initicmp6(void)
217{
218	size_t len;
219	int name[4];
220
221	name[0] = CTL_NET;
222	name[1] = PF_INET6;
223	name[2] = IPPROTO_ICMPV6;
224	name[3] = ICMPV6CTL_STATS;
225
226	len = 0;
227	if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
228		error("sysctl getting icmp6stat size failed");
229		return 0;
230	}
231	if (len > sizeof icmp6stat) {
232		error("icmp6stat structure has grown--recompile systat!");
233		return 0;
234	}
235	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
236		error("sysctl getting icmp6stat size failed");
237		return 0;
238	}
239	oldstat = initstat;
240	return 1;
241}
242
243void
244reseticmp6(void)
245{
246	size_t len;
247	int name[4];
248
249	name[0] = CTL_NET;
250	name[1] = PF_INET6;
251	name[2] = IPPROTO_ICMPV6;
252	name[3] = ICMPV6CTL_STATS;
253
254	len = sizeof initstat;
255	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
256		error("sysctl getting icmp6stat size failed");
257	}
258	oldstat = initstat;
259}
260
261void
262fetchicmp6(void)
263{
264	int name[4];
265	size_t len;
266
267	oldstat = icmp6stat;
268	name[0] = CTL_NET;
269	name[1] = PF_INET6;
270	name[2] = IPPROTO_ICMPV6;
271	name[3] = ICMPV6CTL_STATS;
272	len = sizeof icmp6stat;
273
274	if (sysctl(name, 4, &icmp6stat, &len, 0, 0) < 0)
275		return;
276}
277
278#endif
279