net-snmp
5.4.1
|
00001 /* 00002 * table_array.c 00003 * $Id: table_array.c 14356 2006-03-08 22:48:18Z rstory $ 00004 */ 00005 00006 #include <net-snmp/net-snmp-config.h> 00007 00008 #if HAVE_STRING_H 00009 #include <string.h> 00010 #else 00011 #include <strings.h> 00012 #endif 00013 00014 #include <net-snmp/net-snmp-includes.h> 00015 #include <net-snmp/agent/net-snmp-agent-includes.h> 00016 00017 #include <net-snmp/agent/table.h> 00018 #include <net-snmp/agent/table_array.h> 00019 #include <net-snmp/library/container.h> 00020 #include <net-snmp/library/snmp_assert.h> 00021 00022 /* 00023 * snmp.h:#define SNMP_MSG_INTERNAL_SET_BEGIN -1 00024 * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE1 0 00025 * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE2 1 00026 * snmp.h:#define SNMP_MSG_INTERNAL_SET_ACTION 2 00027 * snmp.h:#define SNMP_MSG_INTERNAL_SET_COMMIT 3 00028 * snmp.h:#define SNMP_MSG_INTERNAL_SET_FREE 4 00029 * snmp.h:#define SNMP_MSG_INTERNAL_SET_UNDO 5 00030 */ 00031 00032 static const char *mode_name[] = { 00033 "Reserve 1", 00034 "Reserve 2", 00035 "Action", 00036 "Commit", 00037 "Free", 00038 "Undo" 00039 }; 00040 00041 /* 00042 * PRIVATE structure for holding important info for each table. 00043 */ 00044 typedef struct table_container_data_s { 00045 00047 netsnmp_table_registration_info *tblreg_info; 00048 00050 netsnmp_container *table; 00051 00052 /* 00053 * mutex_type lock; 00054 */ 00055 00058 int group_rows; 00059 00061 netsnmp_table_array_callbacks *cb; 00062 00063 } table_container_data; 00064 00134 /********************************************************************** 00135 ********************************************************************** 00136 * * 00137 * * 00138 * PUBLIC Registration functions * 00139 * * 00140 * * 00141 ********************************************************************** 00142 **********************************************************************/ 00148 int 00149 netsnmp_table_container_register(netsnmp_handler_registration *reginfo, 00150 netsnmp_table_registration_info *tabreg, 00151 netsnmp_table_array_callbacks *cb, 00152 netsnmp_container *container, 00153 int group_rows) 00154 { 00155 table_container_data *tad = SNMP_MALLOC_TYPEDEF(table_container_data); 00156 if (!tad) 00157 return SNMPERR_GENERR; 00158 tad->tblreg_info = tabreg; /* we need it too, but it really is not ours */ 00159 00160 if (!cb) { 00161 snmp_log(LOG_ERR, "table_array registration with no callbacks\n" ); 00162 free(tad); /* SNMP_FREE is overkill for local var */ 00163 return SNMPERR_GENERR; 00164 } 00165 /* 00166 * check for required callbacks 00167 */ 00168 if ((cb->can_set && 00169 ((NULL==cb->duplicate_row) || (NULL==cb->delete_row) || 00170 (NULL==cb->row_copy)) )) { 00171 snmp_log(LOG_ERR, "table_array registration with incomplete " 00172 "callback structure.\n"); 00173 free(tad); /* SNMP_FREE is overkill for local var */ 00174 return SNMPERR_GENERR; 00175 } 00176 00177 if (NULL==container) { 00178 tad->table = netsnmp_container_find("table_array"); 00179 snmp_log(LOG_ERR, "table_array couldn't allocate container\n" ); 00180 free(tad); /* SNMP_FREE is overkill for local var */ 00181 return SNMPERR_GENERR; 00182 } else 00183 tad->table = container; 00184 if (NULL==tad->table->compare) 00185 tad->table->compare = netsnmp_compare_netsnmp_index; 00186 if (NULL==tad->table->ncompare) 00187 tad->table->ncompare = netsnmp_ncompare_netsnmp_index; 00188 00189 tad->cb = cb; 00190 00191 reginfo->handler->myvoid = tad; 00192 00193 return netsnmp_register_table(reginfo, tabreg); 00194 } 00195 00196 int 00197 netsnmp_table_array_register(netsnmp_handler_registration *reginfo, 00198 netsnmp_table_registration_info *tabreg, 00199 netsnmp_table_array_callbacks *cb, 00200 netsnmp_container *container, 00201 int group_rows) 00202 { 00203 netsnmp_inject_handler(reginfo, 00204 netsnmp_create_handler(reginfo->handlerName, 00205 netsnmp_table_array_helper_handler)); 00206 return netsnmp_table_container_register(reginfo, tabreg, cb, 00207 container, group_rows); 00208 } 00209 00211 netsnmp_mib_handler * 00212 netsnmp_find_table_array_handler(netsnmp_handler_registration *reginfo) 00213 { 00214 netsnmp_mib_handler *mh; 00215 if (!reginfo) 00216 return NULL; 00217 mh = reginfo->handler; 00218 while (mh) { 00219 if (mh->access_method == netsnmp_table_array_helper_handler) 00220 break; 00221 mh = mh->next; 00222 } 00223 00224 return mh; 00225 } 00226 00228 netsnmp_container * 00229 netsnmp_extract_array_context(netsnmp_request_info *request) 00230 { 00231 return netsnmp_request_get_list_data(request, TABLE_ARRAY_NAME); 00232 } 00233 00235 int 00236 netsnmp_table_array_check_row_status(netsnmp_table_array_callbacks *cb, 00237 netsnmp_request_group *ag, 00238 long *rs_new, long *rs_old) 00239 { 00240 netsnmp_index *row_ctx; 00241 netsnmp_index *undo_ctx; 00242 if (!ag || !cb) 00243 return SNMPERR_GENERR; 00244 row_ctx = ag->existing_row; 00245 undo_ctx = ag->undo_info; 00246 00247 /* 00248 * xxx-rks: revisit row delete scenario 00249 */ 00250 if (row_ctx) { 00251 /* 00252 * either a new row, or change to old row 00253 */ 00254 /* 00255 * is it set to active? 00256 */ 00257 if (RS_IS_GOING_ACTIVE(*rs_new)) { 00258 /* 00259 * is it ready to be active? 00260 */ 00261 if ((NULL==cb->can_activate) || 00262 cb->can_activate(undo_ctx, row_ctx, ag)) 00263 *rs_new = RS_ACTIVE; 00264 else 00265 return SNMP_ERR_INCONSISTENTVALUE; 00266 } else { 00267 /* 00268 * not going active 00269 */ 00270 if (undo_ctx) { 00271 /* 00272 * change 00273 */ 00274 if (RS_IS_ACTIVE(*rs_old)) { 00275 /* 00276 * check pre-reqs for deactivation 00277 */ 00278 if (cb->can_deactivate && 00279 !cb->can_deactivate(undo_ctx, row_ctx, ag)) { 00280 return SNMP_ERR_INCONSISTENTVALUE; 00281 } 00282 } 00283 } else { 00284 /* 00285 * new row 00286 */ 00287 } 00288 00289 if (*rs_new != RS_DESTROY) { 00290 if ((NULL==cb->can_activate) || 00291 cb->can_activate(undo_ctx, row_ctx, ag)) 00292 *rs_new = RS_NOTINSERVICE; 00293 else 00294 *rs_new = RS_NOTREADY; 00295 } else { 00296 if (cb->can_delete && !cb->can_delete(undo_ctx, row_ctx, ag)) { 00297 return SNMP_ERR_INCONSISTENTVALUE; 00298 } 00299 ag->row_deleted = 1; 00300 } 00301 } 00302 } else { 00303 /* 00304 * check pre-reqs for delete row 00305 */ 00306 if (cb->can_delete && !cb->can_delete(undo_ctx, row_ctx, ag)) { 00307 return SNMP_ERR_INCONSISTENTVALUE; 00308 } 00309 } 00310 00311 return SNMP_ERR_NOERROR; 00312 } 00313 00317 /********************************************************************** 00318 ********************************************************************** 00319 ********************************************************************** 00320 ********************************************************************** 00321 * * 00322 * * 00323 * * 00324 * * 00325 * EVERYTHING BELOW THIS IS PRIVATE IMPLEMENTATION DETAILS. * 00326 * * 00327 * * 00328 * * 00329 * * 00330 ********************************************************************** 00331 ********************************************************************** 00332 ********************************************************************** 00333 **********************************************************************/ 00334 00335 /********************************************************************** 00336 ********************************************************************** 00337 * * 00338 * * 00339 * Structures, Utility/convenience functions * 00340 * * 00341 * * 00342 ********************************************************************** 00343 **********************************************************************/ 00344 /* 00345 * context info for SET requests 00346 */ 00347 typedef struct set_context_s { 00348 netsnmp_agent_request_info *agtreq_info; 00349 table_container_data *tad; 00350 int status; 00351 } set_context; 00352 00353 static void 00354 release_netsnmp_request_group(netsnmp_index *g, void *v) 00355 { 00356 netsnmp_request_group_item *tmp; 00357 netsnmp_request_group *group = (netsnmp_request_group *) g; 00358 00359 if (!g) 00360 return; 00361 while (group->list) { 00362 tmp = group->list; 00363 group->list = tmp->next; 00364 free(tmp); 00365 } 00366 00367 free(group); 00368 } 00369 00370 static void 00371 release_netsnmp_request_groups(void *vp) 00372 { 00373 netsnmp_container *c = (netsnmp_container*)vp; 00374 CONTAINER_FOR_EACH(c, (netsnmp_container_obj_func*) 00375 release_netsnmp_request_group, NULL); 00376 CONTAINER_FREE(c); 00377 } 00378 00379 void 00380 build_new_oid(netsnmp_handler_registration *reginfo, 00381 netsnmp_table_request_info *tblreq_info, 00382 netsnmp_index *row, netsnmp_request_info *current) 00383 { 00384 oid coloid[MAX_OID_LEN]; 00385 int coloid_len; 00386 00387 if (!tblreq_info || !reginfo || !row || !current) 00388 return; 00389 00390 coloid_len = reginfo->rootoid_len + 2; 00391 memcpy(coloid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid)); 00392 00394 coloid[reginfo->rootoid_len] = 1; 00395 00397 coloid[reginfo->rootoid_len + 1] = tblreq_info->colnum; 00398 00400 memcpy(&coloid[reginfo->rootoid_len + 2], row->oids, 00401 row->len * sizeof(oid)); 00402 00403 snmp_set_var_objid(current->requestvb, coloid, 00404 reginfo->rootoid_len + 2 + row->len); 00405 } 00406 00407 /********************************************************************** 00408 ********************************************************************** 00409 * * 00410 * * 00411 * GET procession functions * 00412 * * 00413 * * 00414 ********************************************************************** 00415 **********************************************************************/ 00416 int 00417 process_get_requests(netsnmp_handler_registration *reginfo, 00418 netsnmp_agent_request_info *agtreq_info, 00419 netsnmp_request_info *requests, 00420 table_container_data * tad) 00421 { 00422 int rc = SNMP_ERR_NOERROR; 00423 netsnmp_request_info *current; 00424 netsnmp_index *row = NULL; 00425 netsnmp_table_request_info *tblreq_info; 00426 netsnmp_variable_list *var; 00427 00428 /* 00429 * Loop through each of the requests, and 00430 * try to find the appropriate row from the container. 00431 */ 00432 for (current = requests; current; current = current->next) { 00433 00434 var = current->requestvb; 00435 DEBUGMSGTL(("table_array:get", 00436 " process_get_request oid:")); 00437 DEBUGMSGOID(("table_array:get", var->name, 00438 var->name_length)); 00439 DEBUGMSG(("table_array:get", "\n")); 00440 00441 /* 00442 * skip anything that doesn't need processing. 00443 */ 00444 if (current->processed != 0) { 00445 DEBUGMSGTL(("table_array:get", "already processed\n")); 00446 continue; 00447 } 00448 00449 /* 00450 * Get pointer to the table information for this request. This 00451 * information was saved by table_helper_handler. When 00452 * debugging, we double check a few assumptions. For example, 00453 * the table_helper_handler should enforce column boundaries. 00454 */ 00455 tblreq_info = netsnmp_extract_table_info(current); 00456 netsnmp_assert(tblreq_info->colnum <= tad->tblreg_info->max_column); 00457 00458 if ((agtreq_info->mode == MODE_GETNEXT) || 00459 (agtreq_info->mode == MODE_GETBULK)) { 00460 /* 00461 * find the row 00462 */ 00463 row = netsnmp_table_index_find_next_row(tad->table, tblreq_info); 00464 if (!row) { 00465 /* 00466 * no results found. 00467 * 00468 * xxx-rks: how do we skip this entry for the next handler, 00469 * but still allow it a chance to hit another handler? 00470 */ 00471 DEBUGMSGTL(("table_array:get", "no row found\n")); 00472 netsnmp_set_request_error(agtreq_info, current, 00473 SNMP_ENDOFMIBVIEW); 00474 continue; 00475 } 00476 00477 /* 00478 * * if data was found, make sure it has the column we want 00479 */ 00480 /* xxx-rks: add suport for sparse tables */ 00481 00482 /* 00483 * build new oid 00484 */ 00485 build_new_oid(reginfo, tblreq_info, row, current); 00486 00487 } 00488 else { 00489 netsnmp_index index; 00490 index.oids = tblreq_info->index_oid; 00491 index.len = tblreq_info->index_oid_len; 00492 00493 row = CONTAINER_FIND(tad->table, &index); 00494 if (!row) { 00495 DEBUGMSGTL(("table_array:get", "no row found\n")); 00496 netsnmp_set_request_error(agtreq_info, current, 00497 SNMP_NOSUCHINSTANCE); 00498 continue; 00499 } 00500 } 00502 /* 00503 * get the data 00504 */ 00505 rc = tad->cb->get_value(current, row, tblreq_info); 00506 00507 } 00509 return rc; 00510 } 00511 00512 /********************************************************************** 00513 ********************************************************************** 00514 * * 00515 * * 00516 * SET procession functions * 00517 * * 00518 * * 00519 ********************************************************************** 00520 **********************************************************************/ 00521 00522 void 00523 group_requests(netsnmp_agent_request_info *agtreq_info, 00524 netsnmp_request_info *requests, 00525 netsnmp_container *request_group, table_container_data * tad) 00526 { 00527 netsnmp_table_request_info *tblreq_info; 00528 netsnmp_variable_list *var; 00529 netsnmp_index *row, *tmp, index; 00530 netsnmp_request_info *current; 00531 netsnmp_request_group *g; 00532 netsnmp_request_group_item *i; 00533 00534 for (current = requests; current; current = current->next) { 00535 00536 var = current->requestvb; 00537 00538 /* 00539 * skip anything that doesn't need processing. 00540 */ 00541 if (current->processed != 0) { 00542 DEBUGMSGTL(("table_array:group", 00543 "already processed\n")); 00544 continue; 00545 } 00546 00547 /* 00548 * 3.2.1 Setup and paranoia 00549 * * 00550 * * Get pointer to the table information for this request. This 00551 * * information was saved by table_helper_handler. When 00552 * * debugging, we double check a few assumptions. For example, 00553 * * the table_helper_handler should enforce column boundaries. 00554 */ 00555 row = NULL; 00556 tblreq_info = netsnmp_extract_table_info(current); 00557 netsnmp_assert(tblreq_info->colnum <= tad->tblreg_info->max_column); 00558 00559 /* 00560 * search for index 00561 */ 00562 index.oids = tblreq_info->index_oid; 00563 index.len = tblreq_info->index_oid_len; 00564 tmp = CONTAINER_FIND(request_group, &index); 00565 if (tmp) { 00566 DEBUGMSGTL(("table_array:group", 00567 " existing group:")); 00568 DEBUGMSGOID(("table_array:group", index.oids, 00569 index.len)); 00570 DEBUGMSG(("table_array:group", "\n")); 00571 g = (netsnmp_request_group *) tmp; 00572 i = SNMP_MALLOC_TYPEDEF(netsnmp_request_group_item); 00573 i->ri = current; 00574 i->tri = tblreq_info; 00575 i->next = g->list; 00576 g->list = i; 00577 00579 continue; 00580 } 00581 00582 DEBUGMSGTL(("table_array:group", " new group")); 00583 DEBUGMSGOID(("table_array:group", index.oids, 00584 index.len)); 00585 DEBUGMSG(("table_array:group", "\n")); 00586 g = SNMP_MALLOC_TYPEDEF(netsnmp_request_group); 00587 i = SNMP_MALLOC_TYPEDEF(netsnmp_request_group_item); 00588 g->list = i; 00589 g->table = tad->table; 00590 i->ri = current; 00591 i->tri = tblreq_info; 00594 /* 00595 * search for row. all changes are made to the original row, 00596 * later, we'll make a copy in undo_info before we start processing. 00597 */ 00598 row = g->existing_row = CONTAINER_FIND(tad->table, &index); 00599 if (!g->existing_row) { 00600 if (!tad->cb->create_row) { 00601 if(MODE_IS_SET(agtreq_info->mode)) 00602 netsnmp_set_request_error(agtreq_info, current, 00603 SNMP_ERR_NOTWRITABLE); 00604 else 00605 netsnmp_set_request_error(agtreq_info, current, 00606 SNMP_NOSUCHINSTANCE); 00607 free(g); 00608 free(i); 00609 continue; 00610 } 00612 row = g->existing_row = tad->cb->create_row(&index); 00613 if (!row) { 00614 /* xxx-rks : parameter to create_row to allow 00615 * for better error reporting. */ 00616 netsnmp_set_request_error(agtreq_info, current, 00617 SNMP_ERR_GENERR); 00618 free(g); 00619 free(i); 00620 continue; 00621 } 00622 g->row_created = 1; 00623 } 00624 00625 g->index.oids = row->oids; 00626 g->index.len = row->len; 00627 00628 CONTAINER_INSERT(request_group, g); 00629 00630 } 00631 } 00632 00633 static void 00634 process_set_group(netsnmp_index *o, void *c) 00635 { 00636 /* xxx-rks: should we continue processing after an error?? */ 00637 set_context *context = (set_context *) c; 00638 netsnmp_request_group *ag = (netsnmp_request_group *) o; 00639 int rc = SNMP_ERR_NOERROR; 00640 00641 switch (context->agtreq_info->mode) { 00642 00643 case MODE_SET_RESERVE1: 00645 /* 00646 * if not a new row, save undo info 00647 */ 00648 if (ag->row_created == 0) { 00649 if (context->tad->cb->duplicate_row) 00650 ag->undo_info = context->tad->cb->duplicate_row(ag->existing_row); 00651 else 00652 ag->undo_info = NULL; 00653 if (NULL == ag->undo_info) { 00654 rc = SNMP_ERR_RESOURCEUNAVAILABLE; 00655 break; 00656 } 00657 } 00658 00659 if (context->tad->cb->set_reserve1) 00660 context->tad->cb->set_reserve1(ag); 00661 break; 00662 00663 case MODE_SET_RESERVE2: 00664 if (context->tad->cb->set_reserve2) 00665 context->tad->cb->set_reserve2(ag); 00666 break; 00667 00668 case MODE_SET_ACTION: 00669 if (context->tad->cb->set_action) 00670 context->tad->cb->set_action(ag); 00671 break; 00672 00673 case MODE_SET_COMMIT: 00674 if (ag->row_created == 0) { 00675 /* 00676 * this is an existing row, has it been deleted? 00677 */ 00678 if (ag->row_deleted == 1) { 00679 DEBUGMSGT((TABLE_ARRAY_NAME, "action: deleting row\n")); 00680 if (CONTAINER_REMOVE(ag->table, ag->existing_row) != 0) { 00681 rc = SNMP_ERR_COMMITFAILED; 00682 break; 00683 } 00684 } 00685 } else if (ag->row_deleted == 0) { 00686 /* 00687 * new row (that hasn't been deleted) should be inserted 00688 */ 00689 DEBUGMSGT((TABLE_ARRAY_NAME, "action: inserting row\n")); 00690 if (CONTAINER_INSERT(ag->table, ag->existing_row) != 0) { 00691 rc = SNMP_ERR_COMMITFAILED; 00692 break; 00693 } 00694 } 00695 00696 if (context->tad->cb->set_commit) 00697 context->tad->cb->set_commit(ag); 00698 00700 if (ag->undo_info) { 00701 context->tad->cb->delete_row(ag->undo_info); 00702 ag->undo_info = NULL; 00703 } 00704 00705 #if 0 00706 /* XXX-rks: finish row cooperative notifications 00707 * if the table has requested it, send cooperative notifications 00708 * for row operations. 00709 */ 00710 if (context->tad->notifications) { 00711 if (ag->undo_info) { 00712 if (!ag->existing_row) 00713 netsnmp_monitor_notify(EVENT_ROW_DEL); 00714 else 00715 netsnmp_monitor_notify(EVENT_ROW_MOD); 00716 } 00717 else 00718 netsnmp_monitor_notify(EVENT_ROW_ADD); 00719 } 00720 #endif 00721 00722 if ((ag->row_created == 0) && (ag->row_deleted == 1)) { 00723 context->tad->cb->delete_row(ag->existing_row); 00724 ag->existing_row = NULL; 00725 } 00726 break; 00727 00728 case MODE_SET_FREE: 00729 if (context->tad->cb->set_free) 00730 context->tad->cb->set_free(ag); 00731 00733 if (ag->row_created == 1) { 00734 if (context->tad->cb->delete_row) 00735 context->tad->cb->delete_row(ag->existing_row); 00736 ag->existing_row = NULL; 00737 } 00738 else { 00739 if (context->tad->cb->delete_row) 00740 context->tad->cb->delete_row(ag->undo_info); 00741 ag->undo_info = NULL; 00742 } 00743 break; 00744 00745 case MODE_SET_UNDO: 00746 /* 00747 * status already set - don't change it now 00748 */ 00749 if (context->tad->cb->set_undo) 00750 context->tad->cb->set_undo(ag); 00751 00752 /* 00753 * no more use for undo_info, so free it 00754 */ 00755 if (ag->row_created == 0) { 00756 /* 00757 * restore old values 00758 */ 00759 context->tad->cb->row_copy(ag->existing_row, ag->undo_info); 00760 context->tad->cb->delete_row(ag->undo_info); 00761 ag->undo_info = NULL; 00762 } 00763 else { 00764 context->tad->cb->delete_row(ag->existing_row); 00765 ag->existing_row = NULL; 00766 } 00767 break; 00768 00769 default: 00770 snmp_log(LOG_ERR, "unknown mode processing SET for " 00771 "netsnmp_table_array_helper_handler\n"); 00772 rc = SNMP_ERR_GENERR; 00773 break; 00774 } 00775 00776 if (rc) 00777 netsnmp_set_request_error(context->agtreq_info, 00778 ag->list->ri, rc); 00779 00780 } 00781 00782 int 00783 process_set_requests(netsnmp_agent_request_info *agtreq_info, 00784 netsnmp_request_info *requests, 00785 table_container_data * tad, char *handler_name) 00786 { 00787 set_context context; 00788 netsnmp_container *request_group; 00789 00790 /* 00791 * create and save structure for set info 00792 */ 00793 request_group = (netsnmp_container*) netsnmp_agent_get_list_data 00794 (agtreq_info, handler_name); 00795 if (request_group == NULL) { 00796 netsnmp_data_list *tmp; 00797 request_group = netsnmp_container_find("request_group:" 00798 "table_container"); 00799 request_group->compare = netsnmp_compare_netsnmp_index; 00800 request_group->ncompare = netsnmp_ncompare_netsnmp_index; 00801 00802 DEBUGMSGTL(("table_array", "Grouping requests by oid\n")); 00803 00804 tmp = netsnmp_create_data_list(handler_name, 00805 request_group, 00806 release_netsnmp_request_groups); 00807 netsnmp_agent_add_list_data(agtreq_info, tmp); 00808 /* 00809 * group requests. 00810 */ 00811 group_requests(agtreq_info, requests, request_group, tad); 00812 } 00813 00814 /* 00815 * process each group one at a time 00816 */ 00817 context.agtreq_info = agtreq_info; 00818 context.tad = tad; 00819 context.status = SNMP_ERR_NOERROR; 00820 CONTAINER_FOR_EACH(request_group, 00821 (netsnmp_container_obj_func*)process_set_group, 00822 &context); 00823 00824 return context.status; 00825 } 00826 00827 00828 /********************************************************************** 00829 ********************************************************************** 00830 * * 00831 * * 00832 * netsnmp_table_array_helper_handler() * 00833 * * 00834 * * 00835 ********************************************************************** 00836 **********************************************************************/ 00837 int 00838 netsnmp_table_array_helper_handler(netsnmp_mib_handler *handler, 00839 netsnmp_handler_registration *reginfo, 00840 netsnmp_agent_request_info *agtreq_info, 00841 netsnmp_request_info *requests) 00842 { 00843 00844 /* 00845 * First off, get our pointer from the handler. This 00846 * lets us get to the table registration information we 00847 * saved in get_table_array_handler(), as well as the 00848 * container where the actual table data is stored. 00849 */ 00850 int rc = SNMP_ERR_NOERROR; 00851 table_container_data *tad = (table_container_data *)handler->myvoid; 00852 00853 if (agtreq_info->mode < 0 || agtreq_info->mode > 5) { 00854 DEBUGMSGTL(("table_array", "Mode %d, Got request:\n", 00855 agtreq_info->mode)); 00856 } else { 00857 DEBUGMSGTL(("table_array", "Mode %s, Got request:\n", 00858 mode_name[agtreq_info->mode])); 00859 } 00860 00861 if (MODE_IS_SET(agtreq_info->mode)) { 00862 /* 00863 * netsnmp_mutex_lock(&tad->lock); 00864 */ 00865 rc = process_set_requests(agtreq_info, requests, 00866 tad, handler->handler_name); 00867 /* 00868 * netsnmp_mutex_unlock(&tad->lock); 00869 */ 00870 } else 00871 rc = process_get_requests(reginfo, agtreq_info, requests, tad); 00872 00873 if (rc != SNMP_ERR_NOERROR) { 00874 DEBUGMSGTL(("table_array", "processing returned rc %d\n", rc)); 00875 } 00876 00877 /* 00878 * Now we've done our processing. If there is another handler below us, 00879 * call them. 00880 */ 00881 if (handler->next) { 00882 rc = netsnmp_call_next_handler(handler, reginfo, agtreq_info, requests); 00883 if (rc != SNMP_ERR_NOERROR) { 00884 DEBUGMSGTL(("table_array", "next handler returned rc %d\n", rc)); 00885 } 00886 } 00887 00888 return rc; 00889 }