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