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