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