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