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 if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL) {
118 value->v.octetstring.len = 0;
119 return (SNMP_ERR_RES_UNAVAIL);
121 value->v.octetstring.len = (u_long)len;
122 memcpy(value->v.octetstring.octets, ptr, (size_t)len);
123 return (SNMP_ERR_NOERROR);
127 * Get a string value for a response packet but cut it if it is too long.
130 string_get_max(struct snmp_value *value, const u_char *ptr, ssize_t len,
135 value->v.octetstring.len = 0;
136 value->v.octetstring.octets = NULL;
137 return (SNMP_ERR_NOERROR);
141 if ((size_t)len > maxlen)
143 if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL) {
144 value->v.octetstring.len = 0;
145 return (SNMP_ERR_RES_UNAVAIL);
147 value->v.octetstring.len = (u_long)len;
148 memcpy(value->v.octetstring.octets, ptr, (size_t)len);
149 return (SNMP_ERR_NOERROR);
153 * Support for IPADDRESS
155 * Save the old IP address in scratch->int1 and set the new one.
158 ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp)
160 ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8)
163 valp[0] = value->v.ipaddress[0];
164 valp[1] = value->v.ipaddress[1];
165 valp[2] = value->v.ipaddress[2];
166 valp[3] = value->v.ipaddress[3];
172 * Rollback the address by copying back the old one
175 ip_rollback(struct snmp_context *ctx, u_char *valp)
177 valp[0] = ctx->scratch->int1 >> 24;
178 valp[1] = ctx->scratch->int1 >> 16;
179 valp[2] = ctx->scratch->int1 >> 8;
180 valp[3] = ctx->scratch->int1;
184 * Nothing to do for commit
187 ip_commit(struct snmp_context *ctx __unused)
192 * Retrieve an IP address
195 ip_get(struct snmp_value *value, u_char *valp)
197 value->v.ipaddress[0] = valp[0];
198 value->v.ipaddress[1] = valp[1];
199 value->v.ipaddress[2] = valp[2];
200 value->v.ipaddress[3] = valp[3];
202 return (SNMP_ERR_NOERROR);
208 * Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
211 oid_save(struct snmp_value *value, struct snmp_context *ctx,
214 if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL)
215 return (SNMP_ERR_RES_UNAVAIL);
216 *(struct asn_oid *)ctx->scratch->ptr1 = *oid;
223 oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
225 *oid = *(struct asn_oid *)ctx->scratch->ptr1;
226 free(ctx->scratch->ptr1);
230 oid_commit(struct snmp_context *ctx)
232 free(ctx->scratch->ptr1);
236 oid_get(struct snmp_value *value, const struct asn_oid *oid)
239 return (SNMP_ERR_NOERROR);
246 index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
255 index_count = SNMP_INDEX_COUNT(code);
258 for (idx = 0; idx < index_count; idx++) {
259 switch (SNMP_INDEX(code, idx)) {
261 case SNMP_SYNTAX_NULL:
264 case SNMP_SYNTAX_INTEGER:
267 *va_arg(ap, int32_t *) = oid->subs[sub++];
270 case SNMP_SYNTAX_COUNTER64:
273 *va_arg(ap, u_int64_t *) = oid->subs[sub++];
276 case SNMP_SYNTAX_OCTETSTRING:
282 /* only variable size supported */
285 cval = va_arg(ap, u_char **);
286 sval = va_arg(ap, size_t *);
287 *sval = oid->subs[sub++];
288 if (sub + *sval > oid->len)
290 if ((*cval = malloc(*sval)) == NULL) {
291 syslog(LOG_ERR, "%s: %m", __func__);
294 octs[nocts++] = *cval;
295 for (i = 0; i < *sval; i++) {
296 if (oid->subs[sub] > 0xff)
298 (*cval)[i] = oid->subs[sub++];
303 case SNMP_SYNTAX_OID:
305 struct asn_oid *aval;
310 aval = va_arg(ap, struct asn_oid *);
311 aval->len = oid->subs[sub++];
312 if (aval->len > ASN_MAXOIDLEN)
314 for (i = 0; i < aval->len; i++)
315 aval->subs[i] = oid->subs[sub++];
319 case SNMP_SYNTAX_IPADDRESS:
324 if (sub + 4 > oid->len)
326 pval = va_arg(ap, u_int8_t *);
327 for (i = 0; i < 4; i++) {
328 if (oid->subs[sub] > 0xff)
330 pval[i] = oid->subs[sub++];
335 case SNMP_SYNTAX_COUNTER:
336 case SNMP_SYNTAX_GAUGE:
337 case SNMP_SYNTAX_TIMETICKS:
340 if (oid->subs[sub] > 0xffffffff)
342 *va_arg(ap, u_int32_t *) = oid->subs[sub++];
358 * Compare the index part of an OID and an index.
361 index_compare_off(const struct asn_oid *oid, u_int sub,
362 const struct asn_oid *idx, u_int off)
366 for (i = off; i < idx->len && i < oid->len - sub; i++) {
367 if (oid->subs[sub + i] < idx->subs[i])
369 if (oid->subs[sub + i] > idx->subs[i])
372 if (oid->len - sub < idx->len)
374 if (oid->len - sub > idx->len)
381 index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
383 return (index_compare_off(oid, sub, idx, 0));
387 * Append an index to an oid
390 index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
395 var->len = sub + idx->len;
396 for (i = off; i < idx->len; i++)
397 var->subs[sub + i] = idx->subs[i];
400 index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
402 index_append_off(var, sub, idx, 0);