net-snmp 5.7
|
00001 /* 00002 * table_container.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_container.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_provide(table_container) 00025 netsnmp_feature_child_of(table_container, table_container_all) 00026 netsnmp_feature_child_of(table_container_replace_row, table_container_all) 00027 netsnmp_feature_child_of(table_container_extract, table_container_all) 00028 netsnmp_feature_child_of(table_container_management, table_container_all) 00029 netsnmp_feature_child_of(table_container_row_remove, table_container_all) 00030 netsnmp_feature_child_of(table_container_row_insert, table_container_all) 00031 netsnmp_feature_child_of(table_container_all, mib_helpers) 00032 00033 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER 00034 00035 /* 00036 * snmp.h:#define SNMP_MSG_INTERNAL_SET_BEGIN -1 00037 * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE1 0 00038 * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE2 1 00039 * snmp.h:#define SNMP_MSG_INTERNAL_SET_ACTION 2 00040 * snmp.h:#define SNMP_MSG_INTERNAL_SET_COMMIT 3 00041 * snmp.h:#define SNMP_MSG_INTERNAL_SET_FREE 4 00042 * snmp.h:#define SNMP_MSG_INTERNAL_SET_UNDO 5 00043 */ 00044 00045 /* 00046 * PRIVATE structure for holding important info for each table. 00047 */ 00048 typedef struct container_table_data_s { 00049 00051 int refcnt; 00052 00054 netsnmp_table_registration_info *tblreg_info; 00055 00057 netsnmp_container *table; 00058 00059 /* 00060 * mutex_type lock; 00061 */ 00062 00063 /* what type of key do we want? */ 00064 char key_type; 00065 00066 } container_table_data; 00067 00151 static int 00152 _container_table_handler(netsnmp_mib_handler *handler, 00153 netsnmp_handler_registration *reginfo, 00154 netsnmp_agent_request_info *agtreq_info, 00155 netsnmp_request_info *requests); 00156 00157 static void * 00158 _find_next_row(netsnmp_container *c, 00159 netsnmp_table_request_info *tblreq, 00160 void * key); 00161 00162 /********************************************************************** 00163 ********************************************************************** 00164 * * 00165 * * 00166 * PUBLIC Registration functions * 00167 * * 00168 * * 00169 ********************************************************************** 00170 **********************************************************************/ 00171 00172 /* ================================== 00173 * 00174 * Container Table API: Table maintenance 00175 * 00176 * ================================== */ 00177 00178 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_MANAGEMENT 00179 container_table_data * 00180 netsnmp_tcontainer_create_table( const char *name, 00181 netsnmp_container *container, long flags ) 00182 { 00183 container_table_data *table; 00184 00185 table = SNMP_MALLOC_TYPEDEF(container_table_data); 00186 if (!table) 00187 return NULL; 00188 if (container) 00189 table->table = container; 00190 else { 00191 table->table = netsnmp_container_find("table_container"); 00192 if (!table->table) { 00193 SNMP_FREE(table); 00194 return NULL; 00195 } 00196 } 00197 00198 if (flags) 00199 table->key_type = (char)(flags & 0x03); /* Use lowest two bits */ 00200 else 00201 table->key_type = TABLE_CONTAINER_KEY_NETSNMP_INDEX; 00202 00203 if (!table->table->compare) 00204 table->table->compare = netsnmp_compare_netsnmp_index; 00205 if (!table->table->ncompare) 00206 table->table->ncompare = netsnmp_ncompare_netsnmp_index; 00207 00208 return table; 00209 } 00210 00211 void 00212 netsnmp_tcontainer_delete_table( container_table_data *table ) 00213 { 00214 if (!table) 00215 return; 00216 00217 if (table->table) 00218 CONTAINER_FREE(table->table); 00219 00220 SNMP_FREE(table); 00221 return; 00222 } 00223 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_MANAGEMENT */ 00224 00225 /* 00226 * The various standalone row operation routines 00227 * (create/clone/copy/delete) 00228 * will be specific to a particular table, 00229 * so can't be implemented here. 00230 */ 00231 00232 int 00233 netsnmp_tcontainer_add_row( container_table_data *table, netsnmp_index *row ) 00234 { 00235 if (!table || !table->table || !row) 00236 return -1; 00237 CONTAINER_INSERT( table->table, row ); 00238 return 0; 00239 } 00240 00241 netsnmp_index * 00242 netsnmp_tcontainer_remove_row( container_table_data *table, netsnmp_index *row ) 00243 { 00244 if (!table || !table->table || !row) 00245 return NULL; 00246 CONTAINER_REMOVE( table->table, row ); 00247 return NULL; 00248 } 00249 00250 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_REPLACE_ROW 00251 int 00252 netsnmp_tcontainer_replace_row( container_table_data *table, 00253 netsnmp_index *old_row, netsnmp_index *new_row ) 00254 { 00255 if (!table || !table->table || !old_row || !new_row) 00256 return -1; 00257 netsnmp_tcontainer_remove_row( table, old_row ); 00258 netsnmp_tcontainer_add_row( table, new_row ); 00259 return 0; 00260 } 00261 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_REPLACE_ROW */ 00262 00263 /* netsnmp_tcontainer_remove_delete_row() will be table-specific too */ 00264 00265 00266 /* ================================== 00267 * 00268 * Container Table API: MIB maintenance 00269 * 00270 * ================================== */ 00271 00272 static container_table_data * 00273 netsnmp_container_table_data_clone(container_table_data *tad) 00274 { 00275 ++tad->refcnt; 00276 return tad; 00277 } 00278 00279 static void 00280 netsnmp_container_table_data_free(container_table_data *tad) 00281 { 00282 if (--tad->refcnt == 0) 00283 free(tad); 00284 } 00285 00287 netsnmp_mib_handler * 00288 netsnmp_container_table_handler_get(netsnmp_table_registration_info *tabreg, 00289 netsnmp_container *container, char key_type) 00290 { 00291 container_table_data *tad; 00292 netsnmp_mib_handler *handler; 00293 00294 if (NULL == tabreg) { 00295 snmp_log(LOG_ERR, "bad param in netsnmp_container_table_register\n"); 00296 return NULL; 00297 } 00298 00299 tad = SNMP_MALLOC_TYPEDEF(container_table_data); 00300 handler = netsnmp_create_handler("table_container", 00301 _container_table_handler); 00302 if((NULL == tad) || (NULL == handler)) { 00303 if(tad) free(tad); /* SNMP_FREE wasted on locals */ 00304 if(handler) free(handler); /* SNMP_FREE wasted on locals */ 00305 snmp_log(LOG_ERR, 00306 "malloc failure in netsnmp_container_table_register\n"); 00307 return NULL; 00308 } 00309 00310 tad->refcnt = 1; 00311 tad->tblreg_info = tabreg; /* we need it too, but it really is not ours */ 00312 if(key_type) 00313 tad->key_type = key_type; 00314 else 00315 tad->key_type = TABLE_CONTAINER_KEY_NETSNMP_INDEX; 00316 00317 if(NULL == container) 00318 container = netsnmp_container_find("table_container"); 00319 tad->table = container; 00320 00321 if (NULL==container->compare) 00322 container->compare = netsnmp_compare_netsnmp_index; 00323 if (NULL==container->ncompare) 00324 container->ncompare = netsnmp_ncompare_netsnmp_index; 00325 00326 handler->myvoid = (void*)tad; 00327 handler->data_clone = (void *(*)(void *))netsnmp_container_table_data_clone; 00328 handler->data_free = (void (*)(void *))netsnmp_container_table_data_free; 00329 handler->flags |= MIB_HANDLER_AUTO_NEXT; 00330 00331 return handler; 00332 } 00333 00334 int 00335 netsnmp_container_table_register(netsnmp_handler_registration *reginfo, 00336 netsnmp_table_registration_info *tabreg, 00337 netsnmp_container *container, char key_type ) 00338 { 00339 netsnmp_mib_handler *handler; 00340 00341 if ((NULL == reginfo) || (NULL == reginfo->handler) || (NULL == tabreg)) { 00342 snmp_log(LOG_ERR, "bad param in netsnmp_container_table_register\n"); 00343 return SNMPERR_GENERR; 00344 } 00345 00346 if (NULL==container) 00347 container = netsnmp_container_find(reginfo->handlerName); 00348 00349 handler = netsnmp_container_table_handler_get(tabreg, container, key_type); 00350 netsnmp_inject_handler(reginfo, handler ); 00351 00352 return netsnmp_register_table(reginfo, tabreg); 00353 } 00354 00355 int 00356 netsnmp_container_table_unregister(netsnmp_handler_registration *reginfo) 00357 { 00358 container_table_data *tad; 00359 00360 if (!reginfo) 00361 return MIB_UNREGISTRATION_FAILED; 00362 tad = (container_table_data *) 00363 netsnmp_find_handler_data_by_name(reginfo, "table_container"); 00364 if (tad) { 00365 CONTAINER_FREE( tad->table ); 00366 tad->table = NULL; 00367 /* 00368 * Note: don't free the memory tad points at here - that is done 00369 * by netsnmp_container_table_data_free(). 00370 */ 00371 } 00372 return netsnmp_unregister_table( reginfo ); 00373 } 00374 00376 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_EXTRACT 00377 netsnmp_container* 00378 netsnmp_container_table_container_extract(netsnmp_request_info *request) 00379 { 00380 return (netsnmp_container *) 00381 netsnmp_request_get_list_data(request, TABLE_CONTAINER_CONTAINER); 00382 } 00383 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_EXTRACT */ 00384 00385 #ifndef NETSNMP_USE_INLINE 00386 00387 void * 00388 netsnmp_container_table_row_extract(netsnmp_request_info *request) 00389 { 00390 /* 00391 * NOTE: this function must match in table_container.c and table_container.h. 00392 * if you change one, change them both! 00393 */ 00394 return netsnmp_request_get_list_data(request, TABLE_CONTAINER_ROW); 00395 } 00397 void * 00398 netsnmp_container_table_extract_context(netsnmp_request_info *request) 00399 { 00400 /* 00401 * NOTE: this function must match in table_container.c and table_container.h. 00402 * if you change one, change them both! 00403 */ 00404 return netsnmp_request_get_list_data(request, TABLE_CONTAINER_ROW); 00405 } 00406 #endif /* inline */ 00407 00408 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_ROW_INSERT 00409 00410 void 00411 netsnmp_container_table_row_insert(netsnmp_request_info *request, 00412 netsnmp_index *row) 00413 { 00414 netsnmp_request_info *req; 00415 netsnmp_table_request_info *table_info = NULL; 00416 netsnmp_variable_list *this_index = NULL; 00417 netsnmp_variable_list *that_index = NULL; 00418 oid base_oid[] = {0, 0}; /* Make sure index OIDs are legal! */ 00419 oid this_oid[MAX_OID_LEN]; 00420 oid that_oid[MAX_OID_LEN]; 00421 size_t this_oid_len, that_oid_len; 00422 00423 if (!request) 00424 return; 00425 00426 /* 00427 * We'll add the new row information to any request 00428 * structure with the same index values as the request 00429 * passed in (which includes that one!). 00430 * 00431 * So construct an OID based on these index values. 00432 */ 00433 00434 table_info = netsnmp_extract_table_info(request); 00435 this_index = table_info->indexes; 00436 build_oid_noalloc(this_oid, MAX_OID_LEN, &this_oid_len, 00437 base_oid, 2, this_index); 00438 00439 /* 00440 * We need to look through the whole of the request list 00441 * (as received by the current handler), as there's no 00442 * guarantee that this routine will be called by the first 00443 * varbind that refers to this row. 00444 * In particular, a RowStatus controlled row creation 00445 * may easily occur later in the variable list. 00446 * 00447 * So first, we rewind to the head of the list.... 00448 */ 00449 for (req=request; req->prev; req=req->prev) 00450 ; 00451 00452 /* 00453 * ... and then start looking for matching indexes 00454 * (by constructing OIDs from these index values) 00455 */ 00456 for (; req; req=req->next) { 00457 if (req->processed) 00458 continue; 00459 00460 table_info = netsnmp_extract_table_info(req); 00461 that_index = table_info->indexes; 00462 build_oid_noalloc(that_oid, MAX_OID_LEN, &that_oid_len, 00463 base_oid, 2, that_index); 00464 00465 /* 00466 * This request has the same index values, 00467 * so add the newly-created row information. 00468 */ 00469 if (snmp_oid_compare(this_oid, this_oid_len, 00470 that_oid, that_oid_len) == 0) { 00471 netsnmp_request_add_list_data(req, 00472 netsnmp_create_data_list(TABLE_CONTAINER_ROW, row, NULL)); 00473 } 00474 } 00475 } 00476 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_ROW_INSERT */ 00477 00478 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_ROW_REMOVE 00479 00480 void 00481 netsnmp_container_table_row_remove(netsnmp_request_info *request, 00482 netsnmp_index *row) 00483 { 00484 netsnmp_request_info *req; 00485 netsnmp_table_request_info *table_info = NULL; 00486 netsnmp_variable_list *this_index = NULL; 00487 netsnmp_variable_list *that_index = NULL; 00488 oid base_oid[] = {0, 0}; /* Make sure index OIDs are legal! */ 00489 oid this_oid[MAX_OID_LEN]; 00490 oid that_oid[MAX_OID_LEN]; 00491 size_t this_oid_len, that_oid_len; 00492 00493 if (!request) 00494 return; 00495 00496 /* 00497 * We'll add the new row information to any request 00498 * structure with the same index values as the request 00499 * passed in (which includes that one!). 00500 * 00501 * So construct an OID based on these index values. 00502 */ 00503 00504 table_info = netsnmp_extract_table_info(request); 00505 this_index = table_info->indexes; 00506 build_oid_noalloc(this_oid, MAX_OID_LEN, &this_oid_len, 00507 base_oid, 2, this_index); 00508 00509 /* 00510 * We need to look through the whole of the request list 00511 * (as received by the current handler), as there's no 00512 * guarantee that this routine will be called by the first 00513 * varbind that refers to this row. 00514 * In particular, a RowStatus controlled row creation 00515 * may easily occur later in the variable list. 00516 * 00517 * So first, we rewind to the head of the list.... 00518 */ 00519 for (req=request; req->prev; req=req->prev) 00520 ; 00521 00522 /* 00523 * ... and then start looking for matching indexes 00524 * (by constructing OIDs from these index values) 00525 */ 00526 for (; req; req=req->next) { 00527 if (req->processed) 00528 continue; 00529 00530 table_info = netsnmp_extract_table_info(req); 00531 that_index = table_info->indexes; 00532 build_oid_noalloc(that_oid, MAX_OID_LEN, &that_oid_len, 00533 base_oid, 2, that_index); 00534 00535 /* 00536 * This request has the same index values, 00537 * so add the newly-created row information. 00538 */ 00539 if (snmp_oid_compare(this_oid, this_oid_len, 00540 that_oid, that_oid_len) == 0) { 00541 netsnmp_request_remove_list_data(req, TABLE_CONTAINER_ROW); 00542 } 00543 } 00544 } 00545 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER_ROW_REMOVE */ 00546 00548 /********************************************************************** 00549 ********************************************************************** 00550 * * 00551 * * 00552 * DATA LOOKUP functions * 00553 * * 00554 * * 00555 ********************************************************************** 00556 **********************************************************************/ 00557 NETSNMP_STATIC_INLINE void 00558 _set_key( container_table_data * tad, netsnmp_request_info *request, 00559 netsnmp_table_request_info *tblreq_info, 00560 void **key, netsnmp_index *index ) 00561 { 00562 if (TABLE_CONTAINER_KEY_NETSNMP_INDEX == tad->key_type) { 00563 index->oids = tblreq_info->index_oid; 00564 index->len = tblreq_info->index_oid_len; 00565 *key = index; 00566 } 00567 else if (TABLE_CONTAINER_KEY_VARBIND_INDEX == tad->key_type) { 00568 *key = tblreq_info->indexes; 00569 } 00570 #if 0 00571 else if (TABLE_CONTAINER_KEY_VARBIND_RAW == tad->key_type) { 00572 *key = request->requestvb; 00573 } 00574 #endif 00575 else 00576 *key = NULL; 00577 } 00578 00579 00580 NETSNMP_STATIC_INLINE void 00581 _data_lookup(netsnmp_handler_registration *reginfo, 00582 netsnmp_agent_request_info *agtreq_info, 00583 netsnmp_request_info *request, container_table_data * tad) 00584 { 00585 netsnmp_index *row = NULL; 00586 netsnmp_table_request_info *tblreq_info; 00587 netsnmp_variable_list *var; 00588 netsnmp_index index; 00589 void *key; 00590 00591 var = request->requestvb; 00592 00593 DEBUGIF("table_container") { 00594 DEBUGMSGTL(("table_container", " data_lookup oid:")); 00595 DEBUGMSGOID(("table_container", var->name, var->name_length)); 00596 DEBUGMSG(("table_container", "\n")); 00597 } 00598 00599 /* 00600 * Get pointer to the table information for this request. This 00601 * information was saved by table_helper_handler. 00602 */ 00603 tblreq_info = netsnmp_extract_table_info(request); 00605 netsnmp_assert((NULL != tblreq_info) && 00606 (tblreq_info->colnum <= tad->tblreg_info->max_column)); 00607 00608 if ((agtreq_info->mode == MODE_GETNEXT) || 00609 (agtreq_info->mode == MODE_GETBULK)) { 00610 /* 00611 * find the row. This will automatically move to the next 00612 * column, if necessary. 00613 */ 00614 _set_key( tad, request, tblreq_info, &key, &index ); 00615 row = (netsnmp_index*)_find_next_row(tad->table, tblreq_info, key); 00616 if (row) { 00617 /* 00618 * update indexes in tblreq_info (index & varbind), 00619 * then update request varbind oid 00620 */ 00621 if(TABLE_CONTAINER_KEY_NETSNMP_INDEX == tad->key_type) { 00622 tblreq_info->index_oid_len = row->len; 00623 memcpy(tblreq_info->index_oid, row->oids, 00624 row->len * sizeof(oid)); 00625 netsnmp_update_variable_list_from_index(tblreq_info); 00626 } 00627 else if (TABLE_CONTAINER_KEY_VARBIND_INDEX == tad->key_type) { 00630 netsnmp_update_indexes_from_variable_list(tblreq_info); 00631 } 00632 00633 if (TABLE_CONTAINER_KEY_VARBIND_RAW != tad->key_type) { 00634 netsnmp_table_build_oid_from_index(reginfo, request, 00635 tblreq_info); 00636 } 00637 } 00638 else { 00639 /* 00640 * no results found. Flag the request so lower handlers will 00641 * ignore it, but it is not an error - getnext will move 00642 * on to another handler to process this request. 00643 */ 00644 netsnmp_set_request_error(agtreq_info, request, SNMP_ENDOFMIBVIEW); 00645 DEBUGMSGTL(("table_container", "no row found\n")); 00646 } 00647 } 00648 else { 00649 00650 _set_key( tad, request, tblreq_info, &key, &index ); 00651 row = (netsnmp_index*)CONTAINER_FIND(tad->table, key); 00652 if (NULL == row) { 00653 /* 00654 * not results found. For a get, that is an error 00655 */ 00656 DEBUGMSGTL(("table_container", "no row found\n")); 00657 #ifndef NETSNMP_NO_WRITE_SUPPORT 00658 if((agtreq_info->mode != MODE_SET_RESERVE1) || /* get */ 00659 (reginfo->modes & HANDLER_CAN_NOT_CREATE)) { /* no create */ 00660 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 00661 netsnmp_set_request_error(agtreq_info, request, 00662 SNMP_NOSUCHINSTANCE); 00663 #ifndef NETSNMP_NO_WRITE_SUPPORT 00664 } 00665 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 00666 } 00667 } 00669 /* 00670 * save the data and table in the request. 00671 */ 00672 if (SNMP_ENDOFMIBVIEW != request->requestvb->type) { 00673 if (NULL != row) 00674 netsnmp_request_add_list_data(request, 00675 netsnmp_create_data_list 00676 (TABLE_CONTAINER_ROW, 00677 row, NULL)); 00678 netsnmp_request_add_list_data(request, 00679 netsnmp_create_data_list 00680 (TABLE_CONTAINER_CONTAINER, 00681 tad->table, NULL)); 00682 } 00683 } 00684 00685 /********************************************************************** 00686 ********************************************************************** 00687 * * 00688 * * 00689 * netsnmp_table_container_helper_handler() * 00690 * * 00691 * * 00692 ********************************************************************** 00693 **********************************************************************/ 00694 static int 00695 _container_table_handler(netsnmp_mib_handler *handler, 00696 netsnmp_handler_registration *reginfo, 00697 netsnmp_agent_request_info *agtreq_info, 00698 netsnmp_request_info *requests) 00699 { 00700 int rc = SNMP_ERR_NOERROR; 00701 int oldmode, need_processing = 0; 00702 container_table_data *tad; 00703 00705 netsnmp_assert((NULL != handler) && (NULL != handler->myvoid)); 00706 netsnmp_assert((NULL != reginfo) && (NULL != agtreq_info)); 00707 00708 DEBUGMSGTL(("table_container", "Mode %s, Got request:\n", 00709 se_find_label_in_slist("agent_mode",agtreq_info->mode))); 00710 00711 /* 00712 * First off, get our pointer from the handler. This 00713 * lets us get to the table registration information we 00714 * saved in get_table_container_handler(), as well as the 00715 * container where the actual table data is stored. 00716 */ 00717 tad = (container_table_data *)handler->myvoid; 00718 00719 /* 00720 * only do data lookup for first pass 00721 * 00722 * xxx-rks: this should really be handled up one level. we should 00723 * be able to say what modes we want to be called for during table 00724 * registration. 00725 */ 00726 oldmode = agtreq_info->mode; 00727 if(MODE_IS_GET(oldmode) 00728 #ifndef NETSNMP_NO_WRITE_SUPPORT 00729 || (MODE_SET_RESERVE1 == oldmode) 00730 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 00731 ) { 00732 netsnmp_request_info *curr_request; 00733 /* 00734 * Loop through each of the requests, and 00735 * try to find the appropriate row from the container. 00736 */ 00737 for (curr_request = requests; curr_request; curr_request = curr_request->next) { 00738 /* 00739 * skip anything that doesn't need processing. 00740 */ 00741 if (curr_request->processed != 0) { 00742 DEBUGMSGTL(("table_container", "already processed\n")); 00743 continue; 00744 } 00745 00746 /* 00747 * find data for this request 00748 */ 00749 _data_lookup(reginfo, agtreq_info, curr_request, tad); 00750 00751 if(curr_request->processed) 00752 continue; 00753 00754 ++need_processing; 00755 } 00756 } 00757 00758 /* 00759 * send GET instead of GETNEXT to sub-handlers 00760 * xxx-rks: again, this should be handled further up. 00761 */ 00762 if ((oldmode == MODE_GETNEXT) && (handler->next)) { 00763 /* 00764 * tell agent handlder not to auto call next handler 00765 */ 00766 handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE; 00767 00768 /* 00769 * if we found rows to process, pretend to be a get request 00770 * and call handler below us. 00771 */ 00772 if(need_processing > 0) { 00773 agtreq_info->mode = MODE_GET; 00774 rc = netsnmp_call_next_handler(handler, reginfo, agtreq_info, 00775 requests); 00776 if (rc != SNMP_ERR_NOERROR) { 00777 DEBUGMSGTL(("table_container", 00778 "next handler returned %d\n", rc)); 00779 } 00780 00781 agtreq_info->mode = oldmode; /* restore saved mode */ 00782 } 00783 } 00784 00785 return rc; 00786 } 00790 /* ================================== 00791 * 00792 * Container Table API: Row operations 00793 * 00794 * ================================== */ 00795 00796 static void * 00797 _find_next_row(netsnmp_container *c, 00798 netsnmp_table_request_info *tblreq, 00799 void * key) 00800 { 00801 void *row = NULL; 00802 00803 if (!c || !tblreq || !tblreq->reg_info ) { 00804 snmp_log(LOG_ERR,"_find_next_row param error\n"); 00805 return NULL; 00806 } 00807 00808 /* 00809 * table helper should have made sure we aren't below our minimum column 00810 */ 00811 netsnmp_assert(tblreq->colnum >= tblreq->reg_info->min_column); 00812 00813 /* 00814 * if no indexes then use first row. 00815 */ 00816 if(tblreq->number_indexes == 0) { 00817 row = CONTAINER_FIRST(c); 00818 } else { 00819 00820 if(NULL == key) { 00821 netsnmp_index index; 00822 index.oids = tblreq->index_oid; 00823 index.len = tblreq->index_oid_len; 00824 row = CONTAINER_NEXT(c, &index); 00825 } 00826 else 00827 row = CONTAINER_NEXT(c, key); 00828 00829 /* 00830 * we don't have a row, but we might be at the end of a 00831 * column, so try the next column. 00832 */ 00833 if (NULL == row) { 00834 /* 00835 * don't set tblreq next_col unless we know there is one, 00836 * so we don't mess up table handler sparse table processing. 00837 */ 00838 oid next_col = netsnmp_table_next_column(tblreq); 00839 if (0 != next_col) { 00840 tblreq->colnum = next_col; 00841 row = CONTAINER_FIRST(c); 00842 } 00843 } 00844 } 00845 00846 return row; 00847 } 00848 00858 netsnmp_index * 00859 netsnmp_table_index_find_next_row(netsnmp_container *c, 00860 netsnmp_table_request_info *tblreq) 00861 { 00862 return (netsnmp_index*)_find_next_row(c, tblreq, NULL ); 00863 } 00864 00865 /* ================================== 00866 * 00867 * Container Table API: Index operations 00868 * 00869 * ================================== */ 00870 00871 #else /* NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER */ 00872 netsnmp_feature_unused(table_container); 00873 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_CONTAINER */ 00874