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];
197 return (SNMP_ERR_NOERROR);
203 * Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
206 oid_save(struct snmp_value *value, struct snmp_context *ctx,
209 if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL)
210 return (SNMP_ERR_RES_UNAVAIL);
211 *(struct asn_oid *)ctx->scratch->ptr1 = *oid;
218 oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
220 *oid = *(struct asn_oid *)ctx->scratch->ptr1;
221 free(ctx->scratch->ptr1);
225 oid_commit(struct snmp_context *ctx)
227 free(ctx->scratch->ptr1);
231 oid_get(struct snmp_value *value, const struct asn_oid *oid)
234 return (SNMP_ERR_NOERROR);
241 index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
250 index_count = SNMP_INDEX_COUNT(code);
253 for (idx = 0; idx < index_count; idx++) {
254 switch (SNMP_INDEX(code, idx)) {
256 case SNMP_SYNTAX_NULL:
259 case SNMP_SYNTAX_INTEGER:
262 *va_arg(ap, int32_t *) = oid->subs[sub++];
265 case SNMP_SYNTAX_COUNTER64:
268 *va_arg(ap, u_int64_t *) = oid->subs[sub++];
271 case SNMP_SYNTAX_OCTETSTRING:
277 /* only variable size supported */
280 cval = va_arg(ap, u_char **);
281 sval = va_arg(ap, size_t *);
282 *sval = oid->subs[sub++];
283 if (sub + *sval > oid->len)
285 if ((*cval = malloc(*sval)) == NULL) {
286 syslog(LOG_ERR, "%s: %m", __func__);
289 octs[nocts++] = *cval;
290 for (i = 0; i < *sval; i++) {
291 if (oid->subs[sub] > 0xff)
293 (*cval)[i] = oid->subs[sub++];
298 case SNMP_SYNTAX_OID:
300 struct asn_oid *aval;
305 aval = va_arg(ap, struct asn_oid *);
306 aval->len = oid->subs[sub++];
307 if (aval->len > ASN_MAXOIDLEN)
309 for (i = 0; i < aval->len; i++)
310 aval->subs[i] = oid->subs[sub++];
314 case SNMP_SYNTAX_IPADDRESS:
319 if (sub + 4 > oid->len)
321 pval = va_arg(ap, u_int8_t *);
322 for (i = 0; i < 4; i++) {
323 if (oid->subs[sub] > 0xff)
325 pval[i] = oid->subs[sub++];
330 case SNMP_SYNTAX_COUNTER:
331 case SNMP_SYNTAX_GAUGE:
332 case SNMP_SYNTAX_TIMETICKS:
335 if (oid->subs[sub] > 0xffffffff)
337 *va_arg(ap, u_int32_t *) = oid->subs[sub++];
353 * Compare the index part of an OID and an index.
356 index_compare_off(const struct asn_oid *oid, u_int sub,
357 const struct asn_oid *idx, u_int off)
361 for (i = off; i < idx->len && i < oid->len - sub; i++) {
362 if (oid->subs[sub + i] < idx->subs[i])
364 if (oid->subs[sub + i] > idx->subs[i])
367 if (oid->len - sub < idx->len)
369 if (oid->len - sub > idx->len)
376 index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
378 return (index_compare_off(oid, sub, idx, 0));
382 * Append an index to an oid
385 index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
390 var->len = sub + idx->len;
391 for (i = off; i < idx->len; i++)
392 var->subs[sub + i] = idx->subs[i];
395 index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
397 index_append_off(var, sub, idx, 0);