2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
6 * Author: Harti Brandt <harti@freebsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
29 * $Begemot: bsnmp/snmpd/export.c,v 1.8 2006/02/14 09:04:20 brandt_h Exp $
31 * Support functions for modules.
33 #include <sys/types.h>
34 #include <sys/queue.h>
51 * This is user for SET of string variables. If 'req' is not -1 then
52 * the arguments is checked to be of that length. The old value is saved
53 * in scratch->ptr1 and the new value is allocated and copied.
54 * If there is an old values it must have been allocated by malloc.
57 string_save(struct snmp_value *value, struct snmp_context *ctx,
58 ssize_t req_size, u_char **valp)
60 if (req_size != -1 && value->v.octetstring.len != (u_long)req_size)
61 return (SNMP_ERR_BADVALUE);
63 ctx->scratch->ptr1 = *valp;
65 if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) {
66 *valp = ctx->scratch->ptr1;
67 return (SNMP_ERR_RES_UNAVAIL);
70 memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len);
71 (*valp)[value->v.octetstring.len] = '\0';
77 * Commit a string. This is easy - free the old value.
80 string_commit(struct snmp_context *ctx)
82 free(ctx->scratch->ptr1);
86 * Rollback a string - free new value and copy back old one.
89 string_rollback(struct snmp_context *ctx, u_char **valp)
92 *valp = ctx->scratch->ptr1;
96 * ROLLBACK or COMMIT fails because instance has disappeared. Free string.
99 string_free(struct snmp_context *ctx)
101 free(ctx->scratch->ptr1);
105 * Get a string value for a response packet
108 string_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
111 value->v.octetstring.len = 0;
112 value->v.octetstring.octets = NULL;
113 return (SNMP_ERR_NOERROR);
117 value->v.octetstring.len = (u_long)len;
118 if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL)
119 return (SNMP_ERR_RES_UNAVAIL);
120 memcpy(value->v.octetstring.octets, ptr, (size_t)len);
121 return (SNMP_ERR_NOERROR);
125 * Get a string value for a response packet but cut it if it is too long.
128 string_get_max(struct snmp_value *value, const u_char *ptr, ssize_t len,
133 value->v.octetstring.len = 0;
134 value->v.octetstring.octets = NULL;
135 return (SNMP_ERR_NOERROR);
139 if ((size_t)len > maxlen)
141 value->v.octetstring.len = (u_long)len;
142 if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL)
143 return (SNMP_ERR_RES_UNAVAIL);
144 memcpy(value->v.octetstring.octets, ptr, (size_t)len);
145 return (SNMP_ERR_NOERROR);
149 * Support for IPADDRESS
151 * Save the old IP address in scratch->int1 and set the new one.
154 ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp)
156 ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8)
159 valp[0] = value->v.ipaddress[0];
160 valp[1] = value->v.ipaddress[1];
161 valp[2] = value->v.ipaddress[2];
162 valp[3] = value->v.ipaddress[3];
168 * Rollback the address by copying back the old one
171 ip_rollback(struct snmp_context *ctx, u_char *valp)
173 valp[0] = ctx->scratch->int1 >> 24;
174 valp[1] = ctx->scratch->int1 >> 16;
175 valp[2] = ctx->scratch->int1 >> 8;
176 valp[3] = ctx->scratch->int1;
180 * Nothing to do for commit
183 ip_commit(struct snmp_context *ctx __unused)
188 * Retrieve an IP address
191 ip_get(struct snmp_value *value, u_char *valp)
193 value->v.ipaddress[0] = valp[0];
194 value->v.ipaddress[1] = valp[1];
195 value->v.ipaddress[2] = valp[2];
196 value->v.ipaddress[3] = valp[3];
198 return (SNMP_ERR_NOERROR);
204 * Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
207 oid_save(struct snmp_value *value, struct snmp_context *ctx,
210 if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL)
211 return (SNMP_ERR_RES_UNAVAIL);
212 *(struct asn_oid *)ctx->scratch->ptr1 = *oid;
219 oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
221 *oid = *(struct asn_oid *)ctx->scratch->ptr1;
222 free(ctx->scratch->ptr1);
226 oid_commit(struct snmp_context *ctx)
228 free(ctx->scratch->ptr1);
232 oid_get(struct snmp_value *value, const struct asn_oid *oid)
235 return (SNMP_ERR_NOERROR);
242 index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
251 index_count = SNMP_INDEX_COUNT(code);
254 for (idx = 0; idx < index_count; idx++) {
255 switch (SNMP_INDEX(code, idx)) {
257 case SNMP_SYNTAX_NULL:
260 case SNMP_SYNTAX_INTEGER:
263 *va_arg(ap, int32_t *) = oid->subs[sub++];
266 case SNMP_SYNTAX_COUNTER64:
269 *va_arg(ap, u_int64_t *) = oid->subs[sub++];
272 case SNMP_SYNTAX_OCTETSTRING:
278 /* only variable size supported */
281 cval = va_arg(ap, u_char **);
282 sval = va_arg(ap, size_t *);
283 *sval = oid->subs[sub++];
284 if (sub + *sval > oid->len)
286 if ((*cval = malloc(*sval)) == NULL) {
287 syslog(LOG_ERR, "%s: %m", __func__);
290 octs[nocts++] = *cval;
291 for (i = 0; i < *sval; i++) {
292 if (oid->subs[sub] > 0xff)
294 (*cval)[i] = oid->subs[sub++];
299 case SNMP_SYNTAX_OID:
301 struct asn_oid *aval;
306 aval = va_arg(ap, struct asn_oid *);
307 aval->len = oid->subs[sub++];
308 if (aval->len > ASN_MAXOIDLEN)
310 for (i = 0; i < aval->len; i++)
311 aval->subs[i] = oid->subs[sub++];
315 case SNMP_SYNTAX_IPADDRESS:
320 if (sub + 4 > oid->len)
322 pval = va_arg(ap, u_int8_t *);
323 for (i = 0; i < 4; i++) {
324 if (oid->subs[sub] > 0xff)
326 pval[i] = oid->subs[sub++];
331 case SNMP_SYNTAX_COUNTER:
332 case SNMP_SYNTAX_GAUGE:
333 case SNMP_SYNTAX_TIMETICKS:
336 if (oid->subs[sub] > 0xffffffff)
338 *va_arg(ap, u_int32_t *) = oid->subs[sub++];
354 * Compare the index part of an OID and an index.
357 index_compare_off(const struct asn_oid *oid, u_int sub,
358 const struct asn_oid *idx, u_int off)
362 for (i = off; i < idx->len && i < oid->len - sub; i++) {
363 if (oid->subs[sub + i] < idx->subs[i])
365 if (oid->subs[sub + i] > idx->subs[i])
368 if (oid->len - sub < idx->len)
370 if (oid->len - sub > idx->len)
377 index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
379 return (index_compare_off(oid, sub, idx, 0));
383 * Append an index to an oid
386 index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
391 var->len = sub + idx->len;
392 for (i = off; i < idx->len; i++)
393 var->subs[sub + i] = idx->subs[i];
396 index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
398 index_append_off(var, sub, idx, 0);