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