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