mibII_ip.c revision 225736
1241519Sattilio/*
2241519Sattilio * Copyright (c) 2001-2003
3241519Sattilio *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4241519Sattilio *	All rights reserved.
5241519Sattilio *
6241519Sattilio * Author: Harti Brandt <harti@freebsd.org>
7241519Sattilio *
8241519Sattilio * Redistribution and use in source and binary forms, with or without
9241519Sattilio * modification, are permitted provided that the following conditions
10241519Sattilio * are met:
11241519Sattilio * 1. Redistributions of source code must retain the above copyright
12241519Sattilio *    notice, this list of conditions and the following disclaimer.
13241519Sattilio * 2. Redistributions in binary form must reproduce the above copyright
14241519Sattilio *    notice, this list of conditions and the following disclaimer in the
15241519Sattilio *    documentation and/or other materials provided with the distribution.
16241519Sattilio *
17241519Sattilio * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18241519Sattilio * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19241519Sattilio * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20241519Sattilio * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21241519Sattilio * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22241519Sattilio * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23241519Sattilio * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24241519Sattilio * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25241519Sattilio * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26241519Sattilio * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27241519Sattilio * SUCH DAMAGE.
28241519Sattilio *
29241519Sattilio * $Begemot: bsnmp/snmp_mibII/mibII_ip.c,v 1.11 2005/05/23 09:03:40 brandt_h Exp $
30241519Sattilio *
31241519Sattilio * ip group scalars.
32241519Sattilio */
33241519Sattilio#include "mibII.h"
34241519Sattilio#include "mibII_oid.h"
35241519Sattilio#include <netinet/in_systm.h>
36241519Sattilio#include <netinet/ip.h>
37241519Sattilio#include <netinet/ip_var.h>
38241519Sattilio#include <netinet/ip_icmp.h>
39241519Sattilio#include <netinet/icmp_var.h>
40241519Sattilio
41241519Sattiliostatic struct ipstat ipstat;
42241519Sattiliostatic u_int	ip_idrop;
43241519Sattiliostatic struct icmpstat icmpstat;
44241519Sattilio
45241519Sattiliostatic int	ip_forwarding;
46241519Sattiliostatic int	ip_defttl;
47241519Sattiliostatic uint64_t ip_tick;
48241519Sattilio
49241519Sattiliostatic uint64_t ipstat_tick;
50241519Sattilio
51241519Sattiliostatic int
52241519Sattiliofetch_ipstat(void)
53241519Sattilio{
54241519Sattilio	size_t len;
55241519Sattilio
56241519Sattilio	len = sizeof(ipstat);
57241519Sattilio	if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, NULL, 0) == -1) {
58241519Sattilio		syslog(LOG_ERR, "net.inet.ip.stats: %m");
59241519Sattilio		return (-1);
60241519Sattilio	}
61241519Sattilio	if (len != sizeof(ipstat)) {
62241519Sattilio		syslog(LOG_ERR, "net.inet.ip.stats: wrong size");
63241519Sattilio		return (-1);
64241519Sattilio	}
65241519Sattilio	len = sizeof(ip_idrop);
66241519Sattilio	if (sysctlbyname("net.inet.ip.intr_queue_drops", &ip_idrop, &len, NULL, 0) == -1)
67241519Sattilio		syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: %m");
68241519Sattilio	if (len != sizeof(ip_idrop)) {
69241519Sattilio		syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: wrong size");
70241519Sattilio		ip_idrop = 0;
71241519Sattilio	}
72241519Sattilio	len = sizeof(icmpstat);
73241519Sattilio	if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len, NULL, 0) == -1) {
74241519Sattilio		syslog(LOG_ERR, "net.inet.icmp.stats: %m");
75241519Sattilio		return (-1);
76241519Sattilio	}
77241519Sattilio	if (len != sizeof(icmpstat)) {
78241519Sattilio		syslog(LOG_ERR, "net.inet.icmp.stats: wrong size");
79241519Sattilio		return (-1);
80241526Sjoel	}
81241519Sattilio
82241519Sattilio	ipstat_tick = get_ticks();
83241519Sattilio	return (0);
84241519Sattilio}
85241519Sattilio
86241519Sattiliostatic int
87241519Sattiliofetch_ip(void)
88241519Sattilio{
89241519Sattilio	size_t len;
90241519Sattilio
91241519Sattilio	len = sizeof(ip_forwarding);
92241519Sattilio	if (sysctlbyname("net.inet.ip.forwarding", &ip_forwarding, &len,
93241519Sattilio	    NULL, 0) == -1) {
94241519Sattilio		syslog(LOG_ERR, "net.inet.ip.forwarding: %m");
95241519Sattilio		return (-1);
96241519Sattilio	}
97241519Sattilio	if (len != sizeof(ip_forwarding)) {
98241519Sattilio		syslog(LOG_ERR, "net.inet.ip.forwarding: wrong size");
99241519Sattilio		return (-1);
100241519Sattilio	}
101241519Sattilio
102241519Sattilio	len = sizeof(ip_defttl);
103241519Sattilio	if (sysctlbyname("net.inet.ip.ttl", &ip_defttl, &len,
104241519Sattilio	    NULL, 0) == -1) {
105241519Sattilio		syslog(LOG_ERR, "net.inet.ip.ttl: %m");
106241519Sattilio		return (-1);
107241519Sattilio	}
108241519Sattilio	if (len != sizeof(ip_defttl)) {
109241519Sattilio		syslog(LOG_ERR, "net.inet.ip.ttl: wrong size");
110241519Sattilio		return (-1);
111241519Sattilio	}
112241519Sattilio
113241519Sattilio	ip_tick = get_ticks();
114241519Sattilio	return (0);
115241519Sattilio}
116241519Sattilio
117241519Sattiliostatic int
118241519Sattilioip_forward(int forw, int *old)
119241519Sattilio{
120241519Sattilio	size_t olen;
121241519Sattilio
122241519Sattilio	olen = sizeof(*old);
123241519Sattilio	if (sysctlbyname("net.inet.ip.forwarding", old, old ? &olen : NULL,
124241519Sattilio	    &forw, sizeof(forw)) == -1) {
125241519Sattilio		syslog(LOG_ERR, "set net.inet.ip.forwarding: %m");
126241519Sattilio		return (-1);
127241519Sattilio	}
128241519Sattilio	ip_forwarding = forw;
129241519Sattilio	return (0);
130241519Sattilio}
131241519Sattilio
132241519Sattiliostatic int
133241519Sattilioip_setttl(int ttl, int *old)
134241519Sattilio{
135241519Sattilio	size_t olen;
136241519Sattilio
137241519Sattilio	olen = sizeof(*old);
138241527Sjoel	if (sysctlbyname("net.inet.ip.ttl", old, old ? &olen : NULL,
139241519Sattilio	    &ttl, sizeof(ttl)) == -1) {
140241519Sattilio		syslog(LOG_ERR, "set net.inet.ip.ttl: %m");
141241519Sattilio		return (-1);
142241519Sattilio	}
143241519Sattilio	ip_defttl = ttl;
144241527Sjoel	return (0);
145241519Sattilio}
146241519Sattilio
147241519Sattilio/*
148241527Sjoel * READ/WRITE ip group.
149241519Sattilio */
150241526Sjoelint
151241519Sattilioop_ip(struct snmp_context *ctx, struct snmp_value *value,
152241519Sattilio    u_int sub, u_int idx __unused, enum snmp_op op)
153241519Sattilio{
154241519Sattilio	int old;
155241519Sattilio
156241519Sattilio	switch (op) {
157241519Sattilio
158241519Sattilio	  case SNMP_OP_GETNEXT:
159241519Sattilio		abort();
160241519Sattilio
161241527Sjoel	  case SNMP_OP_GET:
162241519Sattilio		break;
163241519Sattilio
164241519Sattilio	  case SNMP_OP_SET:
165241519Sattilio		if (ip_tick < this_tick)
166241519Sattilio			if (fetch_ip() == -1)
167241519Sattilio				return (SNMP_ERR_GENERR);
168241519Sattilio
169241519Sattilio		switch (value->var.subs[sub - 1]) {
170241519Sattilio
171241519Sattilio		  case LEAF_ipForwarding:
172241519Sattilio			ctx->scratch->int1 = ip_forwarding ? 1 : 2;
173241526Sjoel			ctx->scratch->int2 = value->v.integer;
174241519Sattilio			if (value->v.integer == 1) {
175241519Sattilio				if (!ip_forwarding && ip_forward(1, &old))
176241519Sattilio					return (SNMP_ERR_GENERR);
177241519Sattilio				ctx->scratch->int1 = old ? 1 : 2;
178241519Sattilio			} else if (value->v.integer == 2) {
179241519Sattilio				if (ip_forwarding && ip_forward(0, &old))
180241519Sattilio					return (SNMP_ERR_GENERR);
181241519Sattilio				ctx->scratch->int1 = old;
182241519Sattilio			} else
183241519Sattilio				return (SNMP_ERR_WRONG_VALUE);
184241519Sattilio			break;
185241519Sattilio
186241519Sattilio		  case LEAF_ipDefaultTTL:
187241519Sattilio			ctx->scratch->int1 = ip_defttl;
188241519Sattilio			ctx->scratch->int2 = value->v.integer;
189241519Sattilio			if (value->v.integer < 1 || value->v.integer > 255)
190241519Sattilio				return (SNMP_ERR_WRONG_VALUE);
191241519Sattilio			if (ip_defttl != value->v.integer &&
192241519Sattilio			    ip_setttl(value->v.integer, &old))
193241519Sattilio				return (SNMP_ERR_GENERR);
194241519Sattilio			ctx->scratch->int1 = old;
195241519Sattilio			break;
196241519Sattilio		}
197241519Sattilio		return (SNMP_ERR_NOERROR);
198241519Sattilio
199241519Sattilio	  case SNMP_OP_ROLLBACK:
200241519Sattilio		switch (value->var.subs[sub - 1]) {
201241519Sattilio
202241519Sattilio		  case LEAF_ipForwarding:
203241519Sattilio			if (ctx->scratch->int1 == 1) {
204241519Sattilio				if (ctx->scratch->int2 == 2)
205241519Sattilio					(void)ip_forward(1, NULL);
206241519Sattilio			} else {
207241519Sattilio				if (ctx->scratch->int2 == 1)
208241519Sattilio					(void)ip_forward(0, NULL);
209241519Sattilio			}
210241519Sattilio			break;
211241519Sattilio
212241519Sattilio		  case LEAF_ipDefaultTTL:
213241519Sattilio			if (ctx->scratch->int1 != ctx->scratch->int2)
214241519Sattilio				(void)ip_setttl(ctx->scratch->int1, NULL);
215241519Sattilio			break;
216241519Sattilio		}
217241519Sattilio		return (SNMP_ERR_NOERROR);
218241519Sattilio
219241519Sattilio	  case SNMP_OP_COMMIT:
220241519Sattilio		return (SNMP_ERR_NOERROR);
221241519Sattilio	}
222241519Sattilio
223241519Sattilio	if (ip_tick < this_tick)
224241519Sattilio		if (fetch_ip() == -1)
225241519Sattilio			return (SNMP_ERR_GENERR);
226241519Sattilio
227241519Sattilio	switch (value->var.subs[sub - 1]) {
228241519Sattilio
229241519Sattilio	  case LEAF_ipForwarding:
230241519Sattilio		value->v.integer = ip_forwarding ? 1 : 2;
231241519Sattilio		break;
232241519Sattilio
233241519Sattilio	  case LEAF_ipDefaultTTL:
234241519Sattilio		value->v.integer = ip_defttl;
235241519Sattilio		break;
236241519Sattilio	}
237241519Sattilio	return (SNMP_ERR_NOERROR);
238241519Sattilio}
239241519Sattilio
240241519Sattilio/*
241241519Sattilio * READ-ONLY statistics ip group.
242241519Sattilio */
243241527Sjoelint
244241519Sattilioop_ipstat(struct snmp_context *ctx __unused, struct snmp_value *value,
245241519Sattilio    u_int sub, u_int idx __unused, enum snmp_op op)
246241519Sattilio{
247241519Sattilio	switch (op) {
248241519Sattilio
249241519Sattilio	  case SNMP_OP_GETNEXT:
250241519Sattilio		abort();
251241519Sattilio
252241519Sattilio	  case SNMP_OP_GET:
253241519Sattilio		break;
254241519Sattilio
255241519Sattilio	  case SNMP_OP_SET:
256241519Sattilio		return (SNMP_ERR_NOT_WRITEABLE);
257241519Sattilio
258241519Sattilio	  case SNMP_OP_ROLLBACK:
259241519Sattilio	  case SNMP_OP_COMMIT:
260241519Sattilio		abort();
261241519Sattilio	}
262241519Sattilio
263241519Sattilio	if (ipstat_tick < this_tick)
264241519Sattilio		fetch_ipstat();
265241519Sattilio
266241519Sattilio	switch (value->var.subs[sub - 1]) {
267241519Sattilio
268241519Sattilio	  case LEAF_ipInReceives:
269241519Sattilio		value->v.uint32 = ipstat.ips_total;
270241519Sattilio		break;
271241519Sattilio
272241519Sattilio	  case LEAF_ipInHdrErrors:
273241519Sattilio		value->v.uint32 = ipstat.ips_badsum + ipstat.ips_tooshort
274241519Sattilio		    + ipstat.ips_toosmall + ipstat.ips_badhlen
275241519Sattilio		    + ipstat.ips_badlen + ipstat.ips_badvers +
276241519Sattilio		    + ipstat.ips_toolong;
277241526Sjoel		break;
278241519Sattilio
279241519Sattilio	  case LEAF_ipInAddrErrors:
280241519Sattilio		value->v.uint32 = ipstat.ips_cantforward;
281241519Sattilio		break;
282241519Sattilio
283241519Sattilio	  case LEAF_ipForwDatagrams:
284241519Sattilio		value->v.uint32 = ipstat.ips_forward;
285241519Sattilio		break;
286241519Sattilio
287241519Sattilio	  case LEAF_ipInUnknownProtos:
288241519Sattilio		value->v.uint32 = ipstat.ips_noproto;
289241526Sjoel		break;
290241519Sattilio
291241519Sattilio	  case LEAF_ipInDiscards:
292241519Sattilio		value->v.uint32 = ip_idrop;
293241519Sattilio		break;
294241519Sattilio
295241519Sattilio	  case LEAF_ipInDelivers:
296241519Sattilio		value->v.uint32 = ipstat.ips_delivered;
297241519Sattilio		break;
298241519Sattilio
299241519Sattilio	  case LEAF_ipOutRequests:
300241519Sattilio		value->v.uint32 = ipstat.ips_localout;
301241519Sattilio		break;
302241519Sattilio
303241519Sattilio	  case LEAF_ipOutDiscards:
304241519Sattilio		value->v.uint32 = ipstat.ips_odropped;
305241519Sattilio		break;
306241519Sattilio
307241519Sattilio	  case LEAF_ipOutNoRoutes:
308241519Sattilio		value->v.uint32 = ipstat.ips_noroute;
309241519Sattilio		break;
310241519Sattilio
311241519Sattilio	  case LEAF_ipReasmTimeout:
312241519Sattilio		value->v.integer = IPFRAGTTL;
313241519Sattilio		break;
314241519Sattilio
315241519Sattilio	  case LEAF_ipReasmReqds:
316241519Sattilio		value->v.uint32 = ipstat.ips_fragments;
317241519Sattilio		break;
318241519Sattilio
319241527Sjoel	  case LEAF_ipReasmOKs:
320241527Sjoel		value->v.uint32 = ipstat.ips_reassembled;
321241519Sattilio		break;
322241519Sattilio
323241519Sattilio	  case LEAF_ipReasmFails:
324241519Sattilio		value->v.uint32 = ipstat.ips_fragdropped
325241519Sattilio		    + ipstat.ips_fragtimeout;
326241519Sattilio		break;
327241519Sattilio
328241519Sattilio	  case LEAF_ipFragOKs:
329241519Sattilio		value->v.uint32 = ipstat.ips_fragmented;
330241519Sattilio		break;
331241519Sattilio
332241526Sjoel	  case LEAF_ipFragFails:
333241526Sjoel		value->v.uint32 = ipstat.ips_cantfrag;
334241526Sjoel		break;
335241526Sjoel
336241519Sattilio	  case LEAF_ipFragCreates:
337241519Sattilio		value->v.uint32 = ipstat.ips_ofragments;
338241519Sattilio		break;
339241519Sattilio	}
340241519Sattilio	return (SNMP_ERR_NOERROR);
341241519Sattilio}
342241519Sattilio
343241519Sattilio/*
344241519Sattilio * READ-ONLY statistics icmp group.
345241519Sattilio */
346241519Sattilioint
347241519Sattilioop_icmpstat(struct snmp_context *ctx __unused, struct snmp_value *value,
348241519Sattilio    u_int sub, u_int idx __unused, enum snmp_op op)
349241519Sattilio{
350241519Sattilio	u_int i;
351241526Sjoel
352241519Sattilio	switch (op) {
353241519Sattilio
354241519Sattilio	  case SNMP_OP_GETNEXT:
355241519Sattilio		abort();
356241519Sattilio
357241519Sattilio	  case SNMP_OP_GET:
358241519Sattilio		break;
359241519Sattilio
360241519Sattilio	  case SNMP_OP_SET:
361241519Sattilio		return (SNMP_ERR_NOT_WRITEABLE);
362241519Sattilio
363241527Sjoel	  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}
494