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