snmp_vars.c
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:16k
源码类别:

SNMP编程

开发平台:

C/C++

  1. /*
  2.  * snmp_vars.c - return a pointer to the named variable.
  3.  *
  4.  *
  5.  */
  6. /***********************************************************
  7. Copyright 1988, 1989, 1990 by Carnegie Mellon University
  8. Copyright 1989 TGV, Incorporated
  9.       All Rights Reserved
  10. Permission to use, copy, modify, and distribute this software and its
  11. documentation for any purpose and without fee is hereby granted,
  12. provided that the above copyright notice appear in all copies and that
  13. both that copyright notice and this permission notice appear in
  14. supporting documentation, and that the name of CMU and TGV not be used
  15. in advertising or publicity pertaining to distribution of the software
  16. without specific, written prior permission.
  17. CMU AND TGV DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  18. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  19. EVENT SHALL CMU OR TGV BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  20. CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  21. USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  22. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  23. PERFORMANCE OF THIS SOFTWARE.
  24. ******************************************************************/
  25. /*
  26.  * additions, fixes and enhancements for Linux by Erik Schoenfelder
  27.  * (schoenfr@ibr.cs.tu-bs.de) 1994/1995.
  28.  * Linux additions taken from CMU to UCD stack by Jennifer Bray of Origin
  29.  * (jbray@origin-at.co.uk) 1997
  30.  */
  31. #include <config.h>
  32. #if HAVE_STRING_H
  33. #include <string.h>
  34. #endif
  35. #if HAVE_STDLIB_H
  36. #include <stdlib.h>
  37. #endif
  38. #include <sys/types.h>
  39. #include <stdio.h>
  40. #include <fcntl.h>
  41. #if TIME_WITH_SYS_TIME
  42. # ifdef WIN32
  43. #  include <sys/timeb.h>
  44. # else
  45. #  include <time.h>
  46. # endif
  47. # include <time.h>
  48. #else
  49. # if HAVE_SYS_TIME_H
  50. #  include <sys/time.h>
  51. # else
  52. #  include <time.h>
  53. # endif
  54. #endif
  55. #ifdef OS_VXWORKS
  56. #include <sys/times.h>
  57. #endif
  58. #if HAVE_SYS_SOCKET_H
  59. #include <sys/socket.h>
  60. #elif HAVE_WINSOCK_H
  61. #include <ip/socket.h>
  62. #endif
  63. #if HAVE_NETINET_IN_H
  64. #include <netinet/in.h>
  65. #endif
  66. #if HAVE_NETINET_IN_SYSTM_H
  67. #include <netinet/in_systm.h>
  68. #endif
  69. #if HAVE_NETINET_IP_H
  70. #include <netinet/ip.h>
  71. #endif
  72. #ifdef INET6
  73. #if HAVE_NETINET_IP6_H
  74. #include <netinet/ip6.h>
  75. #endif
  76. #endif
  77. #if HAVE_SYS_QUEUE_H
  78. #include <sys/queue.h>
  79. #endif
  80. #if HAVE_SYS_STREAM_H
  81. #include <sys/stream.h>
  82. #endif
  83. #if HAVE_NET_ROUTE_H
  84. #include <net/route.h>
  85. #endif
  86. #if HAVE_NETINET_IP_VAR_H
  87. #include <netinet/ip_var.h>
  88. #endif
  89. #ifdef INET6
  90. #if HAVE_NETINET6_IP6_VAR_H
  91. #include <netinet6/ip6_var.h>
  92. #endif
  93. #endif
  94. #if HAVE_NETINET_IN_PCB_H
  95. #include <netinet/in_pcb.h>
  96. #endif
  97. #if HAVE_INET_MIB2_H
  98. #include <inet/mib2.h>
  99. #endif
  100. #if HAVE_DMALLOC_H
  101. #include <dmalloc.h>
  102. #endif
  103. #include "mibGroup/mibincl.h"
  104. #include "snmpv3.h"
  105. #include "snmpusm.h"
  106. #include "system.h"
  107. /*#include "kernel.h"*/
  108. #include "snmp_vars.h"
  109. #include "default_store.h"
  110. #include "ds_agent.h"
  111. #include "mibgroup/struct.h"
  112. #include "read_config.h"
  113. #include "snmp_vars.h"
  114. #include "agent_read_config.h"
  115. #include "agent_registry.h"
  116. #include "callback.h"
  117. #include "snmp_alarm.h"
  118. #include "snmpd.h"
  119. #include "mib_module_includes.h"
  120. #ifndef  MIN
  121. #define  MIN(a,b)                     (((a) < (b)) ? (a) : (b)) 
  122. #endif
  123. /* mib clients are passed a pointer to a oid buffer.  Some mib clients
  124.  * (namely, those first noticed in mibII/vacm.c) modify this oid buffer
  125.  * before they determine if they really need to send results back out
  126.  * using it.  If the master agent determined that the client was not the
  127.  * right one to talk with, it will use the same oid buffer to pass to the
  128.  * rest of the clients, which may not longer be valid.  This should be
  129.  * fixed in all clients rather than the master.  However, its not a
  130.  * particularily easy bug to track down so this saves debugging time at
  131.  * the expense of a few memcpy's.
  132.  */
  133. #define MIB_CLIENTS_ARE_EVIL 1
  134.  
  135. extern struct subtree *subtrees;
  136. int subtree_size;
  137. int subtree_malloc_size;
  138. /*
  139.  * Each variable name is placed in the variable table, without the
  140.  * terminating substring that determines the instance of the variable.  When
  141.  * a string is found that is lexicographicly preceded by the input string,
  142.  * the function for that entry is called to find the method of access of the
  143.  * instance of the named variable.  If that variable is not found, NULL is
  144.  * returned, and the search through the table continues (it will probably
  145.  * stop at the next entry).  If it is found, the function returns a character
  146.  * pointer and a length or a function pointer.  The former is the address
  147.  * of the operand, the latter is a write routine for the variable.
  148.  *
  149.  * u_char *
  150.  * findVar(name, length, exact, var_len, write_method)
  151.  * oid     *name;     IN/OUT - input name requested, output name found
  152.  * int     length;     IN/OUT - number of sub-ids in the in and out oid's
  153.  * int     exact;     IN - TRUE if an exact match was requested.
  154.  * int     len;     OUT - length of variable or 0 if function returned.
  155.  * int     write_method;   OUT - pointer to function to set variable,
  156.  *                                otherwise 0
  157.  *
  158.  *     The writeVar function is returned to handle row addition or complex
  159.  * writes that require boundary checking or executing an action.
  160.  * This routine will be called three times for each varbind in the packet.
  161.  * The first time for each varbind, action is set to RESERVE1.  The type
  162.  * and value should be checked during this pass.  If any other variables
  163.  * in the MIB depend on this variable, this variable will be stored away
  164.  * (but *not* committed!) in a place where it can be found by a call to
  165.  * writeVar for a dependent variable, even in the same PDU.  During
  166.  * the second pass, action is set to RESERVE2.  If this variable is dependent
  167.  * on any other variables, it will check them now.  It must check to see
  168.  * if any non-committed values have been stored for variables in the same
  169.  * PDU that it depends on.  Sometimes resources will need to be reserved
  170.  * in the first two passes to guarantee that the operation can proceed
  171.  * during the third pass.  During the third pass, if there were no errors
  172.  * in the first two passes, writeVar is called for every varbind with action
  173.  * set to COMMIT.  It is now that the values should be written.  If there
  174.  * were errors during the first two passes, writeVar is called in the third
  175.  * pass once for each varbind, with the action set to FREE.  An opportunity
  176.  * is thus provided to free those resources reserved in the first two passes.
  177.  * 
  178.  * writeVar(action, var_val, var_val_type, var_val_len, statP, name, name_len)
  179.  * int     action;     IN - RESERVE1, RESERVE2, COMMIT, or FREE
  180.  * u_char   *var_val;     IN - input or output buffer space
  181.  * u_char   var_val_type;   IN - type of input buffer
  182.  * int     var_val_len;    IN - input and output buffer len
  183.  * u_char   *statP;     IN - pointer to local statistic
  184.  * oid      *name           IN - pointer to name requested
  185.  * int      name_len        IN - number of sub-ids in the name
  186.  */
  187. long long_return;
  188. #ifndef ibm032
  189. u_char return_buf[258];  
  190. #else
  191. u_char return_buf[256]; /* nee 64 */
  192. #endif
  193. extern struct timeval starttime;
  194. void
  195. init_agent (const char *app)
  196. {
  197. /*
  198.   starttime.tv_sec--;
  199.   starttime.tv_usec += 1000000L;
  200. */
  201.   /* we handle alarm signals ourselves in the select loop */
  202.   ds_set_boolean(DS_LIBRARY_ID, DS_LIB_ALARM_DONT_USE_SIG, 1);
  203.   usm_set_reportErrorOnUnknownID(1);
  204. #ifdef CAN_USE_NLIST
  205.   init_kmem("/dev/kmem");
  206. #endif
  207.   setup_tree();
  208.   init_agent_read_config(app);
  209. #ifdef TESTING
  210.   auto_nlist_print_tree(-2, 0);
  211. #endif
  212.   /* initialize agentx subagent if necessary. */
  213. #ifdef USING_AGENTX_SUBAGENT_MODULE
  214.   if(ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT)
  215.       subagent_pre_init();
  216. #endif
  217. }  /* end init_agent() */
  218. oid nullOid[] = {0,0};
  219. int nullOidLen = sizeof(nullOid)/sizeof(oid);
  220. /*
  221.  * getStatPtr - return a pointer to the named variable, as well as it's
  222.  * type, length, and access control list.
  223.  * Now uses 'search_subtree' (recursively) and 'search_subtree_vars'
  224.  * to do most of the work
  225.  *
  226.  * If an exact match for the variable name exists, it is returned.  If not,
  227.  * and exact is false, the next variable lexicographically after the
  228.  * requested one is returned.
  229.  *
  230.  * If no appropriate variable can be found, NULL is returned.
  231.  */
  232. static  int  found;
  233. static u_char *
  234. search_subtree_vars(struct subtree *tp,
  235.     oid *name,    /* IN - name of var, OUT - name matched */
  236.     size_t *namelen, /* IN -number of sub-ids in name,
  237.                                      OUT - subid-is in matched name */
  238.     u_char *type, /* OUT - type of matched variable */
  239.     size_t *len,  /* OUT - length of matched variable */
  240.     u_short *acl, /* OUT - access control list */
  241.     int exact,    /* IN - TRUE if exact match wanted */
  242.     WriteMethod **write_method,
  243.     struct snmp_pdu *pdu, /* IN - relevant auth info re PDU */
  244.     int *noSuchObject)
  245. {
  246.     register struct variable *vp;
  247.     struct variable compat_var, *cvp = &compat_var;
  248.     register int x;
  249.     u_char *access = NULL;
  250.     int result;
  251.     oid  *suffix;
  252.     size_t suffixlen;
  253. #if MIB_CLIENTS_ARE_EVIL
  254.     oid save[MAX_OID_LEN];
  255.     size_t savelen;
  256. #endif
  257.     int  view =0;
  258.     if ( tp->variables == NULL )
  259. return NULL;
  260.     result = compare_tree(name, *namelen, tp->name, tp->namelen);
  261.     suffixlen = *namelen - tp->namelen;
  262.     suffix = name + tp->namelen;
  263.     /* the following is part of the setup for the compatability
  264.        structure below that has been moved out of the main loop.
  265.      */
  266.     memcpy(cvp->name, tp->name, tp->namelen * sizeof(oid));
  267.             *noSuchObject = TRUE; /* In case of null variables_len */
  268.     for(x = 0, vp = tp->variables; x < tp->variables_len;
  269. vp =(struct variable *)((char *)vp +tp->variables_width), x++){
  270. /* if exact and ALWAYS
  271.    if next  and result >= 0 */
  272.                 /* and if vp->namelen != 0   -- Wes */
  273. if (vp->namelen && (exact || result >= 0)){
  274.     result = compare_tree(suffix, suffixlen, vp->name,
  275.      vp->namelen);
  276. }
  277. /* if exact and result == 0
  278.    if next  and result <= 0 */
  279.                 /* or if vp->namelen == 0    -- Wes */
  280. if ((!exact && (result <= 0)) || (exact && (result == 0)) ||
  281.                   vp->namelen == 0) {
  282.     /* builds an old (long) style variable structure to retain
  283.        compatability with var_* functions written previously.
  284.      */
  285.                   if (vp->namelen)
  286.                     memcpy((cvp->name + tp->namelen),
  287.   vp->name, vp->namelen * sizeof(oid));
  288.     cvp->namelen = (u_char)(tp->namelen + vp->namelen);
  289.     cvp->type = vp->type;
  290.     cvp->magic = vp->magic;
  291.     cvp->acl = vp->acl;
  292.     cvp->findVar = vp->findVar;
  293.                     *write_method = NULL;
  294. #if MIB_CLIENTS_ARE_EVIL
  295.                     memcpy(save, name, *namelen*sizeof(oid));
  296.                     savelen = *namelen;
  297. #endif
  298.     DEBUGMSGTL(("snmp_vars", "Trying variable: "));
  299.     DEBUGMSGOID(("snmp_vars", cvp->name, cvp->namelen));
  300.     DEBUGMSG(("snmp_vars"," ...n"));
  301. gaga:
  302.     access =(u_char *)(*(vp->findVar))(cvp, name, (int*)namelen, exact,
  303.   (int*)len, write_method);
  304.          DEBUGMSGTL(("snmp_vars", "Returned %sn",
  305. (access==NULL) ? "(null)" : "something" ));
  306. /*
  307.  * Check that the answer is acceptable.
  308.  *  i.e. lies within the current subtree chunk
  309.  *
  310.  * It might be worth saving this answer just in
  311.  *  case it turns out to be valid, but for now
  312.  *  we'll simply discard it.
  313.  */
  314.     if ( access && snmp_oid_compare(name, *namelen,
  315.     tp->end, tp->end_len) > 0) {
  316. memcpy(name, tp->end, tp->end_len);
  317. access = 0;
  318.     }
  319. #if MIB_CLIENTS_ARE_EVIL
  320.                     if (access == NULL) {
  321.       if (snmp_oid_compare(name, *namelen, save, savelen) != 0) {
  322. DEBUGMSGTL(("snmp_vars", "evil_client: "));
  323. DEBUGMSGOID(("snmp_vars", save, savelen));
  324. DEBUGMSG(("snmp_vars"," =>"));
  325. DEBUGMSGOID(("snmp_vars", name, *namelen));
  326. DEBUGMSG(("snmp_vars","n"));
  327.                         memcpy(name, save, savelen*sizeof(oid));
  328.                         *namelen = savelen;
  329.                       }
  330.                     }
  331. #endif
  332.     if (*write_method)
  333. *acl = cvp->acl;
  334.                     /* check for permission to view this part of the OID tree */
  335.     if ((access != NULL || (*write_method != NULL && exact)) &&
  336.                         (view = in_a_view(name, namelen, pdu, cvp->type))) {
  337. if ( access && !exact ) {
  338. /*
  339.  * We've got an answer, but shouldn't use it.
  340.  * But we *might* be able to use a later
  341.  *  instance of the same object, so we can't
  342.  *  legitimately move on to the next variable
  343.  *  in the variable structure just yet.
  344.  * Let's try re-calling the findVar routine
  345.  *  with the returned name, and see whether
  346.  *  the next answer is acceptable
  347.  */
  348.    *write_method = NULL;
  349.    goto gaga;
  350. }
  351. else if ( access && exact  && (view==5))
  352. {
  353. send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
  354. }/*by yangyuhua(a) 2006-11-15*/
  355.                         access = NULL;
  356. *write_method = NULL;
  357.     } else if (exact){
  358. found = TRUE;
  359.     }
  360.     if (access != NULL || (*write_method != NULL && exact))
  361. break;
  362. }
  363. /* if exact and result <= 0 */
  364. if (exact && (result  <= 0)){
  365.             *type = cvp->type;
  366.     *acl = cvp->acl;
  367.     if (found)
  368.                       *noSuchObject = FALSE;
  369.     else
  370.                       *noSuchObject = TRUE;
  371.     return NULL;
  372. }
  373.     }
  374.     if (access != NULL || (exact && *write_method != NULL)) {
  375.         *type = cvp->type;
  376. *acl = cvp->acl;
  377. return access;
  378.     }
  379.     return NULL;
  380. }
  381. u_char *
  382. getStatPtr(
  383.     oid *name,     /* IN - name of var, OUT - name matched */
  384.     size_t *namelen,   /* IN -number of sub-ids in name,
  385.                                OUT - subid-is in matched name */
  386.     u_char *type,     /* OUT - type of matched variable */
  387.     size_t *len,     /* OUT - length of matched variable */
  388.     u_short *acl,     /* OUT - access control list */
  389.     int exact,     /* IN - TRUE if exact match wanted */
  390.     WriteMethod **write_method,
  391.     struct snmp_pdu *pdu,   /* IN - relevant auth info re PDU */
  392.     int *noSuchObject)
  393. {
  394.     struct subtree *tp;
  395.     oid save[MAX_OID_LEN];
  396.     size_t savelen = 0;
  397.     u_char              result_type;
  398.     u_short             result_acl;
  399.     u_char         *search_return=NULL;
  400.     found = FALSE;
  401.     if (!exact){
  402. memcpy(save, name, *namelen * sizeof(oid));
  403. savelen = *namelen;
  404.     }
  405.     *write_method = NULL;
  406.     DEBUGMSGTL(("snmp_vars", "Looking for: "));
  407.     DEBUGMSGOID(("snmp_vars", name, *namelen));
  408.     DEBUGMSG(("snmp_vars"," ...n"));
  409.     tp = find_subtree(name, *namelen, NULL);
  410.     
  411.     while ( search_return == NULL && tp != NULL ) {
  412. DEBUGMSGTL(("snmp_vars", "Trying tree: "));
  413. DEBUGMSGOID(("snmp_vars", tp->name, tp->namelen));
  414. DEBUGMSG(("snmp_vars"," ...n"));
  415. search_return = search_subtree_vars( tp, name, namelen, &result_type,
  416.                                         len, &result_acl, exact, write_method,
  417.                                         pdu, noSuchObject);
  418. if ( search_return != NULL || exact )
  419.     break;
  420. tp = tp->next;
  421.     }
  422.     if ( tp == NULL ) {
  423. if (!search_return && !exact){
  424.     memcpy(name, save, savelen * sizeof(oid));
  425.     *namelen = savelen;
  426. }
  427. if (found)
  428.     *noSuchObject = FALSE;
  429. else
  430.     *noSuchObject = TRUE;
  431.         return NULL;
  432.     }
  433.     *type = result_type;
  434.     *acl =  result_acl;
  435.     return search_return;
  436. }