xref: /freebsd/usr.bin/systat/icmp6.c (revision a0ee8cc6)
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
35 static 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 
58 static struct icmp6stat icmp6stat, initstat, oldstat;
59 
60 /*-
61 --0         1         2         3         4         5         6         7
62 --0123456789012345678901234567890123456789012345678901234567890123456789012345
63 00          ICMPv6 Input                       ICMPv6 Output
64 01999999999 total messages           999999999 total messages
65 02999999999 with bad code            999999999 errors generated
66 03999999999 with bad length          999999999 suppressed - original too short
67 04999999999 with bad checksum        999999999 suppressed - original was ICMP
68 05999999999 with insufficient data   999999999 responses sent
69 06
70 07          Input Histogram                    Output Histogram
71 08999999999 echo response            999999999 echo response
72 09999999999 echo request             999999999 echo request
73 10999999999 destination unreachable  999999999 destination unreachable
74 11999999999 redirect                 999999999 redirect
75 12999999999 time-to-live exceeded    999999999 time-to-line exceeded
76 13999999999 parameter problem        999999999 parameter problem
77 14999999999 neighbor solicitation    999999999 neighbor solicitation
78 15999999999 neighbor advertisement   999999999 neighbor advertisement
79 16999999999 router advertisement     999999999 router solicitation
80 17
81 18
82 --0123456789012345678901234567890123456789012345678901234567890123456789012345
83 --0         1         2         3         4         5         6         7
84 */
85 
86 WINDOW *
87 openicmp6(void)
88 {
89 	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
90 }
91 
92 void
93 closeicmp6(WINDOW *w)
94 {
95 	if (w == NULL)
96 		return;
97 	wclear(w);
98 	wrefresh(w);
99 	delwin(w);
100 }
101 
102 void
103 labelicmp6(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 advertisement");
125 	L(16, "router advertisement");	R(16, "router solicitation");
126 #undef L
127 #undef R
128 #undef B
129 }
130 
131 static void
132 domode(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 
170 void
171 showicmp6(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 
215 int
216 initicmp6(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 
243 void
244 reseticmp6(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 
261 void
262 fetchicmp6(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