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