Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.bin / systat / icmp.c
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:
36 static char sccsid[] = "@(#)mbufs.c     8.1 (Berkeley) 6/6/93";
37 static const char rcsid[] =
38         "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp";
39 */
40 static const char rcsid[] =
41   "$FreeBSD: src/usr.bin/systat/icmp.c,v 1.2 1999/08/28 01:06:01 peter Exp $";
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
62 static struct icmpstat icmpstat, initstat, oldstat;
63
64 /*-
65 --0         1         2         3         4         5         6         7
66 --0123456789012345678901234567890123456789012345678901234567890123456789012345
67 01          ICMP Input                         ICMP Output
68 02999999999 total messages           999999999 total messages
69 03999999999 with bad code            999999999 errors generated
70 04999999999 with bad length          999999999 suppressed - original too short
71 05999999999 with bad checksum        999999999 suppressed - original was ICMP
72 06999999999 with insufficient data   999999999 responses sent
73 07                                   999999999 suppressed - multicast echo
74 08                                   999999999 suppressed - multicast tstamp
75 09
76 10          Input Histogram                    Output Histogram
77 11999999999 echo response            999999999 echo response
78 12999999999 echo request             999999999 echo request
79 13999999999 destination unreachable  999999999 destination unreachable
80 14999999999 redirect                 999999999 redirect
81 15999999999 time-to-live exceeded    999999999 time-to-line exceeded
82 16999999999 parameter problem        999999999 parameter problem
83 17999999999 router advertisement     999999999 router solicitation
84 18
85 19
86 --0123456789012345678901234567890123456789012345678901234567890123456789012345
87 --0         1         2         3         4         5         6         7
88 */
89
90 WINDOW *
91 openicmp(void)
92 {
93         return (subwin(stdscr, LINES-5-1, 0, 5, 0));
94 }
95
96 void
97 closeicmp(w)
98         WINDOW *w;
99 {
100         if (w == NULL)
101                 return;
102         wclear(w);
103         wrefresh(w);
104         delwin(w);
105 }
106
107 void
108 labelicmp(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
135 static void
136 domode(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         
176 void
177 showicmp(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
221 int
222 initicmp(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
249 void
250 reseticmp(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
267 void
268 fetchicmp(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