icmp.c revision 175387
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 175387 2008-01-16 19:27:43Z delphij $");
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(WINDOW *w)
100{
101	if (w == NULL)
102		return;
103	wclear(w);
104	wrefresh(w);
105	delwin(w);
106}
107
108void
109labelicmp(void)
110{
111	wmove(wnd, 0, 0); wclrtoeol(wnd);
112#define L(row, str) mvwprintw(wnd, row, 10, str)
113#define R(row, str) mvwprintw(wnd, row, 45, str);
114	L(0, "ICMP Input");		R(0, "ICMP Output");
115	L(1, "total messages");		R(1, "total messages");
116	L(2, "with bad code");		R(2, "errors generated");
117	L(3, "with bad length");	R(3, "suppressed - original too short");
118	L(4, "with bad checksum");	R(4, "suppressed - original was ICMP");
119	L(5, "with insufficient data");	R(5, "responses sent");
120					R(6, "suppressed - multicast echo");
121					R(7, "suppressed - multicast tstamp");
122	L(9, "Input Histogram");	R(9, "Output Histogram");
123#define B(row, str) L(row, str); R(row, str)
124	B(10, "echo response");
125	B(11, "echo request");
126	B(12, "destination unreachable");
127	B(13, "redirect");
128	B(14, "time-to-live exceeded");
129	B(15, "parameter problem");
130	L(16, "router advertisement");	R(16, "router solicitation");
131#undef L
132#undef R
133#undef B
134}
135
136static void
137domode(struct icmpstat *ret)
138{
139	const struct icmpstat *sub;
140	int i, divisor = 1;
141
142	switch(currentmode) {
143	case display_RATE:
144		sub = &oldstat;
145		divisor = naptime;
146		break;
147	case display_DELTA:
148		sub = &oldstat;
149		break;
150	case display_SINCE:
151		sub = &initstat;
152		break;
153	default:
154		*ret = icmpstat;
155		return;
156	}
157#define DO(stat) ret->stat = (icmpstat.stat - sub->stat) / divisor
158	DO(icps_error);
159	DO(icps_oldshort);
160	DO(icps_oldicmp);
161	for (i = 0; i <= ICMP_MAXTYPE; i++) {
162		DO(icps_outhist[i]);
163	}
164	DO(icps_badcode);
165	DO(icps_tooshort);
166	DO(icps_checksum);
167	DO(icps_badlen);
168	DO(icps_reflect);
169	for (i = 0; i <= ICMP_MAXTYPE; i++) {
170		DO(icps_inhist[i]);
171	}
172	DO(icps_bmcastecho);
173	DO(icps_bmcasttstamp);
174#undef DO
175}
176
177void
178showicmp(void)
179{
180	struct icmpstat stats;
181	u_long totalin, totalout;
182	int i;
183
184	memset(&stats, 0, sizeof stats);
185	domode(&stats);
186	for (i = totalin = totalout = 0; i <= ICMP_MAXTYPE; i++) {
187		totalin += stats.icps_inhist[i];
188		totalout += stats.icps_outhist[i];
189	}
190	totalin += stats.icps_badcode + stats.icps_badlen +
191		stats.icps_checksum + stats.icps_tooshort;
192	mvwprintw(wnd, 1, 0, "%9lu", totalin);
193	mvwprintw(wnd, 1, 35, "%9lu", totalout);
194
195#define DO(stat, row, col) \
196	mvwprintw(wnd, row, col, "%9lu", stats.stat)
197
198	DO(icps_badcode, 2, 0);
199	DO(icps_badlen, 3, 0);
200	DO(icps_checksum, 4, 0);
201	DO(icps_tooshort, 5, 0);
202	DO(icps_error, 2, 35);
203	DO(icps_oldshort, 3, 35);
204	DO(icps_oldicmp, 4, 35);
205	DO(icps_reflect, 5, 35);
206	DO(icps_bmcastecho, 6, 35);
207	DO(icps_bmcasttstamp, 7, 35);
208#define DO2(type, row) DO(icps_inhist[type], row, 0); DO(icps_outhist[type], \
209							 row, 35)
210	DO2(ICMP_ECHOREPLY, 10);
211	DO2(ICMP_ECHO, 11);
212	DO2(ICMP_UNREACH, 12);
213	DO2(ICMP_REDIRECT, 13);
214	DO2(ICMP_TIMXCEED, 14);
215	DO2(ICMP_PARAMPROB, 15);
216	DO(icps_inhist[ICMP_ROUTERADVERT], 16, 0);
217	DO(icps_outhist[ICMP_ROUTERSOLICIT], 16, 35);
218#undef DO
219#undef DO2
220}
221
222int
223initicmp(void)
224{
225	size_t len;
226	int name[4];
227
228	name[0] = CTL_NET;
229	name[1] = PF_INET;
230	name[2] = IPPROTO_ICMP;
231	name[3] = ICMPCTL_STATS;
232
233	len = 0;
234	if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
235		error("sysctl getting icmpstat size failed");
236		return 0;
237	}
238	if (len > sizeof icmpstat) {
239		error("icmpstat structure has grown--recompile systat!");
240		return 0;
241	}
242	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
243		error("sysctl getting icmpstat size failed");
244		return 0;
245	}
246	oldstat = initstat;
247	return 1;
248}
249
250void
251reseticmp(void)
252{
253	size_t len;
254	int name[4];
255
256	name[0] = CTL_NET;
257	name[1] = PF_INET;
258	name[2] = IPPROTO_ICMP;
259	name[3] = ICMPCTL_STATS;
260
261	len = sizeof initstat;
262	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
263		error("sysctl getting icmpstat size failed");
264	}
265	oldstat = initstat;
266}
267
268void
269fetchicmp(void)
270{
271	int name[4];
272	size_t len;
273
274	oldstat = icmpstat;
275	name[0] = CTL_NET;
276	name[1] = PF_INET;
277	name[2] = IPPROTO_ICMP;
278	name[3] = ICMPCTL_STATS;
279	len = sizeof icmpstat;
280
281	if (sysctl(name, 4, &icmpstat, &len, 0, 0) < 0)
282		return;
283}
284
285