]>
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"
97 /* #define DEBUG_VARS 1 */
98 /* #define DEBUG_VARS_MALLOC 1 */
99 /* #define DEBUG_VARS_DECODE 1 */
100 /* #define DEBUG_VARS_ENCODE 1 */
102 /* Create a new variable_list structure representing oid Name of length Len.
104 * Returns NULL upon error.
107 struct variable_list
*
108 snmp_var_new(oid
* Name
, int Len
) {
109 struct variable_list
*New
;
112 printf("VARS: Creating.\n");
115 New
= xmalloc(sizeof(*New
));
116 /* XXX xmalloc never returns NULL */
118 snmp_set_api_error(SNMPERR_OS_ERR
);
121 memset(New
, '\0', sizeof(struct variable_list
));
122 /* New->next_variable = NULL; */
124 New
->type
= ASN_NULL
;
125 New
->name_length
= Len
;
127 if (New
->name_length
== 0) {
131 New
->name
= (oid
*) xmalloc(Len
* sizeof(oid
));
132 /* XXX xmalloc never returns NULL */
133 if (New
->name
== NULL
) {
135 snmp_set_api_error(SNMPERR_OS_ERR
);
139 printf("VARS: Copying name, size (%d)\n", Len
);
142 /* Only copy a name if it was specified. */
144 memcpy((char *) New
->name
, (char *) Name
, Len
* sizeof(oid
));
149 struct variable_list
*
150 snmp_var_new_integer(oid
* Name
, int Len
, int ival
, unsigned char type
) {
151 variable_list
*v
= snmp_var_new(Name
, Len
);
152 v
->val_len
= sizeof(int);
153 v
->val
.integer
= xmalloc(sizeof(int));
155 *(v
->val
.integer
) = ival
;
159 /* Clone a variable list.
161 * Returns NULL upon error.
164 struct variable_list
*
165 snmp_var_clone(struct variable_list
*Src
) {
166 struct variable_list
*Dest
;
169 printf("VARS: Cloning.\n");
172 Dest
= (struct variable_list
*) xmalloc(sizeof(struct variable_list
));
174 snmp_set_api_error(SNMPERR_OS_ERR
);
178 printf("VARS: Copying entire variable list. (Size %d)\n",
179 sizeof(struct variable_list
));
182 memcpy((char *) Dest
, (char *) Src
, sizeof(struct variable_list
));
184 if (Src
->name
!= NULL
) {
185 Dest
->name
= (oid
*) xmalloc(Src
->name_length
* sizeof(oid
));
186 if (Dest
->name
== NULL
) {
187 snmp_set_api_error(SNMPERR_OS_ERR
);
192 printf("VARS: Copying name OID. (Size %d)\n", Src
->name_length
);
194 memcpy((char *) Dest
->name
, (char *) Src
->name
,
195 Src
->name_length
* sizeof(oid
));
197 /* CISCO Catalyst 2900 returns NULL strings as data of length 0. */
198 if ((Src
->val
.string
!= NULL
) &&
200 Dest
->val
.string
= (u_char
*) xmalloc(Src
->val_len
);
201 if (Dest
->val
.string
== NULL
) {
202 snmp_set_api_error(SNMPERR_OS_ERR
);
208 printf("VARS: Copying value (Size %d)\n", Src
->val_len
);
210 memcpy((char *) Dest
->val
.string
, (char *) Src
->val
.string
, Src
->val_len
);
213 printf("VARS: Cloned %x.\n", (unsigned int) Dest
);
215 #if DEBUG_VARS_MALLOC
216 printf("VARS: Cloned (%x)\n", (unsigned int) Dest
);
217 printf("VARS: Name is (%x)\n", (unsigned int) Dest
->name
);
223 /* Free a variable_list.
226 snmp_var_free(struct variable_list
*Ptr
)
229 xfree((char *) Ptr
->name
);
232 xfree((char *) Ptr
->val
.string
);
233 else if (Ptr
->val
.integer
)
234 xfree((char *) Ptr
->val
.integer
);
239 /**********************************************************************/
241 /* Build a variable binding.
243 * RFC 1905: Protocol Operations for SNMPv2
251 * noSuchObject[0] NULL
252 * noSuchInstance[1] NULL
253 * endOfMibView[2] NULL
258 snmp_var_EncodeVarBind(u_char
* Buffer
, int *BufLenP
,
259 variable_list
* VarList
,
262 struct variable_list
*Vars
;
266 int FakeArg
= *BufLenP
;
270 for (Vars
= VarList
; Vars
; Vars
= Vars
->next_variable
) {
272 /* Build the header for this variable
277 HeaderEnd
= asn_build_header(HeaderStart
, BufLenP
,
278 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
280 if (HeaderEnd
== NULL
)
283 /* Now, let's put the Object Identifier into the buffer */
284 bufp
= asn_build_objid(HeaderEnd
, BufLenP
,
285 (u_char
) (ASN_UNIVERSAL
|
288 Vars
->name
, Vars
->name_length
);
292 /* Now put the data in */
293 switch (Vars
->type
) {
296 bufp
= asn_build_int(bufp
,
298 (int *) Vars
->val
.integer
, Vars
->val_len
);
303 /* case SMI_UNSIGNED32: */
305 bufp
= asn_build_unsigned_int(bufp
, BufLenP
,
307 (u_int
*) Vars
->val
.integer
, Vars
->val_len
);
313 bufp
= asn_build_string(bufp
, BufLenP
, Vars
->type
,
314 Vars
->val
.string
, Vars
->val_len
);
318 bufp
= asn_build_objid(bufp
, BufLenP
, Vars
->type
,
319 (oid
*) Vars
->val
.objid
, Vars
->val_len
/ sizeof(oid
));
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
);
329 bufp
= asn_build_exception(bufp
, BufLenP
, Vars
->type
);
334 bufp
= asn_build_null(bufp
, BufLenP
, Vars
->type
);
338 snmplib_debug(2, "Unable to encode type SMI_COUNTER64!\n");
342 snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE
);
346 /* ASSERT: bufp should now point to the next valid byte. */
350 /* Rebuild the header with the appropriate length */
351 HeaderEnd
= asn_build_header(HeaderStart
, &FakeArg
,
352 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
356 if (HeaderEnd
== NULL
)
361 /* or the end of the entire thing */
368 /* Parse all Vars from the buffer */
370 snmp_var_DecodeVarBind(u_char
* Buffer
, int *BufLen
,
371 struct variable_list
** VarP
,
374 struct variable_list
*Var
= NULL
, **VarLastP
;
379 oid TmpBuf
[MAX_NAME_LEN
];
381 int AllVarLen
= *BufLen
;
385 #if DEBUG_VARS_DECODE
386 printf("VARS: Decoding buffer of length %d\n", *BufLen
);
389 /* Now parse the variables */
390 bufp
= asn_parse_header(Buffer
, &AllVarLen
, &VarBindType
);
394 if (VarBindType
!= (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
)) {
395 snmp_set_api_error(SNMPERR_PDU_PARSE
);
398 #if DEBUG_VARS_DECODE
399 printf("VARS: All Variable length %d\n", AllVarLen
);
402 #define PARSE_ERROR { snmp_var_free(Var); return(NULL); }
404 /* We know how long the variable list is. Parse it. */
405 while ((int) AllVarLen
> 0) {
407 /* Create a new variable */
408 Var
= snmp_var_new(NULL
, MAX_NAME_LEN
);
412 /* Parse the header to find out the length of this variable. */
413 ThisVarLen
= AllVarLen
;
414 tmp
= asn_parse_header(bufp
, &ThisVarLen
, &VarBindType
);
418 /* Now that we know the length , figure out how it relates to
419 * the entire variable list
421 AllVarLen
= AllVarLen
- (ThisVarLen
+ (tmp
- bufp
));
425 if (VarBindType
!= (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
)) {
426 snmp_set_api_error(SNMPERR_PDU_PARSE
);
429 #if DEBUG_VARS_DECODE
430 printf("VARS: Header type 0x%x (%d bytes left)\n", VarBindType
, ThisVarLen
);
433 /* Parse the OBJID */
434 bufp
= asn_parse_objid(bufp
, &ThisVarLen
, &VarBindType
,
435 Var
->name
, &(Var
->name_length
));
439 if (VarBindType
!= (u_char
) (ASN_UNIVERSAL
|
442 snmp_set_api_error(SNMPERR_PDU_PARSE
);
445 #if DEBUG_VARS_DECODE
446 printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)\n",
447 Var
->name_length
, ThisVarLen
);
450 /* Keep a pointer to this object */
452 DataLen
= ThisVarLen
;
454 /* find out type of object */
455 bufp
= asn_parse_header(bufp
, &ThisVarLen
, &(Var
->type
));
458 ThisVarLen
= DataLen
;
460 #if DEBUG_VARS_DECODE
461 printf("VARS: Data type %d\n", Var
->type
);
466 switch ((short) Var
->type
) {
469 Var
->val
.integer
= (int *) xmalloc(sizeof(int));
470 if (Var
->val
.integer
== NULL
) {
471 snmp_set_api_error(SNMPERR_OS_ERR
);
474 Var
->val_len
= sizeof(int);
475 bufp
= asn_parse_int(DataPtr
, &ThisVarLen
,
476 &Var
->type
, (int *) Var
->val
.integer
,
478 #if DEBUG_VARS_DECODE
479 printf("VARS: Decoded integer '%d' (%d bytes left)\n",
480 *(Var
->val
.integer
), ThisVarLen
);
486 /* case SMI_UNSIGNED32: */
488 Var
->val
.integer
= (int *) xmalloc(sizeof(u_int
));
489 if (Var
->val
.integer
== NULL
) {
490 snmp_set_api_error(SNMPERR_OS_ERR
);
493 Var
->val_len
= sizeof(u_int
);
494 bufp
= asn_parse_unsigned_int(DataPtr
, &ThisVarLen
,
495 &Var
->type
, (u_int
*) Var
->val
.integer
,
497 #if DEBUG_VARS_DECODE
498 printf("VARS: Decoded timeticks '%d' (%d bytes left)\n",
499 *(Var
->val
.integer
), ThisVarLen
);
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
);
512 bufp
= asn_parse_string(DataPtr
, &ThisVarLen
,
513 &Var
->type
, Var
->val
.string
,
515 #if DEBUG_VARS_DECODE
516 printf("VARS: Decoded string '%s' (length %d) (%d bytes left)\n",
517 (Var
->val
.string
), Var
->val_len
, ThisVarLen
);
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
);
531 /* Only copy if we successfully decoded something */
533 memcpy((char *) Var
->val
.objid
, (char *) TmpBuf
, Var
->val_len
);
535 #if DEBUG_VARS_DECODE
536 printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n",
537 Var
->val_len
, ThisVarLen
);
542 case SMI_NOSUCHINSTANCE
:
543 case SMI_NOSUCHOBJECT
:
544 case SMI_ENDOFMIBVIEW
:
548 snmplib_debug(2, "Unable to parse type SMI_COUNTER64!\n");
549 snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE
);
553 snmplib_debug(2, "bad type returned (%x)\n", Var
->type
);
554 snmp_set_api_error(SNMPERR_PDU_PARSE
);
556 } /* End of var type switch */
561 #if DEBUG_VARS_DECODE
562 printf("VARS: Adding to list.\n");
564 /* Add variable to the list */
566 VarLastP
= &(Var
->next_variable
);