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

SNMP编程

开发平台:

C/C++

  1. /*
  2.  * snmp_agent.c
  3.  *
  4.  * Simple Network Management Protocol (RFC 1067).
  5.  */
  6. /***********************************************************
  7. Copyright 1988, 1989 by Carnegie Mellon University
  8.                       All Rights Reserved
  9. Permission to use, copy, modify, and distribute this software and its 
  10. documentation for any purpose and without fee is hereby granted, 
  11. provided that the above copyright notice appear in all copies and that
  12. both that copyright notice and this permission notice appear in 
  13. supporting documentation, and that the name of CMU not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.  
  16. CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  17. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  18. CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  19. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  20. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  21. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  22. SOFTWARE.
  23. ******************************************************************/
  24. #include <config.h>
  25. #include <sys/types.h>
  26. #ifdef HAVE_STDLIB_H
  27. #include <stdlib.h>
  28. #endif
  29. #if HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #if HAVE_STRING_H
  33. #include <string.h>
  34. #endif
  35. #if TIME_WITH_SYS_TIME
  36. # ifdef WIN32
  37. #  include <timeb.h>
  38. # else
  39. #  include <time.h>
  40. # endif
  41. # include <time.h>
  42. #else
  43. # if HAVE_SYS_TIME_H
  44. #  include <sys/time.h>
  45. # else
  46. #  include <time.h>
  47. # endif
  48. #endif
  49. #ifdef OS_VXWORKS
  50. #include <sys/times.h>
  51. #endif
  52. #if HAVE_SYS_SELECT_H
  53. #include <sys/select.h>
  54. #endif
  55. #if HAVE_NETINET_IN_H
  56. #include <netinet/in.h>
  57. #endif
  58. #include <errno.h>
  59. #if HAVE_WINSOCK_H
  60. #include <ip/socket.h>
  61. #endif
  62. #if HAVE_DMALLOC_H
  63. #include <dmalloc.h>
  64. #endif
  65. #include "asn1.h"
  66. #define SNMP_NEED_REQUEST_LIST
  67. #include "snmp_api.h"
  68. #include "snmp_impl.h"
  69. #include "snmp.h"
  70. #include "mib.h"
  71. #include "snmp_client.h"
  72. #include "snmp_vars.h"
  73. #include "snmpd.h"
  74. #include "mibgroup/struct.h"
  75. #include "mibgroup/util_funcs.h"
  76. #include "var_struct.h"
  77. #include "read_config.h"
  78. #include "snmp_logging.h"
  79. #include "snmp_debug.h"
  80. #include "mib_module_config.h"
  81. #include "default_store.h"
  82. #include "ds_agent.h"
  83. #include "snmp_agent.h"
  84. #include "agent_trap.h"
  85. static int snmp_vars_inc;
  86. static struct agent_snmp_session *agent_session_list = NULL;
  87. static void dump_var(oid *, size_t, int, void *, size_t);
  88. static int goodValue(u_char, size_t, u_char, size_t);
  89. static void setVariable(u_char *, u_char, size_t, u_char *, size_t);
  90. #ifdef AGENT_USE_STATIC
  91. static struct agent_snmp_session agent_static;
  92. #endif
  93. static void dump_var (
  94.     oid *var_name,
  95.     size_t var_name_len,
  96.     int statType,
  97.     void *statP,
  98.     size_t statLen)
  99. {
  100.     char buf [SPRINT_MAX_LEN];
  101.     struct variable_list temp_var;
  102.     temp_var.type = (unsigned char)statType;
  103.     temp_var.val.string = (u_char *)statP;
  104.     temp_var.val_len = statLen;
  105.     sprint_variable (buf, var_name, var_name_len, &temp_var);
  106.     snmp_trace("    >> %sn", buf);
  107. }
  108. int getNextSessID()
  109. {
  110.     static int SessionID = 0;
  111.     return ++SessionID;
  112. }
  113. int
  114. agent_check_and_process(int block) {
  115.   int numfds;
  116.   fd_set fdset;
  117.   struct timeval timeout, *tvp;
  118.   int count;
  119.   int fakeblock=0;
  120.   
  121.   tvp =  &timeout;
  122.   tvp->tv_sec  = 0;
  123.   tvp->tv_usec = 0;
  124.   numfds = 0;
  125.   FD_ZERO(&fdset);
  126.   snmp_select_info(&numfds, &fdset, tvp, &fakeblock);
  127.   if (block == 1 && fakeblock == 1)
  128.     tvp = NULL; /* block without timeout */
  129.   else if (block == 0) {
  130.       tvp->tv_sec = 0;
  131.       tvp->tv_usec = 0;
  132.   }
  133.   count = so_select(numfds, &fdset, 0, 0, tvp);
  134.   if (count > 0){
  135.     /* packets found, process them */
  136.     snmp_read(&fdset);
  137.   } else switch(count){
  138.     case 0:
  139.       snmp_timeout();
  140.       break;
  141.     case -1:
  142.       if (errno == EINTR){
  143.         return -1;
  144.       } else {
  145.         snmp_log_perror("select");
  146.       }
  147.       return -1;
  148.     default:
  149.       snmp_trace( "select returned %dn", count);
  150.       return -1;
  151.   }  /* endif -- count>0 */
  152.   return count;
  153. }
  154. /*
  155.  * The session is created using the "traditional API" routine snmp_open()
  156.  * so is linked into the global library Sessions list.  It also opens a
  157.  * socket that listens for incoming requests.
  158.  * 
  159.  *   The agent runs in an infinite loop (in the 'receive()' routine),
  160.  * which calls snmp_read() when such a request is received on this socket.
  161.  * This routine then traverses the library 'Sessions' list to identify the
  162.  * relevant session and eventually invokes '_sess_read'.
  163.  *   This then processes the incoming packet, calling the pre_parse, parse,
  164.  * post_parse and callback routines in turn.
  165.  */
  166. /* Global access to the primary session structure for this agent.
  167. for Index Allocation use initially. */
  168. struct snmp_session *main_session;
  169. int
  170. init_master_agent(int dest_port, 
  171.                   int (*pre_parse) (struct snmp_session *, struct soaddr),
  172.                   int (*post_parse) (struct snmp_session *, struct snmp_pdu *,int))
  173. {
  174.     struct snmp_session sess, *session;
  175.     if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) != MASTER_AGENT )
  176. return 0; /* no error if ! MASTER_AGENT */
  177.     DEBUGMSGTL(("snmpd","installing master agent on port %dn", dest_port));
  178.     snmp_sess_init( &sess );
  179.     
  180.     sess.version = SNMP_DEFAULT_VERSION;
  181.     sess.peername = SNMP_DEFAULT_PEERNAME;
  182.     sess.community_len = SNMP_DEFAULT_COMMUNITY_LEN;
  183.      
  184.     sess.local_port = (unsigned char)dest_port;
  185.     sess.callback = handle_snmp_packet;
  186.     sess.authenticator = NULL;
  187.     sess.flags = ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS);
  188.     session = snmp_open_ex( &sess, pre_parse, 0, post_parse, 0, 0 );
  189.     if ( session == NULL ) {
  190.       /* diagnose snmp_open errors with the input struct snmp_session pointer */
  191. snmp_sess_perror("init_master_agent", &sess);
  192. return 1;
  193.     }
  194.     main_session = session;
  195. return 0;
  196. }
  197. struct agent_snmp_session  *
  198. init_agent_snmp_session( struct snmp_session *session, struct snmp_pdu *pdu )
  199. {
  200.     struct agent_snmp_session  *asp;
  201. #ifdef AGENT_USE_STATIC
  202. asp = &agent_static;
  203. memset (asp, 0, sizeof (struct agent_snmp_session));
  204. #else
  205.     asp = malloc( sizeof( struct agent_snmp_session ));
  206.     if ( asp == NULL )
  207. return NULL;
  208. #endif
  209.     asp->start = pdu->variables;
  210.     asp->end   = pdu->variables;
  211.     if ( asp->end != NULL )
  212. while ( asp->end->next_variable != NULL )
  213.     asp->end = asp->end->next_variable;
  214.     asp->session = session;
  215.     asp->pdu     = pdu;
  216.     asp->rw      = READ;
  217.     asp->exact   = TRUE;
  218.     asp->outstanding_requests = NULL;
  219.     asp->next    = NULL;
  220.     asp->mode    = RESERVE1;
  221.     asp->status  = SNMP_ERR_NOERROR;
  222.     return asp;
  223. }
  224. int
  225. count_varbinds( struct snmp_pdu *pdu )
  226. {
  227.   int count = 0;
  228.   struct variable_list *var_ptr;
  229.   
  230.   for ( var_ptr = pdu->variables ; var_ptr != NULL ;
  231.    var_ptr = var_ptr->next_variable )
  232. count++;
  233.   return count;
  234. }
  235. int
  236. handle_snmp_packet(int operation, struct snmp_session *session, int reqid,
  237.                    struct snmp_pdu *pdu, void *magic)
  238. {
  239.     struct agent_snmp_session  *asp;
  240. struct snmp_pdu *ptrPdu;
  241.     int status, allDone, i;
  242.     struct variable_list *var_ptr, *var_ptr2;
  243.     if ( magic == NULL ) {
  244. ptrPdu = snmp_clone_pdu(pdu);
  245. if (ptrPdu == NULL)
  246. /* return NULL;  by yangyuhua 2005-12-5*/
  247. return 0;
  248. asp = init_agent_snmp_session( session, ptrPdu);
  249. if (asp == NULL)
  250. {
  251. snmp_free_pdu (ptrPdu);
  252. return 0;
  253. }
  254. status = SNMP_ERR_NOERROR;
  255.     }
  256.     else {
  257. asp = (struct agent_snmp_session *)magic;
  258.         status =   asp->status;
  259.     }
  260.     if (asp->outstanding_requests != NULL)
  261. {
  262. snmp_free_pdu (asp->pdu);
  263. #ifndef AGENT_USE_STATIC
  264. free (asp);
  265. #endif
  266. return 1;
  267. }
  268.     if ( snmp_check_access(pdu) != 0) {
  269.         /* access control setup is incorrect */
  270. send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
  271.         if (asp->pdu->version != SNMP_VERSION_1 && asp->pdu->version != SNMP_VERSION_2c) {
  272.             asp->pdu->errstat = SNMP_ERR_AUTHORIZATIONERROR;
  273.             asp->pdu->command = SNMP_MSG_RESPONSE;
  274.             snmp_increment_statistic(STAT_SNMPOUTPKTS);
  275.             if (!snmp_send( asp->session, asp->pdu ))
  276.      snmp_free_pdu (asp->pdu);
  277. #ifndef AGENT_USE_STATIC
  278. free (asp);
  279. #endif
  280.             return 1;
  281.         } else {
  282.             /* drop the request */
  283. snmp_free_pdu (asp->pdu);
  284. #ifndef AGENT_USE_STATIC
  285.             free( asp );
  286. #endif
  287.             return 0;
  288.         }
  289.     }
  290.     switch (pdu->command) {
  291.     case SNMP_MSG_GET:
  292. if ( asp->mode != RESERVE1 )
  293.     break; /* Single pass */
  294.         snmp_increment_statistic(STAT_SNMPINGETREQUESTS);
  295. status = handle_next_pass( asp );
  296. asp->mode = RESERVE2;
  297. break;
  298.     case SNMP_MSG_GETNEXT:
  299. if ( asp->mode != RESERVE1 )
  300.     break; /* Single pass */
  301.         snmp_increment_statistic(STAT_SNMPINGETNEXTS);
  302. asp->exact   = FALSE;
  303. status = handle_next_pass( asp );
  304. asp->mode = RESERVE2;
  305. break;
  306.     case SNMP_MSG_GETBULK:
  307.     /*
  308.      * GETBULKS require multiple passes. The first pass handles the
  309.      * explicitly requested varbinds, and subsequent passes append
  310.      * to the existing var_op_list.  Each pass (after the first)
  311.      * uses the results of the preceeding pass as the input list
  312.      * (delimited by the start & end pointers.
  313.      * Processing is terminated if all entries in a pass are
  314.      * EndOfMib, or the maximum number of repetitions are made.
  315.      */
  316. if ( asp->mode == RESERVE1 ) {
  317.             snmp_increment_statistic(STAT_SNMPINGETREQUESTS);
  318.     asp->exact   = FALSE;
  319.     /*
  320.      * Limit max repetitions to something reasonable
  321.      * XXX: We should figure out what will fit somehow...
  322.      */
  323.     if ( asp->pdu->errindex > 100 )
  324.         asp->pdu->errindex = 100;
  325.     
  326.     status = handle_next_pass( asp ); /* First pass */
  327.     asp->mode = RESERVE2;
  328.     if ( status != SNMP_ERR_NOERROR )
  329.         break;
  330.     
  331.     while ( asp->pdu->errstat-- > 0 ) /* Skip non-repeaters */
  332.         asp->start = asp->start->next_variable;
  333.     asp->pdu->errindex--;           /* Handled first repetition */
  334.     if ( asp->outstanding_requests != NULL )
  335. {
  336. snmp_free_pdu (asp->pdu);
  337. #ifndef AGENT_USE_STATIC
  338. free (asp);
  339. #endif
  340. return 1;
  341. }
  342. }
  343. /*Added by sxf 11-29-2k
  344. * Before, when run snmpbulkget_d -v2c 192.2.2.54 public,
  345. * there is an access violation
  346. */
  347. if (pdu->variables == NULL)
  348. {
  349. snmp_free_pdu (asp->pdu);
  350. #ifndef AGENT_USE_STATIC
  351. free (asp);
  352. #endif
  353. return 1;
  354. }
  355. while ( asp->pdu->errindex-- > 0 ) { /* Process repeaters */
  356. /*
  357.  * Add new variable structures for the
  358.  * repeating elements, ready for the next pass.
  359.  * Also check that these are not all EndOfMib
  360.  */
  361.     allDone = TRUE; /* Check for some content */
  362.     for ( var_ptr = asp->start;
  363.   var_ptr != asp->end->next_variable;
  364.   var_ptr = var_ptr->next_variable ) {
  365. /* XXX: we don't know the size of the next
  366. OID, so assume the maximum length */
  367. if ( var_ptr->type != SNMP_ENDOFMIBVIEW )
  368. {
  369. var_ptr2 = snmp_add_null_var(asp->pdu, var_ptr->name, MAX_OID_LEN);
  370. for ( i=var_ptr->name_length ; i<MAX_OID_LEN ; i++)
  371.     var_ptr2->name[i] = 0;
  372. var_ptr2->name_length = var_ptr->name_length;
  373.     allDone = FALSE;
  374. }
  375.     }
  376.     if ( allDone )
  377. break;
  378.     asp->start = asp->end->next_variable;
  379.     while ( asp->end->next_variable != NULL )
  380. asp->end = asp->end->next_variable;
  381.     
  382.     status = handle_next_pass( asp );
  383.     if ( status != SNMP_ERR_NOERROR )
  384. break;
  385.     if ( asp->outstanding_requests != NULL )
  386. {
  387. snmp_free_pdu (asp->pdu);
  388. #ifndef AGENT_USE_STATIC
  389. free (asp);
  390. #endif
  391. return 1;
  392. }
  393. }
  394. break;
  395.     case SNMP_MSG_SET:
  396.          /*
  397.      * SETS require 3-4 passes through the var_op_list.  The first two
  398.      * passes verify that all types, lengths, and values are valid
  399.      * and may reserve resources and the third does the set and a
  400.      * fourth executes any actions.  Then the identical GET RESPONSE
  401.      * packet is returned.
  402.      * If either of the first two passes returns an error, another
  403.      * pass is made so that any reserved resources can be freed.
  404.      * If the third pass returns an error, another pass is made so that
  405.      * any changes can be reversed.
  406.      * If the fourth pass (or any of the error handling passes)
  407.      * return an error, we'd rather not know about it!
  408.      */
  409. if ( asp->mode == RESERVE1 ) {
  410.             snmp_increment_statistic(STAT_SNMPINSETREQUESTS);
  411.     asp->rw      = WRITE;
  412.     status = handle_next_pass( asp );
  413.     if ( status != SNMP_ERR_NOERROR )
  414.         asp->mode = ACTION_FREE;
  415.     else
  416.         asp->mode = RESERVE2;
  417.     if ( asp->outstanding_requests != NULL )
  418. {
  419. snmp_free_pdu (asp->pdu);
  420. #ifndef AGENT_USE_STATIC
  421. free (asp);
  422. #endif
  423. return 1;
  424. }
  425. }
  426. if ( asp->mode == RESERVE2 ) {
  427.     status = handle_next_pass( asp );
  428.     if ( status != SNMP_ERR_NOERROR )
  429.         asp->mode = ACTION_FREE;
  430.     else
  431.         asp->mode = ACTION;
  432.     if ( asp->outstanding_requests != NULL )
  433. {
  434. snmp_free_pdu (asp->pdu);
  435. #ifndef AGENT_USE_STATIC
  436. free (asp);
  437. #endif
  438.   return 1;
  439. }
  440. }
  441. if ( asp->mode == ACTION ) {
  442.     status = handle_next_pass( asp );
  443.     if ( status != SNMP_ERR_NOERROR )
  444.         asp->mode = UNDO;
  445.     else
  446.         asp->mode = COMMIT;
  447.     if ( asp->outstanding_requests != NULL )
  448. {
  449. snmp_free_pdu (asp->pdu);
  450. #ifndef AGENT_USE_STATIC
  451. free (asp);
  452. #endif
  453. return 1;
  454. }
  455. }
  456. if ( asp->mode == COMMIT ) {
  457.     status = handle_next_pass( asp );
  458.     if ( status != SNMP_ERR_NOERROR ) {
  459. status    = SNMP_ERR_COMMITFAILED;
  460.         asp->mode = FINISHED_FAILURE;
  461.     }
  462.     else
  463.         asp->mode = FINISHED_SUCCESS;
  464.     if ( asp->outstanding_requests != NULL )
  465. {
  466. snmp_free_pdu (asp->pdu);
  467. #ifndef AGENT_USE_STATIC
  468. free (asp);
  469. #endif
  470. return 1;
  471. }
  472. }
  473. if ( asp->mode == UNDO ) {
  474.     if (handle_next_pass( asp ) != SNMP_ERR_NOERROR )
  475. status = SNMP_ERR_UNDOFAILED;
  476.     asp->mode = FINISHED_FAILURE;
  477.     break;
  478. }
  479. if ( asp->mode == ACTION_FREE ) {
  480.     (void) handle_next_pass( asp );
  481.     break;
  482. }
  483. break;
  484.     case SNMP_MSG_RESPONSE:
  485.         snmp_increment_statistic(STAT_SNMPINGETRESPONSES);
  486. snmp_free_pdu (asp->pdu);
  487. #ifndef AGENT_USE_STATIC
  488. free( asp );
  489. #endif
  490. return 0;
  491.     case SNMP_MSG_TRAP:
  492.     case SNMP_MSG_TRAP2:
  493.         snmp_increment_statistic(STAT_SNMPINTRAPS);
  494. snmp_free_pdu (asp->pdu);
  495. #ifndef AGENT_USE_STATIC
  496. free( asp );
  497. #endif
  498. return 0;
  499.     default:
  500.         snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
  501. snmp_free_pdu (asp->pdu);
  502. #ifndef AGENT_USE_STATIC
  503. free( asp );
  504. #endif
  505. return 0;
  506.     }
  507.     if ( asp->outstanding_requests != NULL ) {
  508. asp->status = status;
  509. asp->next = agent_session_list;
  510. agent_session_list = asp;
  511. #ifdef AGENT_USE_STATIC
  512. #endif
  513.     }
  514.     else {
  515. /*
  516.  * May need to "dumb down" a SET error status for a
  517.  *  v1 query.  See RFC2576 - section 4.3
  518.  */
  519. if (( asp->pdu->command == SNMP_MSG_SET ) &&
  520.     ( asp->pdu->version == SNMP_VERSION_1 )) {
  521.     switch ( status ) {
  522. case SNMP_ERR_WRONGVALUE:
  523. case SNMP_ERR_WRONGENCODING:
  524. case SNMP_ERR_WRONGTYPE:
  525. case SNMP_ERR_WRONGLENGTH:
  526. case SNMP_ERR_INCONSISTENTVALUE:
  527. status = SNMP_ERR_BADVALUE;
  528. break;
  529. case SNMP_ERR_NOACCESS:
  530. case SNMP_ERR_NOTWRITABLE:
  531. case SNMP_ERR_NOCREATION:
  532. case SNMP_ERR_INCONSISTENTNAME:
  533. case SNMP_ERR_AUTHORIZATIONERROR:
  534. status = SNMP_ERR_NOSUCHNAME;
  535. break;
  536. case SNMP_ERR_RESOURCEUNAVAILABLE:
  537. case SNMP_ERR_COMMITFAILED:
  538. case SNMP_ERR_UNDOFAILED:
  539. status = SNMP_ERR_GENERR;
  540. break;
  541.     }
  542. }
  543. /*
  544.  * Similarly we may need to "dumb down" v2 exception
  545.  *  types to throw an error for a v1 query.
  546.  *  See RFC2576 - section 4.1.2.3
  547.  */
  548. if (( asp->pdu->command != SNMP_MSG_SET ) &&
  549.     ( asp->pdu->version == SNMP_VERSION_1 )) {
  550. for ( var_ptr = asp->pdu->variables, i=0 ;
  551. var_ptr != NULL ;
  552. var_ptr = var_ptr->next_variable, i++ ) {
  553.     switch ( var_ptr->type ) {
  554. case SNMP_NOSUCHOBJECT:
  555. case SNMP_NOSUCHINSTANCE:
  556. case SNMP_ENDOFMIBVIEW:
  557. case ASN_COUNTER64:
  558. status = SNMP_ERR_NOSUCHNAME;
  559. asp->pdu->errindex=i;
  560. break;
  561.     }
  562. }
  563. }
  564. if ( status == SNMP_ERR_NOERROR ) {
  565.     snmp_increment_statistic_by(
  566. (asp->pdu->command == SNMP_MSG_SET ?
  567. STAT_SNMPINTOTALSETVARS : STAT_SNMPINTOTALREQVARS ),
  568.      count_varbinds( asp->pdu ));
  569. }
  570. else {
  571. /*
  572.  * Use a copy of the original request
  573.  *   to report failures.
  574.  */
  575. /*
  576. * --sxf 2001-1-4
  577. */
  578. if (status == SNMP_ERR_NOSUCHNAME)
  579. snmp_increment_statistic (STAT_SNMPOUTNOSUCHNAMES);
  580. else if (status == SNMP_ERR_BADVALUE)
  581. snmp_increment_statistic (STAT_SNMPOUTBADVALUES);
  582. else if (status == SNMP_ERR_GENERR)
  583. snmp_increment_statistic (STAT_SNMPOUTGENERRS);
  584. else if (status == SNMP_ERR_NOTWRITABLE)
  585. snmp_increment_statistic (STAT_SNMPINREADONLYS);
  586.     i = asp->pdu->errindex;
  587.     snmp_free_pdu( asp->pdu );
  588.     asp->pdu = snmp_clone_pdu( pdu );/*find a problem by yangyuhua 2005-12-5 */
  589. if (asp->pdu == NULL)
  590. {
  591. free (asp);
  592. return 0;
  593. }
  594.     asp->pdu->errindex = i;
  595. }
  596. asp->pdu->command = SNMP_MSG_RESPONSE;
  597. asp->pdu->errstat = status;
  598. if (snmp_send( asp->session, asp->pdu ) == 0)
  599. {
  600. snmp_free_pdu (asp->pdu);
  601. }
  602. else
  603. {
  604. snmp_increment_statistic(STAT_SNMPOUTPKTS);
  605. snmp_increment_statistic(STAT_SNMPOUTGETRESPONSES);
  606. }
  607. #ifndef AGENT_USE_STATIC
  608. free( asp );
  609. #endif
  610.     }
  611.     return 1;
  612. }
  613. int
  614. handle_next_pass(struct agent_snmp_session  *asp)
  615. {
  616.     int status;
  617.     struct snmp_pdu *pdu = asp->pdu;
  618.     struct request_list *req_p, *next_req;
  619.         if ( asp->outstanding_requests != NULL )
  620.     return SNMP_ERR_NOERROR;
  621. status = handle_var_list( asp );
  622.         if ( asp->outstanding_requests != NULL ) {
  623.     if ( status == SNMP_ERR_NOERROR ) {
  624. /* Send out any subagent requests */
  625. for ( req_p = asp->outstanding_requests ;
  626. req_p != NULL ; req_p = req_p->next_request ) {
  627.     snmp_async_send( req_p->session,  req_p->pdu,
  628.       req_p->callback, req_p->cb_data );
  629. }
  630. asp->pdu = snmp_clone_pdu( pdu );
  631. if (asp->pdu == NULL)
  632. return SNMP_ERR_GENERR;
  633. asp->pdu->variables = pdu->variables;
  634. pdu->variables = NULL;
  635.     }
  636.     else {
  637.      /* discard outstanding requests */
  638. for ( req_p = asp->outstanding_requests ;
  639. req_p != NULL ; req_p = next_req ) {
  640. next_req = req_p->next_request;
  641. free( req_p );
  642. }
  643. asp->outstanding_requests = NULL;
  644.     }
  645. }
  646. return status;
  647. }
  648. int
  649. handle_var_list(struct agent_snmp_session  *asp)
  650. {
  651.     struct variable_list *varbind_ptr;
  652.     u_char  statType;
  653.     u_char *statP;
  654.     size_t  statLen;
  655.     u_short acl;
  656.     WriteMethod *write_method;
  657.     AddVarMethod *add_method;
  658.     int     noSuchObject = TRUE;
  659.     int     count, view;
  660.     
  661.     count = 0;
  662.     varbind_ptr = asp->start;
  663.     if ( !varbind_ptr ) {
  664. return SNMP_ERR_NOERROR;
  665.     }
  666. if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))
  667. snmp_log (LOG_DEBUG, "  SNMP: Responsen");
  668.     while (1) {
  669.     
  670. count++;
  671. statp_loop:
  672. statP = getStatPtr(  varbind_ptr->name,
  673.    &varbind_ptr->name_length,
  674.    &statType, &statLen, &acl,
  675.    asp->exact, &write_method, asp->pdu, &noSuchObject);
  676.     
  677.    
  678. if (statP == NULL && (asp->rw != WRITE || write_method == NULL)) {
  679.      varbind_ptr->val.integer   = NULL;
  680.      varbind_ptr->val_len = 0;
  681. if ( asp->exact ) {
  682.             if ( noSuchObject == TRUE ){
  683.         statType = SNMP_NOSUCHOBJECT;
  684.     } else {
  685.         statType = SNMP_NOSUCHINSTANCE;
  686.     }
  687. } else {
  688.             statType = SNMP_ENDOFMIBVIEW;
  689. }
  690. /* dump verbose info */
  691.     if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))
  692.         dump_var(varbind_ptr->name, varbind_ptr->name_length,
  693. statType, statP, 0);
  694. if (asp->pdu->version == SNMP_VERSION_1) {
  695.     asp->pdu->errstat = SNMP_ERR_NOSUCHNAME;
  696.     asp->pdu->errindex = count;
  697.     return SNMP_ERR_NOSUCHNAME;
  698. }
  699. else if (asp->rw == WRITE) {
  700.     asp->pdu->errstat =
  701. ( noSuchObject ? SNMP_ERR_NOTWRITABLE
  702. : SNMP_ERR_NOCREATION );
  703.     asp->pdu->errindex = count;
  704.     return asp->pdu->errstat;
  705. }
  706. else
  707.     varbind_ptr->type = statType;
  708.    
  709. }
  710.                 /* Delegated variables should be added to the
  711.                    relevant outgoing request */
  712.         else if ( IS_DELEGATED(statType)) {
  713.                 add_method = (AddVarMethod*)statP;
  714.                 statType = (unsigned char)(*add_method)( asp, varbind_ptr );
  715.         }
  716. /* GETNEXT/GETBULK should just skip inaccessible entries */
  717. else if ((view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length,
  718.    asp->pdu, varbind_ptr->type))
  719.  && !asp->exact) {
  720. if (view != 5) send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
  721. goto statp_loop;
  722. }
  723. /* Other access problems are permanent */
  724. else if (( asp->rw == WRITE && !(acl & 2)) || view) {
  725.     if (asp->pdu->version == SNMP_VERSION_1 || asp->rw != WRITE) {
  726. if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))
  727.                   DEBUGMSGTL(("snmp_agent", "    >> noSuchName (read-only)n"));
  728. ERROR_MSG("read-only");
  729. statType = SNMP_ERR_NOSUCHNAME;
  730.     }
  731.     else {
  732. if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))
  733.                   DEBUGMSGTL(("snmp_agent", "    >> notWritablen"));
  734. ERROR_MSG("Not Writable");
  735. statType = SNMP_ERR_NOTWRITABLE;
  736.     }
  737.     asp->pdu->errstat = statType;
  738.     asp->pdu->errindex = count;
  739.     send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
  740.     return statType;
  741.         }
  742. else {
  743.             /* dump verbose info */
  744.     if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE) && statP)
  745.         dump_var(varbind_ptr->name, varbind_ptr->name_length,
  746. statType, statP, statLen);
  747. /*  FINALLY we can act on SET requests ....*/
  748.     if ( asp->rw == WRITE ) {
  749.         if ( write_method != NULL ) {
  750.     statType = (unsigned char)(*write_method)(asp->mode,
  751.                                                varbind_ptr->val.string,
  752.                                                varbind_ptr->type,
  753.                                                varbind_ptr->val_len, statP,
  754.                                                varbind_ptr->name,
  755.                                                varbind_ptr->name_length);
  756.                     if (statType != SNMP_ERR_NOERROR) {
  757.                       asp->pdu->errstat = statType;
  758.                       asp->pdu->errindex = count;
  759.                       return statType;
  760.                     }
  761. }
  762. else {
  763.                     if (!goodValue(varbind_ptr->type, varbind_ptr->val_len,
  764.                                     statType, statLen)){
  765.                         if (asp->pdu->version == SNMP_VERSION_1)
  766.                             statType = SNMP_ERR_BADVALUE;
  767.                         else
  768.                             statType = SNMP_ERR_WRONGTYPE; /* poor approximation */
  769. asp->pdu->errstat = statType;
  770. asp->pdu->errindex = count;
  771. return statType;
  772.                     }
  773.                     /* actually do the set if necessary */
  774.                     if (asp->mode == COMMIT)
  775.                         setVariable(varbind_ptr->val.string, varbind_ptr->type,
  776.                                     varbind_ptr->val_len, statP, statLen);
  777.                 }
  778.     }
  779. /* ... or save the results from assorted GETs */
  780.     else {
  781.      snmp_set_var_value(varbind_ptr, statP, statLen);
  782.      varbind_ptr->type = statType;
  783.     }
  784. }
  785. if ( varbind_ptr == asp->end )
  786.      return SNMP_ERR_NOERROR;
  787. varbind_ptr = varbind_ptr->next_variable;
  788. if ( asp->mode == RESERVE1 )
  789.     snmp_vars_inc++;
  790.     }
  791. }
  792. static int
  793. goodValue(u_char inType, 
  794.   size_t inLen,
  795.   u_char actualType,
  796.   size_t actualLen)
  797. {
  798.     if (inLen > actualLen)
  799. return FALSE;
  800.     return (inType == actualType);
  801. }
  802. static void
  803. setVariable(u_char *var_val,
  804.     u_char var_val_type,
  805.     size_t var_val_len,
  806.     u_char *statP,
  807.     size_t statLen)
  808. {
  809.     size_t buffersize = 1000;
  810.     switch(var_val_type){
  811. case ASN_INTEGER:
  812.     asn_parse_int(var_val, &buffersize, &var_val_type, (long *)statP, statLen);
  813.     break;
  814. case ASN_COUNTER:
  815. case ASN_GAUGE:
  816. case ASN_TIMETICKS:
  817.     asn_parse_unsigned_int(var_val, &buffersize, &var_val_type, (u_long *)statP, statLen);
  818.     break;
  819. case ASN_COUNTER64:
  820.     asn_parse_unsigned_int64(var_val, &buffersize, &var_val_type,
  821.      (struct counter64 *)statP, statLen);
  822.     break;
  823. case ASN_OCTET_STR:
  824. case ASN_IPADDRESS:
  825. case ASN_OPAQUE:
  826. case ASN_NSAP:
  827.     asn_parse_string(var_val, &buffersize, &var_val_type, statP, &statLen);
  828.     break;
  829. case ASN_OBJECT_ID:
  830.     asn_parse_objid(var_val, &buffersize, &var_val_type, (oid *)statP, &statLen);
  831.     break;
  832. case ASN_BIT_STR:
  833.     asn_parse_bitstring(var_val, &buffersize, &var_val_type, statP, &statLen);
  834.     break;
  835.     }
  836. }