]>
git.ipfire.org Git - thirdparty/squid.git/blob - snmplib/snmp_vars.c
3 * SNMP Variable Binding. Complies with:
5 * RFC 1905: Protocol Operations for SNMPv2
9 /**********************************************************************
11 * Copyright 1997 by Carnegie Mellon University
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.
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
31 * Author: Ryan Troll <ryan+@andrew.cmu.edu>
33 **********************************************************************/
46 #include <sys/types.h>
52 #include <gnumalloc.h>
69 #include <sys/socket.h>
72 #include <netinet/in.h>
75 #include <arpa/inet.h>
86 #include "snmp_vars.h"
90 #include "snmp_api_error.h"
96 /* #define DEBUG_VARS 1 */
97 /* #define DEBUG_VARS_MALLOC 1 */
98 /* #define DEBUG_VARS_DECODE 1 */
99 /* #define DEBUG_VARS_ENCODE 1 */
101 /* Create a new variable_list structure representing oid Name of length Len.
103 * Returns NULL upon error.
106 struct variable_list
*
107 snmp_var_new(oid
* Name
, int Len
) {
108 struct variable_list
*New
;
111 printf("VARS: Creating.\n");
114 New
= xmalloc(sizeof(*New
));
115 /* XXX xmalloc never returns NULL */
117 snmp_set_api_error(SNMPERR_OS_ERR
);
120 memset(New
, '\0', sizeof(struct variable_list
));
121 /* New->next_variable = NULL; */
123 New
->type
= ASN_NULL
;
124 New
->name_length
= Len
;
126 if (New
->name_length
== 0) {
130 New
->name
= (oid
*) xmalloc(Len
* sizeof(oid
));
131 /* XXX xmalloc never returns NULL */
132 if (New
->name
== NULL
) {
134 snmp_set_api_error(SNMPERR_OS_ERR
);
138 printf("VARS: Copying name, size (%d)\n", Len
);
141 /* Only copy a name if it was specified. */
143 memcpy((char *) New
->name
, (char *) Name
, Len
* sizeof(oid
));
148 struct variable_list
*
149 snmp_var_new_integer(oid
* Name
, int Len
, int ival
, unsigned char type
) {
150 variable_list
*v
= snmp_var_new(Name
, Len
);
151 v
->val_len
= sizeof(int);
152 v
->val
.integer
= xmalloc(sizeof(int));
154 *(v
->val
.integer
) = ival
;
158 /* Clone a variable list.
160 * Returns NULL upon error.
163 struct variable_list
*
164 snmp_var_clone(struct variable_list
*Src
) {
165 struct variable_list
*Dest
;
168 printf("VARS: Cloning.\n");
171 Dest
= (struct variable_list
*) xmalloc(sizeof(struct variable_list
));
173 snmp_set_api_error(SNMPERR_OS_ERR
);
177 printf("VARS: Copying entire variable list. (Size %d)\n",
178 sizeof(struct variable_list
));
181 memcpy((char *) Dest
, (char *) Src
, sizeof(struct variable_list
));
183 if (Src
->name
!= NULL
) {
184 Dest
->name
= (oid
*) xmalloc(Src
->name_length
* sizeof(oid
));
185 if (Dest
->name
== NULL
) {
186 snmp_set_api_error(SNMPERR_OS_ERR
);
191 printf("VARS: Copying name OID. (Size %d)\n", Src
->name_length
);
193 memcpy((char *) Dest
->name
, (char *) Src
->name
,
194 Src
->name_length
* sizeof(oid
));
196 /* CISCO Catalyst 2900 returns NULL strings as data of length 0. */
197 if ((Src
->val
.string
!= NULL
) &&
199 Dest
->val
.string
= (u_char
*) xmalloc(Src
->val_len
);
200 if (Dest
->val
.string
== NULL
) {
201 snmp_set_api_error(SNMPERR_OS_ERR
);
207 printf("VARS: Copying value (Size %d)\n", Src
->val_len
);
209 memcpy((char *) Dest
->val
.string
, (char *) Src
->val
.string
, Src
->val_len
);
212 printf("VARS: Cloned %x.\n", (unsigned int) Dest
);
214 #if DEBUG_VARS_MALLOC
215 printf("VARS: Cloned (%x)\n", (unsigned int) Dest
);
216 printf("VARS: Name is (%x)\n", (unsigned int) Dest
->name
);
222 /* Free a variable_list.
225 snmp_var_free(struct variable_list
*Ptr
)
228 xfree((char *) Ptr
->name
);
231 xfree((char *) Ptr
->val
.string
);
232 else if (Ptr
->val
.integer
)
233 xfree((char *) Ptr
->val
.integer
);
238 /**********************************************************************/
240 /* Build a variable binding.
242 * RFC 1905: Protocol Operations for SNMPv2
250 * noSuchObject[0] NULL
251 * noSuchInstance[1] NULL
252 * endOfMibView[2] NULL
257 snmp_var_EncodeVarBind(u_char
* Buffer
, int *BufLenP
,
258 variable_list
* VarList
,
261 struct variable_list
*Vars
;
265 int FakeArg
= *BufLenP
;
269 for (Vars
= VarList
; Vars
; Vars
= Vars
->next_variable
) {
271 /* Build the header for this variable
276 HeaderEnd
= asn_build_header(HeaderStart
, BufLenP
,
277 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
279 if (HeaderEnd
== NULL
)
282 /* Now, let's put the Object Identifier into the buffer */
283 bufp
= asn_build_objid(HeaderEnd
, BufLenP
,
284 (u_char
) (ASN_UNIVERSAL
|
287 Vars
->name
, Vars
->name_length
);
291 /* Now put the data in */
292 switch (Vars
->type
) {
295 bufp
= asn_build_int(bufp
,
297 (int *) Vars
->val
.integer
, Vars
->val_len
);
302 /* case SMI_UNSIGNED32: */
304 bufp
= asn_build_unsigned_int(bufp
, BufLenP
,
306 (u_int
*) Vars
->val
.integer
, Vars
->val_len
);
312 bufp
= asn_build_string(bufp
, BufLenP
, Vars
->type
,
313 Vars
->val
.string
, Vars
->val_len
);
317 bufp
= asn_build_objid(bufp
, BufLenP
, Vars
->type
,
318 (oid
*) Vars
->val
.objid
, Vars
->val_len
/ sizeof(oid
));
321 case SMI_NOSUCHINSTANCE
:
322 case SMI_NOSUCHOBJECT
:
323 case SMI_ENDOFMIBVIEW
:
324 if (Version
== SNMP_VERSION_1
) {
325 /* SNMP Version 1 does not support these error codes. */
326 bufp
= asn_build_null(bufp
, BufLenP
, SMI_NOSUCHOBJECT
);
328 bufp
= asn_build_exception(bufp
, BufLenP
, Vars
->type
);
333 bufp
= asn_build_null(bufp
, BufLenP
, Vars
->type
);
337 snmplib_debug(2, "Unable to encode type SMI_COUNTER64!\n");
341 snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE
);
345 /* ASSERT: bufp should now point to the next valid byte. */
349 /* Rebuild the header with the appropriate length */
350 HeaderEnd
= asn_build_header(HeaderStart
, &FakeArg
,
351 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
355 if (HeaderEnd
== NULL
)
360 /* or the end of the entire thing */
364 /* Parse all Vars from the buffer */
366 snmp_var_DecodeVarBind(u_char
* Buffer
, int *BufLen
,
367 struct variable_list
** VarP
,
370 struct variable_list
*Var
= NULL
, **VarLastP
;
375 oid TmpBuf
[MAX_NAME_LEN
];
376 memset(TmpBuf
, 0, MAX_NAME_LEN
* sizeof(*TmpBuf
));
378 int AllVarLen
= *BufLen
;
382 #if DEBUG_VARS_DECODE
383 printf("VARS: Decoding buffer of length %d\n", *BufLen
);
386 /* Now parse the variables */
387 bufp
= asn_parse_header(Buffer
, &AllVarLen
, &VarBindType
);
391 if (VarBindType
!= (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
)) {
392 snmp_set_api_error(SNMPERR_PDU_PARSE
);
395 #if DEBUG_VARS_DECODE
396 printf("VARS: All Variable length %d\n", AllVarLen
);
399 #define PARSE_ERROR { snmp_var_free(Var); return(NULL); }
401 /* We know how long the variable list is. Parse it. */
402 while ((int) AllVarLen
> 0) {
404 /* Create a new variable */
405 Var
= snmp_var_new(NULL
, MAX_NAME_LEN
);
409 /* Parse the header to find out the length of this variable. */
410 ThisVarLen
= AllVarLen
;
411 tmp
= asn_parse_header(bufp
, &ThisVarLen
, &VarBindType
);
415 /* Now that we know the length , figure out how it relates to
416 * the entire variable list
418 AllVarLen
= AllVarLen
- (ThisVarLen
+ (tmp
- bufp
));
422 if (VarBindType
!= (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
)) {
423 snmp_set_api_error(SNMPERR_PDU_PARSE
);
426 #if DEBUG_VARS_DECODE
427 printf("VARS: Header type 0x%x (%d bytes left)\n", VarBindType
, ThisVarLen
);
430 /* Parse the OBJID */
431 bufp
= asn_parse_objid(bufp
, &ThisVarLen
, &VarBindType
,
432 Var
->name
, &(Var
->name_length
));
436 if (VarBindType
!= (u_char
) (ASN_UNIVERSAL
|
439 snmp_set_api_error(SNMPERR_PDU_PARSE
);
442 #if DEBUG_VARS_DECODE
443 printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)\n",
444 Var
->name_length
, ThisVarLen
);
447 /* Keep a pointer to this object */
449 DataLen
= ThisVarLen
;
451 /* find out type of object */
452 bufp
= asn_parse_header(bufp
, &ThisVarLen
, &(Var
->type
));
455 ThisVarLen
= DataLen
;
457 #if DEBUG_VARS_DECODE
458 printf("VARS: Data type %d\n", Var
->type
);
463 switch ((short) Var
->type
) {
466 Var
->val
.integer
= (int *) xmalloc(sizeof(int));
467 if (Var
->val
.integer
== NULL
) {
468 snmp_set_api_error(SNMPERR_OS_ERR
);
471 Var
->val_len
= sizeof(int);
472 bufp
= asn_parse_int(DataPtr
, &ThisVarLen
,
473 &Var
->type
, (int *) Var
->val
.integer
,
475 #if DEBUG_VARS_DECODE
476 printf("VARS: Decoded integer '%d' (%d bytes left)\n",
477 *(Var
->val
.integer
), ThisVarLen
);
483 /* case SMI_UNSIGNED32: */
485 Var
->val
.integer
= (int *) xmalloc(sizeof(u_int
));
486 if (Var
->val
.integer
== NULL
) {
487 snmp_set_api_error(SNMPERR_OS_ERR
);
490 Var
->val_len
= sizeof(u_int
);
491 bufp
= asn_parse_unsigned_int(DataPtr
, &ThisVarLen
,
492 &Var
->type
, (u_int
*) Var
->val
.integer
,
494 #if DEBUG_VARS_DECODE
495 printf("VARS: Decoded timeticks '%d' (%d bytes left)\n",
496 *(Var
->val
.integer
), ThisVarLen
);
503 Var
->val_len
= *&ThisVarLen
; /* String is this at most */
504 Var
->val
.string
= (u_char
*) xmalloc((unsigned) Var
->val_len
);
505 if (Var
->val
.string
== NULL
) {
506 snmp_set_api_error(SNMPERR_OS_ERR
);
509 bufp
= asn_parse_string(DataPtr
, &ThisVarLen
,
510 &Var
->type
, Var
->val
.string
,
512 #if DEBUG_VARS_DECODE
513 printf("VARS: Decoded string '%s' (length %d) (%d bytes left)\n",
514 (Var
->val
.string
), Var
->val_len
, ThisVarLen
);
519 Var
->val_len
= MAX_NAME_LEN
;
520 bufp
= asn_parse_objid(DataPtr
, &ThisVarLen
,
521 &Var
->type
, TmpBuf
, &Var
->val_len
);
522 Var
->val_len
*= sizeof(oid
);
523 Var
->val
.objid
= (oid
*) xmalloc((unsigned) Var
->val_len
);
524 if (Var
->val
.integer
== NULL
) {
525 snmp_set_api_error(SNMPERR_OS_ERR
);
528 /* Only copy if we successfully decoded something */
530 memcpy((char *) Var
->val
.objid
, (char *) TmpBuf
, Var
->val_len
);
532 #if DEBUG_VARS_DECODE
533 printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n",
534 Var
->val_len
, ThisVarLen
);
539 case SMI_NOSUCHINSTANCE
:
540 case SMI_NOSUCHOBJECT
:
541 case SMI_ENDOFMIBVIEW
:
545 snmplib_debug(2, "Unable to parse type SMI_COUNTER64!\n");
546 snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE
);
550 snmplib_debug(2, "bad type returned (%x)\n", Var
->type
);
551 snmp_set_api_error(SNMPERR_PDU_PARSE
);
553 } /* End of var type switch */
558 #if DEBUG_VARS_DECODE
559 printf("VARS: Adding to list.\n");
561 /* Add variable to the list */
563 VarLastP
= &(Var
->next_variable
);