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