baby_steps.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:17k
- /*
- * baby_steps.c
- * $Id: baby_steps.c,v 1.10.2.1 2004/12/10 03:30:19 rstory Exp $
- */
- #include <net-snmp/net-snmp-config.h>
- #include <net-snmp/net-snmp-includes.h>
- #include <net-snmp/agent/net-snmp-agent-includes.h>
- #include <net-snmp/agent/baby_steps.h>
- #if HAVE_DMALLOC_H
- #include <dmalloc.h>
- #endif
- #define BABY_STEPS_PER_MODE_MAX 4
- #define BSTEP_USE_ORIGINAL 0xffff
- static u_short get_mode_map[BABY_STEPS_PER_MODE_MAX] = {
- MODE_BSTEP_PRE_REQUEST, MODE_BSTEP_OBJECT_LOOKUP, BSTEP_USE_ORIGINAL, MODE_BSTEP_POST_REQUEST };
- static u_short set_mode_map[SNMP_MSG_INTERNAL_SET_MAX][BABY_STEPS_PER_MODE_MAX] = {
- /*R1*/
- { MODE_BSTEP_PRE_REQUEST, MODE_BSTEP_OBJECT_LOOKUP, MODE_BSTEP_ROW_CREATE,
- MODE_BSTEP_CHECK_VALUE },
- /*R2*/
- { MODE_BSTEP_UNDO_SETUP, BABY_STEP_NONE, BABY_STEP_NONE, BABY_STEP_NONE },
- /*A */
- { MODE_BSTEP_SET_VALUE,MODE_BSTEP_CHECK_CONSISTENCY,
- MODE_BSTEP_COMMIT, BABY_STEP_NONE },
- /*C */
- { MODE_BSTEP_IRREVERSIBLE_COMMIT, MODE_BSTEP_UNDO_CLEANUP, MODE_BSTEP_POST_REQUEST,
- BABY_STEP_NONE},
- /*F */
- { MODE_BSTEP_UNDO_CLEANUP, MODE_BSTEP_POST_REQUEST, BABY_STEP_NONE,
- BABY_STEP_NONE },
- /*U */
- { MODE_BSTEP_UNDO_COMMIT, MODE_BSTEP_UNDO_SET, MODE_BSTEP_UNDO_CLEANUP,
- MODE_BSTEP_POST_REQUEST}
- };
- static int
- _baby_steps_helper(netsnmp_mib_handler *handler,
- netsnmp_handler_registration *reginfo,
- netsnmp_agent_request_info *reqinfo,
- netsnmp_request_info *requests);
- static int
- _baby_steps_access_multiplexer(netsnmp_mib_handler *handler,
- netsnmp_handler_registration *reginfo,
- netsnmp_agent_request_info *reqinfo,
- netsnmp_request_info *requests);
-
- /** @defgroup baby_steps baby_steps: calls your handler in baby_steps for set processing.
- * @ingroup handler
- * @{
- */
- /** returns a baby_steps handler that can be injected into a given
- * handler chain.
- */
- netsnmp_mib_handler *
- netsnmp_baby_steps_handler_get(u_long modes)
- {
- netsnmp_mib_handler *mh;
- netsnmp_baby_steps_modes *md;
- mh = netsnmp_create_handler("baby_steps", _baby_steps_helper);
- if(!mh)
- return NULL;
- md = SNMP_MALLOC_TYPEDEF(netsnmp_baby_steps_modes);
- if (NULL == md) {
- snmp_log(LOG_ERR,"malloc failed in netsnmp_baby_steps_handler_getn");
- netsnmp_handler_free(mh);
- mh = NULL;
- }
- else {
- mh->myvoid = md;
- if (0 == modes)
- modes = BABY_STEP_ALL;
- md->registered = modes;
- }
- /*
- * don't set MIB_HANDLER_AUTO_NEXT, since we need to call lower
- * handlers with a munged mode.
- */
-
- return mh;
- }
- /** @internal Implements the baby_steps handler */
- static int
- _baby_steps_helper(netsnmp_mib_handler *handler,
- netsnmp_handler_registration *reginfo,
- netsnmp_agent_request_info *reqinfo,
- netsnmp_request_info *requests)
- {
- netsnmp_baby_steps_modes *bs_modes;
- int save_mode, i, rc = SNMP_ERR_NOERROR;
- u_short *mode_map_ptr;
-
- DEBUGMSGTL(("baby_steps", "Got request, mode %sn",
- se_find_label_in_slist("agent_mode",reqinfo->mode)));
- bs_modes = handler->myvoid;
- netsnmp_assert(NULL != bs_modes);
- switch (reqinfo->mode) {
- case MODE_SET_RESERVE1:
- /*
- * clear completed modes
- * xxx-rks: this will break for pdus with set requests to different
- * rows in the same table when the handler is set up to use the row
- * merge helper as well (or if requests are serialized).
- */
- bs_modes->completed = 0;
- /** fall through */
- case MODE_SET_RESERVE2:
- case MODE_SET_ACTION:
- case MODE_SET_COMMIT:
- case MODE_SET_FREE:
- case MODE_SET_UNDO:
- mode_map_ptr = set_mode_map[reqinfo->mode];
- break;
-
- default:
- /*
- * clear completed modes
- */
- bs_modes->completed = 0;
- mode_map_ptr = get_mode_map;
- }
- /*
- * NOTE: if you update this chart, please update the versions in
- * local/mib2c-conf.d/parent-set.m2i
- * agent/mibgroup/helpers/baby_steps.c
- * while you're at it.
- */
- /*
- ***********************************************************************
- * Baby Steps Flow Chart (2004.06.05) *
- * *
- * +--------------+ +================+ U = unconditional path *
- * |optional state| ||required state|| S = path for success *
- * +--------------+ +================+ E = path for error *
- ***********************************************************************
- *
- * +--------------+
- * | pre |
- * | request |
- * +--------------+
- * | U
- * +-------------+ +==============+
- * | row |f|<-------|| object ||
- * | create |1| E || lookup ||
- * +-------------+ +==============+
- * E | | S | S
- * | +------------------>|
- * | +==============+
- * | E || check ||
- * |<---------------|| values ||
- * | +==============+
- * | | S
- * | +==============+
- * | +<-------|| undo ||
- * | | E || setup ||
- * | | +==============+
- * | | | S
- * | | +==============+
- * | | || set ||-------------------------->+
- * | | || value || E |
- * | | +==============+ |
- * | | | S |
- * | | +--------------+ |
- * | | | check |-------------------------->|
- * | | | consistency | E |
- * | | +--------------+ |
- * | | | S |
- * | | +==============+ +==============+ |
- * | | || commit ||-------->|| undo || |
- * | | || || E || commit || |
- * | | +==============+ +==============+ |
- * | | | S U |<--------+
- * | | +--------------+ +==============+
- * | | | irreversible | || undo ||
- * | | | commit | || set ||
- * | | +--------------+ +==============+
- * | | | U U |
- * | +-------------->|<------------------------+
- * | +==============+
- * | || undo ||
- * | || cleanup ||
- * | +==============+
- * +---------------------->| U
- * |
- * (err && f1)------------------->+
- * | |
- * +--------------+ +--------------+
- * | post |<--------| row |
- * | request | U | release |
- * +--------------+ +--------------+
- *
- */
- /*
- * save original mode
- */
- save_mode = reqinfo->mode;
- for(i = 0; i < BABY_STEPS_PER_MODE_MAX; ++i ) {
- /*
- * break if we run out of baby steps for this mode
- */
- if(mode_map_ptr[i] == BABY_STEP_NONE)
- break;
- DEBUGMSGTL(("baby_steps", " baby step mode %sn",
- se_find_label_in_slist("babystep_mode",mode_map_ptr[i])));
- /*
- * skip modes the handler didn't register for
- */
- if (BSTEP_USE_ORIGINAL != mode_map_ptr[i]) {
- u_int mode_flag;
- /*
- * skip undo commit if commit wasn't hit, and
- * undo_cleanup if undo_setup wasn't hit.
- */
- if((MODE_SET_UNDO == save_mode) &&
- (MODE_BSTEP_UNDO_COMMIT == mode_map_ptr[i]) &&
- !(BABY_STEP_COMMIT & bs_modes->completed)) {
- DEBUGMSGTL(("baby_steps",
- " skipping commit undo (no commit)n"));
- continue;
- }
- else if((MODE_SET_FREE == save_mode) &&
- (MODE_BSTEP_UNDO_CLEANUP == mode_map_ptr[i]) &&
- !(BABY_STEP_UNDO_SETUP & bs_modes->completed)) {
- DEBUGMSGTL(("baby_steps",
- " skipping undo cleanup (no undo setup)n"));
- continue;
- }
- reqinfo->mode = mode_map_ptr[i];
- mode_flag = netsnmp_baby_step_mode2flag( mode_map_ptr[i] );
- if((mode_flag & bs_modes->registered))
- bs_modes->completed |= mode_flag;
- else {
- DEBUGMSGTL(("baby_steps",
- " skipping mode (not registered)n"));
- continue;
- }
-
- }
- else {
- reqinfo->mode = save_mode;
- }
- #ifdef BABY_STEPS_NEXT_MODE
- /*
- * I can't remember why I wanted the next mode in the request,
- * but it's not used anywhere, so don't use this code. saved,
- * in case I remember why I thought needed it. - rstory 040911
- */
- if((BABY_STEPS_PER_MODE_MAX - 1) == i)
- reqinfo->next_mode_ok = BABY_STEP_NONE;
- else {
- if(BSTEP_USE_ORIGINAL == mode_map_ptr[i+1])
- reqinfo->next_mode_ok = save_mode;
- else
- reqinfo->next_mode_ok = mode_map_ptr[i+1];
- }
- #endif
- /*
- * call handlers for baby step
- */
- rc = netsnmp_call_next_handler(handler, reginfo, reqinfo,
- requests);
- /*
- * check for error calling handler (unlikely, but...)
- */
- if(rc) {
- DEBUGMSGTL(("baby_steps", " ERROR:handler errorn"));
- break;
- }
- /*
- * check for errors in any of the requests for GET-like, reserve1,
- * reserve2 and action. (there is no recovery from errors
- * in commit, free or undo.)
- */
- if (MODE_IS_GET(save_mode)
- || (save_mode < SNMP_MSG_INTERNAL_SET_COMMIT)) {
- rc = netsnmp_check_requests_error(requests);
- if(rc) {
- DEBUGMSGTL(("baby_steps", " ERROR:request errorn"));
- break;
- }
- }
- }
- /*
- * restore original mode
- */
- reqinfo->mode = save_mode;
-
- return rc;
- }
- /** initializes the baby_steps helper which then registers a baby_steps
- * handler as a run-time injectable handler for configuration file
- * use.
- */
- void
- netsnmp_baby_steps_handler_init(void)
- {
- netsnmp_register_handler_by_name("baby_steps",
- netsnmp_baby_steps_handler_get(BABY_STEP_ALL));
- }
- /** @} */
- /** @defgroup baby_steps baby_steps_access_multiplexer: calls individual access methods based on baby_step mode.
- * @ingroup handler
- * @{
- */
- /** returns a baby_steps handler that can be injected into a given
- * handler chain.
- */
- netsnmp_mib_handler *
- netsnmp_baby_steps_access_multiplexer_get(netsnmp_baby_steps_access_methods *am)
- {
- netsnmp_mib_handler *mh;
- mh = netsnmp_create_handler("baby_steps_mux",
- _baby_steps_access_multiplexer);
- if(!mh)
- return NULL;
- mh->myvoid = am;
- mh->flags |= MIB_HANDLER_AUTO_NEXT;
-
- return mh;
- }
- /** @internal Implements the baby_steps handler */
- static int
- _baby_steps_access_multiplexer(netsnmp_mib_handler *handler,
- netsnmp_handler_registration *reginfo,
- netsnmp_agent_request_info *reqinfo,
- netsnmp_request_info *requests)
- {
- void *temp_void;
- Netsnmp_Node_Handler *method = NULL;
- netsnmp_baby_steps_access_methods *access_methods;
- int rc = SNMP_ERR_NOERROR;
- /** call handlers should enforce these */
- netsnmp_assert((handler!=NULL) && (reginfo!=NULL) && (reqinfo!=NULL) &&
- (requests!=NULL));
- DEBUGMSGT(("baby_steps_mux", "mode %sn",
- se_find_label_in_slist("babystep_mode",reqinfo->mode)));
- access_methods = (netsnmp_baby_steps_access_methods *)handler->myvoid;
- if(!access_methods) {
- snmp_log(LOG_ERR,"baby_steps_access_multiplexer has no methodsn");
- return SNMPERR_GENERR;
- }
- switch(reqinfo->mode) {
-
- case MODE_BSTEP_PRE_REQUEST:
- if( access_methods->pre_request )
- method = access_methods->pre_request;
- break;
-
- case MODE_BSTEP_OBJECT_LOOKUP:
- if( access_methods->object_lookup )
- method = access_methods->object_lookup;
- break;
- case SNMP_MSG_GET:
- case SNMP_MSG_GETNEXT:
- if( access_methods->get_values )
- method = access_methods->get_values;
- break;
-
- case MODE_BSTEP_CHECK_VALUE:
- if( access_methods->object_syntax_checks )
- method = access_methods->object_syntax_checks;
- break;
- case MODE_BSTEP_ROW_CREATE:
- if( access_methods->row_creation )
- method = access_methods->row_creation;
- break;
- case MODE_BSTEP_UNDO_SETUP:
- if( access_methods->undo_setup )
- method = access_methods->undo_setup;
- break;
- case MODE_BSTEP_SET_VALUE:
- if( access_methods->set_values )
- method = access_methods->set_values;
- break;
- case MODE_BSTEP_CHECK_CONSISTENCY:
- if( access_methods->consistency_checks )
- method = access_methods->consistency_checks;
- break;
- case MODE_BSTEP_UNDO_SET:
- if( access_methods->undo_sets )
- method = access_methods->undo_sets;
- break;
- case MODE_BSTEP_COMMIT:
- if( access_methods->commit )
- method = access_methods->commit;
- break;
- case MODE_BSTEP_UNDO_COMMIT:
- if( access_methods->undo_commit )
- method = access_methods->undo_commit;
- break;
- case MODE_BSTEP_IRREVERSIBLE_COMMIT:
- if( access_methods->irreversible_commit )
- method = access_methods->irreversible_commit;
- break;
- case MODE_BSTEP_UNDO_CLEANUP:
- if( access_methods->undo_cleanup )
- method = access_methods->undo_cleanup;
- break;
-
- case MODE_BSTEP_POST_REQUEST:
- if( access_methods->post_request )
- method = access_methods->post_request;
- break;
- default:
- snmp_log(LOG_ERR,"unknown mode %dn", reqinfo->mode);
- return SNMP_ERR_GENERR;
- }
- /*
- * if method exists, set up handler void and call method.
- */
- if(NULL != method) {
- temp_void = handler->myvoid;
- handler->myvoid = access_methods->my_access_void;
- rc = (*method)(handler, reginfo, reqinfo, requests);
- handler->myvoid = temp_void;
- }
- else {
- rc = SNMP_ERR_GENERR;
- snmp_log(LOG_ERR,"baby steps multiplexer handler called for a mode "
- "with no handlern");
- netsnmp_assert(NULL != method);
- }
- /*
- * don't call any lower handlers, it will be done for us
- * since we set MIB_HANDLER_AUTO_NEXT
- */
- return rc;
- }
- /*
- * give a baby step mode, return the flag for that mode
- */
- int
- netsnmp_baby_step_mode2flag( u_int mode )
- {
- switch( mode ) {
- case MODE_BSTEP_OBJECT_LOOKUP:
- return BABY_STEP_OBJECT_LOOKUP;
- case MODE_BSTEP_SET_VALUE:
- return BABY_STEP_SET_VALUE;
- case MODE_BSTEP_IRREVERSIBLE_COMMIT:
- return BABY_STEP_IRREVERSIBLE_COMMIT;
- case MODE_BSTEP_CHECK_VALUE:
- return BABY_STEP_CHECK_VALUE;
- case MODE_BSTEP_PRE_REQUEST:
- return BABY_STEP_PRE_REQUEST;
- case MODE_BSTEP_POST_REQUEST:
- return BABY_STEP_POST_REQUEST;
- case MODE_BSTEP_UNDO_SETUP:
- return BABY_STEP_UNDO_SETUP;
- case MODE_BSTEP_UNDO_CLEANUP:
- return BABY_STEP_UNDO_CLEANUP;
- case MODE_BSTEP_UNDO_SET:
- return BABY_STEP_UNDO_SET;
- case MODE_BSTEP_ROW_CREATE:
- return BABY_STEP_ROW_CREATE;
- case MODE_BSTEP_CHECK_CONSISTENCY:
- return BABY_STEP_CHECK_CONSISTENCY;
- case MODE_BSTEP_COMMIT:
- return BABY_STEP_COMMIT;
- case MODE_BSTEP_UNDO_COMMIT:
- return BABY_STEP_UNDO_COMMIT;
- default:
- netsnmp_assert("unknown flag");
- break;
- }
- return 0;
- }