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 }
1.3.9.1
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.