]>
Commit | Line | Data |
---|---|---|
43d4303e | 1 | |
85269fdf | 2 | /* |
3 | * SNMP Variable Binding. Complies with: | |
4 | * | |
5 | * RFC 1905: Protocol Operations for SNMPv2 | |
6 | * | |
7 | */ | |
8 | ||
9 | /********************************************************************** | |
10 | * | |
11 | * Copyright 1997 by Carnegie Mellon University | |
26ac0430 | 12 | * |
85269fdf | 13 | * All Rights Reserved |
26ac0430 | 14 | * |
85269fdf | 15 | * Permission to use, copy, modify, and distribute this software and its |
16 | * documentation for any purpose and without fee is hereby granted, | |
17 | * provided that the above copyright notice appear in all copies and that | |
18 | * both that copyright notice and this permission notice appear in | |
19 | * supporting documentation, and that the name of CMU not be | |
20 | * used in advertising or publicity pertaining to distribution of the | |
21 | * software without specific, written prior permission. | |
26ac0430 | 22 | * |
85269fdf | 23 | * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING |
24 | * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |
25 | * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |
26 | * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
27 | * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
28 | * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
29 | * SOFTWARE. | |
26ac0430 | 30 | * |
85269fdf | 31 | * Author: Ryan Troll <ryan+@andrew.cmu.edu> |
26ac0430 | 32 | * |
85269fdf | 33 | **********************************************************************/ |
34 | ||
35 | #include "config.h" | |
36 | ||
37 | #include <stdio.h> | |
38 | ||
39 | #if HAVE_UNISTD_H | |
40 | #include <unistd.h> | |
41 | #endif | |
42 | #if HAVE_STDLIB_H | |
43 | #include <stdlib.h> | |
44 | #endif | |
45 | #if HAVE_SYS_TYPES_H | |
46 | #include <sys/types.h> | |
47 | #endif | |
48 | #if HAVE_CTYPE_H | |
49 | #include <ctype.h> | |
50 | #endif | |
51 | #if HAVE_GNUMALLOC_H | |
52 | #include <gnumalloc.h> | |
482aa790 | 53 | #elif HAVE_MALLOC_H |
85269fdf | 54 | #include <malloc.h> |
55 | #endif | |
56 | #if HAVE_MEMORY_H | |
57 | #include <memory.h> | |
58 | #endif | |
59 | #ifdef HAVE_STRING_H | |
60 | #include <string.h> | |
61 | #endif | |
62 | #ifdef HAVE_STRINGS_H | |
63 | #include <strings.h> | |
64 | #endif | |
65 | #if HAVE_BSTRING_H | |
66 | #include <bstring.h> | |
67 | #endif | |
68 | #if HAVE_SYS_SOCKET_H | |
69 | #include <sys/socket.h> | |
70 | #endif | |
71 | #if HAVE_NETINET_IN_H | |
72 | #include <netinet/in.h> | |
73 | #endif | |
74 | #if HAVE_ARPA_INET_H | |
75 | #include <arpa/inet.h> | |
76 | #endif | |
77 | #if HAVE_SYS_TIME_H | |
78 | #include <sys/time.h> | |
79 | #endif | |
80 | #if HAVE_NETDB_H | |
81 | #include <netdb.h> | |
82 | #endif | |
83 | ||
84 | #include "snmp.h" | |
85 | #include "asn1.h" | |
86 | #include "snmp_vars.h" | |
43d4303e | 87 | #if 0 |
85269fdf | 88 | #include "mibii.h" |
43d4303e | 89 | #endif |
85269fdf | 90 | #include "snmp_api_error.h" |
91 | #include "snmp_pdu.h" | |
92 | #include "snmp_msg.h" | |
93 | ||
94 | #include "util.h" | |
95 | ||
96 | ||
97 | /* #define DEBUG_VARS 1 */ | |
98 | /* #define DEBUG_VARS_MALLOC 1 */ | |
99 | /* #define DEBUG_VARS_DECODE 1 */ | |
100 | /* #define DEBUG_VARS_ENCODE 1 */ | |
101 | ||
85269fdf | 102 | /* Create a new variable_list structure representing oid Name of length Len. |
103 | * | |
104 | * Returns NULL upon error. | |
105 | */ | |
106 | ||
43d4303e | 107 | struct variable_list * |
26ac0430 | 108 | snmp_var_new(oid * Name, int Len) { |
43d4303e | 109 | struct variable_list *New; |
85269fdf | 110 | |
111 | #ifdef DEBUG_VARS | |
43d4303e | 112 | printf("VARS: Creating.\n"); |
85269fdf | 113 | #endif |
114 | ||
736eb6ad | 115 | New = xmalloc(sizeof(*New)); |
116 | /* XXX xmalloc never returns NULL */ | |
43d4303e | 117 | if (New == NULL) { |
26ac0430 AJ |
118 | snmp_set_api_error(SNMPERR_OS_ERR); |
119 | return (NULL); | |
43d4303e | 120 | } |
121 | memset(New, '\0', sizeof(struct variable_list)); | |
122 | /* New->next_variable = NULL; */ | |
85269fdf | 123 | |
43d4303e | 124 | New->type = ASN_NULL; |
125 | New->name_length = Len; | |
85269fdf | 126 | |
43d4303e | 127 | if (New->name_length == 0) { |
26ac0430 AJ |
128 | New->name = NULL; |
129 | return (New); | |
43d4303e | 130 | } |
131 | New->name = (oid *) xmalloc(Len * sizeof(oid)); | |
736eb6ad | 132 | /* XXX xmalloc never returns NULL */ |
43d4303e | 133 | if (New->name == NULL) { |
26ac0430 AJ |
134 | xfree(New); |
135 | snmp_set_api_error(SNMPERR_OS_ERR); | |
136 | return (NULL); | |
43d4303e | 137 | } |
85269fdf | 138 | #ifdef DEBUG_VARS |
43d4303e | 139 | printf("VARS: Copying name, size (%d)\n", Len); |
85269fdf | 140 | #endif |
141 | ||
43d4303e | 142 | /* Only copy a name if it was specified. */ |
143 | if (Name) | |
26ac0430 | 144 | xmemcpy((char *) New->name, (char *) Name, Len * sizeof(oid)); |
85269fdf | 145 | |
43d4303e | 146 | return (New); |
85269fdf | 147 | } |
148 | ||
736eb6ad | 149 | struct variable_list * |
26ac0430 | 150 | snmp_var_new_integer(oid * Name, int Len, int ival, unsigned char type) { |
736eb6ad | 151 | variable_list *v = snmp_var_new(Name, Len); |
152 | v->val_len = sizeof(int); | |
153 | v->val.integer = xmalloc(sizeof(int)); | |
154 | v->type = type; | |
155 | *(v->val.integer) = ival; | |
156 | return v; | |
157 | } | |
158 | ||
85269fdf | 159 | /* Clone a variable list. |
160 | * | |
161 | * Returns NULL upon error. | |
162 | */ | |
163 | ||
43d4303e | 164 | struct variable_list * |
26ac0430 | 165 | snmp_var_clone(struct variable_list *Src) { |
43d4303e | 166 | struct variable_list *Dest; |
85269fdf | 167 | |
168 | #ifdef DEBUG_VARS | |
43d4303e | 169 | printf("VARS: Cloning.\n"); |
85269fdf | 170 | #endif |
171 | ||
43d4303e | 172 | Dest = (struct variable_list *) xmalloc(sizeof(struct variable_list)); |
173 | if (Dest == NULL) { | |
26ac0430 AJ |
174 | snmp_set_api_error(SNMPERR_OS_ERR); |
175 | return (NULL); | |
43d4303e | 176 | } |
85269fdf | 177 | #ifdef DEBUG_VARS |
43d4303e | 178 | printf("VARS: Copying entire variable list. (Size %d)\n", |
26ac0430 | 179 | sizeof(struct variable_list)); |
85269fdf | 180 | #endif |
181 | ||
43d4303e | 182 | xmemcpy((char *) Dest, (char *) Src, sizeof(struct variable_list)); |
85269fdf | 183 | |
43d4303e | 184 | if (Src->name != NULL) { |
26ac0430 AJ |
185 | Dest->name = (oid *) xmalloc(Src->name_length * sizeof(oid)); |
186 | if (Dest->name == NULL) { | |
187 | snmp_set_api_error(SNMPERR_OS_ERR); | |
188 | xfree(Dest); | |
189 | return (NULL); | |
190 | } | |
85269fdf | 191 | #ifdef DEBUG_VARS |
26ac0430 | 192 | printf("VARS: Copying name OID. (Size %d)\n", Src->name_length); |
43d4303e | 193 | #endif |
26ac0430 AJ |
194 | xmemcpy((char *) Dest->name, (char *) Src->name, |
195 | Src->name_length * sizeof(oid)); | |
85269fdf | 196 | } |
43d4303e | 197 | /* CISCO Catalyst 2900 returns NULL strings as data of length 0. */ |
198 | if ((Src->val.string != NULL) && | |
26ac0430 AJ |
199 | (Src->val_len)) { |
200 | Dest->val.string = (u_char *) xmalloc(Src->val_len); | |
201 | if (Dest->val.string == NULL) { | |
202 | snmp_set_api_error(SNMPERR_OS_ERR); | |
203 | xfree(Dest->name); | |
204 | xfree(Dest); | |
205 | return (NULL); | |
206 | } | |
85269fdf | 207 | #ifdef DEBUG_VARS |
26ac0430 | 208 | printf("VARS: Copying value (Size %d)\n", Src->val_len); |
85269fdf | 209 | #endif |
26ac0430 | 210 | xmemcpy((char *) Dest->val.string, (char *) Src->val.string, Src->val_len); |
43d4303e | 211 | } |
85269fdf | 212 | #ifdef DEBUG_VARS |
43d4303e | 213 | printf("VARS: Cloned %x.\n", (unsigned int) Dest); |
85269fdf | 214 | #endif |
215 | #ifdef DEBUG_VARS_MALLOC | |
43d4303e | 216 | printf("VARS: Cloned (%x)\n", (unsigned int) Dest); |
217 | printf("VARS: Name is (%x)\n", (unsigned int) Dest->name); | |
85269fdf | 218 | #endif |
219 | ||
43d4303e | 220 | return (Dest); |
85269fdf | 221 | } |
222 | ||
223 | /* Free a variable_list. | |
224 | */ | |
736eb6ad | 225 | void |
43d4303e | 226 | snmp_var_free(struct variable_list *Ptr) |
85269fdf | 227 | { |
63f8db1a | 228 | if (Ptr->name) |
26ac0430 | 229 | xfree((char *) Ptr->name); |
85269fdf | 230 | |
63f8db1a | 231 | if (Ptr->val.string) |
26ac0430 | 232 | xfree((char *) Ptr->val.string); |
63f8db1a | 233 | else if (Ptr->val.integer) |
26ac0430 | 234 | xfree((char *) Ptr->val.integer); |
85269fdf | 235 | |
43d4303e | 236 | xfree(Ptr); |
85269fdf | 237 | } |
238 | ||
239 | /**********************************************************************/ | |
240 | ||
241 | /* Build a variable binding. | |
242 | * | |
243 | * RFC 1905: Protocol Operations for SNMPv2 | |
244 | * | |
26ac0430 | 245 | * VarBind ::= |
85269fdf | 246 | * SEQUENCE { |
247 | * name ObjectName | |
248 | * CHOICE { | |
249 | * value ObjectSyntax | |
250 | * unSpecified NULL | |
251 | * noSuchObject[0] NULL | |
252 | * noSuchInstance[1] NULL | |
253 | * endOfMibView[2] NULL | |
254 | * } | |
255 | * } | |
256 | */ | |
43d4303e | 257 | u_char * |
258 | snmp_var_EncodeVarBind(u_char * Buffer, int *BufLenP, | |
26ac0430 AJ |
259 | variable_list * VarList, |
260 | int Version) | |
85269fdf | 261 | { |
43d4303e | 262 | struct variable_list *Vars; |
263 | u_char *bufp; | |
264 | u_char *HeaderStart; | |
265 | u_char *HeaderEnd; | |
266 | int FakeArg = *BufLenP; | |
267 | ||
268 | bufp = Buffer; | |
269 | ||
270 | for (Vars = VarList; Vars; Vars = Vars->next_variable) { | |
271 | ||
26ac0430 AJ |
272 | /* Build the header for this variable |
273 | * | |
274 | * Use Maximum size. | |
275 | */ | |
276 | HeaderStart = bufp; | |
277 | HeaderEnd = asn_build_header(HeaderStart, BufLenP, | |
278 | (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), | |
279 | FakeArg); | |
280 | if (HeaderEnd == NULL) | |
281 | return (NULL); | |
282 | ||
283 | /* Now, let's put the Object Identifier into the buffer */ | |
284 | bufp = asn_build_objid(HeaderEnd, BufLenP, | |
285 | (u_char) (ASN_UNIVERSAL | | |
286 | ASN_PRIMITIVE | | |
287 | ASN_OBJECT_ID), | |
288 | Vars->name, Vars->name_length); | |
289 | if (bufp == NULL) | |
290 | return (NULL); | |
291 | ||
292 | /* Now put the data in */ | |
293 | switch (Vars->type) { | |
294 | ||
295 | case ASN_INTEGER: | |
296 | bufp = asn_build_int(bufp, | |
297 | BufLenP, Vars->type, | |
298 | (int *) Vars->val.integer, Vars->val_len); | |
299 | break; | |
300 | ||
301 | case SMI_COUNTER32: | |
302 | case SMI_GAUGE32: | |
303 | /* case SMI_UNSIGNED32: */ | |
304 | case SMI_TIMETICKS: | |
305 | bufp = asn_build_unsigned_int(bufp, BufLenP, | |
306 | Vars->type, | |
307 | (u_int *) Vars->val.integer, Vars->val_len); | |
308 | break; | |
309 | ||
310 | case ASN_OCTET_STR: | |
311 | case SMI_IPADDRESS: | |
312 | case SMI_OPAQUE: | |
313 | bufp = asn_build_string(bufp, BufLenP, Vars->type, | |
314 | Vars->val.string, Vars->val_len); | |
315 | break; | |
316 | ||
317 | case ASN_OBJECT_ID: | |
318 | bufp = asn_build_objid(bufp, BufLenP, Vars->type, | |
319 | (oid *) Vars->val.objid, Vars->val_len / sizeof(oid)); | |
320 | break; | |
321 | ||
322 | case SMI_NOSUCHINSTANCE: | |
323 | case SMI_NOSUCHOBJECT: | |
324 | case SMI_ENDOFMIBVIEW: | |
325 | if (Version == SNMP_VERSION_1) { | |
326 | /* SNMP Version 1 does not support these error codes. */ | |
327 | bufp = asn_build_null(bufp, BufLenP, SMI_NOSUCHOBJECT); | |
328 | } else { | |
329 | bufp = asn_build_exception(bufp, BufLenP, Vars->type); | |
330 | } | |
331 | break; | |
332 | ||
333 | case ASN_NULL: | |
334 | bufp = asn_build_null(bufp, BufLenP, Vars->type); | |
335 | break; | |
336 | ||
337 | case SMI_COUNTER64: | |
338 | snmplib_debug(2, "Unable to encode type SMI_COUNTER64!\n"); | |
339 | /* Fall through */ | |
340 | ||
341 | default: | |
342 | snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE); | |
343 | return (NULL); | |
344 | } | |
345 | ||
346 | /* ASSERT: bufp should now point to the next valid byte. */ | |
347 | if (bufp == NULL) | |
348 | return (NULL); | |
349 | ||
350 | /* Rebuild the header with the appropriate length */ | |
351 | HeaderEnd = asn_build_header(HeaderStart, &FakeArg, | |
352 | (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), | |
353 | (bufp - HeaderEnd)); | |
354 | ||
355 | /* Returns NULL */ | |
356 | if (HeaderEnd == NULL) | |
357 | return (NULL); | |
85269fdf | 358 | |
43d4303e | 359 | } |
85269fdf | 360 | |
43d4303e | 361 | /* or the end of the entire thing */ |
362 | return (bufp); | |
85269fdf | 363 | } |
364 | ||
43d4303e | 365 | |
85269fdf | 366 | |
367 | ||
368 | /* Parse all Vars from the buffer */ | |
43d4303e | 369 | u_char * |
370 | snmp_var_DecodeVarBind(u_char * Buffer, int *BufLen, | |
26ac0430 AJ |
371 | struct variable_list ** VarP, |
372 | int Version) | |
85269fdf | 373 | { |
63f8db1a | 374 | struct variable_list *Var = NULL, **VarLastP; |
43d4303e | 375 | u_char *bufp, *tmp; |
376 | u_char VarBindType; | |
377 | u_char *DataPtr; | |
378 | int DataLen; | |
379 | oid TmpBuf[MAX_NAME_LEN]; | |
85269fdf | 380 | |
43d4303e | 381 | int AllVarLen = *BufLen; |
382 | int ThisVarLen = 0; | |
85269fdf | 383 | |
43d4303e | 384 | VarLastP = VarP; |
85269fdf | 385 | #ifdef DEBUG_VARS_DECODE |
43d4303e | 386 | printf("VARS: Decoding buffer of length %d\n", *BufLen); |
85269fdf | 387 | #endif |
388 | ||
43d4303e | 389 | /* Now parse the variables */ |
390 | bufp = asn_parse_header(Buffer, &AllVarLen, &VarBindType); | |
391 | if (bufp == NULL) | |
26ac0430 | 392 | return (NULL); |
85269fdf | 393 | |
43d4303e | 394 | if (VarBindType != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { |
26ac0430 AJ |
395 | snmp_set_api_error(SNMPERR_PDU_PARSE); |
396 | return (NULL); | |
85269fdf | 397 | } |
85269fdf | 398 | #ifdef DEBUG_VARS_DECODE |
43d4303e | 399 | printf("VARS: All Variable length %d\n", AllVarLen); |
400 | #endif | |
401 | ||
63f8db1a | 402 | #define PARSE_ERROR { snmp_var_free(Var); return(NULL); } |
403 | ||
43d4303e | 404 | /* We know how long the variable list is. Parse it. */ |
405 | while ((int) AllVarLen > 0) { | |
406 | ||
26ac0430 AJ |
407 | /* Create a new variable */ |
408 | Var = snmp_var_new(NULL, MAX_NAME_LEN); | |
409 | if (Var == NULL) | |
410 | return (NULL); | |
411 | ||
412 | /* Parse the header to find out the length of this variable. */ | |
413 | ThisVarLen = AllVarLen; | |
414 | tmp = asn_parse_header(bufp, &ThisVarLen, &VarBindType); | |
415 | if (tmp == NULL) | |
416 | PARSE_ERROR; | |
417 | ||
418 | /* Now that we know the length , figure out how it relates to | |
419 | * the entire variable list | |
420 | */ | |
421 | AllVarLen = AllVarLen - (ThisVarLen + (tmp - bufp)); | |
422 | bufp = tmp; | |
423 | ||
424 | /* Is it valid? */ | |
425 | if (VarBindType != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { | |
426 | snmp_set_api_error(SNMPERR_PDU_PARSE); | |
427 | PARSE_ERROR; | |
428 | } | |
43d4303e | 429 | #ifdef DEBUG_VARS_DECODE |
26ac0430 | 430 | printf("VARS: Header type 0x%x (%d bytes left)\n", VarBindType, ThisVarLen); |
85269fdf | 431 | #endif |
432 | ||
26ac0430 AJ |
433 | /* Parse the OBJID */ |
434 | bufp = asn_parse_objid(bufp, &ThisVarLen, &VarBindType, | |
435 | Var->name, &(Var->name_length)); | |
436 | if (bufp == NULL) | |
437 | PARSE_ERROR; | |
85269fdf | 438 | |
26ac0430 AJ |
439 | if (VarBindType != (u_char) (ASN_UNIVERSAL | |
440 | ASN_PRIMITIVE | | |
441 | ASN_OBJECT_ID)) { | |
442 | snmp_set_api_error(SNMPERR_PDU_PARSE); | |
443 | PARSE_ERROR; | |
444 | } | |
85269fdf | 445 | #ifdef DEBUG_VARS_DECODE |
26ac0430 AJ |
446 | printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)\n", |
447 | Var->name_length, ThisVarLen); | |
85269fdf | 448 | #endif |
449 | ||
26ac0430 AJ |
450 | /* Keep a pointer to this object */ |
451 | DataPtr = bufp; | |
452 | DataLen = ThisVarLen; | |
85269fdf | 453 | |
26ac0430 AJ |
454 | /* find out type of object */ |
455 | bufp = asn_parse_header(bufp, &ThisVarLen, &(Var->type)); | |
456 | if (bufp == NULL) | |
457 | PARSE_ERROR; | |
458 | ThisVarLen = DataLen; | |
85269fdf | 459 | |
460 | #ifdef DEBUG_VARS_DECODE | |
26ac0430 | 461 | printf("VARS: Data type %d\n", Var->type); |
85269fdf | 462 | #endif |
463 | ||
26ac0430 | 464 | /* Parse the type */ |
85269fdf | 465 | |
26ac0430 | 466 | switch ((short) Var->type) { |
85269fdf | 467 | |
26ac0430 AJ |
468 | case ASN_INTEGER: |
469 | Var->val.integer = (int *) xmalloc(sizeof(int)); | |
470 | if (Var->val.integer == NULL) { | |
471 | snmp_set_api_error(SNMPERR_OS_ERR); | |
472 | PARSE_ERROR; | |
473 | } | |
474 | Var->val_len = sizeof(int); | |
475 | bufp = asn_parse_int(DataPtr, &ThisVarLen, | |
476 | &Var->type, (int *) Var->val.integer, | |
477 | Var->val_len); | |
85269fdf | 478 | #ifdef DEBUG_VARS_DECODE |
26ac0430 AJ |
479 | printf("VARS: Decoded integer '%d' (%d bytes left)\n", |
480 | *(Var->val.integer), ThisVarLen); | |
481 | #endif | |
482 | break; | |
483 | ||
484 | case SMI_COUNTER32: | |
485 | case SMI_GAUGE32: | |
486 | /* case SMI_UNSIGNED32: */ | |
487 | case SMI_TIMETICKS: | |
488 | Var->val.integer = (int *) xmalloc(sizeof(u_int)); | |
489 | if (Var->val.integer == NULL) { | |
490 | snmp_set_api_error(SNMPERR_OS_ERR); | |
491 | PARSE_ERROR; | |
492 | } | |
493 | Var->val_len = sizeof(u_int); | |
494 | bufp = asn_parse_unsigned_int(DataPtr, &ThisVarLen, | |
495 | &Var->type, (u_int *) Var->val.integer, | |
496 | Var->val_len); | |
85269fdf | 497 | #ifdef DEBUG_VARS_DECODE |
26ac0430 AJ |
498 | printf("VARS: Decoded timeticks '%d' (%d bytes left)\n", |
499 | *(Var->val.integer), ThisVarLen); | |
500 | #endif | |
501 | break; | |
502 | ||
503 | case ASN_OCTET_STR: | |
504 | case SMI_IPADDRESS: | |
505 | case SMI_OPAQUE: | |
506 | Var->val_len = *&ThisVarLen; /* String is this at most */ | |
507 | Var->val.string = (u_char *) xmalloc((unsigned) Var->val_len); | |
508 | if (Var->val.string == NULL) { | |
509 | snmp_set_api_error(SNMPERR_OS_ERR); | |
510 | PARSE_ERROR; | |
511 | } | |
512 | bufp = asn_parse_string(DataPtr, &ThisVarLen, | |
513 | &Var->type, Var->val.string, | |
514 | &Var->val_len); | |
85269fdf | 515 | #ifdef DEBUG_VARS_DECODE |
26ac0430 AJ |
516 | printf("VARS: Decoded string '%s' (length %d) (%d bytes left)\n", |
517 | (Var->val.string), Var->val_len, ThisVarLen); | |
518 | #endif | |
519 | break; | |
520 | ||
521 | case ASN_OBJECT_ID: | |
522 | Var->val_len = MAX_NAME_LEN; | |
523 | bufp = asn_parse_objid(DataPtr, &ThisVarLen, | |
524 | &Var->type, TmpBuf, &Var->val_len); | |
525 | Var->val_len *= sizeof(oid); | |
526 | Var->val.objid = (oid *) xmalloc((unsigned) Var->val_len); | |
527 | if (Var->val.integer == NULL) { | |
528 | snmp_set_api_error(SNMPERR_OS_ERR); | |
529 | PARSE_ERROR; | |
530 | } | |
531 | /* Only copy if we successfully decoded something */ | |
532 | if (bufp) { | |
533 | xmemcpy((char *) Var->val.objid, (char *) TmpBuf, Var->val_len); | |
534 | } | |
43d4303e | 535 | #ifdef DEBUG_VARS_DECODE |
26ac0430 AJ |
536 | printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n", |
537 | Var->val_len, ThisVarLen); | |
43d4303e | 538 | #endif |
26ac0430 | 539 | break; |
85269fdf | 540 | |
26ac0430 AJ |
541 | case ASN_NULL: |
542 | case SMI_NOSUCHINSTANCE: | |
543 | case SMI_NOSUCHOBJECT: | |
544 | case SMI_ENDOFMIBVIEW: | |
545 | break; | |
43d4303e | 546 | |
26ac0430 AJ |
547 | case SMI_COUNTER64: |
548 | snmplib_debug(2, "Unable to parse type SMI_COUNTER64!\n"); | |
549 | snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE); | |
550 | PARSE_ERROR; | |
43d4303e | 551 | |
26ac0430 AJ |
552 | default: |
553 | snmplib_debug(2, "bad type returned (%x)\n", Var->type); | |
554 | snmp_set_api_error(SNMPERR_PDU_PARSE); | |
555 | PARSE_ERROR; | |
556 | } /* End of var type switch */ | |
43d4303e | 557 | |
26ac0430 AJ |
558 | if (bufp == NULL) |
559 | PARSE_ERROR; | |
85269fdf | 560 | |
561 | #ifdef DEBUG_VARS_DECODE | |
26ac0430 | 562 | printf("VARS: Adding to list.\n"); |
85269fdf | 563 | #endif |
26ac0430 AJ |
564 | /* Add variable to the list */ |
565 | *VarLastP = Var; | |
566 | VarLastP = &(Var->next_variable); | |
43d4303e | 567 | } |
63f8db1a | 568 | #undef PARSE_ERROR |
85269fdf | 569 | |
43d4303e | 570 | return (bufp); |
85269fdf | 571 | } |