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