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_tdata.h> 00014 #include <net-snmp/agent/table_container.h> 00015 #include <net-snmp/agent/read_only.h> 00016 00017 #if HAVE_DMALLOC_H 00018 #include <dmalloc.h> 00019 #endif 00020 00037 /* ================================== 00038 * 00039 * TData API: Table maintenance 00040 * 00041 * ================================== */ 00042 00043 /* 00044 * generates the index portion of an table oid from a varlist. 00045 */ 00046 void 00047 _netsnmp_tdata_generate_index_oid(netsnmp_tdata_row *row) 00048 { 00049 build_oid(&row->oid_index.oids, &row->oid_index.len, NULL, 0, row->indexes); 00050 } 00051 00053 netsnmp_tdata * 00054 netsnmp_tdata_create_table(const char *name, long flags) 00055 { 00056 netsnmp_tdata *table = SNMP_MALLOC_TYPEDEF(netsnmp_tdata); 00057 if ( !table ) 00058 return NULL; 00059 00060 table->flags = flags; 00061 if (name) 00062 table->name = strdup(name); 00063 00064 if (!(table->flags & TDATA_FLAG_NO_CONTAINER)) { 00065 table->container = netsnmp_container_find( name ); 00066 if (!table->container) 00067 table->container = netsnmp_container_find( "table_container" ); 00068 if (table->container) 00069 table->container->container_name = strdup(name); 00070 } 00071 00072 return table; 00073 } 00074 00076 void 00077 netsnmp_tdata_delete_table(netsnmp_tdata *table) 00078 { 00079 if (!table) 00080 return; 00081 00082 if (table->name) 00083 free(table->name); 00084 if (table->container) 00085 CONTAINER_FREE(table->container); 00086 00087 SNMP_FREE(table); 00088 return; 00089 } 00090 00092 netsnmp_tdata_row * 00093 netsnmp_tdata_create_row(void) 00094 { 00095 netsnmp_tdata_row *row = SNMP_MALLOC_TYPEDEF(netsnmp_tdata_row); 00096 return row; 00097 } 00098 00100 netsnmp_tdata_row * 00101 netsnmp_tdata_clone_row(netsnmp_tdata_row *row) 00102 { 00103 netsnmp_tdata_row *newrow = NULL; 00104 if (!row) 00105 return NULL; 00106 00107 memdup((u_char **) & newrow, (u_char *) row, 00108 sizeof(netsnmp_tdata_row)); 00109 if (!newrow) 00110 return NULL; 00111 00112 if (row->indexes) { 00113 newrow->indexes = snmp_clone_varbind(newrow->indexes); 00114 if (!newrow->indexes) { 00115 SNMP_FREE(newrow); 00116 return NULL; 00117 } 00118 } 00119 00120 if (row->oid_index.oids) { 00121 memdup((u_char **) & newrow->oid_index.oids, 00122 (u_char *) row->oid_index.oids, 00123 row->oid_index.len * sizeof(oid)); 00124 if (!newrow->oid_index.oids) { 00125 if (newrow->indexes) 00126 snmp_free_varbind(newrow->indexes); 00127 SNMP_FREE(newrow); 00128 return NULL; 00129 } 00130 } 00131 00132 return newrow; 00133 } 00134 00137 int 00138 netsnmp_tdata_copy_row(netsnmp_tdata_row *dst_row, netsnmp_tdata_row *src_row) 00139 { 00140 if ( !src_row || !dst_row ) 00141 return -1; 00142 00143 memcpy((u_char *) dst_row, (u_char *) src_row, 00144 sizeof(netsnmp_tdata_row)); 00145 if (src_row->indexes) { 00146 dst_row->indexes = snmp_clone_varbind(src_row->indexes); 00147 if (!dst_row->indexes) 00148 return -1; 00149 } 00150 00151 if (src_row->oid_index.oids) { 00152 memdup((u_char **) &dst_row->oid_index.oids, 00153 (u_char *) src_row->oid_index.oids, 00154 src_row->oid_index.len * sizeof(oid)); 00155 if (!dst_row->oid_index.oids) 00156 return -1; 00157 } 00158 00159 return 0; 00160 } 00161 00165 void * 00166 netsnmp_tdata_delete_row(netsnmp_tdata_row *row) 00167 { 00168 void *data; 00169 00170 if (!row) 00171 return NULL; 00172 00173 /* 00174 * free the memory we can 00175 */ 00176 if (row->indexes) 00177 snmp_free_varbind(row->indexes); 00178 SNMP_FREE(row->oid_index.oids); 00179 data = row->data; 00180 free(row); 00181 00182 /* 00183 * return the void * pointer 00184 */ 00185 return data; 00186 } 00187 00194 int 00195 netsnmp_tdata_add_row(netsnmp_tdata *table, 00196 netsnmp_tdata_row *row) 00197 { 00198 if (!row || !table) 00199 return SNMPERR_GENERR; 00200 00201 if (row->indexes) 00202 _netsnmp_tdata_generate_index_oid(row); 00203 00204 if (!row->oid_index.oids) { 00205 snmp_log(LOG_ERR, 00206 "illegal data attempted to be added to table %s (no index)\n", 00207 table->name); 00208 return SNMPERR_GENERR; 00209 } 00210 00211 /* 00212 * The individual index values probably won't be needed, 00213 * so this memory can be released. 00214 * Note that this is purely internal to the helper. 00215 * The calling application can set this flag as 00216 * a hint to the helper that these values aren't 00217 * required, but it's up to the helper as to 00218 * whether it takes any notice or not! 00219 */ 00220 if (table->flags & TDATA_FLAG_NO_STORE_INDEXES) { 00221 snmp_free_varbind(row->indexes); 00222 row->indexes = NULL; 00223 } 00224 00225 /* 00226 * add this row to the stored table 00227 */ 00228 CONTAINER_INSERT( table->container, row ); 00229 DEBUGMSGTL(("tdata_add_row", "added row (%x)\n", row)); 00230 00231 return SNMPERR_SUCCESS; 00232 } 00233 00235 void 00236 netsnmp_tdata_replace_row(netsnmp_tdata *table, 00237 netsnmp_tdata_row *origrow, 00238 netsnmp_tdata_row *newrow) 00239 { 00240 netsnmp_tdata_remove_row(table, origrow); 00241 netsnmp_tdata_add_row(table, newrow); 00242 } 00243 00250 netsnmp_tdata_row * 00251 netsnmp_tdata_remove_row(netsnmp_tdata *table, 00252 netsnmp_tdata_row *row) 00253 { 00254 if (!row || !table) 00255 return NULL; 00256 00257 CONTAINER_REMOVE( table->container, row ); 00258 return row; 00259 } 00260 00268 void * 00269 netsnmp_tdata_remove_and_delete_row(netsnmp_tdata *table, 00270 netsnmp_tdata_row *row) 00271 { 00272 if (!row || !table) 00273 return NULL; 00274 00275 /* 00276 * remove it from the list 00277 */ 00278 netsnmp_tdata_remove_row(table, row); 00279 return netsnmp_tdata_delete_row(row); 00280 } 00281 00282 00283 /* ================================== 00284 * 00285 * TData API: MIB maintenance 00286 * 00287 * ================================== */ 00288 00289 Netsnmp_Node_Handler _netsnmp_tdata_helper_handler; 00290 00292 netsnmp_mib_handler * 00293 netsnmp_get_tdata_handler(netsnmp_tdata *table) 00294 { 00295 netsnmp_mib_handler *ret = NULL; 00296 00297 if (!table) { 00298 snmp_log(LOG_INFO, 00299 "netsnmp_get_tdata_handler(NULL) called\n"); 00300 return NULL; 00301 } 00302 00303 ret = netsnmp_create_handler(TABLE_TDATA_NAME, 00304 _netsnmp_tdata_helper_handler); 00305 if (ret) { 00306 ret->flags |= MIB_HANDLER_AUTO_NEXT; 00307 ret->myvoid = (void *) table; 00308 } 00309 return ret; 00310 } 00311 00312 /* 00313 * The helper handler that takes care of passing a specific row of 00314 * data down to the lower handler(s). The table_container helper 00315 * has already taken care of identifying the appropriate row of the 00316 * table (and converting GETNEXT requests into an equivalent GET request) 00317 * So all we need to do here is make sure that the row is accessible 00318 * using tdata-style retrieval techniques as well. 00319 */ 00320 int 00321 _netsnmp_tdata_helper_handler(netsnmp_mib_handler *handler, 00322 netsnmp_handler_registration *reginfo, 00323 netsnmp_agent_request_info *reqinfo, 00324 netsnmp_request_info *requests) 00325 { 00326 netsnmp_tdata *table = (netsnmp_tdata *) handler->myvoid; 00327 netsnmp_request_info *request; 00328 netsnmp_table_request_info *table_info; 00329 netsnmp_tdata_row *row; 00330 00331 switch ( reqinfo->mode ) { 00332 case MODE_GET: 00333 case MODE_SET_RESERVE1: 00334 00335 for (request = requests; request; request = request->next) { 00336 if (request->processed) 00337 continue; 00338 00339 table_info = netsnmp_extract_table_info(request); 00340 if (!table_info) 00341 continue; /* ack */ 00342 row = netsnmp_container_table_row_extract( request ); 00343 00344 netsnmp_request_add_list_data(request, 00345 netsnmp_create_data_list( 00346 TABLE_TDATA_TABLE, table, NULL)); 00347 netsnmp_request_add_list_data(request, 00348 netsnmp_create_data_list( 00349 TABLE_TDATA_ROW, row, NULL)); 00350 } 00351 } 00352 00353 /* next handler called automatically - 'AUTO_NEXT' */ 00354 return SNMP_ERR_NOERROR; 00355 } 00356 00357 00359 int 00360 netsnmp_tdata_register(netsnmp_handler_registration *reginfo, 00361 netsnmp_tdata *table, 00362 netsnmp_table_registration_info *table_info) 00363 { 00364 netsnmp_inject_handler(reginfo, netsnmp_get_tdata_handler(table)); 00365 return netsnmp_container_table_register(reginfo, table_info, 00366 table->container, TABLE_CONTAINER_KEY_NETSNMP_INDEX); 00367 } 00368 00370 netsnmp_tdata * 00371 netsnmp_tdata_extract_table(netsnmp_request_info *request) 00372 { 00373 return (netsnmp_tdata *) netsnmp_request_get_list_data(request, 00374 TABLE_TDATA_TABLE); 00375 } 00376 00378 netsnmp_container * 00379 netsnmp_tdata_extract_container(netsnmp_request_info *request) 00380 { 00381 netsnmp_tdata *tdata = netsnmp_request_get_list_data(request, 00382 TABLE_TDATA_TABLE); 00383 return ( tdata ? tdata->container : NULL ); 00384 } 00385 00387 netsnmp_tdata_row * 00388 netsnmp_tdata_extract_row(netsnmp_request_info *request) 00389 { 00390 return (netsnmp_tdata_row *) netsnmp_container_table_row_extract(request); 00391 } 00392 00395 void * 00396 netsnmp_tdata_extract_entry(netsnmp_request_info *request) 00397 { 00398 netsnmp_tdata_row *row = 00399 (netsnmp_tdata_row *) netsnmp_tdata_extract_row(request); 00400 if (row) 00401 return row->data; 00402 else 00403 return NULL; 00404 } 00405 00407 NETSNMP_INLINE void 00408 netsnmp_insert_tdata_row(netsnmp_request_info *request, 00409 netsnmp_tdata_row *row) 00410 { 00411 netsnmp_container_table_row_insert(request, (netsnmp_index *)row); 00412 } 00413 00414 00415 /* ================================== 00416 * 00417 * Generic API: Row operations 00418 * 00419 * ================================== */ 00420 00422 void * 00423 netsnmp_tdata_row_entry( netsnmp_tdata_row *row ) 00424 { 00425 if (row) 00426 return row->data; 00427 else 00428 return NULL; 00429 } 00430 00432 netsnmp_tdata_row * 00433 netsnmp_tdata_row_first(netsnmp_tdata *table) 00434 { 00435 return (netsnmp_tdata_row *)CONTAINER_FIRST( table->container ); 00436 } 00437 00439 netsnmp_tdata_row * 00440 netsnmp_tdata_row_get( netsnmp_tdata *table, 00441 netsnmp_tdata_row *row) 00442 { 00443 return CONTAINER_FIND( table->container, row ); 00444 } 00445 00447 netsnmp_tdata_row * 00448 netsnmp_tdata_row_next( netsnmp_tdata *table, 00449 netsnmp_tdata_row *row) 00450 { 00451 return (netsnmp_tdata_row *)CONTAINER_NEXT( table->container, row ); 00452 } 00453 00455 netsnmp_tdata_row * 00456 netsnmp_tdata_row_get_byidx(netsnmp_tdata *table, 00457 netsnmp_variable_list *indexes) 00458 { 00459 oid searchfor[ MAX_OID_LEN]; 00460 size_t searchfor_len = MAX_OID_LEN; 00461 00462 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00463 indexes); 00464 return netsnmp_tdata_row_get_byoid(table, searchfor, searchfor_len); 00465 } 00466 00468 netsnmp_tdata_row * 00469 netsnmp_tdata_row_get_byoid(netsnmp_tdata *table, 00470 oid * searchfor, size_t searchfor_len) 00471 { 00472 netsnmp_index index; 00473 if (!table) 00474 return NULL; 00475 00476 index.oids = searchfor; 00477 index.len = searchfor_len; 00478 return CONTAINER_FIND( table->container, &index ); 00479 } 00480 00483 netsnmp_tdata_row * 00484 netsnmp_tdata_row_next_byidx(netsnmp_tdata *table, 00485 netsnmp_variable_list *indexes) 00486 { 00487 oid searchfor[ MAX_OID_LEN]; 00488 size_t searchfor_len = MAX_OID_LEN; 00489 00490 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00491 indexes); 00492 return netsnmp_tdata_row_next_byoid(table, searchfor, searchfor_len); 00493 } 00494 00497 netsnmp_tdata_row * 00498 netsnmp_tdata_row_next_byoid(netsnmp_tdata *table, 00499 oid * searchfor, size_t searchfor_len) 00500 { 00501 netsnmp_index index; 00502 if (!table) 00503 return NULL; 00504 00505 index.oids = searchfor; 00506 index.len = searchfor_len; 00507 return CONTAINER_NEXT( table->container, &index ); 00508 } 00509 00510 int 00511 netsnmp_tdata_row_count(netsnmp_tdata *table) 00512 { 00513 if (!table) 00514 return 0; 00515 return CONTAINER_SIZE( table->container ); 00516 } 00517 00518 /* ================================== 00519 * 00520 * Generic API: Index operations on a 'tdata' table 00521 * 00522 * ================================== */ 00523 00524 00526 int 00527 netsnmp_tdata_compare_idx(netsnmp_tdata_row *row, 00528 netsnmp_variable_list *indexes) 00529 { 00530 oid searchfor[ MAX_OID_LEN]; 00531 size_t searchfor_len = MAX_OID_LEN; 00532 00533 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00534 indexes); 00535 return netsnmp_tdata_compare_oid(row, searchfor, searchfor_len); 00536 } 00537 00539 int 00540 netsnmp_tdata_compare_oid(netsnmp_tdata_row *row, 00541 oid * compareto, size_t compareto_len) 00542 { 00543 netsnmp_index *index = (netsnmp_index *)row; 00544 return snmp_oid_compare( index->oids, index->len, 00545 compareto, compareto_len); 00546 } 00547 00548 int 00549 netsnmp_tdata_compare_subtree_idx(netsnmp_tdata_row *row, 00550 netsnmp_variable_list *indexes) 00551 { 00552 oid searchfor[ MAX_OID_LEN]; 00553 size_t searchfor_len = MAX_OID_LEN; 00554 00555 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0, 00556 indexes); 00557 return netsnmp_tdata_compare_subtree_oid(row, searchfor, searchfor_len); 00558 } 00559 00560 int 00561 netsnmp_tdata_compare_subtree_oid(netsnmp_tdata_row *row, 00562 oid * compareto, size_t compareto_len) 00563 { 00564 netsnmp_index *index = (netsnmp_index *)row; 00565 return snmp_oidtree_compare( index->oids, index->len, 00566 compareto, compareto_len); 00567 } 00568