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