00001 #include <net-snmp/net-snmp-config.h> 00002 00003 #include <net-snmp/net-snmp-includes.h> 00004 #include <net-snmp/agent/net-snmp-agent-includes.h> 00005 00006 #include <net-snmp/agent/table_data.h> 00007 00008 #if HAVE_STRING_H 00009 #include <string.h> 00010 #else 00011 #include <strings.h> 00012 #endif 00013 00014 #include <net-snmp/agent/table.h> 00015 #include <net-snmp/agent/read_only.h> 00016 00036 /* ================================== 00037 * 00038 * Table Data API: Table maintenance 00039 * 00040 * ================================== */ 00041 00042 /* 00043 * generates the index portion of an table oid from a varlist. 00044 */ 00045 void 00046 netsnmp_table_data_generate_index_oid(netsnmp_table_row *row) 00047 { 00048 build_oid(&row->index_oid, &row->index_oid_len, NULL, 0, row->indexes); 00049 } 00050 00052 netsnmp_table_data * 00053 netsnmp_create_table_data(const char *name) 00054 { 00055 netsnmp_table_data *table = SNMP_MALLOC_TYPEDEF(netsnmp_table_data); 00056 if (name && table) 00057 table->name = strdup(name); 00058 return table; 00059 } 00060 00062 netsnmp_table_row * 00063 netsnmp_create_table_data_row(void) 00064 { 00065 netsnmp_table_row *row = SNMP_MALLOC_TYPEDEF(netsnmp_table_row); 00066 return row; 00067 } 00068 00070 netsnmp_table_row * 00071 netsnmp_table_data_clone_row(netsnmp_table_row *row) 00072 { 00073 netsnmp_table_row *newrow = NULL; 00074 if (!row) 00075 return NULL; 00076 00077 memdup((u_char **) & newrow, (u_char *) row, 00078 sizeof(netsnmp_table_row)); 00079 if (!newrow) 00080 return NULL; 00081 00082 if (row->indexes) { 00083 newrow->indexes = snmp_clone_varbind(newrow->indexes); 00084 if (!newrow->indexes) { 00085 free(newrow); 00086 return NULL; 00087 } 00088 } 00089 00090 if (row->index_oid) { 00091 newrow->index_oid = 00092 snmp_duplicate_objid(row->index_oid, row->index_oid_len); 00093 if (!newrow->index_oid) { 00094 free(newrow); 00095 return NULL; 00096 } 00097 } 00098 00099 return newrow; 00100 } 00101 00104 void * 00105 netsnmp_table_data_delete_row(netsnmp_table_row *row) 00106 { 00107 void *data; 00108 00109 if (!row) 00110 return NULL; 00111 00112 /* 00113 * free the memory we can 00114 */ 00115 if (row->indexes) 00116 snmp_free_varbind(row->indexes); 00117 SNMP_FREE(row->index_oid); 00118 data = row->data; 00119 free(row); 00120 00121 /* 00122 * return the void * pointer 00123 */ 00124 return data; 00125 } 00126 00133 int 00134 netsnmp_table_data_add_row(netsnmp_table_data *table, 00135 netsnmp_table_row *row) 00136 { 00137 int rc, dup = 0; 00138 netsnmp_table_row *nextrow = NULL, *prevrow; 00139 00140 if (!row || !table) 00141 return SNMPERR_GENERR; 00142 00143 if (row->indexes) 00144 netsnmp_table_data_generate_index_oid(row); 00145 00146 /* 00147 * we don't store the index info as it 00148 * takes up memory. 00149 */ 00150 if (!table->store_indexes) { 00151 snmp_free_varbind(row->indexes); 00152 row->indexes = NULL; 00153 } 00154 00155 if (!row->index_oid) { 00156 snmp_log(LOG_ERR, 00157 "illegal data attempted to be added to table %s (no index)\n", 00158 table->name); 00159 return SNMPERR_GENERR; 00160 } 00161 00162 /* 00163 * check for simple append 00164 */ 00165 if ((prevrow = table->last_row) != NULL) { 00166 rc = snmp_oid_compare(prevrow->index_oid, prevrow->index_oid_len, 00167 row->index_oid, row->index_oid_len); 00168 if (0 == rc) 00169 dup = 1; 00170 } 00171 else 00172 rc = 1; 00173 00174 /* 00175 * if no last row, or newrow < last row, search the table and 00176 * insert it into the table in the proper oid-lexographical order 00177 */ 00178 if (rc > 0) { 00179 for (nextrow = table->first_row, prevrow = NULL; 00180 nextrow != NULL; prevrow = nextrow, nextrow = nextrow->next) { 00181 if (NULL == nextrow->index_oid) { 00182 DEBUGMSGT(("table_data_add_data", "row doesn't have index!\n")); 00184 continue; 00185 } 00186 rc = snmp_oid_compare(nextrow->index_oid, nextrow->index_oid_len, 00187 row->index_oid, row->index_oid_len); 00188 if(rc > 0) 00189 break; 00190 if (0 == rc) { 00191 dup = 1; 00192 break; 00193 } 00194 } 00195 } 00196 00197 if (dup) { 00198 /* 00199 * exact match. Duplicate entries illegal 00200 */ 00201 snmp_log(LOG_WARNING, 00202 "duplicate table data attempted to be entered. row exists\n"); 00203 return SNMPERR_GENERR; 00204 } 00205 00206 /* 00207 * ok, we have the location of where it should go 00208 */ 00209 /* 00210 * (after prevrow, and before nextrow) 00211 */ 00212 row->next = nextrow; 00213 row->prev = prevrow; 00214 00215 if (row->next) 00216 row->next->prev = row; 00217 00218 if (row->prev) 00219 row->prev->next = row; 00220 00221 if (NULL == row->prev) /* it's the (new) first row */ 00222 table->first_row = row; 00223 if (NULL == row->next) /* it's the last row */ 00224 table->last_row = row; 00225 00226 DEBUGMSGTL(("table_data_add_data", "added something...\n")); 00227 00228 return SNMPERR_SUCCESS; 00229 } 00230 00232 void 00233 netsnmp_table_data_replace_row(netsnmp_table_data *table, 00234 netsnmp_table_row *origrow, 00235 netsnmp_table_row *newrow) 00236 { 00237 netsnmp_table_data_remove_row(table, origrow); 00238 netsnmp_table_data_add_row(table, newrow); 00239 } 00240 00247 netsnmp_table_row * 00248 netsnmp_table_data_remove_row(netsnmp_table_data *table, 00249 netsnmp_table_row *row) 00250 { 00251 if (!row || !table) 00252 return NULL; 00253 00254 if (row->prev) 00255 row->prev->next = row->next; 00256 else 00257 table->first_row = row->next; 00258 00259 if (row->next) 00260 row->next->prev = row->prev; 00261 else 00262 table->last_row = row->prev; 00263 00264 return row; 00265 } 00266 00273 void * 00274 netsnmp_table_data_remove_and_delete_row(netsnmp_table_data *table, 00275 netsnmp_table_row *row) 00276 { 00277 if (!row || !table) 00278 return NULL; 00279 00280 /* 00281 * remove it from the list 00282 */ 00283 netsnmp_table_data_remove_row(table, row); 00284 return netsnmp_table_data_delete_row(row); 00285 } 00286 00287 /* ===================================== 00288 * Generic API - mostly renamed wrappers 00289 * ===================================== */ 00290 00291 netsnmp_table_data * 00292 netsnmp_table_data_create_table(const char *name, long flags) 00293 { 00294 return netsnmp_create_table_data( name ); 00295 } 00296 00297 void 00298 netsnmp_table_data_delete_table( netsnmp_table_data *table ) 00299 { 00300 netsnmp_table_row *row, *nextrow; 00301 00302 if (!table) 00303 return; 00304 00305 for (row = table->first_row; row; row=nextrow) { 00306 nextrow = row->next; 00307 row->next = NULL; 00308 netsnmp_table_data_delete_row(row); 00309 /* Can't delete table-specific entry memory */ 00310 } 00311 table->first_row = NULL; 00312 00313 if (table->name) { 00314 SNMP_FREE(table->name); 00315 table->name = NULL; 00316 } 00317 SNMP_FREE(table); 00318 return; 00319 } 00320 00321 netsnmp_table_row * 00322 netsnmp_table_data_create_row( void* entry ) 00323 { 00324 netsnmp_table_row *row = SNMP_MALLOC_TYPEDEF(netsnmp_table_row); 00325 if (row) 00326 row->data = entry; 00327 return row; 00328 } 00329 00330 /* netsnmp_table_data_clone_row() defined above */ 00331 00332 int 00333 netsnmp_table_data_copy_row( netsnmp_table_row *old_row, 00334 netsnmp_table_row *new_row ) 00335 { 00336 if (!old_row || !new_row) 00337 return -1; 00338 00339 memcpy(new_row, old_row, sizeof(netsnmp_table_row)); 00340 00341 if (old_row->indexes) 00342 new_row->indexes = snmp_clone_varbind(old_row->indexes); 00343 if (old_row->index_oid) 00344 new_row->index_oid = 00345 snmp_duplicate_objid(old_row->index_oid, old_row->index_oid_len); 00346 /* XXX - Doesn't copy table-specific row structure */ 00347 return 0; 00348 } 00349 00350 /* 00351 * netsnmp_table_data_delete_row() 00352 * netsnmp_table_data_add_row() 00353 * netsnmp_table_data_replace_row() 00354 * netsnmp_table_data_remove_row() 00355 * all defined above 00356 */ 00357 00358 void * 00359 netsnmp_table_data_remove_delete_row(netsnmp_table_data *table, 00360 netsnmp_table_row *row) 00361 { 00362 return netsnmp_table_data_remove_and_delete_row(table, row); 00363 } 00364 00365 00366 /* ================================== 00367 * 00368 * Table Data API: MIB maintenance 00369 * 00370 * ================================== */ 00371 00373 netsnmp_mib_handler * 00374 netsnmp_get_table_data_handler(netsnmp_table_data *table) 00375 { 00376 netsnmp_mib_handler *ret = NULL; 00377 00378 if (!table) { 00379 snmp_log(LOG_INFO, 00380 "netsnmp_get_table_data_handler(NULL) called\n"); 00381 return NULL; 00382 } 00383 00384 ret = 00385 netsnmp_create_handler(TABLE_DATA_NAME, 00386 netsnmp_table_data_helper_handler); 00387 if (ret) { 00388 ret->flags |= MIB_HANDLER_AUTO_NEXT; 00389 ret->myvoid = (void *) table; 00390 } 00391 return ret; 00392 } 00393 00396 int 00397 netsnmp_register_table_data(netsnmp_handler_registration *reginfo, 00398 netsnmp_table_data *table, 00399 netsnmp_table_registration_info *table_info) 00400 { 00401 netsnmp_inject_handler(reginfo, netsnmp_get_table_data_handler(table)); 00402 return netsnmp_register_table(reginfo, table_info); 00403 } 00404 00407 int 00408 netsnmp_register_read_only_table_data(netsnmp_handler_registration *reginfo, 00409 netsnmp_table_data *table, 00410 netsnmp_table_registration_info *table_info) 00411 { 00412 netsnmp_inject_handler(reginfo, netsnmp_get_read_only_handler()); 00413 return netsnmp_register_table_data(reginfo, table, table_info); 00414 } 00415 00416 int 00417 netsnmp_unregister_table_data(netsnmp_handler_registration *reginfo) 00418 { 00419 /* free table; */ 00420 return netsnmp_unregister_table(reginfo); 00421 } 00422 00423 /* 00424 * The helper handler that takes care of passing a specific row of 00425 * data down to the lower handler(s). It sets request->processed if 00426 * the request should not be handled. 00427 */ 00428 int 00429 netsnmp_table_data_helper_handler(netsnmp_mib_handler *handler, 00430 netsnmp_handler_registration *reginfo, 00431 netsnmp_agent_request_info *reqinfo, 00432 netsnmp_request_info *requests) 00433 { 00434 netsnmp_table_data *table = (netsnmp_table_data *) handler->myvoid; 00435 netsnmp_request_info *request; 00436 int valid_request = 0; 00437 netsnmp_table_row *row; 00438 netsnmp_table_request_info *table_info; 00439 netsnmp_table_registration_info *table_reg_info = 00440 netsnmp_find_table_registration_info(reginfo); 00441 int result, regresult; 00442 int oldmode; 00443 00444 for (request = requests; request; request = request->next) { 00445 if (request->processed) 00446 continue; 00447 00448 table_info = netsnmp_extract_table_info(request); 00449 if (!table_info) 00450 continue; /* ack */ 00451 switch (reqinfo->mode) { 00452 case MODE_GET: 00453 case MODE_GETNEXT: 00454 case MODE_SET_RESERVE1: 00455 netsnmp_request_add_list_data(request, 00456 netsnmp_create_data_list( 00457 TABLE_DATA_TABLE, table, NULL)); 00458 } 00459 00460 /* 00461 * find the row in question 00462 */ 00463 switch (reqinfo->mode) { 00464 case MODE_GETNEXT: 00465 case MODE_GETBULK: /* XXXWWW */ 00466 if (request->requestvb->type != ASN_NULL) 00467 continue; 00468 /* 00469 * loop through data till we find the next row 00470 */ 00471 result = snmp_oid_compare(request->requestvb->name, 00472 request->requestvb->name_length, 00473 reginfo->rootoid, 00474 reginfo->rootoid_len); 00475 regresult = snmp_oid_compare(request->requestvb->name, 00476 SNMP_MIN(request->requestvb-> 00477 name_length, 00478 reginfo->rootoid_len), 00479 reginfo->rootoid, 00480 reginfo->rootoid_len); 00481 if (regresult == 0 00482 && request->requestvb->name_length < reginfo->rootoid_len) 00483 regresult = -1; 00484 00485 if (result < 0 || 0 == result) { 00486 /* 00487 * before us entirely, return the first 00488 */ 00489 row = table->first_row; 00490 table_info->colnum = table_reg_info->min_column; 00491 } else if (regresult == 0 && request->requestvb->name_length == 00492 reginfo->rootoid_len + 1 && 00493 /* entry node must be 1, but any column is ok */ 00494 request->requestvb->name[reginfo->rootoid_len] == 1) { 00495 /* 00496 * exactly to the entry 00497 */ 00498 row = table->first_row; 00499 table_info->colnum = table_reg_info->min_column; 00500 } else if (regresult == 0 && request->requestvb->name_length == 00501 reginfo->rootoid_len + 2 && 00502 /* entry node must be 1, but any column is ok */ 00503 request->requestvb->name[reginfo->rootoid_len] == 1) { 00504 /* 00505 * exactly to the column 00506 */ 00507 row = table->first_row; 00508 } else { 00509 /* 00510 * loop through all rows looking for the first one 00511 * that is equal to the request or greater than it 00512 */ 00513 for (row = table->first_row; row; row = row->next) { 00514 /* 00515 * compare the index of the request to the row 00516 */ 00517 result = 00518 snmp_oid_compare(row->index_oid, 00519 row->index_oid_len, 00520 request->requestvb->name + 2 + 00521 reginfo->rootoid_len, 00522 request->requestvb->name_length - 00523 2 - reginfo->rootoid_len); 00524 if (result == 0) { 00525 /* 00526 * equal match, return the next row 00527 */ 00528 if (row) { 00529 row = row->next; 00530 } 00531 break; 00532 } else if (result > 0) { 00533 /* 00534 * the current row is greater than the 00535 * request, use it 00536 */ 00537 break; 00538 } 00539 } 00540 } 00541 if (!row) { 00542 table_info->colnum++; 00543 if (table_info->colnum <= table_reg_info->max_column) { 00544 row = table->first_row; 00545 } 00546 } 00547 if (row) { 00548 valid_request = 1; 00549 netsnmp_request_add_list_data(request, 00550 netsnmp_create_data_list 00551 (TABLE_DATA_ROW, row, 00552 NULL)); 00553 /* 00554 * Set the name appropriately, so we can pass this 00555 * request on as a simple GET request 00556 */ 00557 netsnmp_table_data_build_result(reginfo, reqinfo, request, 00558 row, 00559 table_info->colnum, 00560 ASN_NULL, NULL, 0); 00561 } else { /* no decent result found. Give up. It's beyond us. */ 00562 request->processed = 1; 00563 } 00564 break; 00565 00566 case MODE_GET: 00567 if (request->requestvb->type != ASN_NULL) 00568 continue; 00569 /* 00570 * find the row in question 00571 */ 00572 if (request->requestvb->name_length < (reginfo->rootoid_len + 3)) { /* table.entry.column... */ 00573 /* 00574 * request too short 00575 */ 00576 netsnmp_set_request_error(reqinfo, request, 00577 SNMP_NOSUCHINSTANCE); 00578 break; 00579 } else if (NULL == 00580 (row = 00581 netsnmp_table_data_get_from_oid(table, 00582 request-> 00583 requestvb->name + 00584 reginfo-> 00585 rootoid_len + 2, 00586 request-> 00587 requestvb-> 00588 name_length - 00589 reginfo-> 00590 rootoid_len - 00591 2))) { 00592 /* 00593 * no such row 00594 */ 00595 netsnmp_set_request_error(reqinfo, request, 00596 SNMP_NOSUCHINSTANCE); 00597 break; 00598 } else { 00599 valid_request = 1; 00600 netsnmp_request_add_list_data(request, 00601 netsnmp_create_data_list 00602 (TABLE_DATA_ROW, row, 00603 NULL)); 00604 } 00605 break; 00606 00607 case MODE_SET_RESERVE1: 00608 valid_request = 1; 00609 if (NULL != 00610 (row = 00611 netsnmp_table_data_get_from_oid(table, 00612 request->requestvb->name + 00613 reginfo->rootoid_len + 2, 00614 request->requestvb-> 00615 name_length - 00616 reginfo->rootoid_len - 00617 2))) { 00618 netsnmp_request_add_list_data(request, 00619 netsnmp_create_data_list 00620 (TABLE_DATA_ROW, row, 00621 NULL)); 00622 } 00623 break; 00624 00625 case MODE_SET_RESERVE2: 00626 case MODE_SET_ACTION: 00627 case MODE_SET_COMMIT: 00628 case MODE_SET_FREE: 00629 case MODE_SET_UNDO: 00630 valid_request = 1; 00631 00632 } 00633 } 00634 00635 if (valid_request && 00636 (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK)) { 00637 /* 00638 * If this is a GetNext or GetBulk request, then we've identified 00639 * the row that ought to include the appropriate next instance. 00640 * Convert the request into a Get request, so that the lower-level 00641 * handlers don't need to worry about skipping on, and call these 00642 * handlers ourselves (so we can undo this again afterwards). 00643 */ 00644 oldmode = reqinfo->mode; 00645 reqinfo->mode = MODE_GET; 00646 result = netsnmp_call_next_handler(handler, reginfo, reqinfo, 00647 requests); 00648 reqinfo->mode = oldmode; 00649 handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE; 00650 return result; 00651 } 00652 else 00653 /* next handler called automatically - 'AUTO_NEXT' */ 00654 return SNMP_ERR_NOERROR; 00655 } 00656 00658 netsnmp_table_data * 00659 netsnmp_extract_table(netsnmp_request_info *request) 00660 { 00661 return (netsnmp_table_data *) 00662 netsnmp_request_get_list_data(request, TABLE_DATA_TABLE); 00663 } 00664 00666 netsnmp_table_row * 00667 netsnmp_extract_table_row(netsnmp_request_info *request) 00668 { 00669 return (netsnmp_table_row *) netsnmp_request_get_list_data(request, 00670 TABLE_DATA_ROW); 00671 } 00672 00675 void * 00676 netsnmp_extract_table_row_data(netsnmp_request_info *request) 00677 { 00678 netsnmp_table_row *row; 00679 row = (netsnmp_table_row *) netsnmp_extract_table_row(request); 00680 if (row) 00681 return row->data; 00682 else 00683 return NULL; 00684 } 00685 00687 void 00688 netsnmp_insert_table_row(netsnmp_request_info *request, 00689 netsnmp_table_row *row) 00690 { 00691 netsnmp_request_info *req; 00692 netsnmp_table_request_info *table_info = NULL; 00693 netsnmp_variable_list *this_index = NULL; 00694 netsnmp_variable_list *that_index = NULL; 00695 oid base_oid[] = {0, 0}; /* Make sure index OIDs are legal! */ 00696 oid this_oid[MAX_OID_LEN]; 00697 oid that_oid[MAX_OID_LEN]; 00698 size_t this_oid_len, that_oid_len; 00699 00700 if (!request) 00701 return; 00702 00703 /* 00704 * We'll add the new row information to any request 00705 * structure with the same index values as the request 00706 * passed in (which includes that one!). 00707 * 00708 * So construct an OID based on these index values. 00709 */ 00710 00711 table_info = netsnmp_extract_table_info(request); 00712 this_index = table_info->indexes; 00713 build_oid_noalloc(this_oid, MAX_OID_LEN, &this_oid_len, 00714 base_oid, 2, this_index); 00715 00716 /* 00717 * We need to look through the whole of the request list 00718 * (as received by the current handler), as there's no 00719 * guarantee that this routine will be called by the first 00720 * varbind that refers to this row. 00721 * In particular, a RowStatus controlled row creation 00722 * may easily occur later in the variable list. 00723 * 00724 * So first, we rewind to the head of the list.... 00725 */ 00726 for (req=request; req->prev; req=req->prev) 00727 ; 00728 00729 /* 00730 * ... and then start looking for matching indexes 00731 * (by constructing OIDs from these index values) 00732 */ 00733 for (; req; req=req->next) { 00734 table_info = netsnmp_extract_table_info(req); 00735 that_index = table_info->indexes; 00736 build_oid_noalloc(that_oid, MAX_OID_LEN, &that_oid_len, 00737 base_oid, 2, that_index); 00738 00739 /* 00740 * This request has the same index values, 00741 * so add the newly-created row information. 00742 */ 00743 if (snmp_oid_compare(this_oid, this_oid_len, 00744 that_oid, that_oid_len) == 0) { 00745 netsnmp_request_add_list_data(req, 00746 netsnmp_create_data_list(TABLE_DATA_ROW, row, NULL)); 00747 } 00748 } 00749 } 00750 00751 /* builds a result given a row, a varbind to set and the data */ 00752 int 00753 netsnmp_table_data_build_result(netsnmp_handler_registration *reginfo, 00754 netsnmp_agent_request_info *reqinfo, 00755 netsnmp_request_info *request, 00756 netsnmp_table_row *row, 00757 int column, 00758 u_char type, 00759 u_char * result_data, 00760 size_t result_data_len) 00761 { 00762 oid build_space[MAX_OID_LEN]; 00763 00764 if (!reginfo || !reqinfo || !request) 00765 return SNMPERR_GENERR; 00766 00767 if (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK) { 00768 /* 00769 * only need to do this for getnext type cases where oid is changing 00770 */ 00771 memcpy(build_space, reginfo->rootoid, /* registered oid */ 00772 reginfo->rootoid_len * sizeof(oid)); 00773 build_space[reginfo->rootoid_len] = 1; /* entry */ 00774 build_space[reginfo->rootoid_len + 1] = column; /* column */ 00775 memcpy(build_space + reginfo->rootoid_len + 2, /* index data */ 00776 row->index_oid, row->index_oid_len * sizeof(oid)); 00777 snmp_set_var_objid(request->requestvb, build_space, 00778 reginfo->rootoid_len + 2 + row->index_oid_len); 00779 } 00780 snmp_set_var_typed_value(request->requestvb, type, 00781 result_data, result_data_len); 00782 return SNMPERR_SUCCESS; /* WWWXXX: check for bounds */ 00783 } 00784 00785 00786 /* ================================== 00787 * 00788 * Table Data API: Row operations 00789 * (table-independent rows) 00790 * 00791 * ================================== */ 00792 00794 netsnmp_table_row * 00795 netsnmp_table_data_get_first_row(netsnmp_table_data *table) 00796 { 00797 if (!table) 00798 return NULL; 00799 return table->first_row; 00800 } 00801 00803 netsnmp_table_row * 00804 netsnmp_table_data_get_next_row(netsnmp_table_data *table, 00805 netsnmp_table_row *row) 00806 { 00807 if (!row) 00808 return NULL; 00809 return row->next; 00810 } 00811 00813 netsnmp_table_row * 00814 netsnmp_table_data_get(netsnmp_table_data *table, 00815 netsnmp_variable_list * indexes) 00816 { 00817 oid searchfor[MAX_OID_LEN]; 00818 size_t searchfor_len = MAX_OID_LEN; 00819 00820 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00821 indexes); 00822 return netsnmp_table_data_get_from_oid(table, searchfor, 00823 searchfor_len); 00824 } 00825 00827 netsnmp_table_row * 00828 netsnmp_table_data_get_from_oid(netsnmp_table_data *table, 00829 oid * searchfor, size_t searchfor_len) 00830 { 00831 netsnmp_table_row *row; 00832 if (!table) 00833 return NULL; 00834 00835 for (row = table->first_row; row != NULL; row = row->next) { 00836 if (row->index_oid && 00837 snmp_oid_compare(searchfor, searchfor_len, 00838 row->index_oid, row->index_oid_len) == 0) 00839 return row; 00840 } 00841 return NULL; 00842 } 00843 00844 int 00845 netsnmp_table_data_num_rows(netsnmp_table_data *table) 00846 { 00847 int i=0; 00848 netsnmp_table_row *row; 00849 if (!table) 00850 return 0; 00851 for (row = table->first_row; row; row = row->next) { 00852 i++; 00853 } 00854 return i; 00855 } 00856 00857 /* ===================================== 00858 * Generic API - mostly renamed wrappers 00859 * ===================================== */ 00860 00861 netsnmp_table_row * 00862 netsnmp_table_data_row_first(netsnmp_table_data *table) 00863 { 00864 return netsnmp_table_data_get_first_row(table); 00865 } 00866 00867 netsnmp_table_row * 00868 netsnmp_table_data_row_get( netsnmp_table_data *table, 00869 netsnmp_table_row *row) 00870 { 00871 if (!table || !row) 00872 return NULL; 00873 return netsnmp_table_data_get_from_oid(table, row->index_oid, 00874 row->index_oid_len); 00875 } 00876 00877 netsnmp_table_row * 00878 netsnmp_table_data_row_next( netsnmp_table_data *table, 00879 netsnmp_table_row *row) 00880 { 00881 return netsnmp_table_data_get_next_row(table, row); 00882 } 00883 00884 netsnmp_table_row * 00885 netsnmp_table_data_row_get_byoid( netsnmp_table_data *table, 00886 oid *instance, size_t len) 00887 { 00888 return netsnmp_table_data_get_from_oid(table, instance, len); 00889 } 00890 00891 netsnmp_table_row * 00892 netsnmp_table_data_row_next_byoid(netsnmp_table_data *table, 00893 oid *instance, size_t len) 00894 { 00895 netsnmp_table_row *row; 00896 00897 if (!table || !instance) 00898 return NULL; 00899 00900 for (row = table->first_row; row; row = row->next) { 00901 if (snmp_oid_compare(row->index_oid, 00902 row->index_oid_len, 00903 instance, len) > 0) 00904 return row; 00905 } 00906 return NULL; 00907 } 00908 00909 netsnmp_table_row * 00910 netsnmp_table_data_row_get_byidx( netsnmp_table_data *table, 00911 netsnmp_variable_list *indexes) 00912 { 00913 return netsnmp_table_data_get(table, indexes); 00914 } 00915 00916 netsnmp_table_row * 00917 netsnmp_table_data_row_next_byidx(netsnmp_table_data *table, 00918 netsnmp_variable_list *indexes) 00919 { 00920 oid instance[MAX_OID_LEN]; 00921 size_t len = MAX_OID_LEN; 00922 00923 if (!table || !indexes) 00924 return NULL; 00925 00926 build_oid_noalloc(instance, MAX_OID_LEN, &len, NULL, 0, indexes); 00927 return netsnmp_table_data_row_next_byoid(table, instance, len); 00928 } 00929 00930 int 00931 netsnmp_table_data_row_count(netsnmp_table_data *table) 00932 { 00933 return netsnmp_table_data_num_rows(table); 00934 } 00935 00936 00937 /* ================================== 00938 * 00939 * Table Data API: Row operations 00940 * (table-specific rows) 00941 * 00942 * ================================== */ 00943 00944 void * 00945 netsnmp_table_data_entry_first(netsnmp_table_data *table) 00946 { 00947 netsnmp_table_row *row = 00948 netsnmp_table_data_get_first_row(table); 00949 return (row ? row->data : NULL ); 00950 } 00951 00952 void * 00953 netsnmp_table_data_entry_get( netsnmp_table_data *table, 00954 netsnmp_table_row *row) 00955 { 00956 return (row ? row->data : NULL ); 00957 } 00958 00959 void * 00960 netsnmp_table_data_entry_next( netsnmp_table_data *table, 00961 netsnmp_table_row *row) 00962 { 00963 row = 00964 netsnmp_table_data_row_next(table, row); 00965 return (row ? row->data : NULL ); 00966 } 00967 00968 void * 00969 netsnmp_table_data_entry_get_byidx( netsnmp_table_data *table, 00970 netsnmp_variable_list *indexes) 00971 { 00972 netsnmp_table_row *row = 00973 netsnmp_table_data_row_get_byidx(table, indexes); 00974 return (row ? row->data : NULL ); 00975 } 00976 00977 void * 00978 netsnmp_table_data_entry_next_byidx(netsnmp_table_data *table, 00979 netsnmp_variable_list *indexes) 00980 { 00981 netsnmp_table_row *row = 00982 netsnmp_table_data_row_next_byidx(table, indexes); 00983 return (row ? row->data : NULL ); 00984 } 00985 00986 void * 00987 netsnmp_table_data_entry_get_byoid( netsnmp_table_data *table, 00988 oid *instance, size_t len) 00989 { 00990 netsnmp_table_row *row = 00991 netsnmp_table_data_row_get_byoid(table, instance, len); 00992 return (row ? row->data : NULL ); 00993 } 00994 00995 void * 00996 netsnmp_table_data_entry_next_byoid(netsnmp_table_data *table, 00997 oid *instance, size_t len) 00998 { 00999 netsnmp_table_row *row = 01000 netsnmp_table_data_row_next_byoid(table, instance, len); 01001 return (row ? row->data : NULL ); 01002 } 01003 01004 /* ===================================== 01005 * Generic API - mostly renamed wrappers 01006 * ===================================== */ 01007 01008 /* ================================== 01009 * 01010 * Table Data API: Index operations 01011 * 01012 * ================================== */ 01013
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.