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