📄 snmp_vars.c
字号:
/* * SNMP Variable Binding. Complies with: * * RFC 1905: Protocol Operations for SNMPv2 * *//********************************************************************** * * Copyright 1997 by Carnegie Mellon University * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of CMU not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * * Author: Ryan Troll <ryan+@andrew.cmu.edu> * **********************************************************************/#include "config.h"#include <stdio.h>#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_SYS_TYPES_H#include <sys/types.h>#endif#if HAVE_CTYPE_H#include <ctype.h>#endif#if HAVE_GNUMALLOC_H#include <gnumalloc.h>#elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)#include <malloc.h>#endif#if HAVE_MEMORY_H#include <memory.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#if HAVE_BSTRING_H#include <bstring.h>#endif#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#if HAVE_SYS_TIME_H#include <sys/time.h>#endif#if HAVE_NETDB_H#include <netdb.h>#endif#include "snmp.h"#include "asn1.h"#include "snmp_vars.h"#if 0#include "mibii.h"#endif#include "snmp_api_error.h"#include "snmp_pdu.h"#include "snmp_msg.h"#include "util.h"/* #define DEBUG_VARS 1 *//* #define DEBUG_VARS_MALLOC 1 *//* #define DEBUG_VARS_DECODE 1 *//* #define DEBUG_VARS_ENCODE 1 */#define ASN_PARSE_ERROR(x) { return(x); }/* Create a new variable_list structure representing oid Name of length Len. * * Returns NULL upon error. */struct variable_list *snmp_var_new(oid * Name, int Len){ struct variable_list *New;#ifdef DEBUG_VARS printf("VARS: Creating.\n");#endif New = (struct variable_list *) xmalloc(sizeof(struct variable_list)); if (New == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return (NULL); } memset(New, '\0', sizeof(struct variable_list)); /* New->next_variable = NULL; */ New->type = ASN_NULL; New->name_length = Len; if (New->name_length == 0) { New->name = NULL; return (New); } New->name = (oid *) xmalloc(Len * sizeof(oid)); if (New->name == NULL) { xfree(New); snmp_set_api_error(SNMPERR_OS_ERR); return (NULL); }#ifdef DEBUG_VARS printf("VARS: Copying name, size (%d)\n", Len);#endif /* Only copy a name if it was specified. */ if (Name) xmemcpy((char *) New->name, (char *) Name, Len * sizeof(oid)); return (New);}/* Clone a variable list. * * Returns NULL upon error. */struct variable_list *snmp_var_clone(struct variable_list *Src){ struct variable_list *Dest;#ifdef DEBUG_VARS printf("VARS: Cloning.\n");#endif Dest = (struct variable_list *) xmalloc(sizeof(struct variable_list)); if (Dest == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return (NULL); }#ifdef DEBUG_VARS printf("VARS: Copying entire variable list. (Size %d)\n", sizeof(struct variable_list));#endif xmemcpy((char *) Dest, (char *) Src, sizeof(struct variable_list)); if (Src->name != NULL) { Dest->name = (oid *) xmalloc(Src->name_length * sizeof(oid)); if (Dest->name == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); xfree(Dest); return (NULL); }#ifdef DEBUG_VARS printf("VARS: Copying name OID. (Size %d)\n", Src->name_length);#endif xmemcpy((char *) Dest->name, (char *) Src->name, Src->name_length * sizeof(oid)); } /* CISCO Catalyst 2900 returns NULL strings as data of length 0. */ if ((Src->val.string != NULL) && (Src->val_len)) { Dest->val.string = (u_char *) xmalloc(Src->val_len); if (Dest->val.string == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); xfree(Dest->name); xfree(Dest); return (NULL); }#ifdef DEBUG_VARS printf("VARS: Copying value (Size %d)\n", Src->val_len);#endif xmemcpy((char *) Dest->val.string, (char *) Src->val.string, Src->val_len); }#ifdef DEBUG_VARS printf("VARS: Cloned %x.\n", (unsigned int) Dest);#endif#ifdef DEBUG_VARS_MALLOC printf("VARS: Cloned (%x)\n", (unsigned int) Dest); printf("VARS: Name is (%x)\n", (unsigned int) Dest->name);#endif return (Dest);}/* Free a variable_list. */void snmp_var_free(struct variable_list *Ptr){ if (Ptr->name && Ptr->name_length > 0) xfree((char *) Ptr->name); if (Ptr->val.string && Ptr->val_len > 0) xfree((char *) Ptr->val.string); else if (Ptr->val.integer && Ptr->val_len > 0) xfree((char *) Ptr->val.integer); xfree(Ptr);}/**********************************************************************//* Build a variable binding. * * RFC 1905: Protocol Operations for SNMPv2 * * VarBind ::= * SEQUENCE { * name ObjectName * CHOICE { * value ObjectSyntax * unSpecified NULL * noSuchObject[0] NULL * noSuchInstance[1] NULL * endOfMibView[2] NULL * } * } */u_char *snmp_var_EncodeVarBind(u_char * Buffer, int *BufLenP, variable_list * VarList, int Version){ struct variable_list *Vars; u_char *bufp; u_char *HeaderStart; u_char *HeaderEnd; int FakeArg = *BufLenP; bufp = Buffer; for (Vars = VarList; Vars; Vars = Vars->next_variable) { /* Build the header for this variable * * Use Maximum size. */ HeaderStart = bufp; HeaderEnd = asn_build_header(HeaderStart, BufLenP, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), FakeArg); if (HeaderEnd == NULL) return (NULL); /* Now, let's put the Object Identifier into the buffer */ bufp = asn_build_objid(HeaderEnd, BufLenP, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), Vars->name, Vars->name_length); if (bufp == NULL) return (NULL); /* Now put the data in */ switch (Vars->type) { case ASN_INTEGER: bufp = asn_build_int(bufp, BufLenP, Vars->type, (int *) Vars->val.integer, Vars->val_len); break; case SMI_COUNTER32: case SMI_GAUGE32: /* case SMI_UNSIGNED32: */ case SMI_TIMETICKS: bufp = asn_build_unsigned_int(bufp, BufLenP, Vars->type, (u_int *) Vars->val.integer, Vars->val_len); break; case ASN_OCTET_STR: case SMI_IPADDRESS: case SMI_OPAQUE: bufp = asn_build_string(bufp, BufLenP, Vars->type, Vars->val.string, Vars->val_len); break; case ASN_OBJECT_ID: bufp = asn_build_objid(bufp, BufLenP, Vars->type, (oid *) Vars->val.objid, Vars->val_len / sizeof(oid)); break; case SMI_NOSUCHINSTANCE: case SMI_NOSUCHOBJECT: case SMI_ENDOFMIBVIEW: if (Version == SNMP_VERSION_1) { /* SNMP Version 1 does not support these error codes. */ bufp = asn_build_null(bufp, BufLenP, SMI_NOSUCHOBJECT); } else { bufp = asn_build_exception(bufp, BufLenP, Vars->type); } break; case ASN_NULL: bufp = asn_build_null(bufp, BufLenP, Vars->type); break; case SMI_COUNTER64: snmplib_debug(2, "Unable to encode type SMI_COUNTER64!\n"); /* Fall through */ default: snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE); return (NULL); } /* ASSERT: bufp should now point to the next valid byte. */ if (bufp == NULL) return (NULL); /* Rebuild the header with the appropriate length */ HeaderEnd = asn_build_header(HeaderStart, &FakeArg, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), (bufp - HeaderEnd)); /* Returns NULL */ if (HeaderEnd == NULL) return (NULL); } /* or the end of the entire thing */ return (bufp);}/* Parse all Vars from the buffer */u_char *snmp_var_DecodeVarBind(u_char * Buffer, int *BufLen, struct variable_list ** VarP, int Version){ struct variable_list *Var, **VarLastP; u_char *bufp, *tmp; u_char VarBindType; u_char *DataPtr; int DataLen; oid TmpBuf[MAX_NAME_LEN]; int AllVarLen = *BufLen; int ThisVarLen = 0; VarLastP = VarP;#ifdef DEBUG_VARS_DECODE printf("VARS: Decoding buffer of length %d\n", *BufLen);#endif /* Now parse the variables */ bufp = asn_parse_header(Buffer, &AllVarLen, &VarBindType); if (bufp == NULL) ASN_PARSE_ERROR(NULL); if (VarBindType != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { snmp_set_api_error(SNMPERR_PDU_PARSE); ASN_PARSE_ERROR(NULL); }#ifdef DEBUG_VARS_DECODE printf("VARS: All Variable length %d\n", AllVarLen);#endif /* We know how long the variable list is. Parse it. */ while ((int) AllVarLen > 0) { /* Create a new variable */ Var = snmp_var_new(NULL, MAX_NAME_LEN); if (Var == NULL) return (NULL); /* Parse the header to find out the length of this variable. */ ThisVarLen = AllVarLen; tmp = asn_parse_header(bufp, &ThisVarLen, &VarBindType); if (tmp == NULL) ASN_PARSE_ERROR(NULL); /* Now that we know the length , figure out how it relates to * the entire variable list */ AllVarLen = AllVarLen - (ThisVarLen + (tmp - bufp)); bufp = tmp; /* Is it valid? */ if (VarBindType != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { snmp_set_api_error(SNMPERR_PDU_PARSE); ASN_PARSE_ERROR(NULL); }#ifdef DEBUG_VARS_DECODE printf("VARS: Header type 0x%x (%d bytes left)\n", VarBindType, ThisVarLen);#endif /* Parse the OBJID */ bufp = asn_parse_objid(bufp, &ThisVarLen, &VarBindType, Var->name, &(Var->name_length)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); if (VarBindType != (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID)) { snmp_set_api_error(SNMPERR_PDU_PARSE); ASN_PARSE_ERROR(NULL); }#ifdef DEBUG_VARS_DECODE printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)\n", Var->name_length, ThisVarLen);#endif /* Keep a pointer to this object */ DataPtr = bufp; DataLen = ThisVarLen; /* find out type of object */ bufp = asn_parse_header(bufp, &ThisVarLen, &(Var->type)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); ThisVarLen = DataLen;#ifdef DEBUG_VARS_DECODE printf("VARS: Data type %d\n", Var->type);#endif /* Parse the type */ switch ((short) Var->type) { case ASN_INTEGER: Var->val.integer = (int *) xmalloc(sizeof(int)); if (Var->val.integer == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return (NULL); } Var->val_len = sizeof(int); bufp = asn_parse_int(DataPtr, &ThisVarLen, &Var->type, (int *) Var->val.integer, Var->val_len);#ifdef DEBUG_VARS_DECODE printf("VARS: Decoded integer '%d' (%d bytes left)\n", *(Var->val.integer), ThisVarLen);#endif break; case SMI_COUNTER32: case SMI_GAUGE32: /* case SMI_UNSIGNED32: */ case SMI_TIMETICKS: Var->val.integer = (int *) xmalloc(sizeof(u_int)); if (Var->val.integer == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return (NULL); } Var->val_len = sizeof(u_int); bufp = asn_parse_unsigned_int(DataPtr, &ThisVarLen, &Var->type, (u_int *) Var->val.integer, Var->val_len);#ifdef DEBUG_VARS_DECODE printf("VARS: Decoded timeticks '%d' (%d bytes left)\n", *(Var->val.integer), ThisVarLen);#endif break; case ASN_OCTET_STR: case SMI_IPADDRESS: case SMI_OPAQUE: Var->val_len = *&ThisVarLen; /* String is this at most */ Var->val.string = (u_char *) xmalloc((unsigned) Var->val_len); if (Var->val.string == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return (NULL); } bufp = asn_parse_string(DataPtr, &ThisVarLen, &Var->type, Var->val.string, &Var->val_len);#ifdef DEBUG_VARS_DECODE printf("VARS: Decoded string '%s' (length %d) (%d bytes left)\n", (Var->val.string), Var->val_len, ThisVarLen);#endif break; case ASN_OBJECT_ID: Var->val_len = MAX_NAME_LEN; bufp = asn_parse_objid(DataPtr, &ThisVarLen, &Var->type, TmpBuf, &Var->val_len); Var->val_len *= sizeof(oid); Var->val.objid = (oid *) xmalloc((unsigned) Var->val_len); if (Var->val.integer == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return (NULL); } /* Only copy if we successfully decoded something */ if (bufp) { xmemcpy((char *) Var->val.objid, (char *) TmpBuf, Var->val_len); }#ifdef DEBUG_VARS_DECODE printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n", Var->val_len, ThisVarLen);#endif break; case ASN_NULL: case SMI_NOSUCHINSTANCE: case SMI_NOSUCHOBJECT: case SMI_ENDOFMIBVIEW: break; case SMI_COUNTER64: snmplib_debug(2, "Unable to parse type SMI_COUNTER64!\n"); snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE); return (NULL); break; default: snmplib_debug(2, "bad type returned (%x)\n", Var->type); snmp_set_api_error(SNMPERR_PDU_PARSE); return (NULL); break; } /* End of var type switch */ if (bufp == NULL) return (NULL);#ifdef DEBUG_VARS_DECODE printf("VARS: Adding to list.\n");#endif /* Add variable to the list */ *VarLastP = Var; VarLastP = &(Var->next_variable); } return (bufp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -