]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/bsnmp/snmpd/export.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / bsnmp / snmpd / export.c
1 /*
2  * Copyright (c) 2001-2003
3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *      All rights reserved.
5  *
6  * Author: Harti Brandt <harti@freebsd.org>
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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.
16  * 
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
27  * SUCH DAMAGE.
28  *
29  * $Begemot: bsnmp/snmpd/export.c,v 1.8 2006/02/14 09:04:20 brandt_h Exp $
30  *
31  * Support functions for modules.
32  */
33 #include <sys/types.h>
34 #include <sys/un.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <syslog.h>
39 #include <stdarg.h>
40
41 #include "snmpmod.h"
42 #include "snmpd.h"
43 #include "tree.h"
44
45 /*
46  * Support functions
47  */
48
49 /*
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.
54  */
55 int
56 string_save(struct snmp_value *value, struct snmp_context *ctx,
57     ssize_t req_size, u_char **valp)
58 {
59         if (req_size != -1 && value->v.octetstring.len != (u_long)req_size)
60                 return (SNMP_ERR_BADVALUE);
61
62         ctx->scratch->ptr1 = *valp;
63
64         if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) {
65                 *valp = ctx->scratch->ptr1;
66                 return (SNMP_ERR_RES_UNAVAIL);
67         }
68
69         memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len);
70         (*valp)[value->v.octetstring.len] = '\0';
71
72         return (0);
73 }
74
75 /*
76  * Commit a string. This is easy - free the old value.
77  */
78 void
79 string_commit(struct snmp_context *ctx)
80 {
81         free(ctx->scratch->ptr1);
82 }
83
84 /*
85  * Rollback a string - free new value and copy back old one.
86  */
87 void
88 string_rollback(struct snmp_context *ctx, u_char **valp)
89 {
90         free(*valp);
91         *valp = ctx->scratch->ptr1;
92 }
93
94 /*
95  * ROLLBACK or COMMIT fails because instance has disappeared. Free string.
96  */
97 void
98 string_free(struct snmp_context *ctx)
99 {
100         free(ctx->scratch->ptr1);
101 }
102
103 /*
104  * Get a string value for a response packet
105  */
106 int
107 string_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
108 {
109         if (ptr == NULL) {
110                 value->v.octetstring.len = 0;
111                 value->v.octetstring.octets = NULL;
112                 return (SNMP_ERR_NOERROR);
113         }
114         if (len == -1)
115                 len = strlen(ptr);
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);
121 }
122
123 /*
124  * Get a string value for a response packet but cut it if it is too long.
125  */
126 int
127 string_get_max(struct snmp_value *value, const u_char *ptr, ssize_t len,
128     size_t maxlen)
129 {
130
131         if (ptr == NULL) {
132                 value->v.octetstring.len = 0;
133                 value->v.octetstring.octets = NULL;
134                 return (SNMP_ERR_NOERROR);
135         }
136         if (len == -1)
137                 len = strlen(ptr);
138         if ((size_t)len > maxlen)
139                 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);
145 }
146
147 /*
148  * Support for IPADDRESS
149  *
150  * Save the old IP address in scratch->int1 and set the new one.
151  */
152 int
153 ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp)
154 {
155         ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8)
156             | valp[3];
157
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];
162
163         return (0);
164 }
165
166 /*
167  * Rollback the address by copying back the old one
168  */
169 void
170 ip_rollback(struct snmp_context *ctx, u_char *valp)
171 {
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;
176 }
177
178 /*
179  * Nothing to do for commit
180  */
181 void
182 ip_commit(struct snmp_context *ctx __unused)
183 {
184 }
185
186 /*
187  * Retrieve an IP address
188  */
189 int
190 ip_get(struct snmp_value *value, u_char *valp)
191 {
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);
197 }
198
199 /*
200  * Object ID support
201  *
202  * Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
203  */
204 int
205 oid_save(struct snmp_value *value, struct snmp_context *ctx,
206     struct asn_oid *oid)
207 {
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;
211         *oid = value->v.oid;
212
213         return (0);
214 }
215
216 void
217 oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
218 {
219         *oid = *(struct asn_oid *)ctx->scratch->ptr1;
220         free(ctx->scratch->ptr1);
221 }
222
223 void
224 oid_commit(struct snmp_context *ctx)
225 {
226         free(ctx->scratch->ptr1);
227 }
228
229 int
230 oid_get(struct snmp_value *value, const struct asn_oid *oid)
231 {
232         value->v.oid = *oid;
233         return (SNMP_ERR_NOERROR);
234 }
235
236 /*
237  * Decode an index
238  */
239 int
240 index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
241 {
242         va_list ap;
243         u_int index_count;
244         void *octs[10];
245         u_int nocts;
246         u_int idx;
247
248         va_start(ap, code);
249         index_count = SNMP_INDEX_COUNT(code);
250         nocts = 0;
251
252         for (idx = 0; idx < index_count; idx++) {
253                 switch (SNMP_INDEX(code, idx)) {
254
255                   case SNMP_SYNTAX_NULL:
256                         break;
257
258                   case SNMP_SYNTAX_INTEGER:
259                         if (sub == oid->len)
260                                 goto err;
261                         *va_arg(ap, int32_t *) = oid->subs[sub++];
262                         break;
263
264                   case SNMP_SYNTAX_COUNTER64:
265                         if (sub == oid->len)
266                                 goto err;
267                         *va_arg(ap, u_int64_t *) = oid->subs[sub++];
268                         break;
269
270                   case SNMP_SYNTAX_OCTETSTRING:
271                     {
272                         u_char **cval;
273                         size_t *sval;
274                         u_int i;
275
276                         /* only variable size supported */
277                         if (sub == oid->len)
278                                 goto err;
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)
283                                 goto err;
284                         if ((*cval = malloc(*sval)) == NULL) {
285                                 syslog(LOG_ERR, "%s: %m", __func__);
286                                 goto err;
287                         }
288                         octs[nocts++] = *cval;
289                         for (i = 0; i < *sval; i++) {
290                                 if (oid->subs[sub] > 0xff)
291                                         goto err;
292                                 (*cval)[i] = oid->subs[sub++];
293                         }
294                         break;
295                     }
296
297                   case SNMP_SYNTAX_OID:
298                     {
299                         struct asn_oid *aval;
300                         u_int i;
301
302                         if (sub == oid->len)
303                                 goto err;
304                         aval = va_arg(ap, struct asn_oid *);
305                         aval->len = oid->subs[sub++];
306                         if (aval->len > ASN_MAXOIDLEN)
307                                 goto err;
308                         for (i = 0; i < aval->len; i++)
309                                 aval->subs[i] = oid->subs[sub++];
310                         break;
311                     }
312
313                   case SNMP_SYNTAX_IPADDRESS:
314                     {
315                         u_int8_t *pval;
316                         u_int i;
317
318                         if (sub + 4 > oid->len)
319                                 goto err;
320                         pval = va_arg(ap, u_int8_t *);
321                         for (i = 0; i < 4; i++) {
322                                 if (oid->subs[sub] > 0xff)
323                                         goto err;
324                                 pval[i] = oid->subs[sub++];
325                         }
326                         break;
327                     }
328
329                   case SNMP_SYNTAX_COUNTER:
330                   case SNMP_SYNTAX_GAUGE:
331                   case SNMP_SYNTAX_TIMETICKS:
332                         if (sub == oid->len)
333                                 goto err;
334                         if (oid->subs[sub] > 0xffffffff)
335                                 goto err;
336                         *va_arg(ap, u_int32_t *) = oid->subs[sub++];
337                         break;
338                 }
339         }
340
341         va_end(ap);
342         return (0);
343
344   err:
345         va_end(ap);
346         while(nocts > 0)
347                 free(octs[--nocts]);
348         return (-1);
349 }
350
351 /*
352  * Compare the index part of an OID and an index.
353  */
354 int
355 index_compare_off(const struct asn_oid *oid, u_int sub,
356     const struct asn_oid *idx, u_int off)
357 {
358         u_int i;
359
360         for (i = off; i < idx->len && i < oid->len - sub; i++) {
361                 if (oid->subs[sub + i] < idx->subs[i])
362                         return (-1);
363                 if (oid->subs[sub + i] > idx->subs[i])
364                         return (+1);
365         }
366         if (oid->len - sub < idx->len)
367                 return (-1);
368         if (oid->len - sub > idx->len)
369                 return (+1);
370
371         return (0);
372 }
373
374 int
375 index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
376 {
377         return (index_compare_off(oid, sub, idx, 0));
378 }
379
380 /*
381  * Append an index to an oid
382  */
383 void
384 index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
385     u_int off)
386 {
387         u_int i;
388
389         var->len = sub + idx->len;
390         for (i = off; i < idx->len; i++)
391                 var->subs[sub + i] = idx->subs[i];
392 }
393 void
394 index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
395 {
396         index_append_off(var, sub, idx, 0);
397 }
398