delayed_instance.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:8k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /**  @example delayed_instance.c
  2.  *  This example implements the netSnmpExampleSleeper object.
  3.  *
  4.  *  It demonstrates 2 things:
  5.  *
  6.  *  - The instance helper, which is a way of registering an exact OID
  7.  *    such that GENEXT requests are handled entirely by the helper.
  8.  *
  9.  *  - how to implement objects which normally would block the agent as
  10.  *    it waits for external events in such a way that the agent can
  11.  *    continue responding to other requests while this implementation
  12.  *    waits.
  13.  *
  14.  *  - Added bonus: normally the nsTransactionTable is empty, since
  15.  *    there aren't any outstanding requests generally.  When accessed,
  16.  *    this module will create some however.  Try setting
  17.  *    netSnmpExampleSleeper.0 to 10 and then accessing it (use
  18.  *    "snmpget -t 15 ..." to access it), and then walk the
  19.  *    nsTransactionTable from another shell to see that not only is
  20.  *    the walk not blocked, but that the nsTransactionTable is not
  21.  *    empty.
  22.  *
  23.  */
  24. #include <net-snmp/net-snmp-config.h>
  25. #include <net-snmp/net-snmp-includes.h>
  26. #include <net-snmp/agent/net-snmp-agent-includes.h>
  27. #include "delayed_instance.h"
  28. static u_long   delay_time = 1;
  29. void
  30. init_delayed_instance(void)
  31. {
  32.     static oid      my_delayed_oid[] =
  33.         { 1, 3, 6, 1, 4, 1, 8072, 2, 1, 2, 0 };
  34.     /*
  35.      * delayed handler test
  36.      */
  37.     netsnmp_handler_registration *my_test;
  38.     my_test =
  39.         netsnmp_create_handler_registration("delayed_instance_example",
  40.                                             delayed_instance_handler,
  41.                                             my_delayed_oid,
  42.                                             OID_LENGTH(my_delayed_oid),
  43.                                             HANDLER_CAN_RWRITE);
  44.     netsnmp_register_instance(my_test);
  45. }
  46. #define DELAYED_INSTANCE_SET_NAME "test_delayed"
  47. int
  48. delayed_instance_handler(netsnmp_mib_handler *handler,
  49.                          netsnmp_handler_registration *reginfo,
  50.                          netsnmp_agent_request_info *reqinfo,
  51.                          netsnmp_request_info *requests)
  52. {
  53.     DEBUGMSGTL(("delayed_instance", "Got request, mode = %d:n",
  54.                 reqinfo->mode));
  55.     switch (reqinfo->mode) {
  56.         /*
  57.          * here we merely mention that we'll answer this request
  58.          * later.  we don't actually care about the mode type in this
  59.          * example, but for certain cases you may, so I'll leave in the
  60.          * otherwise useless switch and case statements 
  61.          */
  62.     default:
  63.         /*
  64.          * mark this variable as something that can't be handled now.
  65.          * We'll answer it later. 
  66.          */
  67.         requests->delegated = 1;
  68.         /*
  69.          * register an alarm to update the results at a later
  70.          * time.  Normally, we might have to query something else
  71.          * (like an external request sent to a different network
  72.          * or system socket, etc), but for this example we'll do
  73.          * something really simply and just insert an alarm for a
  74.          * certain period of time 
  75.          */
  76.         snmp_alarm_register(delay_time, /* seconds */
  77.                             0,  /* dont repeat. */
  78.                             return_delayed_response,    /* the function
  79.                                                          * to call */
  80.                             /*
  81.                              * here we create a "cache" of useful
  82.                              * information that we'll want later
  83.                              * on.  This argument is passed back
  84.                              * to us in the callback function for
  85.                              * an alarm 
  86.                              */
  87.                             (void *)
  88.                             netsnmp_create_delegated_cache(handler,
  89.                                                            reginfo,
  90.                                                            reqinfo,
  91.                                                            requests,
  92.                                                            NULL));
  93.         break;
  94.     }
  95.     return SNMP_ERR_NOERROR;
  96. }
  97. void
  98. return_delayed_response(unsigned int clientreg, void *clientarg)
  99. {
  100.     /*
  101.      * extract the cache from the passed argument 
  102.      */
  103.     netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) clientarg;
  104.     netsnmp_request_info *requests;
  105.     netsnmp_agent_request_info *reqinfo;
  106.     u_long         *delay_time_cache = NULL;
  107.     /*
  108.      * here we double check that the cache we created earlier is still
  109.      * * valid.  If not, the request timed out for some reason and we
  110.      * * don't need to keep processing things.  Should never happen, but
  111.      * * this double checks. 
  112.      */
  113.     cache = netsnmp_handler_check_cache(cache);
  114.     if (!cache) {
  115.         snmp_log(LOG_ERR, "illegal call to return delayed responsen");
  116.         return;
  117.     }
  118.     /*
  119.      * re-establish the previous pointers we are used to having 
  120.      */
  121.     reqinfo = cache->reqinfo;
  122.     requests = cache->requests;
  123.     DEBUGMSGTL(("delayed_instance",
  124.                 "continuing delayed request, mode = %dn",
  125.                 cache->reqinfo->mode));
  126.     /*
  127.      * mention that it's no longer delegated, and we've now answered
  128.      * the query (which we'll do down below). 
  129.      */
  130.     requests->delegated = 0;
  131.     switch (cache->reqinfo->mode) {
  132.         /*
  133.          * registering as an instance means we don't need to deal with
  134.          * getnext processing, so we don't handle it here at all.
  135.          * 
  136.          * However, since the instance handler already reset the mode
  137.          * back to GETNEXT from the faked GET mode, we need to do the
  138.          * same thing in both cases.  This should be fixed in future
  139.          * versions of net-snmp hopefully. 
  140.          */
  141.     case MODE_GET:
  142.     case MODE_GETNEXT:
  143.         /*
  144.          * return the currend delay time 
  145.          */
  146.         snmp_set_var_typed_value(cache->requests->requestvb,
  147.                                  ASN_INTEGER,
  148.                                  (u_char *) & delay_time,
  149.                                  sizeof(delay_time));
  150.         break;
  151.     case MODE_SET_RESERVE1:
  152.         /*
  153.          * check type 
  154.          */
  155.         if (requests->requestvb->type != ASN_INTEGER) {
  156.             /*
  157.              * not an integer.  Bad dog, no bone. 
  158.              */
  159.             netsnmp_set_request_error(reqinfo, requests,
  160.                                       SNMP_ERR_WRONGTYPE);
  161.             /*
  162.              * we don't need the cache any longer 
  163.              */
  164.             netsnmp_free_delegated_cache(cache);
  165.             return;
  166.         }
  167.         break;
  168.     case MODE_SET_RESERVE2:
  169.         /*
  170.          * store old value for UNDO support in the future. 
  171.          */
  172.         memdup((u_char **) & delay_time_cache,
  173.                (u_char *) & delay_time, sizeof(delay_time));
  174.         /*
  175.          * malloc failed 
  176.          */
  177.         if (delay_time_cache == NULL) {
  178.             netsnmp_set_request_error(reqinfo, requests,
  179.                                       SNMP_ERR_RESOURCEUNAVAILABLE);
  180.             netsnmp_free_delegated_cache(cache);
  181.             return;
  182.         }
  183.         /*
  184.          * Add our temporary information to the request itself.
  185.          * This is then retrivable later.  The free function
  186.          * passed auto-frees it when the request is later
  187.          * deleted.  
  188.          */
  189.         netsnmp_request_add_list_data(requests,
  190.                                       netsnmp_create_data_list
  191.                                       (DELAYED_INSTANCE_SET_NAME,
  192.                                        delay_time_cache, free));
  193.         break;
  194.     case MODE_SET_ACTION:
  195.         /*
  196.          * update current value 
  197.          */
  198.         delay_time = *(requests->requestvb->val.integer);
  199.         DEBUGMSGTL(("testhandler", "updated delay_time -> %dn",
  200.                     delay_time));
  201.         break;
  202.     case MODE_SET_UNDO:
  203.         /*
  204.          * ack, something somewhere failed.  We reset back to the
  205.          * previously old value by extracting the previosuly
  206.          * stored information back out of the request 
  207.          */
  208.         delay_time =
  209.             *((u_long *) netsnmp_request_get_list_data(requests,
  210.                                                        DELAYED_INSTANCE_SET_NAME));
  211.         break;
  212.     case MODE_SET_COMMIT:
  213.     case MODE_SET_FREE:
  214.         /*
  215.          * the only thing to do here is free the old memdup'ed
  216.          * value, but it's auto-freed by the datalist recovery, so
  217.          * we don't have anything to actually do here 
  218.          */
  219.         break;
  220.     }
  221.     /*
  222.      * free the information cache 
  223.      */
  224.     netsnmp_free_delegated_cache(cache);
  225. }