Logo
Home page Net-SNMP

Archive Search:

Require all words?

Site Search:
Google
Main Page | Modules | Data Structures | File List | Data Fields | Related Pages | Examples

baby_steps.c

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

Generated on Fri Dec 30 13:47:44 2005 for net-snmp by  doxygen 1.3.9.1

Valid CSS!


Last modified: Thursday, 01-Mar-2007 16:20:01 PST
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.