xref: /freebsd/contrib/bsnmp/snmpd/export.c (revision 560c5ef9a22baa2915380cfb6eccc7962c1e5d15)
1f06ca4afSHartmut Brandt /*
2f06ca4afSHartmut Brandt  * Copyright (c) 2001-2003
3f06ca4afSHartmut Brandt  *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4f06ca4afSHartmut Brandt  *	All rights reserved.
5f06ca4afSHartmut Brandt  *
6f06ca4afSHartmut Brandt  * Author: Harti Brandt <harti@freebsd.org>
7f06ca4afSHartmut Brandt  *
8896052c1SHartmut Brandt  * Redistribution and use in source and binary forms, with or without
9896052c1SHartmut Brandt  * modification, are permitted provided that the following conditions
10896052c1SHartmut Brandt  * are met:
11896052c1SHartmut Brandt  * 1. Redistributions of source code must retain the above copyright
12896052c1SHartmut Brandt  *    notice, this list of conditions and the following disclaimer.
13f06ca4afSHartmut Brandt  * 2. Redistributions in binary form must reproduce the above copyright
14f06ca4afSHartmut Brandt  *    notice, this list of conditions and the following disclaimer in the
15f06ca4afSHartmut Brandt  *    documentation and/or other materials provided with the distribution.
16f06ca4afSHartmut Brandt  *
17896052c1SHartmut Brandt  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18896052c1SHartmut Brandt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19896052c1SHartmut Brandt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20896052c1SHartmut Brandt  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21896052c1SHartmut Brandt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22896052c1SHartmut Brandt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23896052c1SHartmut Brandt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24896052c1SHartmut Brandt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25896052c1SHartmut Brandt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26896052c1SHartmut Brandt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27896052c1SHartmut Brandt  * SUCH DAMAGE.
28f06ca4afSHartmut Brandt  *
29748b5b1eSHartmut Brandt  * $Begemot: bsnmp/snmpd/export.c,v 1.8 2006/02/14 09:04:20 brandt_h Exp $
30f06ca4afSHartmut Brandt  *
31f06ca4afSHartmut Brandt  * Support functions for modules.
32f06ca4afSHartmut Brandt  */
33f06ca4afSHartmut Brandt #include <sys/types.h>
34135f7de5SShteryana Shopova #include <sys/queue.h>
35f06ca4afSHartmut Brandt #include <sys/un.h>
36f06ca4afSHartmut Brandt #include <stdio.h>
37f06ca4afSHartmut Brandt #include <stdlib.h>
38f06ca4afSHartmut Brandt #include <string.h>
39f06ca4afSHartmut Brandt #include <syslog.h>
40f06ca4afSHartmut Brandt #include <stdarg.h>
41f06ca4afSHartmut Brandt 
42f06ca4afSHartmut Brandt #include "snmpmod.h"
43f06ca4afSHartmut Brandt #include "snmpd.h"
44f06ca4afSHartmut Brandt #include "tree.h"
45f06ca4afSHartmut Brandt 
46f06ca4afSHartmut Brandt /*
47f06ca4afSHartmut Brandt  * Support functions
48f06ca4afSHartmut Brandt  */
49f06ca4afSHartmut Brandt 
50f06ca4afSHartmut Brandt /*
51f06ca4afSHartmut Brandt  * This is user for SET of string variables. If 'req' is not -1 then
52f06ca4afSHartmut Brandt  * the arguments is checked to be of that length. The old value is saved
53f06ca4afSHartmut Brandt  * in scratch->ptr1 and the new value is allocated and copied.
54f06ca4afSHartmut Brandt  * If there is an old values it must have been allocated by malloc.
55f06ca4afSHartmut Brandt  */
56f06ca4afSHartmut Brandt int
string_save(struct snmp_value * value,struct snmp_context * ctx,ssize_t req_size,u_char ** valp)57f06ca4afSHartmut Brandt string_save(struct snmp_value *value, struct snmp_context *ctx,
58f06ca4afSHartmut Brandt     ssize_t req_size, u_char **valp)
59f06ca4afSHartmut Brandt {
60f06ca4afSHartmut Brandt 	if (req_size != -1 && value->v.octetstring.len != (u_long)req_size)
61f06ca4afSHartmut Brandt 		return (SNMP_ERR_BADVALUE);
62f06ca4afSHartmut Brandt 
63f06ca4afSHartmut Brandt 	ctx->scratch->ptr1 = *valp;
64f06ca4afSHartmut Brandt 
65f06ca4afSHartmut Brandt 	if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) {
66f06ca4afSHartmut Brandt 		*valp = ctx->scratch->ptr1;
67f06ca4afSHartmut Brandt 		return (SNMP_ERR_RES_UNAVAIL);
68f06ca4afSHartmut Brandt 	}
69f06ca4afSHartmut Brandt 
70f06ca4afSHartmut Brandt 	memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len);
71f06ca4afSHartmut Brandt 	(*valp)[value->v.octetstring.len] = '\0';
72f06ca4afSHartmut Brandt 
73f06ca4afSHartmut Brandt 	return (0);
74f06ca4afSHartmut Brandt }
75f06ca4afSHartmut Brandt 
76f06ca4afSHartmut Brandt /*
77f06ca4afSHartmut Brandt  * Commit a string. This is easy - free the old value.
78f06ca4afSHartmut Brandt  */
79f06ca4afSHartmut Brandt void
string_commit(struct snmp_context * ctx)80f06ca4afSHartmut Brandt string_commit(struct snmp_context *ctx)
81f06ca4afSHartmut Brandt {
82f06ca4afSHartmut Brandt 	free(ctx->scratch->ptr1);
83f06ca4afSHartmut Brandt }
84f06ca4afSHartmut Brandt 
85f06ca4afSHartmut Brandt /*
86f06ca4afSHartmut Brandt  * Rollback a string - free new value and copy back old one.
87f06ca4afSHartmut Brandt  */
88f06ca4afSHartmut Brandt void
string_rollback(struct snmp_context * ctx,u_char ** valp)89f06ca4afSHartmut Brandt string_rollback(struct snmp_context *ctx, u_char **valp)
90f06ca4afSHartmut Brandt {
91f06ca4afSHartmut Brandt 	free(*valp);
92f06ca4afSHartmut Brandt 	*valp = ctx->scratch->ptr1;
93f06ca4afSHartmut Brandt }
94f06ca4afSHartmut Brandt 
95f06ca4afSHartmut Brandt /*
96f06ca4afSHartmut Brandt  * ROLLBACK or COMMIT fails because instance has disappeared. Free string.
97f06ca4afSHartmut Brandt  */
98f06ca4afSHartmut Brandt void
string_free(struct snmp_context * ctx)99f06ca4afSHartmut Brandt string_free(struct snmp_context *ctx)
100f06ca4afSHartmut Brandt {
101f06ca4afSHartmut Brandt 	free(ctx->scratch->ptr1);
102f06ca4afSHartmut Brandt }
103f06ca4afSHartmut Brandt 
104f06ca4afSHartmut Brandt /*
105f06ca4afSHartmut Brandt  * Get a string value for a response packet
106f06ca4afSHartmut Brandt  */
107f06ca4afSHartmut Brandt int
string_get(struct snmp_value * value,const u_char * ptr,ssize_t len)108f06ca4afSHartmut Brandt string_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
109f06ca4afSHartmut Brandt {
110f06ca4afSHartmut Brandt 	if (ptr == NULL) {
111f06ca4afSHartmut Brandt 		value->v.octetstring.len = 0;
112f06ca4afSHartmut Brandt 		value->v.octetstring.octets = NULL;
113f06ca4afSHartmut Brandt 		return (SNMP_ERR_NOERROR);
114f06ca4afSHartmut Brandt 	}
115f06ca4afSHartmut Brandt 	if (len == -1)
116f06ca4afSHartmut Brandt 		len = strlen(ptr);
117*560c5ef9SEnji Cooper 	if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL) {
118*560c5ef9SEnji Cooper 		value->v.octetstring.len = 0;
119f06ca4afSHartmut Brandt 		return (SNMP_ERR_RES_UNAVAIL);
120*560c5ef9SEnji Cooper 	}
121*560c5ef9SEnji Cooper 	value->v.octetstring.len = (u_long)len;
122f06ca4afSHartmut Brandt 	memcpy(value->v.octetstring.octets, ptr, (size_t)len);
123f06ca4afSHartmut Brandt 	return (SNMP_ERR_NOERROR);
124f06ca4afSHartmut Brandt }
125f06ca4afSHartmut Brandt 
126f06ca4afSHartmut Brandt /*
127fa122c20SHartmut Brandt  * Get a string value for a response packet but cut it if it is too long.
128fa122c20SHartmut Brandt  */
129fa122c20SHartmut Brandt int
string_get_max(struct snmp_value * value,const u_char * ptr,ssize_t len,size_t maxlen)130fa122c20SHartmut Brandt string_get_max(struct snmp_value *value, const u_char *ptr, ssize_t len,
131fa122c20SHartmut Brandt     size_t maxlen)
132fa122c20SHartmut Brandt {
133fa122c20SHartmut Brandt 
134fa122c20SHartmut Brandt 	if (ptr == NULL) {
135fa122c20SHartmut Brandt 		value->v.octetstring.len = 0;
136fa122c20SHartmut Brandt 		value->v.octetstring.octets = NULL;
137fa122c20SHartmut Brandt 		return (SNMP_ERR_NOERROR);
138fa122c20SHartmut Brandt 	}
139fa122c20SHartmut Brandt 	if (len == -1)
140fa122c20SHartmut Brandt 		len = strlen(ptr);
141fa122c20SHartmut Brandt 	if ((size_t)len > maxlen)
142fa122c20SHartmut Brandt 		len = maxlen;
143*560c5ef9SEnji Cooper 	if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL) {
144*560c5ef9SEnji Cooper 		value->v.octetstring.len = 0;
145fa122c20SHartmut Brandt 		return (SNMP_ERR_RES_UNAVAIL);
146*560c5ef9SEnji Cooper 	}
147*560c5ef9SEnji Cooper 	value->v.octetstring.len = (u_long)len;
148fa122c20SHartmut Brandt 	memcpy(value->v.octetstring.octets, ptr, (size_t)len);
149fa122c20SHartmut Brandt 	return (SNMP_ERR_NOERROR);
150fa122c20SHartmut Brandt }
151fa122c20SHartmut Brandt 
152fa122c20SHartmut Brandt /*
153f06ca4afSHartmut Brandt  * Support for IPADDRESS
154f06ca4afSHartmut Brandt  *
155f06ca4afSHartmut Brandt  * Save the old IP address in scratch->int1 and set the new one.
156f06ca4afSHartmut Brandt  */
157f06ca4afSHartmut Brandt int
ip_save(struct snmp_value * value,struct snmp_context * ctx,u_char * valp)158f06ca4afSHartmut Brandt ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp)
159f06ca4afSHartmut Brandt {
160f06ca4afSHartmut Brandt 	ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8)
161f06ca4afSHartmut Brandt 	    | valp[3];
162f06ca4afSHartmut Brandt 
163f06ca4afSHartmut Brandt 	valp[0] = value->v.ipaddress[0];
164f06ca4afSHartmut Brandt 	valp[1] = value->v.ipaddress[1];
165f06ca4afSHartmut Brandt 	valp[2] = value->v.ipaddress[2];
166f06ca4afSHartmut Brandt 	valp[3] = value->v.ipaddress[3];
167f06ca4afSHartmut Brandt 
168f06ca4afSHartmut Brandt 	return (0);
169f06ca4afSHartmut Brandt }
170f06ca4afSHartmut Brandt 
171f06ca4afSHartmut Brandt /*
172f06ca4afSHartmut Brandt  * Rollback the address by copying back the old one
173f06ca4afSHartmut Brandt  */
174f06ca4afSHartmut Brandt void
ip_rollback(struct snmp_context * ctx,u_char * valp)175f06ca4afSHartmut Brandt ip_rollback(struct snmp_context *ctx, u_char *valp)
176f06ca4afSHartmut Brandt {
177f06ca4afSHartmut Brandt 	valp[0] = ctx->scratch->int1 >> 24;
178f06ca4afSHartmut Brandt 	valp[1] = ctx->scratch->int1 >> 16;
179f06ca4afSHartmut Brandt 	valp[2] = ctx->scratch->int1 >> 8;
180f06ca4afSHartmut Brandt 	valp[3] = ctx->scratch->int1;
181f06ca4afSHartmut Brandt }
182f06ca4afSHartmut Brandt 
183f06ca4afSHartmut Brandt /*
184f06ca4afSHartmut Brandt  * Nothing to do for commit
185f06ca4afSHartmut Brandt  */
186f06ca4afSHartmut Brandt void
ip_commit(struct snmp_context * ctx __unused)187f06ca4afSHartmut Brandt ip_commit(struct snmp_context *ctx __unused)
188f06ca4afSHartmut Brandt {
189f06ca4afSHartmut Brandt }
190f06ca4afSHartmut Brandt 
191f06ca4afSHartmut Brandt /*
192f06ca4afSHartmut Brandt  * Retrieve an IP address
193f06ca4afSHartmut Brandt  */
194f06ca4afSHartmut Brandt int
ip_get(struct snmp_value * value,u_char * valp)195f06ca4afSHartmut Brandt ip_get(struct snmp_value *value, u_char *valp)
196f06ca4afSHartmut Brandt {
197f06ca4afSHartmut Brandt 	value->v.ipaddress[0] = valp[0];
198f06ca4afSHartmut Brandt 	value->v.ipaddress[1] = valp[1];
199f06ca4afSHartmut Brandt 	value->v.ipaddress[2] = valp[2];
200f06ca4afSHartmut Brandt 	value->v.ipaddress[3] = valp[3];
201b3972edbSEnji Cooper 
202f06ca4afSHartmut Brandt 	return (SNMP_ERR_NOERROR);
203f06ca4afSHartmut Brandt }
204f06ca4afSHartmut Brandt 
205f06ca4afSHartmut Brandt /*
206f06ca4afSHartmut Brandt  * Object ID support
207f06ca4afSHartmut Brandt  *
208f06ca4afSHartmut Brandt  * Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
209f06ca4afSHartmut Brandt  */
210f06ca4afSHartmut Brandt int
oid_save(struct snmp_value * value,struct snmp_context * ctx,struct asn_oid * oid)211f06ca4afSHartmut Brandt oid_save(struct snmp_value *value, struct snmp_context *ctx,
212f06ca4afSHartmut Brandt     struct asn_oid *oid)
213f06ca4afSHartmut Brandt {
214f06ca4afSHartmut Brandt 	if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL)
215f06ca4afSHartmut Brandt 		return (SNMP_ERR_RES_UNAVAIL);
216f06ca4afSHartmut Brandt 	*(struct asn_oid *)ctx->scratch->ptr1 = *oid;
217f06ca4afSHartmut Brandt 	*oid = value->v.oid;
218f06ca4afSHartmut Brandt 
219f06ca4afSHartmut Brandt 	return (0);
220f06ca4afSHartmut Brandt }
221f06ca4afSHartmut Brandt 
222f06ca4afSHartmut Brandt void
oid_rollback(struct snmp_context * ctx,struct asn_oid * oid)223f06ca4afSHartmut Brandt oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
224f06ca4afSHartmut Brandt {
225f06ca4afSHartmut Brandt 	*oid = *(struct asn_oid *)ctx->scratch->ptr1;
226f06ca4afSHartmut Brandt 	free(ctx->scratch->ptr1);
227f06ca4afSHartmut Brandt }
228f06ca4afSHartmut Brandt 
229f06ca4afSHartmut Brandt void
oid_commit(struct snmp_context * ctx)230f06ca4afSHartmut Brandt oid_commit(struct snmp_context *ctx)
231f06ca4afSHartmut Brandt {
232f06ca4afSHartmut Brandt 	free(ctx->scratch->ptr1);
233f06ca4afSHartmut Brandt }
234f06ca4afSHartmut Brandt 
235f06ca4afSHartmut Brandt int
oid_get(struct snmp_value * value,const struct asn_oid * oid)236f06ca4afSHartmut Brandt oid_get(struct snmp_value *value, const struct asn_oid *oid)
237f06ca4afSHartmut Brandt {
238f06ca4afSHartmut Brandt 	value->v.oid = *oid;
239f06ca4afSHartmut Brandt 	return (SNMP_ERR_NOERROR);
240f06ca4afSHartmut Brandt }
241f06ca4afSHartmut Brandt 
242f06ca4afSHartmut Brandt /*
243f06ca4afSHartmut Brandt  * Decode an index
244f06ca4afSHartmut Brandt  */
245f06ca4afSHartmut Brandt int
index_decode(const struct asn_oid * oid,u_int sub,u_int code,...)246f06ca4afSHartmut Brandt index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
247f06ca4afSHartmut Brandt {
248f06ca4afSHartmut Brandt 	va_list ap;
249f06ca4afSHartmut Brandt 	u_int index_count;
250f06ca4afSHartmut Brandt 	void *octs[10];
251f06ca4afSHartmut Brandt 	u_int nocts;
252f06ca4afSHartmut Brandt 	u_int idx;
253f06ca4afSHartmut Brandt 
254f06ca4afSHartmut Brandt 	va_start(ap, code);
255f06ca4afSHartmut Brandt 	index_count = SNMP_INDEX_COUNT(code);
256f06ca4afSHartmut Brandt 	nocts = 0;
257f06ca4afSHartmut Brandt 
258f06ca4afSHartmut Brandt 	for (idx = 0; idx < index_count; idx++) {
259f06ca4afSHartmut Brandt 		switch (SNMP_INDEX(code, idx)) {
260f06ca4afSHartmut Brandt 
261f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_NULL:
262f06ca4afSHartmut Brandt 			break;
263f06ca4afSHartmut Brandt 
264f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_INTEGER:
265f06ca4afSHartmut Brandt 			if (sub == oid->len)
266f06ca4afSHartmut Brandt 				goto err;
267f06ca4afSHartmut Brandt 			*va_arg(ap, int32_t *) = oid->subs[sub++];
268f06ca4afSHartmut Brandt 			break;
269f06ca4afSHartmut Brandt 
270f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_COUNTER64:
271f06ca4afSHartmut Brandt 			if (sub == oid->len)
272f06ca4afSHartmut Brandt 				goto err;
273f06ca4afSHartmut Brandt 			*va_arg(ap, u_int64_t *) = oid->subs[sub++];
274f06ca4afSHartmut Brandt 			break;
275f06ca4afSHartmut Brandt 
276f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_OCTETSTRING:
277f06ca4afSHartmut Brandt 		    {
278f06ca4afSHartmut Brandt 			u_char **cval;
279f06ca4afSHartmut Brandt 			size_t *sval;
280f06ca4afSHartmut Brandt 			u_int i;
281f06ca4afSHartmut Brandt 
282f06ca4afSHartmut Brandt 			/* only variable size supported */
283f06ca4afSHartmut Brandt 			if (sub == oid->len)
284f06ca4afSHartmut Brandt 				goto err;
285f06ca4afSHartmut Brandt 			cval = va_arg(ap, u_char **);
286f06ca4afSHartmut Brandt 			sval = va_arg(ap, size_t *);
287f06ca4afSHartmut Brandt 			*sval = oid->subs[sub++];
288f06ca4afSHartmut Brandt 			if (sub + *sval > oid->len)
289f06ca4afSHartmut Brandt 				goto err;
290f06ca4afSHartmut Brandt 			if ((*cval = malloc(*sval)) == NULL) {
291f06ca4afSHartmut Brandt 				syslog(LOG_ERR, "%s: %m", __func__);
292f06ca4afSHartmut Brandt 				goto err;
293f06ca4afSHartmut Brandt 			}
294f06ca4afSHartmut Brandt 			octs[nocts++] = *cval;
295f06ca4afSHartmut Brandt 			for (i = 0; i < *sval; i++) {
296f06ca4afSHartmut Brandt 				if (oid->subs[sub] > 0xff)
297f06ca4afSHartmut Brandt 					goto err;
298f06ca4afSHartmut Brandt 				(*cval)[i] = oid->subs[sub++];
299f06ca4afSHartmut Brandt 			}
300f06ca4afSHartmut Brandt 			break;
301f06ca4afSHartmut Brandt 		    }
302f06ca4afSHartmut Brandt 
303f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_OID:
304f06ca4afSHartmut Brandt 		    {
305f06ca4afSHartmut Brandt 			struct asn_oid *aval;
306f06ca4afSHartmut Brandt 			u_int i;
307f06ca4afSHartmut Brandt 
308f06ca4afSHartmut Brandt 			if (sub == oid->len)
309f06ca4afSHartmut Brandt 				goto err;
310f06ca4afSHartmut Brandt 			aval = va_arg(ap, struct asn_oid *);
311f06ca4afSHartmut Brandt 			aval->len = oid->subs[sub++];
312f06ca4afSHartmut Brandt 			if (aval->len > ASN_MAXOIDLEN)
313f06ca4afSHartmut Brandt 				goto err;
314f06ca4afSHartmut Brandt 			for (i = 0; i < aval->len; i++)
315f06ca4afSHartmut Brandt 				aval->subs[i] = oid->subs[sub++];
316f06ca4afSHartmut Brandt 			break;
317f06ca4afSHartmut Brandt 		    }
318f06ca4afSHartmut Brandt 
319f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_IPADDRESS:
320f06ca4afSHartmut Brandt 		    {
321f06ca4afSHartmut Brandt 			u_int8_t *pval;
322f06ca4afSHartmut Brandt 			u_int i;
323f06ca4afSHartmut Brandt 
324f06ca4afSHartmut Brandt 			if (sub + 4 > oid->len)
325f06ca4afSHartmut Brandt 				goto err;
326f06ca4afSHartmut Brandt 			pval = va_arg(ap, u_int8_t *);
327f06ca4afSHartmut Brandt 			for (i = 0; i < 4; i++) {
328f06ca4afSHartmut Brandt 				if (oid->subs[sub] > 0xff)
329f06ca4afSHartmut Brandt 					goto err;
330f06ca4afSHartmut Brandt 				pval[i] = oid->subs[sub++];
331f06ca4afSHartmut Brandt 			}
332f06ca4afSHartmut Brandt 			break;
333f06ca4afSHartmut Brandt 		    }
334f06ca4afSHartmut Brandt 
335f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_COUNTER:
336f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_GAUGE:
337f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_TIMETICKS:
338f06ca4afSHartmut Brandt 			if (sub == oid->len)
339f06ca4afSHartmut Brandt 				goto err;
340f06ca4afSHartmut Brandt 			if (oid->subs[sub] > 0xffffffff)
341f06ca4afSHartmut Brandt 				goto err;
342f06ca4afSHartmut Brandt 			*va_arg(ap, u_int32_t *) = oid->subs[sub++];
343f06ca4afSHartmut Brandt 			break;
344f06ca4afSHartmut Brandt 		}
345f06ca4afSHartmut Brandt 	}
346f06ca4afSHartmut Brandt 
347f06ca4afSHartmut Brandt 	va_end(ap);
348f06ca4afSHartmut Brandt 	return (0);
349f06ca4afSHartmut Brandt 
350f06ca4afSHartmut Brandt   err:
351f06ca4afSHartmut Brandt 	va_end(ap);
352f06ca4afSHartmut Brandt 	while(nocts > 0)
353f06ca4afSHartmut Brandt 		free(octs[--nocts]);
354f06ca4afSHartmut Brandt 	return (-1);
355f06ca4afSHartmut Brandt }
356f06ca4afSHartmut Brandt 
357f06ca4afSHartmut Brandt /*
358f06ca4afSHartmut Brandt  * Compare the index part of an OID and an index.
359f06ca4afSHartmut Brandt  */
360f06ca4afSHartmut Brandt int
index_compare_off(const struct asn_oid * oid,u_int sub,const struct asn_oid * idx,u_int off)361f06ca4afSHartmut Brandt index_compare_off(const struct asn_oid *oid, u_int sub,
362f06ca4afSHartmut Brandt     const struct asn_oid *idx, u_int off)
363f06ca4afSHartmut Brandt {
364f06ca4afSHartmut Brandt 	u_int i;
365f06ca4afSHartmut Brandt 
366f06ca4afSHartmut Brandt 	for (i = off; i < idx->len && i < oid->len - sub; i++) {
367f06ca4afSHartmut Brandt 		if (oid->subs[sub + i] < idx->subs[i])
368f06ca4afSHartmut Brandt 			return (-1);
369f06ca4afSHartmut Brandt 		if (oid->subs[sub + i] > idx->subs[i])
370f06ca4afSHartmut Brandt 			return (+1);
371f06ca4afSHartmut Brandt 	}
372f06ca4afSHartmut Brandt 	if (oid->len - sub < idx->len)
373f06ca4afSHartmut Brandt 		return (-1);
374f06ca4afSHartmut Brandt 	if (oid->len - sub > idx->len)
375f06ca4afSHartmut Brandt 		return (+1);
376f06ca4afSHartmut Brandt 
377f06ca4afSHartmut Brandt 	return (0);
378f06ca4afSHartmut Brandt }
379f06ca4afSHartmut Brandt 
380f06ca4afSHartmut Brandt int
index_compare(const struct asn_oid * oid,u_int sub,const struct asn_oid * idx)381f06ca4afSHartmut Brandt index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
382f06ca4afSHartmut Brandt {
383f06ca4afSHartmut Brandt 	return (index_compare_off(oid, sub, idx, 0));
384f06ca4afSHartmut Brandt }
385f06ca4afSHartmut Brandt 
386f06ca4afSHartmut Brandt /*
387f06ca4afSHartmut Brandt  * Append an index to an oid
388f06ca4afSHartmut Brandt  */
389f06ca4afSHartmut Brandt void
index_append_off(struct asn_oid * var,u_int sub,const struct asn_oid * idx,u_int off)390f06ca4afSHartmut Brandt index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
391f06ca4afSHartmut Brandt     u_int off)
392f06ca4afSHartmut Brandt {
393f06ca4afSHartmut Brandt 	u_int i;
394f06ca4afSHartmut Brandt 
395f06ca4afSHartmut Brandt 	var->len = sub + idx->len;
396f06ca4afSHartmut Brandt 	for (i = off; i < idx->len; i++)
397f06ca4afSHartmut Brandt 		var->subs[sub + i] = idx->subs[i];
398f06ca4afSHartmut Brandt }
399f06ca4afSHartmut Brandt void
index_append(struct asn_oid * var,u_int sub,const struct asn_oid * idx)400f06ca4afSHartmut Brandt index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
401f06ca4afSHartmut Brandt {
402f06ca4afSHartmut Brandt 	index_append_off(var, sub, idx, 0);
403f06ca4afSHartmut Brandt }
404f06ca4afSHartmut Brandt 
405