baby_steps.c

00001 /*
00002  * baby_steps.c
00003  * $Id: baby_steps.c 14169 2006-01-25 16:28:12Z dts12 $
00004  */
00005 #include <net-snmp/net-snmp-config.h>
00006 #include <net-snmp/net-snmp-includes.h>
00007 #include <net-snmp/agent/net-snmp-agent-includes.h>
00008 
00009 #include <net-snmp/agent/baby_steps.h>
00010 
00011 #define BABY_STEPS_PER_MODE_MAX     4
00012 #define BSTEP_USE_ORIGINAL          0xffff
00013 
00014 static u_short get_mode_map[BABY_STEPS_PER_MODE_MAX] = {
00015     MODE_BSTEP_PRE_REQUEST, MODE_BSTEP_OBJECT_LOOKUP, BSTEP_USE_ORIGINAL, MODE_BSTEP_POST_REQUEST };
00016 
00017 static u_short set_mode_map[SNMP_MSG_INTERNAL_SET_MAX][BABY_STEPS_PER_MODE_MAX] = {
00018     /*R1*/
00019     { MODE_BSTEP_PRE_REQUEST, MODE_BSTEP_OBJECT_LOOKUP, MODE_BSTEP_ROW_CREATE,
00020       MODE_BSTEP_CHECK_VALUE },
00021     /*R2*/
00022     { MODE_BSTEP_UNDO_SETUP, BABY_STEP_NONE, BABY_STEP_NONE, BABY_STEP_NONE },
00023     /*A */
00024     { MODE_BSTEP_SET_VALUE,MODE_BSTEP_CHECK_CONSISTENCY,
00025       MODE_BSTEP_COMMIT, BABY_STEP_NONE },
00026     /*C */
00027     { MODE_BSTEP_IRREVERSIBLE_COMMIT, MODE_BSTEP_UNDO_CLEANUP, MODE_BSTEP_POST_REQUEST,
00028       BABY_STEP_NONE},
00029     /*F */
00030     { MODE_BSTEP_UNDO_CLEANUP, MODE_BSTEP_POST_REQUEST, BABY_STEP_NONE,
00031       BABY_STEP_NONE },
00032     /*U */
00033     { MODE_BSTEP_UNDO_COMMIT, MODE_BSTEP_UNDO_SET, MODE_BSTEP_UNDO_CLEANUP,
00034       MODE_BSTEP_POST_REQUEST}
00035 };
00036 
00037 static int
00038 _baby_steps_helper(netsnmp_mib_handler *handler,
00039                    netsnmp_handler_registration *reginfo,
00040                    netsnmp_agent_request_info *reqinfo,
00041                    netsnmp_request_info *requests);
00042 static int
00043 _baby_steps_access_multiplexer(netsnmp_mib_handler *handler,
00044                                netsnmp_handler_registration *reginfo,
00045                                netsnmp_agent_request_info *reqinfo,
00046                                netsnmp_request_info *requests);
00047     
00057 netsnmp_mib_handler *
00058 netsnmp_baby_steps_handler_get(u_long modes)
00059 {
00060     netsnmp_mib_handler *mh;
00061     netsnmp_baby_steps_modes *md;
00062 
00063     mh = netsnmp_create_handler("baby_steps", _baby_steps_helper);
00064     if(!mh)
00065         return NULL;
00066 
00067     md = SNMP_MALLOC_TYPEDEF(netsnmp_baby_steps_modes);
00068     if (NULL == md) {
00069         snmp_log(LOG_ERR,"malloc failed in netsnmp_baby_steps_handler_get\n");
00070         netsnmp_handler_free(mh);
00071         mh = NULL;
00072     }
00073     else {
00074         mh->myvoid = md;
00075         if (0 == modes)
00076             modes = BABY_STEP_ALL;
00077         md->registered = modes;
00078     }
00079 
00080     /*
00081      * don't set MIB_HANDLER_AUTO_NEXT, since we need to call lower
00082      * handlers with a munged mode.
00083      */
00084     
00085     return mh;
00086 }
00087 
00089 static int
00090 _baby_steps_helper(netsnmp_mib_handler *handler,
00091                          netsnmp_handler_registration *reginfo,
00092                          netsnmp_agent_request_info *reqinfo,
00093                          netsnmp_request_info *requests)
00094 {
00095     netsnmp_baby_steps_modes *bs_modes;
00096     int save_mode, i, rc = SNMP_ERR_NOERROR;
00097     u_short *mode_map_ptr;
00098     
00099     DEBUGMSGTL(("baby_steps", "Got request, mode %s\n",
00100                 se_find_label_in_slist("agent_mode",reqinfo->mode)));
00101 
00102     bs_modes = handler->myvoid;
00103     netsnmp_assert(NULL != bs_modes);
00104 
00105     switch (reqinfo->mode) {
00106 
00107     case MODE_SET_RESERVE1:
00108         /*
00109          * clear completed modes
00110          * xxx-rks: this will break for pdus with set requests to different
00111          * rows in the same table when the handler is set up to use the row
00112          * merge helper as well (or if requests are serialized).
00113          */
00114         bs_modes->completed = 0;
00117     case MODE_SET_RESERVE2:
00118     case MODE_SET_ACTION:
00119     case MODE_SET_COMMIT:
00120     case MODE_SET_FREE:
00121     case MODE_SET_UNDO:
00122         mode_map_ptr = set_mode_map[reqinfo->mode];
00123         break;
00124             
00125     default:
00126         /*
00127          * clear completed modes
00128          */
00129         bs_modes->completed = 0;
00130 
00131         mode_map_ptr = get_mode_map;
00132     }
00133 
00134     /*
00135      * NOTE: if you update this chart, please update the versions in
00136      *       local/mib2c-conf.d/parent-set.m2i
00137      *       agent/mibgroup/helpers/baby_steps.c
00138      * while you're at it.
00139      */
00140     /*
00141      ***********************************************************************
00142      * Baby Steps Flow Chart (2004.06.05)                                  *
00143      *                                                                     *
00144      * +--------------+    +================+    U = unconditional path    *
00145      * |optional state|    ||required state||    S = path for success      *
00146      * +--------------+    +================+    E = path for error        *
00147      ***********************************************************************
00148      *
00149      *                        +--------------+
00150      *                        |     pre      |
00151      *                        |   request    |
00152      *                        +--------------+
00153      *                               | U
00154      * +-------------+        +==============+
00155      * |    row    |f|<-------||  object    ||
00156      * |  create   |1|      E ||  lookup    ||
00157      * +-------------+        +==============+
00158      *     E |   | S                 | S
00159      *       |   +------------------>|
00160      *       |                +==============+
00161      *       |              E ||   check    ||
00162      *       |<---------------||   values   ||
00163      *       |                +==============+
00164      *       |                       | S
00165      *       |                +==============+
00166      *       |       +<-------||   undo     ||
00167      *       |       |      E ||   setup    ||
00168      *       |       |        +==============+
00169      *       |       |               | S
00170      *       |       |        +==============+
00171      *       |       |        ||    set     ||-------------------------->+
00172      *       |       |        ||   value    || E                         |
00173      *       |       |        +==============+                           |
00174      *       |       |               | S                                 |
00175      *       |       |        +--------------+                           |
00176      *       |       |        |    check     |-------------------------->|
00177      *       |       |        |  consistency | E                         |
00178      *       |       |        +--------------+                           |
00179      *       |       |               | S                                 |
00180      *       |       |        +==============+         +==============+  |
00181      *       |       |        ||   commit   ||-------->||     undo   ||  |
00182      *       |       |        ||            || E       ||    commit  ||  |
00183      *       |       |        +==============+         +==============+  |
00184      *       |       |               | S                     U |<--------+
00185      *       |       |        +--------------+         +==============+
00186      *       |       |        | irreversible |         ||    undo    ||
00187      *       |       |        |    commit    |         ||     set    ||
00188      *       |       |        +--------------+         +==============+
00189      *       |       |               | U                     U |
00190      *       |       +-------------->|<------------------------+
00191      *       |                +==============+
00192      *       |                ||   undo     ||
00193      *       |                ||  cleanup   ||
00194      *       |                +==============+
00195      *       +---------------------->| U
00196      *                               |
00197      *                          (err && f1)------------------->+
00198      *                               |                         |
00199      *                        +--------------+         +--------------+
00200      *                        |    post      |<--------|      row     |
00201      *                        |   request    |       U |    release   |
00202      *                        +--------------+         +--------------+
00203      *
00204      */
00205     /*
00206      * save original mode
00207      */
00208     save_mode = reqinfo->mode;
00209     for(i = 0; i < BABY_STEPS_PER_MODE_MAX; ++i ) {
00210         /*
00211          * break if we run out of baby steps for this mode
00212          */
00213         if(mode_map_ptr[i] == BABY_STEP_NONE)
00214             break;
00215 
00216         DEBUGMSGTL(("baby_steps", " baby step mode %s\n",
00217                     se_find_label_in_slist("babystep_mode",mode_map_ptr[i])));
00218 
00219         /*
00220          * skip modes the handler didn't register for
00221          */
00222         if (BSTEP_USE_ORIGINAL != mode_map_ptr[i]) {
00223             u_int    mode_flag;
00224 
00225             /*
00226              * skip undo commit if commit wasn't hit, and
00227              * undo_cleanup if undo_setup wasn't hit.
00228              */
00229             if((MODE_SET_UNDO == save_mode) &&
00230                (MODE_BSTEP_UNDO_COMMIT == mode_map_ptr[i]) &&
00231                !(BABY_STEP_COMMIT & bs_modes->completed)) {
00232                 DEBUGMSGTL(("baby_steps",
00233                             "   skipping commit undo (no commit)\n"));
00234                 continue;
00235             }
00236             else if((MODE_SET_FREE == save_mode) &&
00237                (MODE_BSTEP_UNDO_CLEANUP == mode_map_ptr[i]) &&
00238                !(BABY_STEP_UNDO_SETUP & bs_modes->completed)) {
00239                 DEBUGMSGTL(("baby_steps",
00240                             "   skipping undo cleanup (no undo setup)\n"));
00241                 continue;
00242             }
00243 
00244             reqinfo->mode = mode_map_ptr[i];
00245             mode_flag = netsnmp_baby_step_mode2flag( mode_map_ptr[i] );
00246             if((mode_flag & bs_modes->registered))
00247                 bs_modes->completed |= mode_flag;
00248             else {
00249                 DEBUGMSGTL(("baby_steps",
00250                             "   skipping mode (not registered)\n"));
00251                 continue;
00252             }
00253 
00254         
00255         }
00256         else {
00257             reqinfo->mode = save_mode;
00258         }
00259 
00260 #ifdef BABY_STEPS_NEXT_MODE
00261         /*
00262          * I can't remember why I wanted the next mode in the request,
00263          * but it's not used anywhere, so don't use this code. saved,
00264          * in case I remember why I thought needed it. - rstory 040911
00265          */
00266         if((BABY_STEPS_PER_MODE_MAX - 1) == i)
00267             reqinfo->next_mode_ok = BABY_STEP_NONE;
00268         else {
00269             if(BSTEP_USE_ORIGINAL == mode_map_ptr[i+1])
00270                 reqinfo->next_mode_ok = save_mode;
00271             else
00272                 reqinfo->next_mode_ok = mode_map_ptr[i+1];
00273         }
00274 #endif
00275 
00276         /*
00277          * call handlers for baby step
00278          */
00279         rc = netsnmp_call_next_handler(handler, reginfo, reqinfo,
00280                                        requests);
00281 
00282         /*
00283          * check for error calling handler (unlikely, but...)
00284          */
00285         if(rc) {
00286             DEBUGMSGTL(("baby_steps", "   ERROR:handler error\n"));
00287             break;
00288         }
00289 
00290         /*
00291          * check for errors in any of the requests for GET-like, reserve1,
00292          * reserve2 and action. (there is no recovery from errors
00293          * in commit, free or undo.)
00294          */
00295         if (MODE_IS_GET(save_mode)
00296             || (save_mode < SNMP_MSG_INTERNAL_SET_COMMIT)) {
00297             rc = netsnmp_check_requests_error(requests);
00298             if(rc) {
00299                 DEBUGMSGTL(("baby_steps", "   ERROR:request error\n"));
00300                 break;
00301             }
00302         }
00303     }
00304 
00305     /*
00306      * restore original mode
00307      */
00308     reqinfo->mode = save_mode;
00309 
00310     
00311     return rc;
00312 }
00313 
00318 void
00319 netsnmp_baby_steps_handler_init(void)
00320 {
00321     netsnmp_register_handler_by_name("baby_steps",
00322                                      netsnmp_baby_steps_handler_get(BABY_STEP_ALL));
00323 }
00324 
00335 netsnmp_mib_handler *
00336 netsnmp_baby_steps_access_multiplexer_get(netsnmp_baby_steps_access_methods *am)
00337 {
00338     netsnmp_mib_handler *mh;
00339 
00340     mh = netsnmp_create_handler("baby_steps_mux",
00341                                 _baby_steps_access_multiplexer);
00342     if(!mh)
00343         return NULL;
00344 
00345     mh->myvoid = am;
00346     mh->flags |= MIB_HANDLER_AUTO_NEXT;
00347     
00348     return mh;
00349 }
00350 
00352 static int
00353 _baby_steps_access_multiplexer(netsnmp_mib_handler *handler,
00354                                netsnmp_handler_registration *reginfo,
00355                                netsnmp_agent_request_info *reqinfo,
00356                                netsnmp_request_info *requests)
00357 {
00358     void *temp_void;
00359     Netsnmp_Node_Handler *method = NULL;
00360     netsnmp_baby_steps_access_methods *access_methods;
00361     int rc = SNMP_ERR_NOERROR;
00362 
00364     netsnmp_assert((handler!=NULL) && (reginfo!=NULL) && (reqinfo!=NULL) &&
00365                    (requests!=NULL));
00366 
00367     DEBUGMSGT(("baby_steps_mux", "mode %s\n",
00368                se_find_label_in_slist("babystep_mode",reqinfo->mode)));
00369 
00370     access_methods = (netsnmp_baby_steps_access_methods *)handler->myvoid;
00371     if(!access_methods) {
00372         snmp_log(LOG_ERR,"baby_steps_access_multiplexer has no methods\n");
00373         return SNMPERR_GENERR;
00374     }
00375 
00376     switch(reqinfo->mode) {
00377         
00378     case MODE_BSTEP_PRE_REQUEST:
00379         if( access_methods->pre_request )
00380             method = access_methods->pre_request;
00381         break;
00382         
00383     case MODE_BSTEP_OBJECT_LOOKUP:
00384         if( access_methods->object_lookup )
00385             method = access_methods->object_lookup;
00386         break;
00387 
00388     case SNMP_MSG_GET:
00389     case SNMP_MSG_GETNEXT:
00390         if( access_methods->get_values )
00391             method = access_methods->get_values;
00392         break;
00393         
00394     case MODE_BSTEP_CHECK_VALUE:
00395         if( access_methods->object_syntax_checks )
00396             method = access_methods->object_syntax_checks;
00397         break;
00398 
00399     case MODE_BSTEP_ROW_CREATE:
00400         if( access_methods->row_creation )
00401             method = access_methods->row_creation;
00402         break;
00403 
00404     case MODE_BSTEP_UNDO_SETUP:
00405         if( access_methods->undo_setup )
00406             method = access_methods->undo_setup;
00407         break;
00408 
00409     case MODE_BSTEP_SET_VALUE:
00410         if( access_methods->set_values )
00411             method = access_methods->set_values;
00412         break;
00413 
00414     case MODE_BSTEP_CHECK_CONSISTENCY:
00415         if( access_methods->consistency_checks )
00416             method = access_methods->consistency_checks;
00417         break;
00418 
00419     case MODE_BSTEP_UNDO_SET:
00420         if( access_methods->undo_sets )
00421             method = access_methods->undo_sets;
00422         break;
00423 
00424     case MODE_BSTEP_COMMIT:
00425         if( access_methods->commit )
00426             method = access_methods->commit;
00427         break;
00428 
00429     case MODE_BSTEP_UNDO_COMMIT:
00430         if( access_methods->undo_commit )
00431             method = access_methods->undo_commit;
00432         break;
00433 
00434     case MODE_BSTEP_IRREVERSIBLE_COMMIT:
00435         if( access_methods->irreversible_commit )
00436             method = access_methods->irreversible_commit;
00437         break;
00438 
00439     case MODE_BSTEP_UNDO_CLEANUP:
00440         if( access_methods->undo_cleanup )
00441             method = access_methods->undo_cleanup;
00442         break;
00443         
00444     case MODE_BSTEP_POST_REQUEST:
00445         if( access_methods->post_request )
00446             method = access_methods->post_request;
00447         break;
00448 
00449     default:
00450         snmp_log(LOG_ERR,"unknown mode %d\n", reqinfo->mode);
00451         return SNMP_ERR_GENERR;
00452     }
00453 
00454     /*
00455      * if method exists, set up handler void and call method.
00456      */
00457     if(NULL != method) {
00458         temp_void = handler->myvoid;
00459         handler->myvoid = access_methods->my_access_void;
00460         rc = (*method)(handler, reginfo, reqinfo, requests);
00461         handler->myvoid = temp_void;
00462     }
00463     else {
00464         rc = SNMP_ERR_GENERR;
00465         snmp_log(LOG_ERR,"baby steps multiplexer handler called for a mode "
00466                  "with no handler\n");
00467         netsnmp_assert(NULL != method);
00468     }
00469 
00470     /*
00471      * don't call any lower handlers, it will be done for us 
00472      * since we set MIB_HANDLER_AUTO_NEXT
00473      */
00474 
00475     return rc;
00476 }
00477 
00478 /*
00479  * give a baby step mode, return the flag for that mode
00480  */
00481 int
00482 netsnmp_baby_step_mode2flag( u_int mode )
00483 {
00484     switch( mode ) {
00485         case MODE_BSTEP_OBJECT_LOOKUP:
00486             return BABY_STEP_OBJECT_LOOKUP;
00487         case MODE_BSTEP_SET_VALUE:
00488             return BABY_STEP_SET_VALUE;
00489         case MODE_BSTEP_IRREVERSIBLE_COMMIT:
00490             return BABY_STEP_IRREVERSIBLE_COMMIT;
00491         case MODE_BSTEP_CHECK_VALUE:
00492             return BABY_STEP_CHECK_VALUE;
00493         case MODE_BSTEP_PRE_REQUEST:
00494             return BABY_STEP_PRE_REQUEST;
00495         case MODE_BSTEP_POST_REQUEST:
00496             return BABY_STEP_POST_REQUEST;
00497         case MODE_BSTEP_UNDO_SETUP:
00498             return BABY_STEP_UNDO_SETUP;
00499         case MODE_BSTEP_UNDO_CLEANUP:
00500             return BABY_STEP_UNDO_CLEANUP;
00501         case MODE_BSTEP_UNDO_SET:
00502             return BABY_STEP_UNDO_SET;
00503         case MODE_BSTEP_ROW_CREATE:
00504             return BABY_STEP_ROW_CREATE;
00505         case MODE_BSTEP_CHECK_CONSISTENCY:
00506             return BABY_STEP_CHECK_CONSISTENCY;
00507         case MODE_BSTEP_COMMIT:
00508             return BABY_STEP_COMMIT;
00509         case MODE_BSTEP_UNDO_COMMIT:
00510             return BABY_STEP_UNDO_COMMIT;
00511         default:
00512             netsnmp_assert("unknown flag");
00513             break;
00514     }
00515     return 0;
00516 }

net-snmpに対してSat Sep 5 13:14:20 2009に生成されました。  doxygen 1.4.7