]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/bsnmp/snmp_mibII/mibII_ip.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / bsnmp / snmp_mibII / mibII_ip.c
1 /*
2  * Copyright (c) 2001-2003
3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *      All rights reserved.
5  *
6  * Author: Harti Brandt <harti@freebsd.org>
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 
17  * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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  * $Begemot: bsnmp/snmp_mibII/mibII_ip.c,v 1.11 2005/05/23 09:03:40 brandt_h Exp $
30  *
31  * ip group scalars.
32  */
33 #include "mibII.h"
34 #include "mibII_oid.h"
35 #include <netinet/in_systm.h>
36 #include <netinet/ip.h>
37 #include <netinet/ip_var.h>
38 #include <netinet/ip_icmp.h>
39 #include <netinet/icmp_var.h>
40
41 static struct ipstat ipstat;
42 static u_int    ip_idrop;
43 static struct icmpstat icmpstat;
44
45 static int      ip_forwarding;
46 static int      ip_defttl;
47 static uint64_t ip_tick;
48
49 static uint64_t ipstat_tick;
50
51 static int
52 fetch_ipstat(void)
53 {
54         size_t len;
55
56         len = sizeof(ipstat);
57         if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, NULL, 0) == -1) {
58                 syslog(LOG_ERR, "net.inet.ip.stats: %m");
59                 return (-1);
60         }
61         if (len != sizeof(ipstat)) {
62                 syslog(LOG_ERR, "net.inet.ip.stats: wrong size");
63                 return (-1);
64         }
65         len = sizeof(ip_idrop);
66         if (sysctlbyname("net.inet.ip.intr_queue_drops", &ip_idrop, &len, NULL, 0) == -1)
67                 syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: %m");
68         if (len != sizeof(ip_idrop)) {
69                 syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: wrong size");
70                 ip_idrop = 0;
71         }
72         len = sizeof(icmpstat);
73         if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len, NULL, 0) == -1) {
74                 syslog(LOG_ERR, "net.inet.icmp.stats: %m");
75                 return (-1);
76         }
77         if (len != sizeof(icmpstat)) {
78                 syslog(LOG_ERR, "net.inet.icmp.stats: wrong size");
79                 return (-1);
80         }
81
82         ipstat_tick = get_ticks();
83         return (0);
84 }
85
86 static int
87 fetch_ip(void)
88 {
89         size_t len;
90
91         len = sizeof(ip_forwarding);
92         if (sysctlbyname("net.inet.ip.forwarding", &ip_forwarding, &len,
93             NULL, 0) == -1) {
94                 syslog(LOG_ERR, "net.inet.ip.forwarding: %m");
95                 return (-1);
96         }
97         if (len != sizeof(ip_forwarding)) {
98                 syslog(LOG_ERR, "net.inet.ip.forwarding: wrong size");
99                 return (-1);
100         }
101
102         len = sizeof(ip_defttl);
103         if (sysctlbyname("net.inet.ip.ttl", &ip_defttl, &len,
104             NULL, 0) == -1) {
105                 syslog(LOG_ERR, "net.inet.ip.ttl: %m");
106                 return (-1);
107         }
108         if (len != sizeof(ip_defttl)) {
109                 syslog(LOG_ERR, "net.inet.ip.ttl: wrong size");
110                 return (-1);
111         }
112
113         ip_tick = get_ticks();
114         return (0);
115 }
116
117 static int
118 ip_forward(int forw, int *old)
119 {
120         size_t olen;
121
122         olen = sizeof(*old);
123         if (sysctlbyname("net.inet.ip.forwarding", old, old ? &olen : NULL,
124             &forw, sizeof(forw)) == -1) {
125                 syslog(LOG_ERR, "set net.inet.ip.forwarding: %m");
126                 return (-1);
127         }
128         ip_forwarding = forw;
129         return (0);
130 }
131
132 static int
133 ip_setttl(int ttl, int *old)
134 {
135         size_t olen;
136
137         olen = sizeof(*old);
138         if (sysctlbyname("net.inet.ip.ttl", old, old ? &olen : NULL,
139             &ttl, sizeof(ttl)) == -1) {
140                 syslog(LOG_ERR, "set net.inet.ip.ttl: %m");
141                 return (-1);
142         }
143         ip_defttl = ttl;
144         return (0);
145 }
146
147 /*
148  * READ/WRITE ip group.
149  */
150 int
151 op_ip(struct snmp_context *ctx, struct snmp_value *value,
152     u_int sub, u_int idx __unused, enum snmp_op op)
153 {
154         int old;
155
156         switch (op) {
157
158           case SNMP_OP_GETNEXT:
159                 abort();
160
161           case SNMP_OP_GET:
162                 break;
163
164           case SNMP_OP_SET:
165                 if (ip_tick < this_tick)
166                         if (fetch_ip() == -1)
167                                 return (SNMP_ERR_GENERR);
168
169                 switch (value->var.subs[sub - 1]) {
170
171                   case LEAF_ipForwarding:
172                         ctx->scratch->int1 = ip_forwarding ? 1 : 2;
173                         ctx->scratch->int2 = value->v.integer;
174                         if (value->v.integer == 1) {
175                                 if (!ip_forwarding && ip_forward(1, &old))
176                                         return (SNMP_ERR_GENERR);
177                                 ctx->scratch->int1 = old ? 1 : 2;
178                         } else if (value->v.integer == 2) {
179                                 if (ip_forwarding && ip_forward(0, &old))
180                                         return (SNMP_ERR_GENERR);
181                                 ctx->scratch->int1 = old;
182                         } else
183                                 return (SNMP_ERR_WRONG_VALUE);
184                         break;
185
186                   case LEAF_ipDefaultTTL:
187                         ctx->scratch->int1 = ip_defttl;
188                         ctx->scratch->int2 = value->v.integer;
189                         if (value->v.integer < 1 || value->v.integer > 255)
190                                 return (SNMP_ERR_WRONG_VALUE);
191                         if (ip_defttl != value->v.integer &&
192                             ip_setttl(value->v.integer, &old))
193                                 return (SNMP_ERR_GENERR);
194                         ctx->scratch->int1 = old;
195                         break;
196                 }
197                 return (SNMP_ERR_NOERROR);
198
199           case SNMP_OP_ROLLBACK:
200                 switch (value->var.subs[sub - 1]) {
201
202                   case LEAF_ipForwarding:
203                         if (ctx->scratch->int1 == 1) {
204                                 if (ctx->scratch->int2 == 2)
205                                         (void)ip_forward(1, NULL);
206                         } else {
207                                 if (ctx->scratch->int2 == 1)
208                                         (void)ip_forward(0, NULL);
209                         }
210                         break;
211
212                   case LEAF_ipDefaultTTL:
213                         if (ctx->scratch->int1 != ctx->scratch->int2)
214                                 (void)ip_setttl(ctx->scratch->int1, NULL);
215                         break;
216                 }
217                 return (SNMP_ERR_NOERROR);
218
219           case SNMP_OP_COMMIT:
220                 return (SNMP_ERR_NOERROR);
221         }
222
223         if (ip_tick < this_tick)
224                 if (fetch_ip() == -1)
225                         return (SNMP_ERR_GENERR);
226
227         switch (value->var.subs[sub - 1]) {
228
229           case LEAF_ipForwarding:
230                 value->v.integer = ip_forwarding ? 1 : 2;
231                 break;
232
233           case LEAF_ipDefaultTTL:
234                 value->v.integer = ip_defttl;
235                 break;
236         }
237         return (SNMP_ERR_NOERROR);
238 }
239
240 /*
241  * READ-ONLY statistics ip group.
242  */
243 int
244 op_ipstat(struct snmp_context *ctx __unused, struct snmp_value *value,
245     u_int sub, u_int idx __unused, enum snmp_op op)
246 {
247         switch (op) {
248
249           case SNMP_OP_GETNEXT:
250                 abort();
251
252           case SNMP_OP_GET:
253                 break;
254
255           case SNMP_OP_SET:
256                 return (SNMP_ERR_NOT_WRITEABLE);
257
258           case SNMP_OP_ROLLBACK:
259           case SNMP_OP_COMMIT:
260                 abort();
261         }
262
263         if (ipstat_tick < this_tick)
264                 fetch_ipstat();
265
266         switch (value->var.subs[sub - 1]) {
267
268           case LEAF_ipInReceives:
269                 value->v.uint32 = ipstat.ips_total;
270                 break;
271
272           case LEAF_ipInHdrErrors:
273                 value->v.uint32 = ipstat.ips_badsum + ipstat.ips_tooshort
274                     + ipstat.ips_toosmall + ipstat.ips_badhlen
275                     + ipstat.ips_badlen + ipstat.ips_badvers +
276                     + ipstat.ips_toolong;
277                 break;
278
279           case LEAF_ipInAddrErrors:
280                 value->v.uint32 = ipstat.ips_cantforward;
281                 break;
282
283           case LEAF_ipForwDatagrams:
284                 value->v.uint32 = ipstat.ips_forward;
285                 break;
286
287           case LEAF_ipInUnknownProtos:
288                 value->v.uint32 = ipstat.ips_noproto;
289                 break;
290
291           case LEAF_ipInDiscards:
292                 value->v.uint32 = ip_idrop;
293                 break;
294
295           case LEAF_ipInDelivers:
296                 value->v.uint32 = ipstat.ips_delivered;
297                 break;
298
299           case LEAF_ipOutRequests:
300                 value->v.uint32 = ipstat.ips_localout;
301                 break;
302
303           case LEAF_ipOutDiscards:
304                 value->v.uint32 = ipstat.ips_odropped;
305                 break;
306
307           case LEAF_ipOutNoRoutes:
308                 value->v.uint32 = ipstat.ips_noroute;
309                 break;
310
311           case LEAF_ipReasmTimeout:
312                 value->v.integer = IPFRAGTTL;
313                 break;
314
315           case LEAF_ipReasmReqds:
316                 value->v.uint32 = ipstat.ips_fragments;
317                 break;
318
319           case LEAF_ipReasmOKs:
320                 value->v.uint32 = ipstat.ips_reassembled;
321                 break;
322
323           case LEAF_ipReasmFails:
324                 value->v.uint32 = ipstat.ips_fragdropped
325                     + ipstat.ips_fragtimeout;
326                 break;
327
328           case LEAF_ipFragOKs:
329                 value->v.uint32 = ipstat.ips_fragmented;
330                 break;
331
332           case LEAF_ipFragFails:
333                 value->v.uint32 = ipstat.ips_cantfrag;
334                 break;
335
336           case LEAF_ipFragCreates:
337                 value->v.uint32 = ipstat.ips_ofragments;
338                 break;
339         }
340         return (SNMP_ERR_NOERROR);
341 }
342
343 /*
344  * READ-ONLY statistics icmp group.
345  */
346 int
347 op_icmpstat(struct snmp_context *ctx __unused, struct snmp_value *value,
348     u_int sub, u_int idx __unused, enum snmp_op op)
349 {
350         u_int i;
351
352         switch (op) {
353
354           case SNMP_OP_GETNEXT:
355                 abort();
356
357           case SNMP_OP_GET:
358                 break;
359
360           case SNMP_OP_SET:
361                 return (SNMP_ERR_NOT_WRITEABLE);
362
363           case SNMP_OP_ROLLBACK:
364           case SNMP_OP_COMMIT:
365                 abort();
366         }
367
368         if (ipstat_tick < this_tick)
369                 fetch_ipstat();
370
371         switch (value->var.subs[sub - 1]) {
372
373           case LEAF_icmpInMsgs:
374                 value->v.integer = 0;
375                 for (i = 0; i <= ICMP_MAXTYPE; i++)
376                         value->v.integer += icmpstat.icps_inhist[i];
377                 value->v.integer += icmpstat.icps_tooshort +
378                     icmpstat.icps_checksum;
379                 /* missing: bad type and packets on faith */
380                 break;
381
382           case LEAF_icmpInErrors:
383                 value->v.integer = icmpstat.icps_tooshort +
384                     icmpstat.icps_checksum +
385                     icmpstat.icps_badlen +
386                     icmpstat.icps_badcode +
387                     icmpstat.icps_bmcastecho +
388                     icmpstat.icps_bmcasttstamp;
389                 break;
390
391           case LEAF_icmpInDestUnreachs:
392                 value->v.integer = icmpstat.icps_inhist[ICMP_UNREACH];
393                 break;
394
395           case LEAF_icmpInTimeExcds:
396                 value->v.integer = icmpstat.icps_inhist[ICMP_TIMXCEED];
397                 break;
398
399           case LEAF_icmpInParmProbs:
400                 value->v.integer = icmpstat.icps_inhist[ICMP_PARAMPROB];
401                 break;
402
403           case LEAF_icmpInSrcQuenchs:
404                 value->v.integer = icmpstat.icps_inhist[ICMP_SOURCEQUENCH];
405                 break;
406
407           case LEAF_icmpInRedirects:
408                 value->v.integer = icmpstat.icps_inhist[ICMP_REDIRECT];
409                 break;
410
411           case LEAF_icmpInEchos:
412                 value->v.integer = icmpstat.icps_inhist[ICMP_ECHO];
413                 break;
414
415           case LEAF_icmpInEchoReps:
416                 value->v.integer = icmpstat.icps_inhist[ICMP_ECHOREPLY];
417                 break;
418
419           case LEAF_icmpInTimestamps:
420                 value->v.integer = icmpstat.icps_inhist[ICMP_TSTAMP];
421                 break;
422
423           case LEAF_icmpInTimestampReps:
424                 value->v.integer = icmpstat.icps_inhist[ICMP_TSTAMPREPLY];
425                 break;
426
427           case LEAF_icmpInAddrMasks:
428                 value->v.integer = icmpstat.icps_inhist[ICMP_MASKREQ];
429                 break;
430
431           case LEAF_icmpInAddrMaskReps:
432                 value->v.integer = icmpstat.icps_inhist[ICMP_MASKREPLY];
433                 break;
434
435           case LEAF_icmpOutMsgs:
436                 value->v.integer = 0;
437                 for (i = 0; i <= ICMP_MAXTYPE; i++)
438                         value->v.integer += icmpstat.icps_outhist[i];
439                 value->v.integer += icmpstat.icps_badaddr +
440                     icmpstat.icps_noroute;
441                 break;
442
443           case LEAF_icmpOutErrors:
444                 value->v.integer = icmpstat.icps_badaddr +
445                     icmpstat.icps_noroute;
446                 break;
447
448           case LEAF_icmpOutDestUnreachs:
449                 value->v.integer = icmpstat.icps_outhist[ICMP_UNREACH];
450                 break;
451
452           case LEAF_icmpOutTimeExcds:
453                 value->v.integer = icmpstat.icps_outhist[ICMP_TIMXCEED];
454                 break;
455
456           case LEAF_icmpOutParmProbs:
457                 value->v.integer = icmpstat.icps_outhist[ICMP_PARAMPROB];
458                 break;
459
460           case LEAF_icmpOutSrcQuenchs:
461                 value->v.integer = icmpstat.icps_outhist[ICMP_SOURCEQUENCH];
462                 break;
463
464           case LEAF_icmpOutRedirects:
465                 value->v.integer = icmpstat.icps_outhist[ICMP_REDIRECT];
466                 break;
467
468           case LEAF_icmpOutEchos:
469                 value->v.integer = icmpstat.icps_outhist[ICMP_ECHO];
470                 break;
471
472           case LEAF_icmpOutEchoReps:
473                 value->v.integer = icmpstat.icps_outhist[ICMP_ECHOREPLY];
474                 break;
475
476           case LEAF_icmpOutTimestamps:
477                 value->v.integer = icmpstat.icps_outhist[ICMP_TSTAMP];
478                 break;
479
480           case LEAF_icmpOutTimestampReps:
481                 value->v.integer = icmpstat.icps_outhist[ICMP_TSTAMPREPLY];
482                 break;
483
484           case LEAF_icmpOutAddrMasks:
485                 value->v.integer = icmpstat.icps_outhist[ICMP_MASKREQ];
486                 break;
487
488           case LEAF_icmpOutAddrMaskReps:
489                 value->v.integer = icmpstat.icps_outhist[ICMP_MASKREPLY];
490                 break;
491         }
492         return (SNMP_ERR_NOERROR);
493 }