xref: /dragonfly/usr.bin/systat/icmp6.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/icmp6.c,v 1.3 2006/04/30 04:47:23 bde Exp $
31  */
32 
33 #ifdef INET6
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/icmp6.h>
41 
42 #include <stdlib.h>
43 #include <string.h>
44 #include <paths.h>
45 #include "systat.h"
46 #include "extern.h"
47 #include "mode.h"
48 
49 static struct icmp6stat icmp6stat, initstat, oldstat;
50 
51 /*-
52 --0         1         2         3         4         5         6         7
53 --0123456789012345678901234567890123456789012345678901234567890123456789012345
54 00          ICMPv6 Input                       ICMPv6 Output
55 01999999999 total messages           999999999 total messages
56 02999999999 with bad code            999999999 errors generated
57 03999999999 with bad length          999999999 suppressed - original too short
58 04999999999 with bad checksum        999999999 suppressed - original was ICMP
59 05999999999 with insufficient data   999999999 responses sent
60 06
61 07          Input Histogram                    Output Histogram
62 08999999999 echo response            999999999 echo response
63 09999999999 echo request             999999999 echo request
64 10999999999 destination unreachable  999999999 destination unreachable
65 11999999999 redirect                 999999999 redirect
66 12999999999 time-to-live exceeded    999999999 time-to-line exceeded
67 13999999999 parameter problem        999999999 parameter problem
68 14999999999 neighbor solicitation    999999999 neighbor solicitation
69 15999999999 neighbor advertisment    999999999 neighbor advertisment
70 16999999999 router advertisement     999999999 router solicitation
71 17
72 18
73 --0123456789012345678901234567890123456789012345678901234567890123456789012345
74 --0         1         2         3         4         5         6         7
75 */
76 
77 WINDOW *
openicmp6(void)78 openicmp6(void)
79 {
80           return (subwin(stdscr, LINES-4-1, 0, 4, 0));
81 }
82 
83 void
closeicmp6(WINDOW * w)84 closeicmp6(WINDOW *w)
85 {
86           if (w == NULL)
87                     return;
88           wclear(w);
89           wrefresh(w);
90           delwin(w);
91 }
92 
93 void
labelicmp6(void)94 labelicmp6(void)
95 {
96           wmove(wnd, 0, 0); wclrtoeol(wnd);
97 #define L(row, str) mvwprintw(wnd, row, 10, str)
98 #define R(row, str) mvwprintw(wnd, row, 45, str);
99           L(1, "ICMPv6 Input");                   R(1, "ICMPv6 Output");
100           L(2, "total messages");                 R(2, "total messages");
101           L(3, "with bad code");                  R(3, "errors generated");
102           L(4, "with bad length");      R(4, "suppressed - original too short");
103           L(5, "with bad checksum");    R(5, "suppressed - original was ICMP");
104           L(6, "with insufficient data");         R(6, "responses sent");
105 
106           L(8, "Input Histogram");      R(8, "Output Histogram");
107 #define B(row, str) L(row, str); R(row, str)
108           B(9, "echo response");
109           B(10, "echo request");
110           B(11, "destination unreachable");
111           B(12, "redirect");
112           B(13, "time-to-live exceeded");
113           B(14, "parameter problem");
114           B(15, "neighbor solicitation");
115           B(16, "neighbor advertisement");
116           L(17, "router advertisement");          R(17, "router solicitation");
117 #undef L
118 #undef R
119 #undef B
120 }
121 
122 static void
domode(struct icmp6stat * ret)123 domode(struct icmp6stat *ret)
124 {
125           const struct icmp6stat *sub;
126           int i, divisor = 1;
127 
128           switch(currentmode) {
129           case display_RATE:
130                     sub = &oldstat;
131                     divisor = naptime;
132                     break;
133           case display_DELTA:
134                     sub = &oldstat;
135                     break;
136           case display_SINCE:
137                     sub = &initstat;
138                     break;
139           default:
140                     *ret = icmp6stat;
141                     return;
142           }
143 #define DO(stat) ret->stat = (icmp6stat.stat - sub->stat) / divisor
144           DO(icp6s_error);
145           DO(icp6s_tooshort);
146           DO(icp6s_canterror);
147           for (i = 0; i <= ICMP6_MAXTYPE; i++) {
148                     DO(icp6s_outhist[i]);
149           }
150           DO(icp6s_badcode);
151           DO(icp6s_tooshort);
152           DO(icp6s_checksum);
153           DO(icp6s_badlen);
154           DO(icp6s_reflect);
155           for (i = 0; i <= ICMP6_MAXTYPE; i++) {
156                     DO(icp6s_inhist[i]);
157           }
158 #undef DO
159 }
160 
161 void
showicmp6(void)162 showicmp6(void)
163 {
164           struct icmp6stat stats;
165           u_long totalin, totalout;
166           int i;
167 
168           memset(&stats, 0, sizeof stats);
169           domode(&stats);
170           for (i = totalin = totalout = 0; i <= ICMP6_MAXTYPE; i++) {
171                     totalin += stats.icp6s_inhist[i];
172                     totalout += stats.icp6s_outhist[i];
173           }
174           totalin += stats.icp6s_badcode + stats.icp6s_badlen +
175                     stats.icp6s_checksum + stats.icp6s_tooshort;
176           mvwprintw(wnd, 2, 0, "%9lu", totalin);
177           mvwprintw(wnd, 2, 35, "%9lu", totalout);
178 
179 #define DO(stat, row, col) \
180           mvwprintw(wnd, row, col, "%9lu", stats.stat)
181 
182           DO(icp6s_badcode, 3, 0);
183           DO(icp6s_badlen, 4, 0);
184           DO(icp6s_checksum, 5, 0);
185           DO(icp6s_tooshort, 6, 0);
186           DO(icp6s_error, 3, 35);
187           DO(icp6s_tooshort, 4, 35);
188           DO(icp6s_canterror, 5, 35);
189           DO(icp6s_reflect, 6, 35);
190 #define DO2(type, row) DO(icp6s_inhist[type], row, 0); DO(icp6s_outhist[type], \
191                                                                        row, 35)
192           DO2(ICMP6_ECHO_REPLY, 9);
193           DO2(ICMP6_ECHO_REQUEST, 10);
194           DO2(ICMP6_DST_UNREACH, 11);
195           DO2(ND_REDIRECT, 12);
196           DO2(ICMP6_TIME_EXCEEDED, 13);
197           DO2(ICMP6_PARAM_PROB, 14);
198           DO2(ND_NEIGHBOR_SOLICIT, 15);
199           DO2(ND_NEIGHBOR_ADVERT, 16);
200           DO(icp6s_inhist[ND_ROUTER_SOLICIT], 17, 0);
201           DO(icp6s_outhist[ND_ROUTER_ADVERT], 17, 35);
202 #undef DO
203 #undef DO2
204 }
205 
206 int
initicmp6(void)207 initicmp6(void)
208 {
209           size_t len;
210           int name[4];
211 
212           name[0] = CTL_NET;
213           name[1] = PF_INET6;
214           name[2] = IPPROTO_ICMPV6;
215           name[3] = ICMPV6CTL_STATS;
216 
217           len = 0;
218           if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
219                     error("sysctl getting icmp6stat size failed");
220                     return 0;
221           }
222           if (len > sizeof icmp6stat) {
223                     error("icmp6stat structure has grown--recompile systat!");
224                     return 0;
225           }
226           if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
227                     error("sysctl getting icmp6stat size failed");
228                     return 0;
229           }
230           oldstat = initstat;
231           return 1;
232 }
233 
234 void
reseticmp6(void)235 reseticmp6(void)
236 {
237           size_t len;
238           int name[4];
239 
240           name[0] = CTL_NET;
241           name[1] = PF_INET6;
242           name[2] = IPPROTO_ICMPV6;
243           name[3] = ICMPV6CTL_STATS;
244 
245           len = sizeof initstat;
246           if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
247                     error("sysctl getting icmp6stat size failed");
248           }
249           oldstat = initstat;
250 }
251 
252 void
fetchicmp6(void)253 fetchicmp6(void)
254 {
255           int name[4];
256           size_t len;
257 
258           oldstat = icmp6stat;
259           name[0] = CTL_NET;
260           name[1] = PF_INET6;
261           name[2] = IPPROTO_ICMPV6;
262           name[3] = ICMPV6CTL_STATS;
263           len = sizeof icmp6stat;
264 
265           if (sysctl(name, 4, &icmp6stat, &len, 0, 0) < 0)
266                     return;
267 }
268 
269 #endif
270