00001
00002
00003
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
00019 { MODE_BSTEP_PRE_REQUEST, MODE_BSTEP_OBJECT_LOOKUP, MODE_BSTEP_ROW_CREATE,
00020 MODE_BSTEP_CHECK_VALUE },
00021
00022 { MODE_BSTEP_UNDO_SETUP, BABY_STEP_NONE, BABY_STEP_NONE, BABY_STEP_NONE },
00023
00024 { MODE_BSTEP_SET_VALUE,MODE_BSTEP_CHECK_CONSISTENCY,
00025 MODE_BSTEP_COMMIT, BABY_STEP_NONE },
00026
00027 { MODE_BSTEP_IRREVERSIBLE_COMMIT, MODE_BSTEP_UNDO_CLEANUP, MODE_BSTEP_POST_REQUEST,
00028 BABY_STEP_NONE},
00029
00030 { MODE_BSTEP_UNDO_CLEANUP, MODE_BSTEP_POST_REQUEST, BABY_STEP_NONE,
00031 BABY_STEP_NONE },
00032
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
00082
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
00110
00111
00112
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
00128
00129 bs_modes->completed = 0;
00130
00131 mode_map_ptr = get_mode_map;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 save_mode = reqinfo->mode;
00209 for(i = 0; i < BABY_STEPS_PER_MODE_MAX; ++i ) {
00210
00211
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
00221
00222 if (BSTEP_USE_ORIGINAL != mode_map_ptr[i]) {
00223 u_int mode_flag;
00224
00225
00226
00227
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
00263
00264
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
00278
00279 rc = netsnmp_call_next_handler(handler, reginfo, reqinfo,
00280 requests);
00281
00282
00283
00284
00285 if(rc) {
00286 DEBUGMSGTL(("baby_steps", " ERROR:handler error\n"));
00287 break;
00288 }
00289
00290
00291
00292
00293
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
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
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
00472
00473
00474
00475 return rc;
00476 }
00477
00478
00479
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 }