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>
50 * This is user for SET of string variables. If 'req' is not -1 then
51 * the arguments is checked to be of that length. The old value is saved
52 * in scratch->ptr1 and the new value is allocated and copied.
53 * If there is an old values it must have been allocated by malloc.
56 string_save(struct snmp_value *value, struct snmp_context *ctx,
57 ssize_t req_size, u_char **valp)
59 if (req_size != -1 && value->v.octetstring.len != (u_long)req_size)
60 return (SNMP_ERR_BADVALUE);
62 ctx->scratch->ptr1 = *valp;
64 if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) {
65 *valp = ctx->scratch->ptr1;
66 return (SNMP_ERR_RES_UNAVAIL);
69 memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len);
70 (*valp)[value->v.octetstring.len] = '\0';
76 * Commit a string. This is easy - free the old value.
79 string_commit(struct snmp_context *ctx)
81 free(ctx->scratch->ptr1);
85 * Rollback a string - free new value and copy back old one.
88 string_rollback(struct snmp_context *ctx, u_char **valp)
91 *valp = ctx->scratch->ptr1;
95 * ROLLBACK or COMMIT fails because instance has disappeared. Free string.
98 string_free(struct snmp_context *ctx)
100 free(ctx->scratch->ptr1);
104 * Get a string value for a response packet
107 string_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
110 value->v.octetstring.len = 0;
111 value->v.octetstring.octets = NULL;
112 return (SNMP_ERR_NOERROR);
116 value->v.octetstring.len = (u_long)len;
117 if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL)
118 return (SNMP_ERR_RES_UNAVAIL);
119 memcpy(value->v.octetstring.octets, ptr, (size_t)len);
120 return (SNMP_ERR_NOERROR);
124 * Get a string value for a response packet but cut it if it is too long.
127 string_get_max(struct snmp_value *value, const u_char *ptr, ssize_t len,
132 value->v.octetstring.len = 0;
133 value->v.octetstring.octets = NULL;
134 return (SNMP_ERR_NOERROR);
138 if ((size_t)len > maxlen)
140 value->v.octetstring.len = (u_long)len;
141 if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL)
142 return (SNMP_ERR_RES_UNAVAIL);
143 memcpy(value->v.octetstring.octets, ptr, (size_t)len);
144 return (SNMP_ERR_NOERROR);
148 * Support for IPADDRESS
150 * Save the old IP address in scratch->int1 and set the new one.
153 ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp)
155 ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8)
158 valp[0] = value->v.ipaddress[0];
159 valp[1] = value->v.ipaddress[1];
160 valp[2] = value->v.ipaddress[2];
161 valp[3] = value->v.ipaddress[3];
167 * Rollback the address by copying back the old one
170 ip_rollback(struct snmp_context *ctx, u_char *valp)
172 valp[0] = ctx->scratch->int1 >> 24;
173 valp[1] = ctx->scratch->int1 >> 16;
174 valp[2] = ctx->scratch->int1 >> 8;
175 valp[3] = ctx->scratch->int1;
179 * Nothing to do for commit
182 ip_commit(struct snmp_context *ctx __unused)
187 * Retrieve an IP address
190 ip_get(struct snmp_value *value, u_char *valp)
192 value->v.ipaddress[0] = valp[0];
193 value->v.ipaddress[1] = valp[1];
194 value->v.ipaddress[2] = valp[2];
195 value->v.ipaddress[3] = valp[3];
196 return (SNMP_ERR_NOERROR);
202 * Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
205 oid_save(struct snmp_value *value, struct snmp_context *ctx,
208 if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL)
209 return (SNMP_ERR_RES_UNAVAIL);
210 *(struct asn_oid *)ctx->scratch->ptr1 = *oid;
217 oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
219 *oid = *(struct asn_oid *)ctx->scratch->ptr1;
220 free(ctx->scratch->ptr1);
224 oid_commit(struct snmp_context *ctx)
226 free(ctx->scratch->ptr1);
230 oid_get(struct snmp_value *value, const struct asn_oid *oid)
233 return (SNMP_ERR_NOERROR);
240 index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
249 index_count = SNMP_INDEX_COUNT(code);
252 for (idx = 0; idx < index_count; idx++) {
253 switch (SNMP_INDEX(code, idx)) {
255 case SNMP_SYNTAX_NULL:
258 case SNMP_SYNTAX_INTEGER:
261 *va_arg(ap, int32_t *) = oid->subs[sub++];
264 case SNMP_SYNTAX_COUNTER64:
267 *va_arg(ap, u_int64_t *) = oid->subs[sub++];
270 case SNMP_SYNTAX_OCTETSTRING:
276 /* only variable size supported */
279 cval = va_arg(ap, u_char **);
280 sval = va_arg(ap, size_t *);
281 *sval = oid->subs[sub++];
282 if (sub + *sval > oid->len)
284 if ((*cval = malloc(*sval)) == NULL) {
285 syslog(LOG_ERR, "%s: %m", __func__);
288 octs[nocts++] = *cval;
289 for (i = 0; i < *sval; i++) {
290 if (oid->subs[sub] > 0xff)
292 (*cval)[i] = oid->subs[sub++];
297 case SNMP_SYNTAX_OID:
299 struct asn_oid *aval;
304 aval = va_arg(ap, struct asn_oid *);
305 aval->len = oid->subs[sub++];
306 if (aval->len > ASN_MAXOIDLEN)
308 for (i = 0; i < aval->len; i++)
309 aval->subs[i] = oid->subs[sub++];
313 case SNMP_SYNTAX_IPADDRESS:
318 if (sub + 4 > oid->len)
320 pval = va_arg(ap, u_int8_t *);
321 for (i = 0; i < 4; i++) {
322 if (oid->subs[sub] > 0xff)
324 pval[i] = oid->subs[sub++];
329 case SNMP_SYNTAX_COUNTER:
330 case SNMP_SYNTAX_GAUGE:
331 case SNMP_SYNTAX_TIMETICKS:
334 if (oid->subs[sub] > 0xffffffff)
336 *va_arg(ap, u_int32_t *) = oid->subs[sub++];
352 * Compare the index part of an OID and an index.
355 index_compare_off(const struct asn_oid *oid, u_int sub,
356 const struct asn_oid *idx, u_int off)
360 for (i = off; i < idx->len && i < oid->len - sub; i++) {
361 if (oid->subs[sub + i] < idx->subs[i])
363 if (oid->subs[sub + i] > idx->subs[i])
366 if (oid->len - sub < idx->len)
368 if (oid->len - sub > idx->len)
375 index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
377 return (index_compare_off(oid, sub, idx, 0));
381 * Append an index to an oid
384 index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
389 var->len = sub + idx->len;
390 for (i = off; i < idx->len; i++)
391 var->subs[sub + i] = idx->subs[i];
394 index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
396 index_append_off(var, sub, idx, 0);