xref: /dragonfly/usr.bin/systat/icmp.c (revision dc71b7ab81c4f5270d3668e1625d94a58895fa7a)
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 *
openicmp(void)81 openicmp(void)
82 {
83           return (subwin(stdscr, LINES-5-1, 0, 5, 0));
84 }
85 
86 void
closeicmp(WINDOW * w)87 closeicmp(WINDOW *w)
88 {
89           if (w == NULL)
90                     return;
91           wclear(w);
92           wrefresh(w);
93           delwin(w);
94 }
95 
96 void
labelicmp(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
domode(struct icmpstat * ret)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
showicmp(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
initicmp(void)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
reseticmp(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
fetchicmp(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 
274