net-snmp 5.7
|
00001 #include <net-snmp/net-snmp-config.h> 00002 #include <net-snmp/net-snmp-features.h> 00003 00004 #include <net-snmp/net-snmp-includes.h> 00005 #include <net-snmp/agent/net-snmp-agent-includes.h> 00006 00007 #include <net-snmp/agent/table_tdata.h> 00008 00009 #if HAVE_STRING_H 00010 #include <string.h> 00011 #else 00012 #include <strings.h> 00013 #endif 00014 00015 #include <net-snmp/agent/table.h> 00016 #include <net-snmp/agent/table_container.h> 00017 #include <net-snmp/agent/read_only.h> 00018 00019 #if HAVE_DMALLOC_H 00020 #include <dmalloc.h> 00021 #endif 00022 00023 netsnmp_feature_provide(table_tdata) 00024 netsnmp_feature_child_of(table_tdata_all, mib_helpers) 00025 netsnmp_feature_child_of(table_tdata, table_tdata_all) 00026 netsnmp_feature_child_of(table_tdata_delete_table, table_tdata_all) 00027 netsnmp_feature_child_of(table_tdata_extract_table, table_tdata_all) 00028 netsnmp_feature_child_of(table_tdata_remove_row, table_tdata_all) 00029 netsnmp_feature_child_of(table_tdata_insert_row, table_tdata_all) 00030 00031 #ifdef NETSNMP_FEATURE_REQUIRE_TABLE_TDATA 00032 netsnmp_feature_require(table_container_row_insert) 00033 #ifdef NETSNMP_FEATURE_REQUIRE_TABLE_TDATA_REMOVE_ROW 00034 netsnmp_feature_require(table_container_row_remove) 00035 #endif /* NETSNMP_FEATURE_REQUIRE_TABLE_TDATA_REMOVE_ROW */ 00036 #endif /* NETSNMP_FEATURE_REQUIRE_TABLE_TDATA */ 00037 00038 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_TDATA 00039 00056 /* ================================== 00057 * 00058 * TData API: Table maintenance 00059 * 00060 * ================================== */ 00061 00062 /* 00063 * generates the index portion of an table oid from a varlist. 00064 */ 00065 void 00066 _netsnmp_tdata_generate_index_oid(netsnmp_tdata_row *row) 00067 { 00068 build_oid(&row->oid_index.oids, &row->oid_index.len, NULL, 0, row->indexes); 00069 } 00070 00072 netsnmp_tdata * 00073 netsnmp_tdata_create_table(const char *name, long flags) 00074 { 00075 netsnmp_tdata *table = SNMP_MALLOC_TYPEDEF(netsnmp_tdata); 00076 if ( !table ) 00077 return NULL; 00078 00079 table->flags = flags; 00080 if (name) 00081 table->name = strdup(name); 00082 00083 if (!(table->flags & TDATA_FLAG_NO_CONTAINER)) { 00084 table->container = netsnmp_container_find( name ); 00085 if (!table->container) 00086 table->container = netsnmp_container_find( "table_container" ); 00087 if (table->container) 00088 table->container->container_name = strdup(name); 00089 } 00090 return table; 00091 } 00092 00093 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_TDATA_DELETE_TABLE 00094 00095 void 00096 netsnmp_tdata_delete_table(netsnmp_tdata *table) 00097 { 00098 if (!table) 00099 return; 00100 00101 if (table->name) 00102 free(table->name); 00103 if (table->container) 00104 CONTAINER_FREE(table->container); 00105 00106 SNMP_FREE(table); 00107 return; 00108 } 00109 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_TDATA_DELETE_TABLE */ 00110 00112 netsnmp_tdata_row * 00113 netsnmp_tdata_create_row(void) 00114 { 00115 netsnmp_tdata_row *row = SNMP_MALLOC_TYPEDEF(netsnmp_tdata_row); 00116 return row; 00117 } 00118 00120 netsnmp_feature_child_of(tdata_clone_row, table_tdata_all) 00121 #ifndef NETSNMP_FEATURE_REMOVE_TDATA_CLONE_ROW 00122 netsnmp_tdata_row * 00123 netsnmp_tdata_clone_row(netsnmp_tdata_row *row) 00124 { 00125 netsnmp_tdata_row *newrow = NULL; 00126 if (!row) 00127 return NULL; 00128 00129 memdup((u_char **) & newrow, (u_char *) row, 00130 sizeof(netsnmp_tdata_row)); 00131 if (!newrow) 00132 return NULL; 00133 00134 if (row->indexes) { 00135 newrow->indexes = snmp_clone_varbind(newrow->indexes); 00136 if (!newrow->indexes) { 00137 SNMP_FREE(newrow); 00138 return NULL; 00139 } 00140 } 00141 00142 if (row->oid_index.oids) { 00143 newrow->oid_index.oids = 00144 snmp_duplicate_objid(row->oid_index.oids, row->oid_index.len); 00145 if (!newrow->oid_index.oids) { 00146 if (newrow->indexes) 00147 snmp_free_varbind(newrow->indexes); 00148 SNMP_FREE(newrow); 00149 return NULL; 00150 } 00151 } 00152 00153 return newrow; 00154 } 00155 #endif /* NETSNMP_FEATURE_REMOVE_TDATA_CLONE_ROW */ 00156 00159 netsnmp_feature_child_of(tdata_copy_row, table_tdata_all) 00160 #ifndef NETSNMP_FEATURE_REMOVE_TDATA_COPY_ROW 00161 int 00162 netsnmp_tdata_copy_row(netsnmp_tdata_row *dst_row, netsnmp_tdata_row *src_row) 00163 { 00164 if ( !src_row || !dst_row ) 00165 return -1; 00166 00167 memcpy((u_char *) dst_row, (u_char *) src_row, 00168 sizeof(netsnmp_tdata_row)); 00169 if (src_row->indexes) { 00170 dst_row->indexes = snmp_clone_varbind(src_row->indexes); 00171 if (!dst_row->indexes) 00172 return -1; 00173 } 00174 00175 if (src_row->oid_index.oids) { 00176 dst_row->oid_index.oids = snmp_duplicate_objid(src_row->oid_index.oids, 00177 src_row->oid_index.len); 00178 if (!dst_row->oid_index.oids) 00179 return -1; 00180 } 00181 00182 return 0; 00183 } 00184 #endif /* NETSNMP_FEATURE_REMOVE_TDATA_COPY_ROW */ 00185 00189 void * 00190 netsnmp_tdata_delete_row(netsnmp_tdata_row *row) 00191 { 00192 void *data; 00193 00194 if (!row) 00195 return NULL; 00196 00197 /* 00198 * free the memory we can 00199 */ 00200 if (row->indexes) 00201 snmp_free_varbind(row->indexes); 00202 SNMP_FREE(row->oid_index.oids); 00203 data = row->data; 00204 free(row); 00205 00206 /* 00207 * return the void * pointer 00208 */ 00209 return data; 00210 } 00211 00218 int 00219 netsnmp_tdata_add_row(netsnmp_tdata *table, 00220 netsnmp_tdata_row *row) 00221 { 00222 if (!row || !table) 00223 return SNMPERR_GENERR; 00224 00225 if (row->indexes) 00226 _netsnmp_tdata_generate_index_oid(row); 00227 00228 if (!row->oid_index.oids) { 00229 snmp_log(LOG_ERR, 00230 "illegal data attempted to be added to table %s (no index)\n", 00231 table->name); 00232 return SNMPERR_GENERR; 00233 } 00234 00235 /* 00236 * The individual index values probably won't be needed, 00237 * so this memory can be released. 00238 * Note that this is purely internal to the helper. 00239 * The calling application can set this flag as 00240 * a hint to the helper that these values aren't 00241 * required, but it's up to the helper as to 00242 * whether it takes any notice or not! 00243 */ 00244 if (table->flags & TDATA_FLAG_NO_STORE_INDEXES) { 00245 snmp_free_varbind(row->indexes); 00246 row->indexes = NULL; 00247 } 00248 00249 /* 00250 * add this row to the stored table 00251 */ 00252 if (CONTAINER_INSERT( table->container, row ) != 0) 00253 return SNMPERR_GENERR; 00254 00255 DEBUGMSGTL(("tdata_add_row", "added row (%p)\n", row)); 00256 00257 return SNMPERR_SUCCESS; 00258 } 00259 00261 netsnmp_feature_child_of(tdata_replace_row, table_tdata_all) 00262 #ifndef NETSNMP_FEATURE_REMOVE_TDATA_REPLACE_ROW 00263 void 00264 netsnmp_tdata_replace_row(netsnmp_tdata *table, 00265 netsnmp_tdata_row *origrow, 00266 netsnmp_tdata_row *newrow) 00267 { 00268 netsnmp_tdata_remove_row(table, origrow); 00269 netsnmp_tdata_add_row(table, newrow); 00270 } 00271 #endif /* NETSNMP_FEATURE_REMOVE_TDATA_REPLACE_ROW */ 00272 00279 netsnmp_tdata_row * 00280 netsnmp_tdata_remove_row(netsnmp_tdata *table, 00281 netsnmp_tdata_row *row) 00282 { 00283 if (!row || !table) 00284 return NULL; 00285 00286 CONTAINER_REMOVE( table->container, row ); 00287 return row; 00288 } 00289 00297 void * 00298 netsnmp_tdata_remove_and_delete_row(netsnmp_tdata *table, 00299 netsnmp_tdata_row *row) 00300 { 00301 if (!row || !table) 00302 return NULL; 00303 00304 /* 00305 * remove it from the list 00306 */ 00307 netsnmp_tdata_remove_row(table, row); 00308 return netsnmp_tdata_delete_row(row); 00309 } 00310 00311 00312 /* ================================== 00313 * 00314 * TData API: MIB maintenance 00315 * 00316 * ================================== */ 00317 00318 Netsnmp_Node_Handler _netsnmp_tdata_helper_handler; 00319 00321 netsnmp_mib_handler * 00322 netsnmp_get_tdata_handler(netsnmp_tdata *table) 00323 { 00324 netsnmp_mib_handler *ret = NULL; 00325 00326 if (!table) { 00327 snmp_log(LOG_INFO, 00328 "netsnmp_get_tdata_handler(NULL) called\n"); 00329 return NULL; 00330 } 00331 00332 ret = netsnmp_create_handler(TABLE_TDATA_NAME, 00333 _netsnmp_tdata_helper_handler); 00334 if (ret) { 00335 ret->flags |= MIB_HANDLER_AUTO_NEXT; 00336 ret->myvoid = (void *) table; 00337 } 00338 return ret; 00339 } 00340 00341 /* 00342 * The helper handler that takes care of passing a specific row of 00343 * data down to the lower handler(s). The table_container helper 00344 * has already taken care of identifying the appropriate row of the 00345 * table (and converting GETNEXT requests into an equivalent GET request) 00346 * So all we need to do here is make sure that the row is accessible 00347 * using tdata-style retrieval techniques as well. 00348 */ 00349 int 00350 _netsnmp_tdata_helper_handler(netsnmp_mib_handler *handler, 00351 netsnmp_handler_registration *reginfo, 00352 netsnmp_agent_request_info *reqinfo, 00353 netsnmp_request_info *requests) 00354 { 00355 netsnmp_tdata *table = (netsnmp_tdata *) handler->myvoid; 00356 netsnmp_request_info *request; 00357 netsnmp_table_request_info *table_info; 00358 netsnmp_tdata_row *row; 00359 int need_processing = 1; 00360 00361 switch ( reqinfo->mode ) { 00362 case MODE_GET: 00363 need_processing = 0; /* only need processing if some vars found */ 00366 #ifndef NETSNMP_NO_WRITE_SUPPORT 00367 case MODE_SET_RESERVE1: 00368 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 00369 00370 for (request = requests; request; request = request->next) { 00371 if (request->processed) 00372 continue; 00373 00374 table_info = netsnmp_extract_table_info(request); 00375 if (!table_info) { 00376 netsnmp_assert(table_info); /* yes, this will always hit */ 00377 netsnmp_set_request_error(reqinfo, request, SNMP_ERR_GENERR); 00378 continue; /* eek */ 00379 } 00380 row = (netsnmp_tdata_row*)netsnmp_container_table_row_extract( request ); 00381 if (!row && (reqinfo->mode == MODE_GET)) { 00382 netsnmp_assert(row); /* yes, this will always hit */ 00383 netsnmp_set_request_error(reqinfo, request, SNMP_ERR_GENERR); 00384 continue; /* eek */ 00385 } 00386 ++need_processing; 00387 netsnmp_request_add_list_data(request, 00388 netsnmp_create_data_list( 00389 TABLE_TDATA_TABLE, table, NULL)); 00390 netsnmp_request_add_list_data(request, 00391 netsnmp_create_data_list( 00392 TABLE_TDATA_ROW, row, NULL)); 00393 } 00395 if (!need_processing) 00396 handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE; 00397 } 00398 00399 /* next handler called automatically - 'AUTO_NEXT' */ 00400 return SNMP_ERR_NOERROR; 00401 } 00402 00403 00405 int 00406 netsnmp_tdata_register(netsnmp_handler_registration *reginfo, 00407 netsnmp_tdata *table, 00408 netsnmp_table_registration_info *table_info) 00409 { 00410 netsnmp_inject_handler(reginfo, netsnmp_get_tdata_handler(table)); 00411 return netsnmp_container_table_register(reginfo, table_info, 00412 table->container, TABLE_CONTAINER_KEY_NETSNMP_INDEX); 00413 } 00414 00415 netsnmp_feature_child_of(tdata_unregister, table_tdata_all) 00416 #ifndef NETSNMP_FEATURE_REMOVE_TDATA_UNREGISTER 00417 int 00418 netsnmp_tdata_unregister(netsnmp_handler_registration *reginfo) 00419 { 00420 /* free table; */ 00421 return netsnmp_container_table_unregister(reginfo); 00422 } 00423 #endif /* NETSNMP_FEATURE_REMOVE_TDATA_UNREGISTER */ 00424 00425 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_TDATA_EXTRACT_TABLE 00426 00427 netsnmp_tdata * 00428 netsnmp_tdata_extract_table(netsnmp_request_info *request) 00429 { 00430 return (netsnmp_tdata *) netsnmp_request_get_list_data(request, 00431 TABLE_TDATA_TABLE); 00432 } 00433 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_TDATA_EXTRACT_TABLE */ 00434 00436 netsnmp_feature_child_of(tdata_extract_container, table_tdata_all) 00437 #ifndef NETSNMP_FEATURE_REMOVE_TDATA_EXTRACT_CONTAINER 00438 netsnmp_container * 00439 netsnmp_tdata_extract_container(netsnmp_request_info *request) 00440 { 00441 netsnmp_tdata *tdata = (netsnmp_tdata*) 00442 netsnmp_request_get_list_data(request, TABLE_TDATA_TABLE); 00443 return ( tdata ? tdata->container : NULL ); 00444 } 00445 #endif /* NETSNMP_FEATURE_REMOVE_TDATA_EXTRACT_CONTAINER */ 00446 00448 netsnmp_tdata_row * 00449 netsnmp_tdata_extract_row(netsnmp_request_info *request) 00450 { 00451 return (netsnmp_tdata_row *) netsnmp_container_table_row_extract(request); 00452 } 00453 00456 void * 00457 netsnmp_tdata_extract_entry(netsnmp_request_info *request) 00458 { 00459 netsnmp_tdata_row *row = 00460 (netsnmp_tdata_row *) netsnmp_tdata_extract_row(request); 00461 if (row) 00462 return row->data; 00463 else 00464 return NULL; 00465 } 00466 00467 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_TDATA_INSERT_ROW 00468 00469 NETSNMP_INLINE void 00470 netsnmp_insert_tdata_row(netsnmp_request_info *request, 00471 netsnmp_tdata_row *row) 00472 { 00473 netsnmp_container_table_row_insert(request, (netsnmp_index *)row); 00474 } 00475 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_TDATA_INSERT_ROW */ 00476 00477 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_TDATA_REMOVE_ROW 00478 00479 NETSNMP_INLINE void 00480 netsnmp_remove_tdata_row(netsnmp_request_info *request, 00481 netsnmp_tdata_row *row) 00482 { 00483 netsnmp_container_table_row_remove(request, (netsnmp_index *)row); 00484 } 00485 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_TDATA_REMOVE_ROW */ 00486 00487 00488 /* ================================== 00489 * 00490 * Generic API: Row operations 00491 * 00492 * ================================== */ 00493 00495 void * 00496 netsnmp_tdata_row_entry( netsnmp_tdata_row *row ) 00497 { 00498 if (row) 00499 return row->data; 00500 else 00501 return NULL; 00502 } 00503 00505 netsnmp_tdata_row * 00506 netsnmp_tdata_row_first(netsnmp_tdata *table) 00507 { 00508 return (netsnmp_tdata_row *)CONTAINER_FIRST( table->container ); 00509 } 00510 00512 netsnmp_tdata_row * 00513 netsnmp_tdata_row_get( netsnmp_tdata *table, 00514 netsnmp_tdata_row *row) 00515 { 00516 return (netsnmp_tdata_row*)CONTAINER_FIND( table->container, row ); 00517 } 00518 00520 netsnmp_tdata_row * 00521 netsnmp_tdata_row_next( netsnmp_tdata *table, 00522 netsnmp_tdata_row *row) 00523 { 00524 return (netsnmp_tdata_row *)CONTAINER_NEXT( table->container, row ); 00525 } 00526 00528 netsnmp_tdata_row * 00529 netsnmp_tdata_row_get_byidx(netsnmp_tdata *table, 00530 netsnmp_variable_list *indexes) 00531 { 00532 oid searchfor[ MAX_OID_LEN]; 00533 size_t searchfor_len = MAX_OID_LEN; 00534 00535 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00536 indexes); 00537 return netsnmp_tdata_row_get_byoid(table, searchfor, searchfor_len); 00538 } 00539 00541 netsnmp_tdata_row * 00542 netsnmp_tdata_row_get_byoid(netsnmp_tdata *table, 00543 oid * searchfor, size_t searchfor_len) 00544 { 00545 netsnmp_index index; 00546 if (!table) 00547 return NULL; 00548 00549 index.oids = searchfor; 00550 index.len = searchfor_len; 00551 return (netsnmp_tdata_row*)CONTAINER_FIND( table->container, &index ); 00552 } 00553 00556 netsnmp_tdata_row * 00557 netsnmp_tdata_row_next_byidx(netsnmp_tdata *table, 00558 netsnmp_variable_list *indexes) 00559 { 00560 oid searchfor[ MAX_OID_LEN]; 00561 size_t searchfor_len = MAX_OID_LEN; 00562 00563 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00564 indexes); 00565 return netsnmp_tdata_row_next_byoid(table, searchfor, searchfor_len); 00566 } 00567 00570 netsnmp_tdata_row * 00571 netsnmp_tdata_row_next_byoid(netsnmp_tdata *table, 00572 oid * searchfor, size_t searchfor_len) 00573 { 00574 netsnmp_index index; 00575 if (!table) 00576 return NULL; 00577 00578 index.oids = searchfor; 00579 index.len = searchfor_len; 00580 return (netsnmp_tdata_row*)CONTAINER_NEXT( table->container, &index ); 00581 } 00582 00583 netsnmp_feature_child_of(tdata_row_count, table_tdata_all) 00584 #ifndef NETSNMP_FEATURE_REMOVE_TDATA_ROW_COUNT 00585 int 00586 netsnmp_tdata_row_count(netsnmp_tdata *table) 00587 { 00588 if (!table) 00589 return 0; 00590 return CONTAINER_SIZE( table->container ); 00591 } 00592 #endif /* NETSNMP_FEATURE_REMOVE_TDATA_ROW_COUNT */ 00593 00594 /* ================================== 00595 * 00596 * Generic API: Index operations on a 'tdata' table 00597 * 00598 * ================================== */ 00599 00600 00602 netsnmp_feature_child_of(tdata_compare_idx, table_tdata_all) 00603 #ifndef NETSNMP_FEATURE_REMOVE_TDATA_COMPARE_IDX 00604 int 00605 netsnmp_tdata_compare_idx(netsnmp_tdata_row *row, 00606 netsnmp_variable_list *indexes) 00607 { 00608 oid searchfor[ MAX_OID_LEN]; 00609 size_t searchfor_len = MAX_OID_LEN; 00610 00611 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00612 indexes); 00613 return netsnmp_tdata_compare_oid(row, searchfor, searchfor_len); 00614 } 00615 #endif /* NETSNMP_FEATURE_REMOVE_TDATA_COMPARE_IDX */ 00616 00618 int 00619 netsnmp_tdata_compare_oid(netsnmp_tdata_row *row, 00620 oid * compareto, size_t compareto_len) 00621 { 00622 netsnmp_index *index = (netsnmp_index *)row; 00623 return snmp_oid_compare( index->oids, index->len, 00624 compareto, compareto_len); 00625 } 00626 00627 int 00628 netsnmp_tdata_compare_subtree_idx(netsnmp_tdata_row *row, 00629 netsnmp_variable_list *indexes) 00630 { 00631 oid searchfor[ MAX_OID_LEN]; 00632 size_t searchfor_len = MAX_OID_LEN; 00633 00634 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00635 indexes); 00636 return netsnmp_tdata_compare_subtree_oid(row, searchfor, searchfor_len); 00637 } 00638 00639 int 00640 netsnmp_tdata_compare_subtree_oid(netsnmp_tdata_row *row, 00641 oid * compareto, size_t compareto_len) 00642 { 00643 netsnmp_index *index = (netsnmp_index *)row; 00644 return snmp_oidtree_compare( index->oids, index->len, 00645 compareto, compareto_len); 00646 } 00647 #else /* NETSNMP_FEATURE_REMOVE_TABLE_TDATA */ 00648 netsnmp_feature_unused(table_tdata); 00649 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_TDATA */ 00650 00651