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