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

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * baby_steps.c
  3.  * $Id: baby_steps.c,v 1.10.2.1 2004/12/10 03:30:19 rstory Exp $
  4.  */
  5. #include <net-snmp/net-snmp-config.h>
  6. #include <net-snmp/net-snmp-includes.h>
  7. #include <net-snmp/agent/net-snmp-agent-includes.h>
  8. #include <net-snmp/agent/baby_steps.h>
  9. #if HAVE_DMALLOC_H
  10. #include <dmalloc.h>
  11. #endif
  12. #define BABY_STEPS_PER_MODE_MAX     4
  13. #define BSTEP_USE_ORIGINAL          0xffff
  14. static u_short get_mode_map[BABY_STEPS_PER_MODE_MAX] = {
  15.     MODE_BSTEP_PRE_REQUEST, MODE_BSTEP_OBJECT_LOOKUP, BSTEP_USE_ORIGINAL, MODE_BSTEP_POST_REQUEST };
  16. static u_short set_mode_map[SNMP_MSG_INTERNAL_SET_MAX][BABY_STEPS_PER_MODE_MAX] = {
  17.     /*R1*/
  18.     { MODE_BSTEP_PRE_REQUEST, MODE_BSTEP_OBJECT_LOOKUP, MODE_BSTEP_ROW_CREATE,
  19.       MODE_BSTEP_CHECK_VALUE },
  20.     /*R2*/
  21.     { MODE_BSTEP_UNDO_SETUP, BABY_STEP_NONE, BABY_STEP_NONE, BABY_STEP_NONE },
  22.     /*A */
  23.     { MODE_BSTEP_SET_VALUE,MODE_BSTEP_CHECK_CONSISTENCY,
  24.       MODE_BSTEP_COMMIT, BABY_STEP_NONE },
  25.     /*C */
  26.     { MODE_BSTEP_IRREVERSIBLE_COMMIT, MODE_BSTEP_UNDO_CLEANUP, MODE_BSTEP_POST_REQUEST,
  27.       BABY_STEP_NONE},
  28.     /*F */
  29.     { MODE_BSTEP_UNDO_CLEANUP, MODE_BSTEP_POST_REQUEST, BABY_STEP_NONE,
  30.       BABY_STEP_NONE },
  31.     /*U */
  32.     { MODE_BSTEP_UNDO_COMMIT, MODE_BSTEP_UNDO_SET, MODE_BSTEP_UNDO_CLEANUP,
  33.       MODE_BSTEP_POST_REQUEST}
  34. };
  35. static int
  36. _baby_steps_helper(netsnmp_mib_handler *handler,
  37.                    netsnmp_handler_registration *reginfo,
  38.                    netsnmp_agent_request_info *reqinfo,
  39.                    netsnmp_request_info *requests);
  40. static int
  41. _baby_steps_access_multiplexer(netsnmp_mib_handler *handler,
  42.                                netsnmp_handler_registration *reginfo,
  43.                                netsnmp_agent_request_info *reqinfo,
  44.                                netsnmp_request_info *requests);
  45.     
  46. /** @defgroup baby_steps baby_steps: calls your handler in baby_steps for set processing.
  47.  *  @ingroup handler
  48.  *  @{
  49.  */
  50. /** returns a baby_steps handler that can be injected into a given
  51.  *  handler chain.
  52.  */
  53. netsnmp_mib_handler *
  54. netsnmp_baby_steps_handler_get(u_long modes)
  55. {
  56.     netsnmp_mib_handler *mh;
  57.     netsnmp_baby_steps_modes *md;
  58.     mh = netsnmp_create_handler("baby_steps", _baby_steps_helper);
  59.     if(!mh)
  60.         return NULL;
  61.     md = SNMP_MALLOC_TYPEDEF(netsnmp_baby_steps_modes);
  62.     if (NULL == md) {
  63.         snmp_log(LOG_ERR,"malloc failed in netsnmp_baby_steps_handler_getn");
  64.         netsnmp_handler_free(mh);
  65.         mh = NULL;
  66.     }
  67.     else {
  68.         mh->myvoid = md;
  69.         if (0 == modes)
  70.             modes = BABY_STEP_ALL;
  71.         md->registered = modes;
  72.     }
  73.     /*
  74.      * don't set MIB_HANDLER_AUTO_NEXT, since we need to call lower
  75.      * handlers with a munged mode.
  76.      */
  77.     
  78.     return mh;
  79. }
  80. /** @internal Implements the baby_steps handler */
  81. static int
  82. _baby_steps_helper(netsnmp_mib_handler *handler,
  83.                          netsnmp_handler_registration *reginfo,
  84.                          netsnmp_agent_request_info *reqinfo,
  85.                          netsnmp_request_info *requests)
  86. {
  87.     netsnmp_baby_steps_modes *bs_modes;
  88.     int save_mode, i, rc = SNMP_ERR_NOERROR;
  89.     u_short *mode_map_ptr;
  90.     
  91.     DEBUGMSGTL(("baby_steps", "Got request, mode %sn",
  92.                 se_find_label_in_slist("agent_mode",reqinfo->mode)));
  93.     bs_modes = handler->myvoid;
  94.     netsnmp_assert(NULL != bs_modes);
  95.     switch (reqinfo->mode) {
  96.     case MODE_SET_RESERVE1:
  97.         /*
  98.          * clear completed modes
  99.          * xxx-rks: this will break for pdus with set requests to different
  100.          * rows in the same table when the handler is set up to use the row
  101.          * merge helper as well (or if requests are serialized).
  102.          */
  103.         bs_modes->completed = 0;
  104.         /** fall through */
  105.     case MODE_SET_RESERVE2:
  106.     case MODE_SET_ACTION:
  107.     case MODE_SET_COMMIT:
  108.     case MODE_SET_FREE:
  109.     case MODE_SET_UNDO:
  110.         mode_map_ptr = set_mode_map[reqinfo->mode];
  111.         break;
  112.             
  113.     default:
  114.         /*
  115.          * clear completed modes
  116.          */
  117.         bs_modes->completed = 0;
  118.         mode_map_ptr = get_mode_map;
  119.     }
  120.     /*
  121.      * NOTE: if you update this chart, please update the versions in
  122.      *       local/mib2c-conf.d/parent-set.m2i
  123.      *       agent/mibgroup/helpers/baby_steps.c
  124.      * while you're at it.
  125.      */
  126.     /*
  127.      ***********************************************************************
  128.      * Baby Steps Flow Chart (2004.06.05)                                  *
  129.      *                                                                     *
  130.      * +--------------+    +================+    U = unconditional path    *
  131.      * |optional state|    ||required state||    S = path for success      *
  132.      * +--------------+    +================+    E = path for error        *
  133.      ***********************************************************************
  134.      *
  135.      *                        +--------------+
  136.      *                        |     pre      |
  137.      *                        |   request    |
  138.      *                        +--------------+
  139.      *                               | U
  140.      * +-------------+        +==============+
  141.      * |    row    |f|<-------||  object    ||
  142.      * |  create   |1|      E ||  lookup    ||
  143.      * +-------------+        +==============+
  144.      *     E |   | S                 | S
  145.      *       |   +------------------>|
  146.      *       |                +==============+
  147.      *       |              E ||   check    ||
  148.      *       |<---------------||   values   ||
  149.      *       |                +==============+
  150.      *       |                       | S
  151.      *       |                +==============+
  152.      *       |       +<-------||   undo     ||
  153.      *       |       |      E ||   setup    ||
  154.      *       |       |        +==============+
  155.      *       |       |               | S
  156.      *       |       |        +==============+
  157.      *       |       |        ||    set     ||-------------------------->+
  158.      *       |       |        ||   value    || E                         |
  159.      *       |       |        +==============+                           |
  160.      *       |       |               | S                                 |
  161.      *       |       |        +--------------+                           |
  162.      *       |       |        |    check     |-------------------------->|
  163.      *       |       |        |  consistency | E                         |
  164.      *       |       |        +--------------+                           |
  165.      *       |       |               | S                                 |
  166.      *       |       |        +==============+         +==============+  |
  167.      *       |       |        ||   commit   ||-------->||     undo   ||  |
  168.      *       |       |        ||            || E       ||    commit  ||  |
  169.      *       |       |        +==============+         +==============+  |
  170.      *       |       |               | S                     U |<--------+
  171.      *       |       |        +--------------+         +==============+
  172.      *       |       |        | irreversible |         ||    undo    ||
  173.      *       |       |        |    commit    |         ||     set    ||
  174.      *       |       |        +--------------+         +==============+
  175.      *       |       |               | U                     U |
  176.      *       |       +-------------->|<------------------------+
  177.      *       |                +==============+
  178.      *       |                ||   undo     ||
  179.      *       |                ||  cleanup   ||
  180.      *       |                +==============+
  181.      *       +---------------------->| U
  182.      *                               |
  183.      *                          (err && f1)------------------->+
  184.      *                               |                         |
  185.      *                        +--------------+         +--------------+
  186.      *                        |    post      |<--------|      row     |
  187.      *                        |   request    |       U |    release   |
  188.      *                        +--------------+         +--------------+
  189.      *
  190.      */
  191.     /*
  192.      * save original mode
  193.      */
  194.     save_mode = reqinfo->mode;
  195.     for(i = 0; i < BABY_STEPS_PER_MODE_MAX; ++i ) {
  196.         /*
  197.          * break if we run out of baby steps for this mode
  198.          */
  199.         if(mode_map_ptr[i] == BABY_STEP_NONE)
  200.             break;
  201.         DEBUGMSGTL(("baby_steps", " baby step mode %sn",
  202.                     se_find_label_in_slist("babystep_mode",mode_map_ptr[i])));
  203.         /*
  204.          * skip modes the handler didn't register for
  205.          */
  206.         if (BSTEP_USE_ORIGINAL != mode_map_ptr[i]) {
  207.             u_int    mode_flag;
  208.             /*
  209.              * skip undo commit if commit wasn't hit, and
  210.              * undo_cleanup if undo_setup wasn't hit.
  211.              */
  212.             if((MODE_SET_UNDO == save_mode) &&
  213.                (MODE_BSTEP_UNDO_COMMIT == mode_map_ptr[i]) &&
  214.                !(BABY_STEP_COMMIT & bs_modes->completed)) {
  215.                 DEBUGMSGTL(("baby_steps",
  216.                             "   skipping commit undo (no commit)n"));
  217.                 continue;
  218.             }
  219.             else if((MODE_SET_FREE == save_mode) &&
  220.                (MODE_BSTEP_UNDO_CLEANUP == mode_map_ptr[i]) &&
  221.                !(BABY_STEP_UNDO_SETUP & bs_modes->completed)) {
  222.                 DEBUGMSGTL(("baby_steps",
  223.                             "   skipping undo cleanup (no undo setup)n"));
  224.                 continue;
  225.             }
  226.             reqinfo->mode = mode_map_ptr[i];
  227.             mode_flag = netsnmp_baby_step_mode2flag( mode_map_ptr[i] );
  228.             if((mode_flag & bs_modes->registered))
  229.                 bs_modes->completed |= mode_flag;
  230.             else {
  231.                 DEBUGMSGTL(("baby_steps",
  232.                             "   skipping mode (not registered)n"));
  233.                 continue;
  234.             }
  235.         
  236.         }
  237.         else {
  238.             reqinfo->mode = save_mode;
  239.         }
  240. #ifdef BABY_STEPS_NEXT_MODE
  241.         /*
  242.          * I can't remember why I wanted the next mode in the request,
  243.          * but it's not used anywhere, so don't use this code. saved,
  244.          * in case I remember why I thought needed it. - rstory 040911
  245.          */
  246.         if((BABY_STEPS_PER_MODE_MAX - 1) == i)
  247.             reqinfo->next_mode_ok = BABY_STEP_NONE;
  248.         else {
  249.             if(BSTEP_USE_ORIGINAL == mode_map_ptr[i+1])
  250.                 reqinfo->next_mode_ok = save_mode;
  251.             else
  252.                 reqinfo->next_mode_ok = mode_map_ptr[i+1];
  253.         }
  254. #endif
  255.         /*
  256.          * call handlers for baby step
  257.          */
  258.         rc = netsnmp_call_next_handler(handler, reginfo, reqinfo,
  259.                                        requests);
  260.         /*
  261.          * check for error calling handler (unlikely, but...)
  262.          */
  263.         if(rc) {
  264.             DEBUGMSGTL(("baby_steps", "   ERROR:handler errorn"));
  265.             break;
  266.         }
  267.         /*
  268.          * check for errors in any of the requests for GET-like, reserve1,
  269.          * reserve2 and action. (there is no recovery from errors
  270.          * in commit, free or undo.)
  271.          */
  272.         if (MODE_IS_GET(save_mode)
  273.             || (save_mode < SNMP_MSG_INTERNAL_SET_COMMIT)) {
  274.             rc = netsnmp_check_requests_error(requests);
  275.             if(rc) {
  276.                 DEBUGMSGTL(("baby_steps", "   ERROR:request errorn"));
  277.                 break;
  278.             }
  279.         }
  280.     }
  281.     /*
  282.      * restore original mode
  283.      */
  284.     reqinfo->mode = save_mode;
  285.     
  286.     return rc;
  287. }
  288. /** initializes the baby_steps helper which then registers a baby_steps
  289.  *  handler as a run-time injectable handler for configuration file
  290.  *  use.
  291.  */
  292. void
  293. netsnmp_baby_steps_handler_init(void)
  294. {
  295.     netsnmp_register_handler_by_name("baby_steps",
  296.                                      netsnmp_baby_steps_handler_get(BABY_STEP_ALL));
  297. }
  298. /** @} */
  299. /** @defgroup baby_steps baby_steps_access_multiplexer: calls individual access methods based on baby_step mode.
  300.  *  @ingroup handler
  301.  *  @{
  302.  */
  303. /** returns a baby_steps handler that can be injected into a given
  304.  *  handler chain.
  305.  */
  306. netsnmp_mib_handler *
  307. netsnmp_baby_steps_access_multiplexer_get(netsnmp_baby_steps_access_methods *am)
  308. {
  309.     netsnmp_mib_handler *mh;
  310.     mh = netsnmp_create_handler("baby_steps_mux",
  311.                                 _baby_steps_access_multiplexer);
  312.     if(!mh)
  313.         return NULL;
  314.     mh->myvoid = am;
  315.     mh->flags |= MIB_HANDLER_AUTO_NEXT;
  316.     
  317.     return mh;
  318. }
  319. /** @internal Implements the baby_steps handler */
  320. static int
  321. _baby_steps_access_multiplexer(netsnmp_mib_handler *handler,
  322.                                netsnmp_handler_registration *reginfo,
  323.                                netsnmp_agent_request_info *reqinfo,
  324.                                netsnmp_request_info *requests)
  325. {
  326.     void *temp_void;
  327.     Netsnmp_Node_Handler *method = NULL;
  328.     netsnmp_baby_steps_access_methods *access_methods;
  329.     int rc = SNMP_ERR_NOERROR;
  330.     /** call handlers should enforce these */
  331.     netsnmp_assert((handler!=NULL) && (reginfo!=NULL) && (reqinfo!=NULL) &&
  332.                    (requests!=NULL));
  333.     DEBUGMSGT(("baby_steps_mux", "mode %sn",
  334.                se_find_label_in_slist("babystep_mode",reqinfo->mode)));
  335.     access_methods = (netsnmp_baby_steps_access_methods *)handler->myvoid;
  336.     if(!access_methods) {
  337.         snmp_log(LOG_ERR,"baby_steps_access_multiplexer has no methodsn");
  338.         return SNMPERR_GENERR;
  339.     }
  340.     switch(reqinfo->mode) {
  341.         
  342.     case MODE_BSTEP_PRE_REQUEST:
  343.         if( access_methods->pre_request )
  344.             method = access_methods->pre_request;
  345.         break;
  346.         
  347.     case MODE_BSTEP_OBJECT_LOOKUP:
  348.         if( access_methods->object_lookup )
  349.             method = access_methods->object_lookup;
  350.         break;
  351.     case SNMP_MSG_GET:
  352.     case SNMP_MSG_GETNEXT:
  353.         if( access_methods->get_values )
  354.             method = access_methods->get_values;
  355.         break;
  356.         
  357.     case MODE_BSTEP_CHECK_VALUE:
  358.         if( access_methods->object_syntax_checks )
  359.             method = access_methods->object_syntax_checks;
  360.         break;
  361.     case MODE_BSTEP_ROW_CREATE:
  362.         if( access_methods->row_creation )
  363.             method = access_methods->row_creation;
  364.         break;
  365.     case MODE_BSTEP_UNDO_SETUP:
  366.         if( access_methods->undo_setup )
  367.             method = access_methods->undo_setup;
  368.         break;
  369.     case MODE_BSTEP_SET_VALUE:
  370.         if( access_methods->set_values )
  371.             method = access_methods->set_values;
  372.         break;
  373.     case MODE_BSTEP_CHECK_CONSISTENCY:
  374.         if( access_methods->consistency_checks )
  375.             method = access_methods->consistency_checks;
  376.         break;
  377.     case MODE_BSTEP_UNDO_SET:
  378.         if( access_methods->undo_sets )
  379.             method = access_methods->undo_sets;
  380.         break;
  381.     case MODE_BSTEP_COMMIT:
  382.         if( access_methods->commit )
  383.             method = access_methods->commit;
  384.         break;
  385.     case MODE_BSTEP_UNDO_COMMIT:
  386.         if( access_methods->undo_commit )
  387.             method = access_methods->undo_commit;
  388.         break;
  389.     case MODE_BSTEP_IRREVERSIBLE_COMMIT:
  390.         if( access_methods->irreversible_commit )
  391.             method = access_methods->irreversible_commit;
  392.         break;
  393.     case MODE_BSTEP_UNDO_CLEANUP:
  394.         if( access_methods->undo_cleanup )
  395.             method = access_methods->undo_cleanup;
  396.         break;
  397.         
  398.     case MODE_BSTEP_POST_REQUEST:
  399.         if( access_methods->post_request )
  400.             method = access_methods->post_request;
  401.         break;
  402.     default:
  403.         snmp_log(LOG_ERR,"unknown mode %dn", reqinfo->mode);
  404.         return SNMP_ERR_GENERR;
  405.     }
  406.     /*
  407.      * if method exists, set up handler void and call method.
  408.      */
  409.     if(NULL != method) {
  410.         temp_void = handler->myvoid;
  411.         handler->myvoid = access_methods->my_access_void;
  412.         rc = (*method)(handler, reginfo, reqinfo, requests);
  413.         handler->myvoid = temp_void;
  414.     }
  415.     else {
  416.         rc = SNMP_ERR_GENERR;
  417.         snmp_log(LOG_ERR,"baby steps multiplexer handler called for a mode "
  418.                  "with no handlern");
  419.         netsnmp_assert(NULL != method);
  420.     }
  421.     /*
  422.      * don't call any lower handlers, it will be done for us 
  423.      * since we set MIB_HANDLER_AUTO_NEXT
  424.      */
  425.     return rc;
  426. }
  427. /*
  428.  * give a baby step mode, return the flag for that mode
  429.  */
  430. int
  431. netsnmp_baby_step_mode2flag( u_int mode )
  432. {
  433.     switch( mode ) {
  434.         case MODE_BSTEP_OBJECT_LOOKUP:
  435.             return BABY_STEP_OBJECT_LOOKUP;
  436.         case MODE_BSTEP_SET_VALUE:
  437.             return BABY_STEP_SET_VALUE;
  438.         case MODE_BSTEP_IRREVERSIBLE_COMMIT:
  439.             return BABY_STEP_IRREVERSIBLE_COMMIT;
  440.         case MODE_BSTEP_CHECK_VALUE:
  441.             return BABY_STEP_CHECK_VALUE;
  442.         case MODE_BSTEP_PRE_REQUEST:
  443.             return BABY_STEP_PRE_REQUEST;
  444.         case MODE_BSTEP_POST_REQUEST:
  445.             return BABY_STEP_POST_REQUEST;
  446.         case MODE_BSTEP_UNDO_SETUP:
  447.             return BABY_STEP_UNDO_SETUP;
  448.         case MODE_BSTEP_UNDO_CLEANUP:
  449.             return BABY_STEP_UNDO_CLEANUP;
  450.         case MODE_BSTEP_UNDO_SET:
  451.             return BABY_STEP_UNDO_SET;
  452.         case MODE_BSTEP_ROW_CREATE:
  453.             return BABY_STEP_ROW_CREATE;
  454.         case MODE_BSTEP_CHECK_CONSISTENCY:
  455.             return BABY_STEP_CHECK_CONSISTENCY;
  456.         case MODE_BSTEP_COMMIT:
  457.             return BABY_STEP_COMMIT;
  458.         case MODE_BSTEP_UNDO_COMMIT:
  459.             return BABY_STEP_UNDO_COMMIT;
  460.         default:
  461.             netsnmp_assert("unknown flag");
  462.             break;
  463.     }
  464.     return 0;
  465. }