icmp.c revision 158160
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
34#include <sys/cdefs.h>
35
36__FBSDID("$FreeBSD: head/usr.bin/systat/icmp.c 158160 2006-04-30 04:26:46Z bde $");
37
38#ifdef lint
39static char sccsid[] = "@(#)mbufs.c	8.1 (Berkeley) 6/6/93";
40#endif
41
42/* From:
43	"Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp"
44*/
45
46#include <sys/param.h>
47#include <sys/types.h>
48#include <sys/socket.h>
49#include <sys/sysctl.h>
50
51#include <netinet/in.h>
52#include <netinet/in_systm.h>
53#include <netinet/ip.h>
54#include <netinet/ip_icmp.h>
55#include <netinet/icmp_var.h>
56
57#include <stdlib.h>
58#include <string.h>
59#include <paths.h>
60#include "systat.h"
61#include "extern.h"
62#include "mode.h"
63
64static struct icmpstat icmpstat, initstat, oldstat;
65
66/*-
67--0         1         2         3         4         5         6         7
68--0123456789012345678901234567890123456789012345678901234567890123456789012345
6900          ICMP Input                         ICMP Output
7001999999999 total messages           999999999 total messages
7102999999999 with bad code            999999999 errors generated
7203999999999 with bad length          999999999 suppressed - original too short
7304999999999 with bad checksum        999999999 suppressed - original was ICMP
7405999999999 with insufficient data   999999999 responses sent
7506                                   999999999 suppressed - multicast echo
7607                                   999999999 suppressed - multicast tstamp
7708
7809          Input Histogram                    Output Histogram
7910999999999 echo response            999999999 echo response
8011999999999 echo request             999999999 echo request
8112999999999 destination unreachable  999999999 destination unreachable
8213999999999 redirect                 999999999 redirect
8314999999999 time-to-live exceeded    999999999 time-to-line exceeded
8415999999999 parameter problem        999999999 parameter problem
8516999999999 router advertisement     999999999 router solicitation
8617
8718
88--0123456789012345678901234567890123456789012345678901234567890123456789012345
89--0         1         2         3         4         5         6         7
90*/
91
92WINDOW *
93openicmp(void)
94{
95	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
96}
97
98void
99closeicmp(w)
100	WINDOW *w;
101{
102	if (w == NULL)
103		return;
104	wclear(w);
105	wrefresh(w);
106	delwin(w);
107}
108
109void
110labelicmp(void)
111{
112	wmove(wnd, 0, 0); wclrtoeol(wnd);
113#define L(row, str) mvwprintw(wnd, row, 10, str)
114#define R(row, str) mvwprintw(wnd, row, 45, str);
115	L(0, "ICMP Input");		R(0, "ICMP Output");
116	L(1, "total messages");		R(1, "total messages");
117	L(2, "with bad code");		R(2, "errors generated");
118	L(3, "with bad length");	R(3, "suppressed - original too short");
119	L(4, "with bad checksum");	R(4, "suppressed - original was ICMP");
120	L(5, "with insufficient data");	R(5, "responses sent");
121					R(6, "suppressed - multicast echo");
122					R(7, "suppressed - multicast tstamp");
123	L(9, "Input Histogram");	R(9, "Output Histogram");
124#define B(row, str) L(row, str); R(row, str)
125	B(10, "echo response");
126	B(11, "echo request");
127	B(12, "destination unreachable");
128	B(13, "redirect");
129	B(14, "time-to-live exceeded");
130	B(15, "parameter problem");
131	L(16, "router advertisement");	R(16, "router solicitation");
132#undef L
133#undef R
134#undef B
135}
136
137static void
138domode(struct icmpstat *ret)
139{
140	const struct icmpstat *sub;
141	int i, divisor = 1;
142
143	switch(currentmode) {
144	case display_RATE:
145		sub = &oldstat;
146		divisor = naptime;
147		break;
148	case display_DELTA:
149		sub = &oldstat;
150		break;
151	case display_SINCE:
152		sub = &initstat;
153		break;
154	default:
155		*ret = icmpstat;
156		return;
157	}
158#define DO(stat) ret->stat = (icmpstat.stat - sub->stat) / divisor
159	DO(icps_error);
160	DO(icps_oldshort);
161	DO(icps_oldicmp);
162	for (i = 0; i <= ICMP_MAXTYPE; i++) {
163		DO(icps_outhist[i]);
164	}
165	DO(icps_badcode);
166	DO(icps_tooshort);
167	DO(icps_checksum);
168	DO(icps_badlen);
169	DO(icps_reflect);
170	for (i = 0; i <= ICMP_MAXTYPE; i++) {
171		DO(icps_inhist[i]);
172	}
173	DO(icps_bmcastecho);
174	DO(icps_bmcasttstamp);
175#undef DO
176}
177
178void
179showicmp(void)
180{
181	struct icmpstat stats;
182	u_long totalin, totalout;
183	int i;
184
185	memset(&stats, 0, sizeof stats);
186	domode(&stats);
187	for (i = totalin = totalout = 0; i <= ICMP_MAXTYPE; i++) {
188		totalin += stats.icps_inhist[i];
189		totalout += stats.icps_outhist[i];
190	}
191	totalin += stats.icps_badcode + stats.icps_badlen +
192		stats.icps_checksum + stats.icps_tooshort;
193	mvwprintw(wnd, 1, 0, "%9lu", totalin);
194	mvwprintw(wnd, 1, 35, "%9lu", totalout);
195
196#define DO(stat, row, col) \
197	mvwprintw(wnd, row, col, "%9lu", stats.stat)
198
199	DO(icps_badcode, 2, 0);
200	DO(icps_badlen, 3, 0);
201	DO(icps_checksum, 4, 0);
202	DO(icps_tooshort, 5, 0);
203	DO(icps_error, 2, 35);
204	DO(icps_oldshort, 3, 35);
205	DO(icps_oldicmp, 4, 35);
206	DO(icps_reflect, 5, 35);
207	DO(icps_bmcastecho, 6, 35);
208	DO(icps_bmcasttstamp, 7, 35);
209#define DO2(type, row) DO(icps_inhist[type], row, 0); DO(icps_outhist[type], \
210							 row, 35)
211	DO2(ICMP_ECHOREPLY, 10);
212	DO2(ICMP_ECHO, 11);
213	DO2(ICMP_UNREACH, 12);
214	DO2(ICMP_REDIRECT, 13);
215	DO2(ICMP_TIMXCEED, 14);
216	DO2(ICMP_PARAMPROB, 15);
217	DO(icps_inhist[ICMP_ROUTERADVERT], 16, 0);
218	DO(icps_outhist[ICMP_ROUTERSOLICIT], 16, 35);
219#undef DO
220#undef DO2
221}
222
223int
224initicmp(void)
225{
226	size_t len;
227	int name[4];
228
229	name[0] = CTL_NET;
230	name[1] = PF_INET;
231	name[2] = IPPROTO_ICMP;
232	name[3] = ICMPCTL_STATS;
233
234	len = 0;
235	if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
236		error("sysctl getting icmpstat size failed");
237		return 0;
238	}
239	if (len > sizeof icmpstat) {
240		error("icmpstat structure has grown--recompile systat!");
241		return 0;
242	}
243	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
244		error("sysctl getting icmpstat size failed");
245		return 0;
246	}
247	oldstat = initstat;
248	return 1;
249}
250
251void
252reseticmp(void)
253{
254	size_t len;
255	int name[4];
256
257	name[0] = CTL_NET;
258	name[1] = PF_INET;
259	name[2] = IPPROTO_ICMP;
260	name[3] = ICMPCTL_STATS;
261
262	len = sizeof initstat;
263	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
264		error("sysctl getting icmpstat size failed");
265	}
266	oldstat = initstat;
267}
268
269void
270fetchicmp(void)
271{
272	int name[4];
273	size_t len;
274
275	oldstat = icmpstat;
276	name[0] = CTL_NET;
277	name[1] = PF_INET;
278	name[2] = IPPROTO_ICMP;
279	name[3] = ICMPCTL_STATS;
280	len = sizeof icmpstat;
281
282	if (sysctl(name, 4, &icmpstat, &len, 0, 0) < 0)
283		return;
284}
285
286