snmp_vars.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:14k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * SNMP Variable Binding.  Complies with:
  3.  *
  4.  * RFC 1905: Protocol Operations for SNMPv2
  5.  *
  6.  */
  7. /**********************************************************************
  8.  *
  9.  *           Copyright 1997 by Carnegie Mellon University
  10.  * 
  11.  *                       All Rights Reserved
  12.  * 
  13.  * Permission to use, copy, modify, and distribute this software and its
  14.  * documentation for any purpose and without fee is hereby granted,
  15.  * provided that the above copyright notice appear in all copies and that
  16.  * both that copyright notice and this permission notice appear in
  17.  * supporting documentation, and that the name of CMU not be
  18.  * used in advertising or publicity pertaining to distribution of the
  19.  * software without specific, written prior permission.
  20.  * 
  21.  * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  22.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  23.  * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  24.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  25.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  26.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  27.  * SOFTWARE.
  28.  * 
  29.  * Author: Ryan Troll <ryan+@andrew.cmu.edu>
  30.  * 
  31.  **********************************************************************/
  32. #include "config.h"
  33. #include <stdio.h>
  34. #if HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #if HAVE_STDLIB_H
  38. #include <stdlib.h>
  39. #endif
  40. #if HAVE_SYS_TYPES_H
  41. #include <sys/types.h>
  42. #endif
  43. #if HAVE_CTYPE_H
  44. #include <ctype.h>
  45. #endif
  46. #if HAVE_GNUMALLOC_H
  47. #include <gnumalloc.h>
  48. #elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)
  49. #include <malloc.h>
  50. #endif
  51. #if HAVE_MEMORY_H
  52. #include <memory.h>
  53. #endif
  54. #ifdef HAVE_STRING_H
  55. #include <string.h>
  56. #endif
  57. #ifdef HAVE_STRINGS_H
  58. #include <strings.h>
  59. #endif
  60. #if HAVE_BSTRING_H
  61. #include <bstring.h>
  62. #endif
  63. #if HAVE_SYS_SOCKET_H
  64. #include <sys/socket.h>
  65. #endif
  66. #if HAVE_NETINET_IN_H
  67. #include <netinet/in.h>
  68. #endif
  69. #if HAVE_ARPA_INET_H
  70. #include <arpa/inet.h>
  71. #endif
  72. #if HAVE_SYS_TIME_H
  73. #include <sys/time.h>
  74. #endif
  75. #if HAVE_NETDB_H
  76. #include <netdb.h>
  77. #endif
  78. #include "snmp.h"
  79. #include "asn1.h"
  80. #include "snmp_vars.h"
  81. #if 0
  82. #include "mibii.h"
  83. #endif
  84. #include "snmp_api_error.h"
  85. #include "snmp_pdu.h"
  86. #include "snmp_msg.h"
  87. #include "util.h"
  88. /* #define DEBUG_VARS 1 */
  89. /* #define DEBUG_VARS_MALLOC 1 */
  90. /* #define DEBUG_VARS_DECODE 1 */
  91. /* #define DEBUG_VARS_ENCODE 1 */
  92. #define ASN_PARSE_ERROR(x) { return(x); }
  93. /* Create a new variable_list structure representing oid Name of length Len.
  94.  *
  95.  * Returns NULL upon error.
  96.  */
  97. struct variable_list *
  98. snmp_var_new(oid * Name, int Len)
  99. {
  100.     struct variable_list *New;
  101. #ifdef DEBUG_VARS
  102.     printf("VARS: Creating.n");
  103. #endif
  104.     New = (struct variable_list *) xmalloc(sizeof(struct variable_list));
  105.     if (New == NULL) {
  106. snmp_set_api_error(SNMPERR_OS_ERR);
  107. return (NULL);
  108.     }
  109.     memset(New, '', sizeof(struct variable_list));
  110.     /*  New->next_variable = NULL; */
  111.     New->type = ASN_NULL;
  112.     New->name_length = Len;
  113.     if (New->name_length == 0) {
  114. New->name = NULL;
  115. return (New);
  116.     }
  117.     New->name = (oid *) xmalloc(Len * sizeof(oid));
  118.     if (New->name == NULL) {
  119. xfree(New);
  120. snmp_set_api_error(SNMPERR_OS_ERR);
  121. return (NULL);
  122.     }
  123. #ifdef DEBUG_VARS
  124.     printf("VARS: Copying name, size (%d)n", Len);
  125. #endif
  126.     /* Only copy a name if it was specified. */
  127.     if (Name)
  128. xmemcpy((char *) New->name, (char *) Name, Len * sizeof(oid));
  129.     return (New);
  130. }
  131. /* Clone a variable list.
  132.  *
  133.  * Returns NULL upon error.
  134.  */
  135. struct variable_list *
  136. snmp_var_clone(struct variable_list *Src)
  137. {
  138.     struct variable_list *Dest;
  139. #ifdef DEBUG_VARS
  140.     printf("VARS: Cloning.n");
  141. #endif
  142.     Dest = (struct variable_list *) xmalloc(sizeof(struct variable_list));
  143.     if (Dest == NULL) {
  144. snmp_set_api_error(SNMPERR_OS_ERR);
  145. return (NULL);
  146.     }
  147. #ifdef DEBUG_VARS
  148.     printf("VARS: Copying entire variable list.  (Size %d)n",
  149. sizeof(struct variable_list));
  150. #endif
  151.     xmemcpy((char *) Dest, (char *) Src, sizeof(struct variable_list));
  152.     if (Src->name != NULL) {
  153. Dest->name = (oid *) xmalloc(Src->name_length * sizeof(oid));
  154. if (Dest->name == NULL) {
  155.     snmp_set_api_error(SNMPERR_OS_ERR);
  156.     xfree(Dest);
  157.     return (NULL);
  158. }
  159. #ifdef DEBUG_VARS
  160. printf("VARS: Copying name OID. (Size %d)n", Src->name_length);
  161. #endif
  162. xmemcpy((char *) Dest->name, (char *) Src->name,
  163.     Src->name_length * sizeof(oid));
  164.     }
  165.     /* CISCO Catalyst 2900 returns NULL strings as data of length 0. */
  166.     if ((Src->val.string != NULL) &&
  167. (Src->val_len)) {
  168. Dest->val.string = (u_char *) xmalloc(Src->val_len);
  169. if (Dest->val.string == NULL) {
  170.     snmp_set_api_error(SNMPERR_OS_ERR);
  171.     xfree(Dest->name);
  172.     xfree(Dest);
  173.     return (NULL);
  174. }
  175. #ifdef DEBUG_VARS
  176. printf("VARS: Copying value (Size %d)n", Src->val_len);
  177. #endif
  178. xmemcpy((char *) Dest->val.string, (char *) Src->val.string, Src->val_len);
  179.     }
  180. #ifdef DEBUG_VARS
  181.     printf("VARS: Cloned %x.n", (unsigned int) Dest);
  182. #endif
  183. #ifdef DEBUG_VARS_MALLOC
  184.     printf("VARS: Cloned  (%x)n", (unsigned int) Dest);
  185.     printf("VARS: Name is (%x)n", (unsigned int) Dest->name);
  186. #endif
  187.     return (Dest);
  188. }
  189. /* Free a variable_list.
  190.  */
  191. void 
  192. snmp_var_free(struct variable_list *Ptr)
  193. {
  194.     if (Ptr->name && Ptr->name_length > 0)
  195. xfree((char *) Ptr->name);
  196.     if (Ptr->val.string && Ptr->val_len > 0)
  197. xfree((char *) Ptr->val.string);
  198.     else if (Ptr->val.integer && Ptr->val_len > 0)
  199. xfree((char *) Ptr->val.integer);
  200.     xfree(Ptr);
  201. }
  202. /**********************************************************************/
  203. /* Build a variable binding.
  204.  *
  205.  * RFC 1905: Protocol Operations for SNMPv2
  206.  *
  207.  * VarBind ::= 
  208.  *   SEQUENCE {
  209.  *     name ObjectName
  210.  *     CHOICE {
  211.  *       value ObjectSyntax
  212.  *       unSpecified NULL
  213.  *       noSuchObject[0] NULL
  214.  *       noSuchInstance[1] NULL
  215.  *       endOfMibView[2] NULL
  216.  *     }
  217.  *   }
  218.  */
  219. u_char *
  220. snmp_var_EncodeVarBind(u_char * Buffer, int *BufLenP,
  221.     variable_list * VarList,
  222.     int Version)
  223. {
  224.     struct variable_list *Vars;
  225.     u_char *bufp;
  226.     u_char *HeaderStart;
  227.     u_char *HeaderEnd;
  228.     int FakeArg = *BufLenP;
  229.     bufp = Buffer;
  230.     for (Vars = VarList; Vars; Vars = Vars->next_variable) {
  231. /* Build the header for this variable
  232.  *
  233.  * Use Maximum size.
  234.  */
  235. HeaderStart = bufp;
  236. HeaderEnd = asn_build_header(HeaderStart, BufLenP,
  237.     (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
  238.     FakeArg);
  239. if (HeaderEnd == NULL)
  240.     return (NULL);
  241. /* Now, let's put the Object Identifier into the buffer */
  242. bufp = asn_build_objid(HeaderEnd, BufLenP,
  243.     (u_char) (ASN_UNIVERSAL |
  244. ASN_PRIMITIVE |
  245. ASN_OBJECT_ID),
  246.     Vars->name, Vars->name_length);
  247. if (bufp == NULL)
  248.     return (NULL);
  249. /* Now put the data in */
  250. switch (Vars->type) {
  251. case ASN_INTEGER:
  252.     bufp = asn_build_int(bufp,
  253. BufLenP, Vars->type,
  254. (int *) Vars->val.integer, Vars->val_len);
  255.     break;
  256. case SMI_COUNTER32:
  257. case SMI_GAUGE32:
  258.     /*  case SMI_UNSIGNED32: */
  259. case SMI_TIMETICKS:
  260.     bufp = asn_build_unsigned_int(bufp, BufLenP,
  261. Vars->type,
  262. (u_int *) Vars->val.integer, Vars->val_len);
  263.     break;
  264. case ASN_OCTET_STR:
  265. case SMI_IPADDRESS:
  266. case SMI_OPAQUE:
  267.     bufp = asn_build_string(bufp, BufLenP, Vars->type,
  268. Vars->val.string, Vars->val_len);
  269.     break;
  270. case ASN_OBJECT_ID:
  271.     bufp = asn_build_objid(bufp, BufLenP, Vars->type,
  272. (oid *) Vars->val.objid, Vars->val_len / sizeof(oid));
  273.     break;
  274. case SMI_NOSUCHINSTANCE:
  275. case SMI_NOSUCHOBJECT:
  276. case SMI_ENDOFMIBVIEW:
  277.     if (Version == SNMP_VERSION_1) {
  278. /* SNMP Version 1 does not support these error codes. */
  279. bufp = asn_build_null(bufp, BufLenP, SMI_NOSUCHOBJECT);
  280.     } else {
  281. bufp = asn_build_exception(bufp, BufLenP, Vars->type);
  282.     }
  283.     break;
  284. case ASN_NULL:
  285.     bufp = asn_build_null(bufp, BufLenP, Vars->type);
  286.     break;
  287. case SMI_COUNTER64:
  288.     snmplib_debug(2, "Unable to encode type SMI_COUNTER64!n");
  289.     /* Fall through */
  290. default:
  291.     snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE);
  292.     return (NULL);
  293. }
  294. /* ASSERT:  bufp should now point to the next valid byte. */
  295. if (bufp == NULL)
  296.     return (NULL);
  297. /* Rebuild the header with the appropriate length */
  298. HeaderEnd = asn_build_header(HeaderStart, &FakeArg,
  299.     (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
  300.     (bufp - HeaderEnd));
  301. /* Returns NULL */
  302. if (HeaderEnd == NULL)
  303.     return (NULL);
  304.     }
  305.     /* or the end of the entire thing */
  306.     return (bufp);
  307. }
  308. /* Parse all Vars from the buffer */
  309. u_char *
  310. snmp_var_DecodeVarBind(u_char * Buffer, int *BufLen,
  311.     struct variable_list ** VarP,
  312.     int Version)
  313. {
  314.     struct variable_list *Var, **VarLastP;
  315.     u_char *bufp, *tmp;
  316.     u_char VarBindType;
  317.     u_char *DataPtr;
  318.     int DataLen;
  319.     oid TmpBuf[MAX_NAME_LEN];
  320.     int AllVarLen = *BufLen;
  321.     int ThisVarLen = 0;
  322.     VarLastP = VarP;
  323. #ifdef DEBUG_VARS_DECODE
  324.     printf("VARS: Decoding buffer of length %dn", *BufLen);
  325. #endif
  326.     /* Now parse the variables */
  327.     bufp = asn_parse_header(Buffer, &AllVarLen, &VarBindType);
  328.     if (bufp == NULL)
  329. ASN_PARSE_ERROR(NULL);
  330.     if (VarBindType != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
  331. snmp_set_api_error(SNMPERR_PDU_PARSE);
  332. ASN_PARSE_ERROR(NULL);
  333.     }
  334. #ifdef DEBUG_VARS_DECODE
  335.     printf("VARS: All Variable length %dn", AllVarLen);
  336. #endif
  337.     /* We know how long the variable list is.  Parse it. */
  338.     while ((int) AllVarLen > 0) {
  339. /* Create a new variable */
  340. Var = snmp_var_new(NULL, MAX_NAME_LEN);
  341. if (Var == NULL)
  342.     return (NULL);
  343. /* Parse the header to find out the length of this variable. */
  344. ThisVarLen = AllVarLen;
  345. tmp = asn_parse_header(bufp, &ThisVarLen, &VarBindType);
  346. if (tmp == NULL)
  347.     ASN_PARSE_ERROR(NULL);
  348. /* Now that we know the length , figure out how it relates to 
  349.  * the entire variable list
  350.  */
  351. AllVarLen = AllVarLen - (ThisVarLen + (tmp - bufp));
  352. bufp = tmp;
  353. /* Is it valid? */
  354. if (VarBindType != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
  355.     snmp_set_api_error(SNMPERR_PDU_PARSE);
  356.     ASN_PARSE_ERROR(NULL);
  357. }
  358. #ifdef DEBUG_VARS_DECODE
  359. printf("VARS: Header type 0x%x (%d bytes left)n", VarBindType, ThisVarLen);
  360. #endif
  361. /* Parse the OBJID */
  362. bufp = asn_parse_objid(bufp, &ThisVarLen, &VarBindType,
  363.     Var->name, &(Var->name_length));
  364. if (bufp == NULL)
  365.     ASN_PARSE_ERROR(NULL);
  366. if (VarBindType != (u_char) (ASN_UNIVERSAL |
  367. ASN_PRIMITIVE |
  368. ASN_OBJECT_ID)) {
  369.     snmp_set_api_error(SNMPERR_PDU_PARSE);
  370.     ASN_PARSE_ERROR(NULL);
  371. }
  372. #ifdef DEBUG_VARS_DECODE
  373. printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)n",
  374.     Var->name_length, ThisVarLen);
  375. #endif
  376. /* Keep a pointer to this object */
  377. DataPtr = bufp;
  378. DataLen = ThisVarLen;
  379. /* find out type of object */
  380. bufp = asn_parse_header(bufp, &ThisVarLen, &(Var->type));
  381. if (bufp == NULL)
  382.     ASN_PARSE_ERROR(NULL);
  383. ThisVarLen = DataLen;
  384. #ifdef DEBUG_VARS_DECODE
  385. printf("VARS: Data type %dn", Var->type);
  386. #endif
  387. /* Parse the type */
  388. switch ((short) Var->type) {
  389. case ASN_INTEGER:
  390.     Var->val.integer = (int *) xmalloc(sizeof(int));
  391.     if (Var->val.integer == NULL) {
  392. snmp_set_api_error(SNMPERR_OS_ERR);
  393. return (NULL);
  394.     }
  395.     Var->val_len = sizeof(int);
  396.     bufp = asn_parse_int(DataPtr, &ThisVarLen,
  397. &Var->type, (int *) Var->val.integer,
  398. Var->val_len);
  399. #ifdef DEBUG_VARS_DECODE
  400.     printf("VARS: Decoded integer '%d' (%d bytes left)n",
  401. *(Var->val.integer), ThisVarLen);
  402. #endif
  403.     break;
  404. case SMI_COUNTER32:
  405. case SMI_GAUGE32:
  406.     /*  case SMI_UNSIGNED32: */
  407. case SMI_TIMETICKS:
  408.     Var->val.integer = (int *) xmalloc(sizeof(u_int));
  409.     if (Var->val.integer == NULL) {
  410. snmp_set_api_error(SNMPERR_OS_ERR);
  411. return (NULL);
  412.     }
  413.     Var->val_len = sizeof(u_int);
  414.     bufp = asn_parse_unsigned_int(DataPtr, &ThisVarLen,
  415. &Var->type, (u_int *) Var->val.integer,
  416. Var->val_len);
  417. #ifdef DEBUG_VARS_DECODE
  418.     printf("VARS: Decoded timeticks '%d' (%d bytes left)n",
  419. *(Var->val.integer), ThisVarLen);
  420. #endif
  421.     break;
  422. case ASN_OCTET_STR:
  423. case SMI_IPADDRESS:
  424. case SMI_OPAQUE:
  425.     Var->val_len = *&ThisVarLen; /* String is this at most */
  426.     Var->val.string = (u_char *) xmalloc((unsigned) Var->val_len);
  427.     if (Var->val.string == NULL) {
  428. snmp_set_api_error(SNMPERR_OS_ERR);
  429. return (NULL);
  430.     }
  431.     bufp = asn_parse_string(DataPtr, &ThisVarLen,
  432. &Var->type, Var->val.string,
  433. &Var->val_len);
  434. #ifdef DEBUG_VARS_DECODE
  435.     printf("VARS: Decoded string '%s' (length %d) (%d bytes left)n",
  436. (Var->val.string), Var->val_len, ThisVarLen);
  437. #endif
  438.     break;
  439. case ASN_OBJECT_ID:
  440.     Var->val_len = MAX_NAME_LEN;
  441.     bufp = asn_parse_objid(DataPtr, &ThisVarLen,
  442. &Var->type, TmpBuf, &Var->val_len);
  443.     Var->val_len *= sizeof(oid);
  444.     Var->val.objid = (oid *) xmalloc((unsigned) Var->val_len);
  445.     if (Var->val.integer == NULL) {
  446. snmp_set_api_error(SNMPERR_OS_ERR);
  447. return (NULL);
  448.     }
  449.     /* Only copy if we successfully decoded something */
  450.     if (bufp) {
  451. xmemcpy((char *) Var->val.objid, (char *) TmpBuf, Var->val_len);
  452.     }
  453. #ifdef DEBUG_VARS_DECODE
  454.     printf("VARS: Decoded OBJID (length %d) (%d bytes left)n",
  455. Var->val_len, ThisVarLen);
  456. #endif
  457.     break;
  458. case ASN_NULL:
  459. case SMI_NOSUCHINSTANCE:
  460. case SMI_NOSUCHOBJECT:
  461. case SMI_ENDOFMIBVIEW:
  462.     break;
  463. case SMI_COUNTER64:
  464.     snmplib_debug(2, "Unable to parse type SMI_COUNTER64!n");
  465.     snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE);
  466.     return (NULL);
  467.     break;
  468. default:
  469.     snmplib_debug(2, "bad type returned (%x)n", Var->type);
  470.     snmp_set_api_error(SNMPERR_PDU_PARSE);
  471.     return (NULL);
  472.     break;
  473. } /* End of var type switch */
  474. if (bufp == NULL)
  475.     return (NULL);
  476. #ifdef DEBUG_VARS_DECODE
  477. printf("VARS:  Adding to list.n");
  478. #endif
  479. /* Add variable to the list */
  480. *VarLastP = Var;
  481. VarLastP = &(Var->next_variable);
  482.     }
  483.     return (bufp);
  484. }