delayed_instance.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:8k
- /** @example delayed_instance.c
- * This example implements the netSnmpExampleSleeper object.
- *
- * It demonstrates 2 things:
- *
- * - The instance helper, which is a way of registering an exact OID
- * such that GENEXT requests are handled entirely by the helper.
- *
- * - how to implement objects which normally would block the agent as
- * it waits for external events in such a way that the agent can
- * continue responding to other requests while this implementation
- * waits.
- *
- * - Added bonus: normally the nsTransactionTable is empty, since
- * there aren't any outstanding requests generally. When accessed,
- * this module will create some however. Try setting
- * netSnmpExampleSleeper.0 to 10 and then accessing it (use
- * "snmpget -t 15 ..." to access it), and then walk the
- * nsTransactionTable from another shell to see that not only is
- * the walk not blocked, but that the nsTransactionTable is not
- * empty.
- *
- */
- #include <net-snmp/net-snmp-config.h>
- #include <net-snmp/net-snmp-includes.h>
- #include <net-snmp/agent/net-snmp-agent-includes.h>
- #include "delayed_instance.h"
- static u_long delay_time = 1;
- void
- init_delayed_instance(void)
- {
- static oid my_delayed_oid[] =
- { 1, 3, 6, 1, 4, 1, 8072, 2, 1, 2, 0 };
- /*
- * delayed handler test
- */
- netsnmp_handler_registration *my_test;
- my_test =
- netsnmp_create_handler_registration("delayed_instance_example",
- delayed_instance_handler,
- my_delayed_oid,
- OID_LENGTH(my_delayed_oid),
- HANDLER_CAN_RWRITE);
- netsnmp_register_instance(my_test);
- }
- #define DELAYED_INSTANCE_SET_NAME "test_delayed"
- int
- delayed_instance_handler(netsnmp_mib_handler *handler,
- netsnmp_handler_registration *reginfo,
- netsnmp_agent_request_info *reqinfo,
- netsnmp_request_info *requests)
- {
- DEBUGMSGTL(("delayed_instance", "Got request, mode = %d:n",
- reqinfo->mode));
- switch (reqinfo->mode) {
- /*
- * here we merely mention that we'll answer this request
- * later. we don't actually care about the mode type in this
- * example, but for certain cases you may, so I'll leave in the
- * otherwise useless switch and case statements
- */
- default:
- /*
- * mark this variable as something that can't be handled now.
- * We'll answer it later.
- */
- requests->delegated = 1;
- /*
- * register an alarm to update the results at a later
- * time. Normally, we might have to query something else
- * (like an external request sent to a different network
- * or system socket, etc), but for this example we'll do
- * something really simply and just insert an alarm for a
- * certain period of time
- */
- snmp_alarm_register(delay_time, /* seconds */
- 0, /* dont repeat. */
- return_delayed_response, /* the function
- * to call */
- /*
- * here we create a "cache" of useful
- * information that we'll want later
- * on. This argument is passed back
- * to us in the callback function for
- * an alarm
- */
- (void *)
- netsnmp_create_delegated_cache(handler,
- reginfo,
- reqinfo,
- requests,
- NULL));
- break;
- }
- return SNMP_ERR_NOERROR;
- }
- void
- return_delayed_response(unsigned int clientreg, void *clientarg)
- {
- /*
- * extract the cache from the passed argument
- */
- netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) clientarg;
- netsnmp_request_info *requests;
- netsnmp_agent_request_info *reqinfo;
- u_long *delay_time_cache = NULL;
- /*
- * here we double check that the cache we created earlier is still
- * * valid. If not, the request timed out for some reason and we
- * * don't need to keep processing things. Should never happen, but
- * * this double checks.
- */
- cache = netsnmp_handler_check_cache(cache);
- if (!cache) {
- snmp_log(LOG_ERR, "illegal call to return delayed responsen");
- return;
- }
- /*
- * re-establish the previous pointers we are used to having
- */
- reqinfo = cache->reqinfo;
- requests = cache->requests;
- DEBUGMSGTL(("delayed_instance",
- "continuing delayed request, mode = %dn",
- cache->reqinfo->mode));
- /*
- * mention that it's no longer delegated, and we've now answered
- * the query (which we'll do down below).
- */
- requests->delegated = 0;
- switch (cache->reqinfo->mode) {
- /*
- * registering as an instance means we don't need to deal with
- * getnext processing, so we don't handle it here at all.
- *
- * However, since the instance handler already reset the mode
- * back to GETNEXT from the faked GET mode, we need to do the
- * same thing in both cases. This should be fixed in future
- * versions of net-snmp hopefully.
- */
- case MODE_GET:
- case MODE_GETNEXT:
- /*
- * return the currend delay time
- */
- snmp_set_var_typed_value(cache->requests->requestvb,
- ASN_INTEGER,
- (u_char *) & delay_time,
- sizeof(delay_time));
- break;
- case MODE_SET_RESERVE1:
- /*
- * check type
- */
- if (requests->requestvb->type != ASN_INTEGER) {
- /*
- * not an integer. Bad dog, no bone.
- */
- netsnmp_set_request_error(reqinfo, requests,
- SNMP_ERR_WRONGTYPE);
- /*
- * we don't need the cache any longer
- */
- netsnmp_free_delegated_cache(cache);
- return;
- }
- break;
- case MODE_SET_RESERVE2:
- /*
- * store old value for UNDO support in the future.
- */
- memdup((u_char **) & delay_time_cache,
- (u_char *) & delay_time, sizeof(delay_time));
- /*
- * malloc failed
- */
- if (delay_time_cache == NULL) {
- netsnmp_set_request_error(reqinfo, requests,
- SNMP_ERR_RESOURCEUNAVAILABLE);
- netsnmp_free_delegated_cache(cache);
- return;
- }
- /*
- * Add our temporary information to the request itself.
- * This is then retrivable later. The free function
- * passed auto-frees it when the request is later
- * deleted.
- */
- netsnmp_request_add_list_data(requests,
- netsnmp_create_data_list
- (DELAYED_INSTANCE_SET_NAME,
- delay_time_cache, free));
- break;
- case MODE_SET_ACTION:
- /*
- * update current value
- */
- delay_time = *(requests->requestvb->val.integer);
- DEBUGMSGTL(("testhandler", "updated delay_time -> %dn",
- delay_time));
- break;
- case MODE_SET_UNDO:
- /*
- * ack, something somewhere failed. We reset back to the
- * previously old value by extracting the previosuly
- * stored information back out of the request
- */
- delay_time =
- *((u_long *) netsnmp_request_get_list_data(requests,
- DELAYED_INSTANCE_SET_NAME));
- break;
- case MODE_SET_COMMIT:
- case MODE_SET_FREE:
- /*
- * the only thing to do here is free the old memdup'ed
- * value, but it's auto-freed by the datalist recovery, so
- * we don't have anything to actually do here
- */
- break;
- }
- /*
- * free the information cache
- */
- netsnmp_free_delegated_cache(cache);
- }