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