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