00001 /* 00002 * baby_steps.c 00003 * $Id$ 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 }
Last modified: Wednesday, 01-Aug-2018 04:41:28 UTC
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.