129759Swollman/*-
229759Swollman * Copyright (c) 1980, 1992, 1993
329759Swollman *	The Regents of the University of California.  All rights reserved.
429759Swollman *
529759Swollman * Redistribution and use in source and binary forms, with or without
629759Swollman * modification, are permitted provided that the following conditions
729759Swollman * are met:
829759Swollman * 1. Redistributions of source code must retain the above copyright
929759Swollman *    notice, this list of conditions and the following disclaimer.
1029759Swollman * 2. Redistributions in binary form must reproduce the above copyright
1129759Swollman *    notice, this list of conditions and the following disclaimer in the
1229759Swollman *    documentation and/or other materials provided with the distribution.
1329759Swollman * 4. Neither the name of the University nor the names of its contributors
1429759Swollman *    may be used to endorse or promote products derived from this software
1529759Swollman *    without specific prior written permission.
1629759Swollman *
1729759Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1829759Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1929759Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2029759Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2129759Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2229759Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2329759Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2429759Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2529759Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2629759Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2729759Swollman * SUCH DAMAGE.
2829759Swollman */
2929759Swollman
3087715Smarkm#include <sys/cdefs.h>
3187715Smarkm
3287715Smarkm__FBSDID("$FreeBSD: releng/10.2/usr.bin/systat/icmp.c 240605 2012-09-17 13:36:47Z melifaro $");
3387715Smarkm
3487715Smarkm#ifdef lint
3587715Smarkmstatic char sccsid[] = "@(#)mbufs.c	8.1 (Berkeley) 6/6/93";
3687715Smarkm#endif
3787715Smarkm
3829759Swollman/* From:
3987715Smarkm	"Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp"
4029759Swollman*/
4129759Swollman
4229759Swollman#include <sys/param.h>
4329759Swollman#include <sys/types.h>
4429759Swollman#include <sys/socket.h>
4529759Swollman#include <sys/sysctl.h>
4629759Swollman
4729759Swollman#include <netinet/in.h>
4829759Swollman#include <netinet/in_systm.h>
4929759Swollman#include <netinet/ip.h>
5029759Swollman#include <netinet/ip_icmp.h>
5129759Swollman#include <netinet/icmp_var.h>
5229759Swollman
53200462Sdelphij#include <stdlib.h>
5429759Swollman#include <string.h>
55200462Sdelphij#include <paths.h>
5629759Swollman#include "systat.h"
5729759Swollman#include "extern.h"
5829759Swollman#include "mode.h"
5929759Swollman
6029759Swollmanstatic struct icmpstat icmpstat, initstat, oldstat;
6129759Swollman
6229759Swollman/*-
6329759Swollman--0         1         2         3         4         5         6         7
6429759Swollman--0123456789012345678901234567890123456789012345678901234567890123456789012345
65158160Sbde00          ICMP Input                         ICMP Output
66158160Sbde01999999999 total messages           999999999 total messages
67158160Sbde02999999999 with bad code            999999999 errors generated
68158160Sbde03999999999 with bad length          999999999 suppressed - original too short
69158160Sbde04999999999 with bad checksum        999999999 suppressed - original was ICMP
70158160Sbde05999999999 with insufficient data   999999999 responses sent
71158160Sbde06                                   999999999 suppressed - multicast echo
72158160Sbde07                                   999999999 suppressed - multicast tstamp
73158160Sbde08
74158160Sbde09          Input Histogram                    Output Histogram
75158160Sbde10999999999 echo response            999999999 echo response
76158160Sbde11999999999 echo request             999999999 echo request
77158160Sbde12999999999 destination unreachable  999999999 destination unreachable
78158160Sbde13999999999 redirect                 999999999 redirect
79158160Sbde14999999999 time-to-live exceeded    999999999 time-to-line exceeded
80158160Sbde15999999999 parameter problem        999999999 parameter problem
81158160Sbde16999999999 router advertisement     999999999 router solicitation
82158160Sbde17
8329759Swollman18
8429759Swollman--0123456789012345678901234567890123456789012345678901234567890123456789012345
8529759Swollman--0         1         2         3         4         5         6         7
8629759Swollman*/
8729759Swollman
8829759SwollmanWINDOW *
8929759Swollmanopenicmp(void)
9029759Swollman{
91158160Sbde	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
9229759Swollman}
9329759Swollman
9429759Swollmanvoid
95175387Sdelphijcloseicmp(WINDOW *w)
9629759Swollman{
9729759Swollman	if (w == NULL)
9829759Swollman		return;
9929759Swollman	wclear(w);
10029759Swollman	wrefresh(w);
10129759Swollman	delwin(w);
10229759Swollman}
10329759Swollman
10429759Swollmanvoid
10529759Swollmanlabelicmp(void)
10629759Swollman{
10729759Swollman	wmove(wnd, 0, 0); wclrtoeol(wnd);
10829759Swollman#define L(row, str) mvwprintw(wnd, row, 10, str)
10929759Swollman#define R(row, str) mvwprintw(wnd, row, 45, str);
110158160Sbde	L(0, "ICMP Input");		R(0, "ICMP Output");
111158160Sbde	L(1, "total messages");		R(1, "total messages");
112158160Sbde	L(2, "with bad code");		R(2, "errors generated");
113158160Sbde	L(3, "with bad length");	R(3, "suppressed - original too short");
114158160Sbde	L(4, "with bad checksum");	R(4, "suppressed - original was ICMP");
115158160Sbde	L(5, "with insufficient data");	R(5, "responses sent");
116158160Sbde					R(6, "suppressed - multicast echo");
117158160Sbde					R(7, "suppressed - multicast tstamp");
118158160Sbde	L(9, "Input Histogram");	R(9, "Output Histogram");
11929759Swollman#define B(row, str) L(row, str); R(row, str)
120158160Sbde	B(10, "echo response");
121158160Sbde	B(11, "echo request");
122158160Sbde	B(12, "destination unreachable");
123158160Sbde	B(13, "redirect");
124158160Sbde	B(14, "time-to-live exceeded");
125158160Sbde	B(15, "parameter problem");
126158160Sbde	L(16, "router advertisement");	R(16, "router solicitation");
12729759Swollman#undef L
12829759Swollman#undef R
12929759Swollman#undef B
13029759Swollman}
13129759Swollman
13229759Swollmanstatic void
13329759Swollmandomode(struct icmpstat *ret)
13429759Swollman{
13529759Swollman	const struct icmpstat *sub;
13629759Swollman	int i, divisor = 1;
13729759Swollman
13829759Swollman	switch(currentmode) {
13929759Swollman	case display_RATE:
14029759Swollman		sub = &oldstat;
141240605Smelifaro		divisor = (delay > 1000000) ? delay / 1000000 : 1;
14229759Swollman		break;
14329759Swollman	case display_DELTA:
14429759Swollman		sub = &oldstat;
14529759Swollman		break;
14629759Swollman	case display_SINCE:
14729759Swollman		sub = &initstat;
14829759Swollman		break;
14929759Swollman	default:
15029759Swollman		*ret = icmpstat;
15129759Swollman		return;
15229759Swollman	}
15329759Swollman#define DO(stat) ret->stat = (icmpstat.stat - sub->stat) / divisor
15429759Swollman	DO(icps_error);
15529759Swollman	DO(icps_oldshort);
15629759Swollman	DO(icps_oldicmp);
15729759Swollman	for (i = 0; i <= ICMP_MAXTYPE; i++) {
15829759Swollman		DO(icps_outhist[i]);
15929759Swollman	}
16029759Swollman	DO(icps_badcode);
16129759Swollman	DO(icps_tooshort);
16229759Swollman	DO(icps_checksum);
16329759Swollman	DO(icps_badlen);
16429759Swollman	DO(icps_reflect);
16529759Swollman	for (i = 0; i <= ICMP_MAXTYPE; i++) {
16629759Swollman		DO(icps_inhist[i]);
16729759Swollman	}
16829759Swollman	DO(icps_bmcastecho);
16929759Swollman	DO(icps_bmcasttstamp);
17029759Swollman#undef DO
17129759Swollman}
172158161Sbde
17329759Swollmanvoid
17429759Swollmanshowicmp(void)
17529759Swollman{
17629759Swollman	struct icmpstat stats;
17729759Swollman	u_long totalin, totalout;
17829759Swollman	int i;
17929759Swollman
18029759Swollman	memset(&stats, 0, sizeof stats);
18129759Swollman	domode(&stats);
18229759Swollman	for (i = totalin = totalout = 0; i <= ICMP_MAXTYPE; i++) {
18329759Swollman		totalin += stats.icps_inhist[i];
18429759Swollman		totalout += stats.icps_outhist[i];
18529759Swollman	}
186158161Sbde	totalin += stats.icps_badcode + stats.icps_badlen +
18729759Swollman		stats.icps_checksum + stats.icps_tooshort;
188158160Sbde	mvwprintw(wnd, 1, 0, "%9lu", totalin);
189158160Sbde	mvwprintw(wnd, 1, 35, "%9lu", totalout);
19029759Swollman
19129759Swollman#define DO(stat, row, col) \
19229759Swollman	mvwprintw(wnd, row, col, "%9lu", stats.stat)
19329759Swollman
194158160Sbde	DO(icps_badcode, 2, 0);
195158160Sbde	DO(icps_badlen, 3, 0);
196158160Sbde	DO(icps_checksum, 4, 0);
197158160Sbde	DO(icps_tooshort, 5, 0);
198158160Sbde	DO(icps_error, 2, 35);
199158160Sbde	DO(icps_oldshort, 3, 35);
200158160Sbde	DO(icps_oldicmp, 4, 35);
201158160Sbde	DO(icps_reflect, 5, 35);
202158160Sbde	DO(icps_bmcastecho, 6, 35);
203158160Sbde	DO(icps_bmcasttstamp, 7, 35);
20429759Swollman#define DO2(type, row) DO(icps_inhist[type], row, 0); DO(icps_outhist[type], \
20529759Swollman							 row, 35)
206158160Sbde	DO2(ICMP_ECHOREPLY, 10);
207158160Sbde	DO2(ICMP_ECHO, 11);
208158160Sbde	DO2(ICMP_UNREACH, 12);
209158160Sbde	DO2(ICMP_REDIRECT, 13);
210158160Sbde	DO2(ICMP_TIMXCEED, 14);
211158160Sbde	DO2(ICMP_PARAMPROB, 15);
212158160Sbde	DO(icps_inhist[ICMP_ROUTERADVERT], 16, 0);
213158160Sbde	DO(icps_outhist[ICMP_ROUTERSOLICIT], 16, 35);
21429759Swollman#undef DO
21529759Swollman#undef DO2
21629759Swollman}
21729759Swollman
21829759Swollmanint
21929759Swollmaniniticmp(void)
22029759Swollman{
22129759Swollman	size_t len;
22229759Swollman	int name[4];
22329759Swollman
22429759Swollman	name[0] = CTL_NET;
22529759Swollman	name[1] = PF_INET;
22629759Swollman	name[2] = IPPROTO_ICMP;
22729759Swollman	name[3] = ICMPCTL_STATS;
22829759Swollman
22929759Swollman	len = 0;
23029759Swollman	if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
23129759Swollman		error("sysctl getting icmpstat size failed");
23229759Swollman		return 0;
23329759Swollman	}
23429759Swollman	if (len > sizeof icmpstat) {
23529759Swollman		error("icmpstat structure has grown--recompile systat!");
23629759Swollman		return 0;
23729759Swollman	}
23829759Swollman	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
23929759Swollman		error("sysctl getting icmpstat size failed");
24029759Swollman		return 0;
24129759Swollman	}
24229759Swollman	oldstat = initstat;
24329759Swollman	return 1;
24429759Swollman}
24529759Swollman
24629759Swollmanvoid
24729759Swollmanreseticmp(void)
24829759Swollman{
24929759Swollman	size_t len;
25029759Swollman	int name[4];
25129759Swollman
25229759Swollman	name[0] = CTL_NET;
25329759Swollman	name[1] = PF_INET;
25429759Swollman	name[2] = IPPROTO_ICMP;
25529759Swollman	name[3] = ICMPCTL_STATS;
25629759Swollman
25729759Swollman	len = sizeof initstat;
25829759Swollman	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
25929759Swollman		error("sysctl getting icmpstat size failed");
26029759Swollman	}
26129759Swollman	oldstat = initstat;
26229759Swollman}
26329759Swollman
26429759Swollmanvoid
26529759Swollmanfetchicmp(void)
26629759Swollman{
26729759Swollman	int name[4];
26829759Swollman	size_t len;
26929759Swollman
27029759Swollman	oldstat = icmpstat;
27129759Swollman	name[0] = CTL_NET;
27229759Swollman	name[1] = PF_INET;
27329759Swollman	name[2] = IPPROTO_ICMP;
27429759Swollman	name[3] = ICMPCTL_STATS;
27529759Swollman	len = sizeof icmpstat;
27629759Swollman
27729759Swollman	if (sysctl(name, 4, &icmpstat, &len, 0, 0) < 0)
27829759Swollman		return;
27929759Swollman}
280