]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/snmplib/snmp_vars.c
2 * Copyright (C) 1996-2023 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_api_error.h"
94 #include "snmp_vars.h"
98 /* #define DEBUG_VARS 1 */
99 /* #define DEBUG_VARS_MALLOC 1 */
100 /* #define DEBUG_VARS_DECODE 1 */
101 /* #define DEBUG_VARS_ENCODE 1 */
103 /* Create a new variable_list structure representing oid Name of length Len.
105 * Returns NULL upon error.
108 struct variable_list
*
109 snmp_var_new(oid
* Name
, int Len
) {
110 struct variable_list
*New
;
113 printf("VARS: Creating.\n");
116 New
= xmalloc(sizeof(*New
));
117 /* XXX xmalloc never returns NULL */
119 snmp_set_api_error(SNMPERR_OS_ERR
);
122 memset(New
, '\0', sizeof(struct variable_list
));
123 /* New->next_variable = NULL; */
125 New
->type
= ASN_NULL
;
126 New
->name_length
= Len
;
128 if (New
->name_length
== 0) {
132 New
->name
= (oid
*) xmalloc(Len
* sizeof(oid
));
133 /* XXX xmalloc never returns NULL */
134 if (New
->name
== NULL
) {
136 snmp_set_api_error(SNMPERR_OS_ERR
);
140 printf("VARS: Copying name, size (%d)\n", Len
);
143 /* Only copy a name if it was specified. */
145 memcpy((char *) New
->name
, (char *) Name
, Len
* sizeof(oid
));
150 struct variable_list
*
151 snmp_var_new_integer(oid
* Name
, int Len
, int ival
, unsigned char type
) {
152 variable_list
*v
= snmp_var_new(Name
, Len
);
153 v
->val_len
= sizeof(int);
154 v
->val
.integer
= xmalloc(sizeof(int));
156 *(v
->val
.integer
) = ival
;
160 /* Clone a variable list.
162 * Returns NULL upon error.
165 struct variable_list
*
166 snmp_var_clone(struct variable_list
*Src
) {
167 struct variable_list
*Dest
;
170 printf("VARS: Cloning.\n");
173 Dest
= (struct variable_list
*) xmalloc(sizeof(struct variable_list
));
175 snmp_set_api_error(SNMPERR_OS_ERR
);
179 printf("VARS: Copying entire variable list. (Size %d)\n",
180 sizeof(struct variable_list
));
183 memcpy((char *) Dest
, (char *) Src
, sizeof(struct variable_list
));
185 if (Src
->name
!= NULL
) {
186 Dest
->name
= (oid
*) xmalloc(Src
->name_length
* sizeof(oid
));
187 if (Dest
->name
== NULL
) {
188 snmp_set_api_error(SNMPERR_OS_ERR
);
193 printf("VARS: Copying name OID. (Size %d)\n", Src
->name_length
);
195 memcpy((char *) Dest
->name
, (char *) Src
->name
,
196 Src
->name_length
* sizeof(oid
));
198 /* CISCO Catalyst 2900 returns NULL strings as data of length 0. */
199 if ((Src
->val
.string
!= NULL
) &&
201 Dest
->val
.string
= (u_char
*) xmalloc(Src
->val_len
);
202 if (Dest
->val
.string
== NULL
) {
203 snmp_set_api_error(SNMPERR_OS_ERR
);
209 printf("VARS: Copying value (Size %d)\n", Src
->val_len
);
211 memcpy((char *) Dest
->val
.string
, (char *) Src
->val
.string
, Src
->val_len
);
214 printf("VARS: Cloned %x.\n", (unsigned int) Dest
);
216 #if DEBUG_VARS_MALLOC
217 printf("VARS: Cloned (%x)\n", (unsigned int) Dest
);
218 printf("VARS: Name is (%x)\n", (unsigned int) Dest
->name
);
224 /* Free a variable_list.
227 snmp_var_free(struct variable_list
*Ptr
)
230 xfree((char *) Ptr
->name
);
233 xfree((char *) Ptr
->val
.string
);
234 else if (Ptr
->val
.integer
)
235 xfree((char *) Ptr
->val
.integer
);
240 /**********************************************************************/
242 /* Build a variable binding.
244 * RFC 1905: Protocol Operations for SNMPv2
252 * noSuchObject[0] NULL
253 * noSuchInstance[1] NULL
254 * endOfMibView[2] NULL
259 snmp_var_EncodeVarBind(u_char
* Buffer
, int *BufLenP
,
260 variable_list
* VarList
,
263 struct variable_list
*Vars
;
267 int FakeArg
= *BufLenP
;
271 for (Vars
= VarList
; Vars
; Vars
= Vars
->next_variable
) {
273 /* Build the header for this variable
278 HeaderEnd
= asn_build_header(HeaderStart
, BufLenP
,
279 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
281 if (HeaderEnd
== NULL
)
284 /* Now, let's put the Object Identifier into the buffer */
285 bufp
= asn_build_objid(HeaderEnd
, BufLenP
,
286 (u_char
) (ASN_UNIVERSAL
|
289 Vars
->name
, Vars
->name_length
);
293 /* Now put the data in */
294 switch (Vars
->type
) {
297 bufp
= asn_build_int(bufp
,
299 (int *) Vars
->val
.integer
, Vars
->val_len
);
304 /* case SMI_UNSIGNED32: */
306 bufp
= asn_build_unsigned_int(bufp
, BufLenP
,
308 (u_int
*) Vars
->val
.integer
, Vars
->val_len
);
314 bufp
= asn_build_string(bufp
, BufLenP
, Vars
->type
,
315 Vars
->val
.string
, Vars
->val_len
);
319 bufp
= asn_build_objid(bufp
, BufLenP
, Vars
->type
,
320 (oid
*) Vars
->val
.objid
, Vars
->val_len
/ sizeof(oid
));
323 case SMI_NOSUCHINSTANCE
:
324 case SMI_NOSUCHOBJECT
:
325 case SMI_ENDOFMIBVIEW
:
326 if (Version
== SNMP_VERSION_1
) {
327 /* SNMP Version 1 does not support these error codes. */
328 bufp
= asn_build_null(bufp
, BufLenP
, SMI_NOSUCHOBJECT
);
330 bufp
= asn_build_exception(bufp
, BufLenP
, Vars
->type
);
335 bufp
= asn_build_null(bufp
, BufLenP
, Vars
->type
);
339 snmplib_debug(2, "Unable to encode type SMI_COUNTER64!\n");
343 snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE
);
347 /* ASSERT: bufp should now point to the next valid byte. */
351 /* Rebuild the header with the appropriate length */
352 HeaderEnd
= asn_build_header(HeaderStart
, &FakeArg
,
353 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
357 if (HeaderEnd
== NULL
)
362 /* or the end of the entire thing */
366 /* Parse all Vars from the buffer */
368 snmp_var_DecodeVarBind(u_char
* Buffer
, int *BufLen
,
369 struct variable_list
** VarP
,
372 struct variable_list
*Var
= NULL
, **VarLastP
;
377 oid TmpBuf
[MAX_NAME_LEN
];
378 memset(TmpBuf
, 0, MAX_NAME_LEN
* sizeof(*TmpBuf
));
380 int AllVarLen
= *BufLen
;
384 #if DEBUG_VARS_DECODE
385 printf("VARS: Decoding buffer of length %d\n", *BufLen
);
388 /* Now parse the variables */
389 bufp
= asn_parse_header(Buffer
, &AllVarLen
, &VarBindType
);
393 if (VarBindType
!= (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
)) {
394 snmp_set_api_error(SNMPERR_PDU_PARSE
);
397 #if DEBUG_VARS_DECODE
398 printf("VARS: All Variable length %d\n", AllVarLen
);
401 #define PARSE_ERROR { snmp_var_free(Var); return(NULL); }
403 /* We know how long the variable list is. Parse it. */
404 while ((int) AllVarLen
> 0) {
406 /* Create a new variable */
407 Var
= snmp_var_new(NULL
, MAX_NAME_LEN
);
411 /* Parse the header to find out the length of this variable. */
412 ThisVarLen
= AllVarLen
;
413 tmp
= asn_parse_header(bufp
, &ThisVarLen
, &VarBindType
);
417 /* Now that we know the length , figure out how it relates to
418 * the entire variable list
420 AllVarLen
= AllVarLen
- (ThisVarLen
+ (tmp
- bufp
));
424 if (VarBindType
!= (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
)) {
425 snmp_set_api_error(SNMPERR_PDU_PARSE
);
428 #if DEBUG_VARS_DECODE
429 printf("VARS: Header type 0x%x (%d bytes left)\n", VarBindType
, ThisVarLen
);
432 /* Parse the OBJID */
433 bufp
= asn_parse_objid(bufp
, &ThisVarLen
, &VarBindType
,
434 Var
->name
, &(Var
->name_length
));
438 if (VarBindType
!= (u_char
) (ASN_UNIVERSAL
|
441 snmp_set_api_error(SNMPERR_PDU_PARSE
);
444 #if DEBUG_VARS_DECODE
445 printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)\n",
446 Var
->name_length
, ThisVarLen
);
449 /* Keep a pointer to this object */
451 DataLen
= ThisVarLen
;
453 /* find out type of object */
454 bufp
= asn_parse_header(bufp
, &ThisVarLen
, &(Var
->type
));
457 ThisVarLen
= DataLen
;
459 #if DEBUG_VARS_DECODE
460 printf("VARS: Data type %d\n", Var
->type
);
465 switch ((short) Var
->type
) {
468 Var
->val
.integer
= (int *) xmalloc(sizeof(int));
469 if (Var
->val
.integer
== NULL
) {
470 snmp_set_api_error(SNMPERR_OS_ERR
);
473 Var
->val_len
= sizeof(int);
474 bufp
= asn_parse_int(DataPtr
, &ThisVarLen
,
475 &Var
->type
, (int *) Var
->val
.integer
,
477 #if DEBUG_VARS_DECODE
478 printf("VARS: Decoded integer '%d' (%d bytes left)\n",
479 *(Var
->val
.integer
), ThisVarLen
);
485 /* case SMI_UNSIGNED32: */
487 Var
->val
.integer
= (int *) xmalloc(sizeof(u_int
));
488 if (Var
->val
.integer
== NULL
) {
489 snmp_set_api_error(SNMPERR_OS_ERR
);
492 Var
->val_len
= sizeof(u_int
);
493 bufp
= asn_parse_unsigned_int(DataPtr
, &ThisVarLen
,
494 &Var
->type
, (u_int
*) Var
->val
.integer
,
496 #if DEBUG_VARS_DECODE
497 printf("VARS: Decoded timeticks '%d' (%d bytes left)\n",
498 *(Var
->val
.integer
), ThisVarLen
);
505 Var
->val_len
= *&ThisVarLen
; /* String is this at most */
506 Var
->val
.string
= (u_char
*) xmalloc((unsigned) Var
->val_len
);
507 if (Var
->val
.string
== NULL
) {
508 snmp_set_api_error(SNMPERR_OS_ERR
);
511 int terminatorPos
= Var
->val_len
- 1;
512 bufp
= asn_parse_string(DataPtr
, &ThisVarLen
,
513 &Var
->type
, Var
->val
.string
,
515 if (Var
->val_len
< terminatorPos
) {
516 terminatorPos
= Var
->val_len
;
518 Var
->val
.string
[terminatorPos
] = '\0';
519 #if DEBUG_VARS_DECODE
520 printf("VARS: Decoded string '%s' (length %d) (%d bytes left)\n",
521 (Var
->val
.string
), Var
->val_len
, ThisVarLen
);
526 Var
->val_len
= MAX_NAME_LEN
;
527 bufp
= asn_parse_objid(DataPtr
, &ThisVarLen
,
528 &Var
->type
, TmpBuf
, &Var
->val_len
);
529 Var
->val_len
*= sizeof(oid
);
530 Var
->val
.objid
= (oid
*) xmalloc((unsigned) Var
->val_len
);
531 if (Var
->val
.integer
== NULL
) {
532 snmp_set_api_error(SNMPERR_OS_ERR
);
535 /* Only copy if we successfully decoded something */
537 memcpy((char *) Var
->val
.objid
, (char *) TmpBuf
, Var
->val_len
);
539 #if DEBUG_VARS_DECODE
540 printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n",
541 Var
->val_len
, ThisVarLen
);
546 case SMI_NOSUCHINSTANCE
:
547 case SMI_NOSUCHOBJECT
:
548 case SMI_ENDOFMIBVIEW
:
552 snmplib_debug(2, "Unable to parse type SMI_COUNTER64!\n");
553 snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE
);
557 snmplib_debug(2, "bad type returned (%x)\n", Var
->type
);
558 snmp_set_api_error(SNMPERR_PDU_PARSE
);
560 } /* End of var type switch */
565 #if DEBUG_VARS_DECODE
566 printf("VARS: Adding to list.\n");
568 /* Add variable to the list */
570 VarLastP
= &(Var
->next_variable
);