xref: /dragonfly/usr.bin/systat/icmp.c (revision 38a690d7)
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/icmp.c,v 1.2 1999/08/28 01:06:01 peter Exp $
35  * $DragonFly: src/usr.bin/systat/icmp.c,v 1.3 2003/07/12 03:09:50 dillon Exp $
36  */
37 
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/in_systm.h>
45 #include <netinet/ip.h>
46 #include <netinet/ip_icmp.h>
47 #include <netinet/icmp_var.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 icmpstat icmpstat, initstat, oldstat;
57 
58 /*-
59 --0         1         2         3         4         5         6         7
60 --0123456789012345678901234567890123456789012345678901234567890123456789012345
61 01          ICMP Input                         ICMP Output
62 02999999999 total messages           999999999 total messages
63 03999999999 with bad code            999999999 errors generated
64 04999999999 with bad length          999999999 suppressed - original too short
65 05999999999 with bad checksum        999999999 suppressed - original was ICMP
66 06999999999 with insufficient data   999999999 responses sent
67 07                                   999999999 suppressed - multicast echo
68 08                                   999999999 suppressed - multicast tstamp
69 09
70 10          Input Histogram                    Output Histogram
71 11999999999 echo response            999999999 echo response
72 12999999999 echo request             999999999 echo request
73 13999999999 destination unreachable  999999999 destination unreachable
74 14999999999 redirect                 999999999 redirect
75 15999999999 time-to-live exceeded    999999999 time-to-line exceeded
76 16999999999 parameter problem        999999999 parameter problem
77 17999999999 router advertisement     999999999 router solicitation
78 18
79 19
80 --0123456789012345678901234567890123456789012345678901234567890123456789012345
81 --0         1         2         3         4         5         6         7
82 */
83 
84 WINDOW *
85 openicmp(void)
86 {
87 	return (subwin(stdscr, LINES-5-1, 0, 5, 0));
88 }
89 
90 void
91 closeicmp(w)
92 	WINDOW *w;
93 {
94 	if (w == NULL)
95 		return;
96 	wclear(w);
97 	wrefresh(w);
98 	delwin(w);
99 }
100 
101 void
102 labelicmp(void)
103 {
104 	wmove(wnd, 0, 0); wclrtoeol(wnd);
105 #define L(row, str) mvwprintw(wnd, row, 10, str)
106 #define R(row, str) mvwprintw(wnd, row, 45, str);
107 	L(1, "ICMP Input");		R(1, "ICMP Output");
108 	L(2, "total messages");		R(2, "total messages");
109 	L(3, "with bad code");		R(3, "errors generated");
110 	L(4, "with bad length");	R(4, "suppressed - original too short");
111 	L(5, "with bad checksum");	R(5, "suppressed - original was ICMP");
112 	L(6, "with insufficient data");	R(6, "responses sent");
113 	;				R(7, "suppressed - multicast echo");
114 	;				R(8, "suppressed - multicast tstamp");
115 	L(10, "Input Histogram");	R(10, "Output Histogram");
116 #define B(row, str) L(row, str); R(row, str)
117 	B(11, "echo response");
118 	B(12, "echo request");
119 	B(13, "destination unreachable");
120 	B(14, "redirect");
121 	B(15, "time-to-live exceeded");
122 	B(16, "parameter problem");
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 icmpstat *ret)
131 {
132 	const struct icmpstat *sub;
133 	int i;
134 	double divisor = 1.0;
135 
136 	switch(currentmode) {
137 	case display_RATE:
138 		sub = &oldstat;
139 		divisor = naptime;
140 		break;
141 	case display_DELTA:
142 		sub = &oldstat;
143 		break;
144 	case display_SINCE:
145 		sub = &initstat;
146 		break;
147 	default:
148 		*ret = icmpstat;
149 		return;
150 	}
151 #define DO(stat) ret->stat = (double)(icmpstat.stat - sub->stat) / divisor
152 	DO(icps_error);
153 	DO(icps_oldshort);
154 	DO(icps_oldicmp);
155 	for (i = 0; i <= ICMP_MAXTYPE; i++) {
156 		DO(icps_outhist[i]);
157 	}
158 	DO(icps_badcode);
159 	DO(icps_tooshort);
160 	DO(icps_checksum);
161 	DO(icps_badlen);
162 	DO(icps_reflect);
163 	for (i = 0; i <= ICMP_MAXTYPE; i++) {
164 		DO(icps_inhist[i]);
165 	}
166 	DO(icps_bmcastecho);
167 	DO(icps_bmcasttstamp);
168 #undef DO
169 }
170 
171 void
172 showicmp(void)
173 {
174 	struct icmpstat stats;
175 	u_long totalin, totalout;
176 	int i;
177 
178 	memset(&stats, 0, sizeof stats);
179 	domode(&stats);
180 	for (i = totalin = totalout = 0; i <= ICMP_MAXTYPE; i++) {
181 		totalin += stats.icps_inhist[i];
182 		totalout += stats.icps_outhist[i];
183 	}
184 	totalin += stats.icps_badcode + stats.icps_badlen +
185 		stats.icps_checksum + stats.icps_tooshort;
186 	mvwprintw(wnd, 2, 0, "%9lu", totalin);
187 	mvwprintw(wnd, 2, 35, "%9lu", totalout);
188 
189 #define DO(stat, row, col) \
190 	mvwprintw(wnd, row, col, "%9lu", stats.stat)
191 
192 	DO(icps_badcode, 3, 0);
193 	DO(icps_badlen, 4, 0);
194 	DO(icps_checksum, 5, 0);
195 	DO(icps_tooshort, 6, 0);
196 	DO(icps_error, 3, 35);
197 	DO(icps_oldshort, 4, 35);
198 	DO(icps_oldicmp, 5, 35);
199 	DO(icps_reflect, 6, 35);
200 	DO(icps_bmcastecho, 7, 35);
201 	DO(icps_bmcasttstamp, 8, 35);
202 #define DO2(type, row) DO(icps_inhist[type], row, 0); DO(icps_outhist[type], \
203 							 row, 35)
204 	DO2(ICMP_ECHOREPLY, 11);
205 	DO2(ICMP_ECHO, 12);
206 	DO2(ICMP_UNREACH, 13);
207 	DO2(ICMP_REDIRECT, 14);
208 	DO2(ICMP_TIMXCEED, 15);
209 	DO2(ICMP_PARAMPROB, 16);
210 	DO(icps_inhist[ICMP_ROUTERADVERT], 17, 0);
211 	DO(icps_outhist[ICMP_ROUTERSOLICIT], 17, 35);
212 #undef DO
213 #undef DO2
214 }
215 
216 int
217 initicmp(void)
218 {
219 	size_t len;
220 	int name[4];
221 
222 	name[0] = CTL_NET;
223 	name[1] = PF_INET;
224 	name[2] = IPPROTO_ICMP;
225 	name[3] = ICMPCTL_STATS;
226 
227 	len = 0;
228 	if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
229 		error("sysctl getting icmpstat size failed");
230 		return 0;
231 	}
232 	if (len > sizeof icmpstat) {
233 		error("icmpstat structure has grown--recompile systat!");
234 		return 0;
235 	}
236 	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
237 		error("sysctl getting icmpstat size failed");
238 		return 0;
239 	}
240 	oldstat = initstat;
241 	return 1;
242 }
243 
244 void
245 reseticmp(void)
246 {
247 	size_t len;
248 	int name[4];
249 
250 	name[0] = CTL_NET;
251 	name[1] = PF_INET;
252 	name[2] = IPPROTO_ICMP;
253 	name[3] = ICMPCTL_STATS;
254 
255 	len = sizeof initstat;
256 	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
257 		error("sysctl getting icmpstat size failed");
258 	}
259 	oldstat = initstat;
260 }
261 
262 void
263 fetchicmp(void)
264 {
265 	int name[4];
266 	size_t len;
267 
268 	oldstat = icmpstat;
269 	name[0] = CTL_NET;
270 	name[1] = PF_INET;
271 	name[2] = IPPROTO_ICMP;
272 	name[3] = ICMPCTL_STATS;
273 	len = sizeof icmpstat;
274 
275 	if (sysctl(name, 4, &icmpstat, &len, 0, 0) < 0)
276 		return;
277 }
278 
279