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