]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/snmplib/snmp_vars.c
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
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.
10 * SNMP Variable Binding. Complies with:
12 * RFC 1905: Protocol Operations for SNMPv2
16 /**********************************************************************
18 * Copyright 1997 by Carnegie Mellon University
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.
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
38 * Author: Ryan Troll <ryan+@andrew.cmu.edu>
40 **********************************************************************/
51 #include <sys/types.h>
57 #include <gnumalloc.h>
74 #include <sys/socket.h>
77 #include <netinet/in.h>
80 #include <arpa/inet.h>
91 #include "snmp_vars.h"
95 #include "snmp_api_error.h"
101 /* #define DEBUG_VARS 1 */
102 /* #define DEBUG_VARS_MALLOC 1 */
103 /* #define DEBUG_VARS_DECODE 1 */
104 /* #define DEBUG_VARS_ENCODE 1 */
106 /* Create a new variable_list structure representing oid Name of length Len.
108 * Returns NULL upon error.
111 struct variable_list
*
112 snmp_var_new(oid
* Name
, int Len
) {
113 struct variable_list
*New
;
116 printf("VARS: Creating.\n");
119 New
= xmalloc(sizeof(*New
));
120 /* XXX xmalloc never returns NULL */
122 snmp_set_api_error(SNMPERR_OS_ERR
);
125 memset(New
, '\0', sizeof(struct variable_list
));
126 /* New->next_variable = NULL; */
128 New
->type
= ASN_NULL
;
129 New
->name_length
= Len
;
131 if (New
->name_length
== 0) {
135 New
->name
= (oid
*) xmalloc(Len
* sizeof(oid
));
136 /* XXX xmalloc never returns NULL */
137 if (New
->name
== NULL
) {
139 snmp_set_api_error(SNMPERR_OS_ERR
);
143 printf("VARS: Copying name, size (%d)\n", Len
);
146 /* Only copy a name if it was specified. */
148 memcpy((char *) New
->name
, (char *) Name
, Len
* sizeof(oid
));
153 struct variable_list
*
154 snmp_var_new_integer(oid
* Name
, int Len
, int ival
, unsigned char type
) {
155 variable_list
*v
= snmp_var_new(Name
, Len
);
156 v
->val_len
= sizeof(int);
157 v
->val
.integer
= xmalloc(sizeof(int));
159 *(v
->val
.integer
) = ival
;
163 /* Clone a variable list.
165 * Returns NULL upon error.
168 struct variable_list
*
169 snmp_var_clone(struct variable_list
*Src
) {
170 struct variable_list
*Dest
;
173 printf("VARS: Cloning.\n");
176 Dest
= (struct variable_list
*) xmalloc(sizeof(struct variable_list
));
178 snmp_set_api_error(SNMPERR_OS_ERR
);
182 printf("VARS: Copying entire variable list. (Size %d)\n",
183 sizeof(struct variable_list
));
186 memcpy((char *) Dest
, (char *) Src
, sizeof(struct variable_list
));
188 if (Src
->name
!= NULL
) {
189 Dest
->name
= (oid
*) xmalloc(Src
->name_length
* sizeof(oid
));
190 if (Dest
->name
== NULL
) {
191 snmp_set_api_error(SNMPERR_OS_ERR
);
196 printf("VARS: Copying name OID. (Size %d)\n", Src
->name_length
);
198 memcpy((char *) Dest
->name
, (char *) Src
->name
,
199 Src
->name_length
* sizeof(oid
));
201 /* CISCO Catalyst 2900 returns NULL strings as data of length 0. */
202 if ((Src
->val
.string
!= NULL
) &&
204 Dest
->val
.string
= (u_char
*) xmalloc(Src
->val_len
);
205 if (Dest
->val
.string
== NULL
) {
206 snmp_set_api_error(SNMPERR_OS_ERR
);
212 printf("VARS: Copying value (Size %d)\n", Src
->val_len
);
214 memcpy((char *) Dest
->val
.string
, (char *) Src
->val
.string
, Src
->val_len
);
217 printf("VARS: Cloned %x.\n", (unsigned int) Dest
);
219 #if DEBUG_VARS_MALLOC
220 printf("VARS: Cloned (%x)\n", (unsigned int) Dest
);
221 printf("VARS: Name is (%x)\n", (unsigned int) Dest
->name
);
227 /* Free a variable_list.
230 snmp_var_free(struct variable_list
*Ptr
)
233 xfree((char *) Ptr
->name
);
236 xfree((char *) Ptr
->val
.string
);
237 else if (Ptr
->val
.integer
)
238 xfree((char *) Ptr
->val
.integer
);
243 /**********************************************************************/
245 /* Build a variable binding.
247 * RFC 1905: Protocol Operations for SNMPv2
255 * noSuchObject[0] NULL
256 * noSuchInstance[1] NULL
257 * endOfMibView[2] NULL
262 snmp_var_EncodeVarBind(u_char
* Buffer
, int *BufLenP
,
263 variable_list
* VarList
,
266 struct variable_list
*Vars
;
270 int FakeArg
= *BufLenP
;
274 for (Vars
= VarList
; Vars
; Vars
= Vars
->next_variable
) {
276 /* Build the header for this variable
281 HeaderEnd
= asn_build_header(HeaderStart
, BufLenP
,
282 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
284 if (HeaderEnd
== NULL
)
287 /* Now, let's put the Object Identifier into the buffer */
288 bufp
= asn_build_objid(HeaderEnd
, BufLenP
,
289 (u_char
) (ASN_UNIVERSAL
|
292 Vars
->name
, Vars
->name_length
);
296 /* Now put the data in */
297 switch (Vars
->type
) {
300 bufp
= asn_build_int(bufp
,
302 (int *) Vars
->val
.integer
, Vars
->val_len
);
307 /* case SMI_UNSIGNED32: */
309 bufp
= asn_build_unsigned_int(bufp
, BufLenP
,
311 (u_int
*) Vars
->val
.integer
, Vars
->val_len
);
317 bufp
= asn_build_string(bufp
, BufLenP
, Vars
->type
,
318 Vars
->val
.string
, Vars
->val_len
);
322 bufp
= asn_build_objid(bufp
, BufLenP
, Vars
->type
,
323 (oid
*) Vars
->val
.objid
, Vars
->val_len
/ sizeof(oid
));
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
);
333 bufp
= asn_build_exception(bufp
, BufLenP
, Vars
->type
);
338 bufp
= asn_build_null(bufp
, BufLenP
, Vars
->type
);
342 snmplib_debug(2, "Unable to encode type SMI_COUNTER64!\n");
346 snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE
);
350 /* ASSERT: bufp should now point to the next valid byte. */
354 /* Rebuild the header with the appropriate length */
355 HeaderEnd
= asn_build_header(HeaderStart
, &FakeArg
,
356 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
360 if (HeaderEnd
== NULL
)
365 /* or the end of the entire thing */
369 /* Parse all Vars from the buffer */
371 snmp_var_DecodeVarBind(u_char
* Buffer
, int *BufLen
,
372 struct variable_list
** VarP
,
375 struct variable_list
*Var
= NULL
, **VarLastP
;
380 oid TmpBuf
[MAX_NAME_LEN
];
381 memset(TmpBuf
, 0, MAX_NAME_LEN
* sizeof(*TmpBuf
));
383 int AllVarLen
= *BufLen
;
387 #if DEBUG_VARS_DECODE
388 printf("VARS: Decoding buffer of length %d\n", *BufLen
);
391 /* Now parse the variables */
392 bufp
= asn_parse_header(Buffer
, &AllVarLen
, &VarBindType
);
396 if (VarBindType
!= (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
)) {
397 snmp_set_api_error(SNMPERR_PDU_PARSE
);
400 #if DEBUG_VARS_DECODE
401 printf("VARS: All Variable length %d\n", AllVarLen
);
404 #define PARSE_ERROR { snmp_var_free(Var); return(NULL); }
406 /* We know how long the variable list is. Parse it. */
407 while ((int) AllVarLen
> 0) {
409 /* Create a new variable */
410 Var
= snmp_var_new(NULL
, MAX_NAME_LEN
);
414 /* Parse the header to find out the length of this variable. */
415 ThisVarLen
= AllVarLen
;
416 tmp
= asn_parse_header(bufp
, &ThisVarLen
, &VarBindType
);
420 /* Now that we know the length , figure out how it relates to
421 * the entire variable list
423 AllVarLen
= AllVarLen
- (ThisVarLen
+ (tmp
- bufp
));
427 if (VarBindType
!= (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
)) {
428 snmp_set_api_error(SNMPERR_PDU_PARSE
);
431 #if DEBUG_VARS_DECODE
432 printf("VARS: Header type 0x%x (%d bytes left)\n", VarBindType
, ThisVarLen
);
435 /* Parse the OBJID */
436 bufp
= asn_parse_objid(bufp
, &ThisVarLen
, &VarBindType
,
437 Var
->name
, &(Var
->name_length
));
441 if (VarBindType
!= (u_char
) (ASN_UNIVERSAL
|
444 snmp_set_api_error(SNMPERR_PDU_PARSE
);
447 #if DEBUG_VARS_DECODE
448 printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)\n",
449 Var
->name_length
, ThisVarLen
);
452 /* Keep a pointer to this object */
454 DataLen
= ThisVarLen
;
456 /* find out type of object */
457 bufp
= asn_parse_header(bufp
, &ThisVarLen
, &(Var
->type
));
460 ThisVarLen
= DataLen
;
462 #if DEBUG_VARS_DECODE
463 printf("VARS: Data type %d\n", Var
->type
);
468 switch ((short) Var
->type
) {
471 Var
->val
.integer
= (int *) xmalloc(sizeof(int));
472 if (Var
->val
.integer
== NULL
) {
473 snmp_set_api_error(SNMPERR_OS_ERR
);
476 Var
->val_len
= sizeof(int);
477 bufp
= asn_parse_int(DataPtr
, &ThisVarLen
,
478 &Var
->type
, (int *) Var
->val
.integer
,
480 #if DEBUG_VARS_DECODE
481 printf("VARS: Decoded integer '%d' (%d bytes left)\n",
482 *(Var
->val
.integer
), ThisVarLen
);
488 /* case SMI_UNSIGNED32: */
490 Var
->val
.integer
= (int *) xmalloc(sizeof(u_int
));
491 if (Var
->val
.integer
== NULL
) {
492 snmp_set_api_error(SNMPERR_OS_ERR
);
495 Var
->val_len
= sizeof(u_int
);
496 bufp
= asn_parse_unsigned_int(DataPtr
, &ThisVarLen
,
497 &Var
->type
, (u_int
*) Var
->val
.integer
,
499 #if DEBUG_VARS_DECODE
500 printf("VARS: Decoded timeticks '%d' (%d bytes left)\n",
501 *(Var
->val
.integer
), ThisVarLen
);
508 Var
->val_len
= *&ThisVarLen
; /* String is this at most */
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
);
514 bufp
= asn_parse_string(DataPtr
, &ThisVarLen
,
515 &Var
->type
, Var
->val
.string
,
517 #if DEBUG_VARS_DECODE
518 printf("VARS: Decoded string '%s' (length %d) (%d bytes left)\n",
519 (Var
->val
.string
), Var
->val_len
, ThisVarLen
);
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
);
533 /* Only copy if we successfully decoded something */
535 memcpy((char *) Var
->val
.objid
, (char *) TmpBuf
, Var
->val_len
);
537 #if DEBUG_VARS_DECODE
538 printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n",
539 Var
->val_len
, ThisVarLen
);
544 case SMI_NOSUCHINSTANCE
:
545 case SMI_NOSUCHOBJECT
:
546 case SMI_ENDOFMIBVIEW
:
550 snmplib_debug(2, "Unable to parse type SMI_COUNTER64!\n");
551 snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE
);
555 snmplib_debug(2, "bad type returned (%x)\n", Var
->type
);
556 snmp_set_api_error(SNMPERR_PDU_PARSE
);
558 } /* End of var type switch */
563 #if DEBUG_VARS_DECODE
564 printf("VARS: Adding to list.\n");
566 /* Add variable to the list */
568 VarLastP
= &(Var
->next_variable
);