xref: /freebsd/contrib/bsnmp/snmpd/export.c (revision 896052c10f33c29a53b63fc67d4c8238b87f5b3e)
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  *
29896052c1SHartmut Brandt  * $Begemot: bsnmp/snmpd/export.c,v 1.7 2004/08/06 08:47:11 brandt Exp $
30f06ca4afSHartmut Brandt  *
31f06ca4afSHartmut Brandt  * Support functions for modules.
32f06ca4afSHartmut Brandt  */
33f06ca4afSHartmut Brandt #include <sys/types.h>
34f06ca4afSHartmut Brandt #include <sys/un.h>
35f06ca4afSHartmut Brandt #include <stdio.h>
36f06ca4afSHartmut Brandt #include <stdlib.h>
37f06ca4afSHartmut Brandt #include <string.h>
38f06ca4afSHartmut Brandt #include <syslog.h>
39f06ca4afSHartmut Brandt #include <stdarg.h>
40f06ca4afSHartmut Brandt 
41f06ca4afSHartmut Brandt #include "snmpmod.h"
42f06ca4afSHartmut Brandt #include "snmpd.h"
43f06ca4afSHartmut Brandt #include "tree.h"
44f06ca4afSHartmut Brandt 
45f06ca4afSHartmut Brandt /*
46f06ca4afSHartmut Brandt  * Support functions
47f06ca4afSHartmut Brandt  */
48f06ca4afSHartmut Brandt 
49f06ca4afSHartmut Brandt /*
50f06ca4afSHartmut Brandt  * This is user for SET of string variables. If 'req' is not -1 then
51f06ca4afSHartmut Brandt  * the arguments is checked to be of that length. The old value is saved
52f06ca4afSHartmut Brandt  * in scratch->ptr1 and the new value is allocated and copied.
53f06ca4afSHartmut Brandt  * If there is an old values it must have been allocated by malloc.
54f06ca4afSHartmut Brandt  */
55f06ca4afSHartmut Brandt int
56f06ca4afSHartmut Brandt string_save(struct snmp_value *value, struct snmp_context *ctx,
57f06ca4afSHartmut Brandt     ssize_t req_size, u_char **valp)
58f06ca4afSHartmut Brandt {
59f06ca4afSHartmut Brandt 	if (req_size != -1 && value->v.octetstring.len != (u_long)req_size)
60f06ca4afSHartmut Brandt 		return (SNMP_ERR_BADVALUE);
61f06ca4afSHartmut Brandt 
62f06ca4afSHartmut Brandt 	ctx->scratch->ptr1 = *valp;
63f06ca4afSHartmut Brandt 
64f06ca4afSHartmut Brandt 	if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) {
65f06ca4afSHartmut Brandt 		*valp = ctx->scratch->ptr1;
66f06ca4afSHartmut Brandt 		return (SNMP_ERR_RES_UNAVAIL);
67f06ca4afSHartmut Brandt 	}
68f06ca4afSHartmut Brandt 
69f06ca4afSHartmut Brandt 	memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len);
70f06ca4afSHartmut Brandt 	(*valp)[value->v.octetstring.len] = '\0';
71f06ca4afSHartmut Brandt 
72f06ca4afSHartmut Brandt 	return (0);
73f06ca4afSHartmut Brandt }
74f06ca4afSHartmut Brandt 
75f06ca4afSHartmut Brandt /*
76f06ca4afSHartmut Brandt  * Commit a string. This is easy - free the old value.
77f06ca4afSHartmut Brandt  */
78f06ca4afSHartmut Brandt void
79f06ca4afSHartmut Brandt string_commit(struct snmp_context *ctx)
80f06ca4afSHartmut Brandt {
81f06ca4afSHartmut Brandt 	free(ctx->scratch->ptr1);
82f06ca4afSHartmut Brandt }
83f06ca4afSHartmut Brandt 
84f06ca4afSHartmut Brandt /*
85f06ca4afSHartmut Brandt  * Rollback a string - free new value and copy back old one.
86f06ca4afSHartmut Brandt  */
87f06ca4afSHartmut Brandt void
88f06ca4afSHartmut Brandt string_rollback(struct snmp_context *ctx, u_char **valp)
89f06ca4afSHartmut Brandt {
90f06ca4afSHartmut Brandt 	free(*valp);
91f06ca4afSHartmut Brandt 	*valp = ctx->scratch->ptr1;
92f06ca4afSHartmut Brandt }
93f06ca4afSHartmut Brandt 
94f06ca4afSHartmut Brandt /*
95f06ca4afSHartmut Brandt  * ROLLBACK or COMMIT fails because instance has disappeared. Free string.
96f06ca4afSHartmut Brandt  */
97f06ca4afSHartmut Brandt void
98f06ca4afSHartmut Brandt string_free(struct snmp_context *ctx)
99f06ca4afSHartmut Brandt {
100f06ca4afSHartmut Brandt 	free(ctx->scratch->ptr1);
101f06ca4afSHartmut Brandt }
102f06ca4afSHartmut Brandt 
103f06ca4afSHartmut Brandt /*
104f06ca4afSHartmut Brandt  * Get a string value for a response packet
105f06ca4afSHartmut Brandt  */
106f06ca4afSHartmut Brandt int
107f06ca4afSHartmut Brandt string_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
108f06ca4afSHartmut Brandt {
109f06ca4afSHartmut Brandt 	if (ptr == NULL) {
110f06ca4afSHartmut Brandt 		value->v.octetstring.len = 0;
111f06ca4afSHartmut Brandt 		value->v.octetstring.octets = NULL;
112f06ca4afSHartmut Brandt 		return (SNMP_ERR_NOERROR);
113f06ca4afSHartmut Brandt 	}
114f06ca4afSHartmut Brandt 	if (len == -1)
115f06ca4afSHartmut Brandt 		len = strlen(ptr);
116f06ca4afSHartmut Brandt 	value->v.octetstring.len = (u_long)len;
117f06ca4afSHartmut Brandt 	if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL)
118f06ca4afSHartmut Brandt 		return (SNMP_ERR_RES_UNAVAIL);
119f06ca4afSHartmut Brandt 	memcpy(value->v.octetstring.octets, ptr, (size_t)len);
120f06ca4afSHartmut Brandt 	return (SNMP_ERR_NOERROR);
121f06ca4afSHartmut Brandt }
122f06ca4afSHartmut Brandt 
123f06ca4afSHartmut Brandt /*
124f06ca4afSHartmut Brandt  * Support for IPADDRESS
125f06ca4afSHartmut Brandt  *
126f06ca4afSHartmut Brandt  * Save the old IP address in scratch->int1 and set the new one.
127f06ca4afSHartmut Brandt  */
128f06ca4afSHartmut Brandt int
129f06ca4afSHartmut Brandt ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp)
130f06ca4afSHartmut Brandt {
131f06ca4afSHartmut Brandt 	ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8)
132f06ca4afSHartmut Brandt 	    | valp[3];
133f06ca4afSHartmut Brandt 
134f06ca4afSHartmut Brandt 	valp[0] = value->v.ipaddress[0];
135f06ca4afSHartmut Brandt 	valp[1] = value->v.ipaddress[1];
136f06ca4afSHartmut Brandt 	valp[2] = value->v.ipaddress[2];
137f06ca4afSHartmut Brandt 	valp[3] = value->v.ipaddress[3];
138f06ca4afSHartmut Brandt 
139f06ca4afSHartmut Brandt 	return (0);
140f06ca4afSHartmut Brandt }
141f06ca4afSHartmut Brandt 
142f06ca4afSHartmut Brandt /*
143f06ca4afSHartmut Brandt  * Rollback the address by copying back the old one
144f06ca4afSHartmut Brandt  */
145f06ca4afSHartmut Brandt void
146f06ca4afSHartmut Brandt ip_rollback(struct snmp_context *ctx, u_char *valp)
147f06ca4afSHartmut Brandt {
148f06ca4afSHartmut Brandt 	valp[0] = ctx->scratch->int1 >> 24;
149f06ca4afSHartmut Brandt 	valp[1] = ctx->scratch->int1 >> 16;
150f06ca4afSHartmut Brandt 	valp[2] = ctx->scratch->int1 >> 8;
151f06ca4afSHartmut Brandt 	valp[3] = ctx->scratch->int1;
152f06ca4afSHartmut Brandt }
153f06ca4afSHartmut Brandt 
154f06ca4afSHartmut Brandt /*
155f06ca4afSHartmut Brandt  * Nothing to do for commit
156f06ca4afSHartmut Brandt  */
157f06ca4afSHartmut Brandt void
158f06ca4afSHartmut Brandt ip_commit(struct snmp_context *ctx __unused)
159f06ca4afSHartmut Brandt {
160f06ca4afSHartmut Brandt }
161f06ca4afSHartmut Brandt 
162f06ca4afSHartmut Brandt /*
163f06ca4afSHartmut Brandt  * Retrieve an IP address
164f06ca4afSHartmut Brandt  */
165f06ca4afSHartmut Brandt int
166f06ca4afSHartmut Brandt ip_get(struct snmp_value *value, u_char *valp)
167f06ca4afSHartmut Brandt {
168f06ca4afSHartmut Brandt 	value->v.ipaddress[0] = valp[0];
169f06ca4afSHartmut Brandt 	value->v.ipaddress[1] = valp[1];
170f06ca4afSHartmut Brandt 	value->v.ipaddress[2] = valp[2];
171f06ca4afSHartmut Brandt 	value->v.ipaddress[3] = valp[3];
172f06ca4afSHartmut Brandt 	return (SNMP_ERR_NOERROR);
173f06ca4afSHartmut Brandt }
174f06ca4afSHartmut Brandt 
175f06ca4afSHartmut Brandt /*
176f06ca4afSHartmut Brandt  * Object ID support
177f06ca4afSHartmut Brandt  *
178f06ca4afSHartmut Brandt  * Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
179f06ca4afSHartmut Brandt  */
180f06ca4afSHartmut Brandt int
181f06ca4afSHartmut Brandt oid_save(struct snmp_value *value, struct snmp_context *ctx,
182f06ca4afSHartmut Brandt     struct asn_oid *oid)
183f06ca4afSHartmut Brandt {
184f06ca4afSHartmut Brandt 	if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL)
185f06ca4afSHartmut Brandt 		return (SNMP_ERR_RES_UNAVAIL);
186f06ca4afSHartmut Brandt 	*(struct asn_oid *)ctx->scratch->ptr1 = *oid;
187f06ca4afSHartmut Brandt 	*oid = value->v.oid;
188f06ca4afSHartmut Brandt 
189f06ca4afSHartmut Brandt 	return (0);
190f06ca4afSHartmut Brandt }
191f06ca4afSHartmut Brandt 
192f06ca4afSHartmut Brandt void
193f06ca4afSHartmut Brandt oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
194f06ca4afSHartmut Brandt {
195f06ca4afSHartmut Brandt 	*oid = *(struct asn_oid *)ctx->scratch->ptr1;
196f06ca4afSHartmut Brandt 	free(ctx->scratch->ptr1);
197f06ca4afSHartmut Brandt }
198f06ca4afSHartmut Brandt 
199f06ca4afSHartmut Brandt void
200f06ca4afSHartmut Brandt oid_commit(struct snmp_context *ctx)
201f06ca4afSHartmut Brandt {
202f06ca4afSHartmut Brandt 	free(ctx->scratch->ptr1);
203f06ca4afSHartmut Brandt }
204f06ca4afSHartmut Brandt 
205f06ca4afSHartmut Brandt int
206f06ca4afSHartmut Brandt oid_get(struct snmp_value *value, const struct asn_oid *oid)
207f06ca4afSHartmut Brandt {
208f06ca4afSHartmut Brandt 	value->v.oid = *oid;
209f06ca4afSHartmut Brandt 	return (SNMP_ERR_NOERROR);
210f06ca4afSHartmut Brandt }
211f06ca4afSHartmut Brandt 
212f06ca4afSHartmut Brandt /*
213f06ca4afSHartmut Brandt  * Decode an index
214f06ca4afSHartmut Brandt  */
215f06ca4afSHartmut Brandt int
216f06ca4afSHartmut Brandt index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
217f06ca4afSHartmut Brandt {
218f06ca4afSHartmut Brandt 	va_list ap;
219f06ca4afSHartmut Brandt 	u_int index_count;
220f06ca4afSHartmut Brandt 	void *octs[10];
221f06ca4afSHartmut Brandt 	u_int nocts;
222f06ca4afSHartmut Brandt 	u_int idx;
223f06ca4afSHartmut Brandt 
224f06ca4afSHartmut Brandt 	va_start(ap, code);
225f06ca4afSHartmut Brandt 	index_count = SNMP_INDEX_COUNT(code);
226f06ca4afSHartmut Brandt 	nocts = 0;
227f06ca4afSHartmut Brandt 
228f06ca4afSHartmut Brandt 	for (idx = 0; idx < index_count; idx++) {
229f06ca4afSHartmut Brandt 		switch (SNMP_INDEX(code, idx)) {
230f06ca4afSHartmut Brandt 
231f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_NULL:
232f06ca4afSHartmut Brandt 			break;
233f06ca4afSHartmut Brandt 
234f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_INTEGER:
235f06ca4afSHartmut Brandt 			if (sub == oid->len)
236f06ca4afSHartmut Brandt 				goto err;
237f06ca4afSHartmut Brandt 			*va_arg(ap, int32_t *) = oid->subs[sub++];
238f06ca4afSHartmut Brandt 			break;
239f06ca4afSHartmut Brandt 
240f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_COUNTER64:
241f06ca4afSHartmut Brandt 			if (sub == oid->len)
242f06ca4afSHartmut Brandt 				goto err;
243f06ca4afSHartmut Brandt 			*va_arg(ap, u_int64_t *) = oid->subs[sub++];
244f06ca4afSHartmut Brandt 			break;
245f06ca4afSHartmut Brandt 
246f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_OCTETSTRING:
247f06ca4afSHartmut Brandt 		    {
248f06ca4afSHartmut Brandt 			u_char **cval;
249f06ca4afSHartmut Brandt 			size_t *sval;
250f06ca4afSHartmut Brandt 			u_int i;
251f06ca4afSHartmut Brandt 
252f06ca4afSHartmut Brandt 			/* only variable size supported */
253f06ca4afSHartmut Brandt 			if (sub == oid->len)
254f06ca4afSHartmut Brandt 				goto err;
255f06ca4afSHartmut Brandt 			cval = va_arg(ap, u_char **);
256f06ca4afSHartmut Brandt 			sval = va_arg(ap, size_t *);
257f06ca4afSHartmut Brandt 			*sval = oid->subs[sub++];
258f06ca4afSHartmut Brandt 			if (sub + *sval > oid->len)
259f06ca4afSHartmut Brandt 				goto err;
260f06ca4afSHartmut Brandt 			if ((*cval = malloc(*sval)) == NULL) {
261f06ca4afSHartmut Brandt 				syslog(LOG_ERR, "%s: %m", __func__);
262f06ca4afSHartmut Brandt 				goto err;
263f06ca4afSHartmut Brandt 			}
264f06ca4afSHartmut Brandt 			octs[nocts++] = *cval;
265f06ca4afSHartmut Brandt 			for (i = 0; i < *sval; i++) {
266f06ca4afSHartmut Brandt 				if (oid->subs[sub] > 0xff)
267f06ca4afSHartmut Brandt 					goto err;
268f06ca4afSHartmut Brandt 				(*cval)[i] = oid->subs[sub++];
269f06ca4afSHartmut Brandt 			}
270f06ca4afSHartmut Brandt 			break;
271f06ca4afSHartmut Brandt 		    }
272f06ca4afSHartmut Brandt 
273f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_OID:
274f06ca4afSHartmut Brandt 		    {
275f06ca4afSHartmut Brandt 			struct asn_oid *aval;
276f06ca4afSHartmut Brandt 			u_int i;
277f06ca4afSHartmut Brandt 
278f06ca4afSHartmut Brandt 			if (sub == oid->len)
279f06ca4afSHartmut Brandt 				goto err;
280f06ca4afSHartmut Brandt 			aval = va_arg(ap, struct asn_oid *);
281f06ca4afSHartmut Brandt 			aval->len = oid->subs[sub++];
282f06ca4afSHartmut Brandt 			if (aval->len > ASN_MAXOIDLEN)
283f06ca4afSHartmut Brandt 				goto err;
284f06ca4afSHartmut Brandt 			for (i = 0; i < aval->len; i++)
285f06ca4afSHartmut Brandt 				aval->subs[i] = oid->subs[sub++];
286f06ca4afSHartmut Brandt 			break;
287f06ca4afSHartmut Brandt 		    }
288f06ca4afSHartmut Brandt 
289f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_IPADDRESS:
290f06ca4afSHartmut Brandt 		    {
291f06ca4afSHartmut Brandt 			u_int8_t *pval;
292f06ca4afSHartmut Brandt 			u_int i;
293f06ca4afSHartmut Brandt 
294f06ca4afSHartmut Brandt 			if (sub + 4 > oid->len)
295f06ca4afSHartmut Brandt 				goto err;
296f06ca4afSHartmut Brandt 			pval = va_arg(ap, u_int8_t *);
297f06ca4afSHartmut Brandt 			for (i = 0; i < 4; i++) {
298f06ca4afSHartmut Brandt 				if (oid->subs[sub] > 0xff)
299f06ca4afSHartmut Brandt 					goto err;
300f06ca4afSHartmut Brandt 				pval[i] = oid->subs[sub++];
301f06ca4afSHartmut Brandt 			}
302f06ca4afSHartmut Brandt 			break;
303f06ca4afSHartmut Brandt 		    }
304f06ca4afSHartmut Brandt 
305f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_COUNTER:
306f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_GAUGE:
307f06ca4afSHartmut Brandt 		  case SNMP_SYNTAX_TIMETICKS:
308f06ca4afSHartmut Brandt 			if (sub == oid->len)
309f06ca4afSHartmut Brandt 				goto err;
310f06ca4afSHartmut Brandt 			if (oid->subs[sub] > 0xffffffff)
311f06ca4afSHartmut Brandt 				goto err;
312f06ca4afSHartmut Brandt 			*va_arg(ap, u_int32_t *) = oid->subs[sub++];
313f06ca4afSHartmut Brandt 			break;
314f06ca4afSHartmut Brandt 		}
315f06ca4afSHartmut Brandt 	}
316f06ca4afSHartmut Brandt 
317f06ca4afSHartmut Brandt 	va_end(ap);
318f06ca4afSHartmut Brandt 	return (0);
319f06ca4afSHartmut Brandt 
320f06ca4afSHartmut Brandt   err:
321f06ca4afSHartmut Brandt 	va_end(ap);
322f06ca4afSHartmut Brandt 	while(nocts > 0)
323f06ca4afSHartmut Brandt 		free(octs[--nocts]);
324f06ca4afSHartmut Brandt 	return (-1);
325f06ca4afSHartmut Brandt }
326f06ca4afSHartmut Brandt 
327f06ca4afSHartmut Brandt /*
328f06ca4afSHartmut Brandt  * Compare the index part of an OID and an index.
329f06ca4afSHartmut Brandt  */
330f06ca4afSHartmut Brandt int
331f06ca4afSHartmut Brandt index_compare_off(const struct asn_oid *oid, u_int sub,
332f06ca4afSHartmut Brandt     const struct asn_oid *idx, u_int off)
333f06ca4afSHartmut Brandt {
334f06ca4afSHartmut Brandt 	u_int i;
335f06ca4afSHartmut Brandt 
336f06ca4afSHartmut Brandt 	for (i = off; i < idx->len && i < oid->len - sub; i++) {
337f06ca4afSHartmut Brandt 		if (oid->subs[sub + i] < idx->subs[i])
338f06ca4afSHartmut Brandt 			return (-1);
339f06ca4afSHartmut Brandt 		if (oid->subs[sub + i] > idx->subs[i])
340f06ca4afSHartmut Brandt 			return (+1);
341f06ca4afSHartmut Brandt 	}
342f06ca4afSHartmut Brandt 	if (oid->len - sub < idx->len)
343f06ca4afSHartmut Brandt 		return (-1);
344f06ca4afSHartmut Brandt 	if (oid->len - sub > idx->len)
345f06ca4afSHartmut Brandt 		return (+1);
346f06ca4afSHartmut Brandt 
347f06ca4afSHartmut Brandt 	return (0);
348f06ca4afSHartmut Brandt }
349f06ca4afSHartmut Brandt 
350f06ca4afSHartmut Brandt int
351f06ca4afSHartmut Brandt index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
352f06ca4afSHartmut Brandt {
353f06ca4afSHartmut Brandt 	return (index_compare_off(oid, sub, idx, 0));
354f06ca4afSHartmut Brandt }
355f06ca4afSHartmut Brandt 
356f06ca4afSHartmut Brandt /*
357f06ca4afSHartmut Brandt  * Append an index to an oid
358f06ca4afSHartmut Brandt  */
359f06ca4afSHartmut Brandt void
360f06ca4afSHartmut Brandt index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
361f06ca4afSHartmut Brandt     u_int off)
362f06ca4afSHartmut Brandt {
363f06ca4afSHartmut Brandt 	u_int i;
364f06ca4afSHartmut Brandt 
365f06ca4afSHartmut Brandt 	var->len = sub + idx->len;
366f06ca4afSHartmut Brandt 	for (i = off; i < idx->len; i++)
367f06ca4afSHartmut Brandt 		var->subs[sub + i] = idx->subs[i];
368f06ca4afSHartmut Brandt }
369f06ca4afSHartmut Brandt void
370f06ca4afSHartmut Brandt index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
371f06ca4afSHartmut Brandt {
372f06ca4afSHartmut Brandt 	index_append_off(var, sub, idx, 0);
373f06ca4afSHartmut Brandt }
374f06ca4afSHartmut Brandt 
375