00001 #include <net-snmp/net-snmp-config.h>
00002
00003 #include <net-snmp/net-snmp-includes.h>
00004 #include <net-snmp/agent/net-snmp-agent-includes.h>
00005
00006 #include <net-snmp/agent/table_tdata.h>
00007
00008 #if HAVE_STRING_H
00009 #include <string.h>
00010 #else
00011 #include <strings.h>
00012 #endif
00013
00014 #include <net-snmp/agent/table.h>
00015 #include <net-snmp/agent/table_container.h>
00016 #include <net-snmp/agent/read_only.h>
00017
00018 #if HAVE_DMALLOC_H
00019 #include <dmalloc.h>
00020 #endif
00021
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 void
00048 _netsnmp_tdata_generate_index_oid(netsnmp_tdata_row *row)
00049 {
00050 build_oid(&row->oid_index.oids, &row->oid_index.len, NULL, 0, row->indexes);
00051 }
00052
00054 netsnmp_tdata *
00055 netsnmp_tdata_create_table(const char *name, long flags)
00056 {
00057 netsnmp_tdata *table = SNMP_MALLOC_TYPEDEF(netsnmp_tdata);
00058 if ( !table )
00059 return NULL;
00060
00061 if (name)
00062 table->name = strdup(name);
00063 table->container = netsnmp_container_find( "table_container" );
00064 return table;
00065 }
00066
00068 void
00069 netsnmp_tdata_delete_table(netsnmp_tdata *table)
00070 {
00071 if (!table)
00072 return;
00073
00074 if (table->name)
00075 free(table->name);
00076 if (table->container)
00077 CONTAINER_FREE(table->container);
00078
00079 SNMP_FREE(table);
00080 return;
00081 }
00082
00084 netsnmp_tdata_row *
00085 netsnmp_tdata_create_row(void)
00086 {
00087 netsnmp_tdata_row *row = SNMP_MALLOC_TYPEDEF(netsnmp_tdata_row);
00088 return row;
00089 }
00090
00092 netsnmp_tdata_row *
00093 netsnmp_tdata_clone_row(netsnmp_tdata_row *row)
00094 {
00095 netsnmp_tdata_row *newrow = NULL;
00096 if (!row)
00097 return NULL;
00098
00099 memdup((u_char **) & newrow, (u_char *) row,
00100 sizeof(netsnmp_tdata_row));
00101 if (!newrow)
00102 return NULL;
00103
00104 if (row->indexes) {
00105 newrow->indexes = snmp_clone_varbind(newrow->indexes);
00106 if (!newrow->indexes) {
00107 SNMP_FREE(newrow);
00108 return NULL;
00109 }
00110 }
00111
00112 if (row->oid_index.oids) {
00113 newrow->oid_index.oids =
00114 snmp_duplicate_objid(row->oid_index.oids, row->oid_index.len);
00115 if (!newrow->oid_index.oids) {
00116 if (newrow->indexes)
00117 snmp_free_varbind(newrow->indexes);
00118 SNMP_FREE(newrow);
00119 return NULL;
00120 }
00121 }
00122
00123 return newrow;
00124 }
00125
00128 int
00129 netsnmp_tdata_copy_row(netsnmp_tdata_row *dst_row, netsnmp_tdata_row *src_row)
00130 {
00131 if ( !src_row || !dst_row )
00132 return -1;
00133
00134 memcpy((u_char *) dst_row, (u_char *) src_row,
00135 sizeof(netsnmp_tdata_row));
00136 if (src_row->indexes) {
00137 dst_row->indexes = snmp_clone_varbind(src_row->indexes);
00138 if (!dst_row->indexes)
00139 return -1;
00140 }
00141
00142 if (src_row->oid_index.oids) {
00143 dst_row->oid_index.oids = snmp_duplicate_objid(src_row->oid_index.oids,
00144 src_row->oid_index.len);
00145 if (!dst_row->oid_index.oids)
00146 return -1;
00147 }
00148
00149 return 0;
00150 }
00151
00155 void *
00156 netsnmp_tdata_delete_row(netsnmp_tdata_row *row)
00157 {
00158 void *data;
00159
00160 if (!row)
00161 return NULL;
00162
00163
00164
00165
00166 if (row->indexes)
00167 snmp_free_varbind(row->indexes);
00168 SNMP_FREE(row->oid_index.oids);
00169 data = row->data;
00170 free(row);
00171
00172
00173
00174
00175 return data;
00176 }
00177
00184 int
00185 netsnmp_tdata_add_row(netsnmp_tdata *table,
00186 netsnmp_tdata_row *row)
00187 {
00188 if (!row || !table)
00189 return SNMPERR_GENERR;
00190
00191 if (row->indexes)
00192 _netsnmp_tdata_generate_index_oid(row);
00193
00194 if (!row->oid_index.oids) {
00195 snmp_log(LOG_ERR,
00196 "illegal data attempted to be added to table %s (no index)\n",
00197 table->name);
00198 return SNMPERR_GENERR;
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 if (table->flags & TDATA_FLAG_NO_STORE_INDEXES) {
00211 snmp_free_varbind(row->indexes);
00212 row->indexes = NULL;
00213 }
00214
00215
00216
00217
00218 CONTAINER_INSERT( table->container, row );
00219 DEBUGMSGTL(("tdata_add_row", "added row (%p)\n", row));
00220
00221 return SNMPERR_SUCCESS;
00222 }
00223
00225 void
00226 netsnmp_tdata_replace_row(netsnmp_tdata *table,
00227 netsnmp_tdata_row *origrow,
00228 netsnmp_tdata_row *newrow)
00229 {
00230 netsnmp_tdata_remove_row(table, origrow);
00231 netsnmp_tdata_add_row(table, newrow);
00232 }
00233
00240 netsnmp_tdata_row *
00241 netsnmp_tdata_remove_row(netsnmp_tdata *table,
00242 netsnmp_tdata_row *row)
00243 {
00244 if (!row || !table)
00245 return NULL;
00246
00247 CONTAINER_REMOVE( table->container, row );
00248 return row;
00249 }
00250
00258 void *
00259 netsnmp_tdata_remove_and_delete_row(netsnmp_tdata *table,
00260 netsnmp_tdata_row *row)
00261 {
00262 if (!row || !table)
00263 return NULL;
00264
00265
00266
00267
00268 netsnmp_tdata_remove_row(table, row);
00269 return netsnmp_tdata_delete_row(row);
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279 Netsnmp_Node_Handler _netsnmp_tdata_helper_handler;
00280
00282 netsnmp_mib_handler *
00283 netsnmp_get_tdata_handler(netsnmp_tdata *table)
00284 {
00285 netsnmp_mib_handler *ret = NULL;
00286
00287 if (!table) {
00288 snmp_log(LOG_INFO,
00289 "netsnmp_get_tdata_handler(NULL) called\n");
00290 return NULL;
00291 }
00292
00293 ret = netsnmp_create_handler(TABLE_TDATA_NAME,
00294 _netsnmp_tdata_helper_handler);
00295 if (ret) {
00296 ret->flags |= MIB_HANDLER_AUTO_NEXT;
00297 ret->myvoid = (void *) table;
00298 }
00299 return ret;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 int
00311 _netsnmp_tdata_helper_handler(netsnmp_mib_handler *handler,
00312 netsnmp_handler_registration *reginfo,
00313 netsnmp_agent_request_info *reqinfo,
00314 netsnmp_request_info *requests)
00315 {
00316 netsnmp_tdata *table = (netsnmp_tdata *) handler->myvoid;
00317 netsnmp_request_info *request;
00318 netsnmp_table_request_info *table_info;
00319 netsnmp_tdata_row *row;
00320
00321 switch ( reqinfo->mode ) {
00322 case MODE_GET:
00323 case MODE_SET_RESERVE1:
00324
00325 for (request = requests; request; request = request->next) {
00326 if (request->processed)
00327 continue;
00328
00329 table_info = netsnmp_extract_table_info(request);
00330 if (!table_info)
00331 continue;
00332 row = netsnmp_container_table_row_extract( request );
00333
00334 netsnmp_request_add_list_data(request,
00335 netsnmp_create_data_list(
00336 TABLE_TDATA_TABLE, table, NULL));
00337 netsnmp_request_add_list_data(request,
00338 netsnmp_create_data_list(
00339 TABLE_TDATA_ROW, row, NULL));
00340 }
00341 }
00342
00343
00344 return SNMP_ERR_NOERROR;
00345 }
00346
00347
00349 int
00350 netsnmp_tdata_register(netsnmp_handler_registration *reginfo,
00351 netsnmp_tdata *table,
00352 netsnmp_table_registration_info *table_info)
00353 {
00354 netsnmp_inject_handler(reginfo, netsnmp_get_tdata_handler(table));
00355 return netsnmp_container_table_register(reginfo, table_info,
00356 table->container, TABLE_CONTAINER_KEY_NETSNMP_INDEX);
00357 }
00358
00359 int
00360 netsnmp_tdata_unregister(netsnmp_handler_registration *reginfo)
00361 {
00362
00363 return netsnmp_container_table_unregister(reginfo);
00364 }
00365
00367 netsnmp_tdata *
00368 netsnmp_tdata_extract_table(netsnmp_request_info *request)
00369 {
00370 return (netsnmp_tdata *) netsnmp_request_get_list_data(request,
00371 TABLE_TDATA_TABLE);
00372 }
00373
00375 netsnmp_container *
00376 netsnmp_tdata_extract_container(netsnmp_request_info *request)
00377 {
00378 netsnmp_tdata *tdata = netsnmp_request_get_list_data(request,
00379 TABLE_TDATA_TABLE);
00380 return ( tdata ? tdata->container : NULL );
00381 }
00382
00384 netsnmp_tdata_row *
00385 netsnmp_tdata_extract_row(netsnmp_request_info *request)
00386 {
00387 return (netsnmp_tdata_row *) netsnmp_container_table_row_extract(request);
00388 }
00389
00392 void *
00393 netsnmp_tdata_extract_entry(netsnmp_request_info *request)
00394 {
00395 netsnmp_tdata_row *row =
00396 (netsnmp_tdata_row *) netsnmp_tdata_extract_row(request);
00397 if (row)
00398 return row->data;
00399 else
00400 return NULL;
00401 }
00402
00404 NETSNMP_INLINE void
00405 netsnmp_insert_tdata_row(netsnmp_request_info *request,
00406 netsnmp_tdata_row *row)
00407 {
00408 netsnmp_container_table_row_insert(request, (netsnmp_index *)row);
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00419 void *
00420 netsnmp_tdata_row_entry( netsnmp_tdata_row *row )
00421 {
00422 if (row)
00423 return row->data;
00424 else
00425 return NULL;
00426 }
00427
00429 netsnmp_tdata_row *
00430 netsnmp_tdata_row_first(netsnmp_tdata *table)
00431 {
00432 return (netsnmp_tdata_row *)CONTAINER_FIRST( table->container );
00433 }
00434
00436 netsnmp_tdata_row *
00437 netsnmp_tdata_row_get( netsnmp_tdata *table,
00438 netsnmp_tdata_row *row)
00439 {
00440 return CONTAINER_FIND( table->container, row );
00441 }
00442
00444 netsnmp_tdata_row *
00445 netsnmp_tdata_row_next( netsnmp_tdata *table,
00446 netsnmp_tdata_row *row)
00447 {
00448 return (netsnmp_tdata_row *)CONTAINER_NEXT( table->container, row );
00449 }
00450
00452 netsnmp_tdata_row *
00453 netsnmp_tdata_row_get_byidx(netsnmp_tdata *table,
00454 netsnmp_variable_list *indexes)
00455 {
00456 oid searchfor[ MAX_OID_LEN];
00457 size_t searchfor_len = MAX_OID_LEN;
00458
00459 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00460 indexes);
00461 return netsnmp_tdata_row_get_byoid(table, searchfor, searchfor_len);
00462 }
00463
00465 netsnmp_tdata_row *
00466 netsnmp_tdata_row_get_byoid(netsnmp_tdata *table,
00467 oid * searchfor, size_t searchfor_len)
00468 {
00469 netsnmp_index index;
00470 if (!table)
00471 return NULL;
00472
00473 index.oids = searchfor;
00474 index.len = searchfor_len;
00475 return CONTAINER_FIND( table->container, &index );
00476 }
00477
00480 netsnmp_tdata_row *
00481 netsnmp_tdata_row_next_byidx(netsnmp_tdata *table,
00482 netsnmp_variable_list *indexes)
00483 {
00484 oid searchfor[ MAX_OID_LEN];
00485 size_t searchfor_len = MAX_OID_LEN;
00486
00487 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00488 indexes);
00489 return netsnmp_tdata_row_next_byoid(table, searchfor, searchfor_len);
00490 }
00491
00494 netsnmp_tdata_row *
00495 netsnmp_tdata_row_next_byoid(netsnmp_tdata *table,
00496 oid * searchfor, size_t searchfor_len)
00497 {
00498 netsnmp_index index;
00499 if (!table)
00500 return NULL;
00501
00502 index.oids = searchfor;
00503 index.len = searchfor_len;
00504 return CONTAINER_NEXT( table->container, &index );
00505 }
00506
00507 int
00508 netsnmp_tdata_row_count(netsnmp_tdata *table)
00509 {
00510 if (!table)
00511 return 0;
00512 return CONTAINER_SIZE( table->container );
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00523 int
00524 netsnmp_tdata_compare_idx(netsnmp_tdata_row *row,
00525 netsnmp_variable_list *indexes)
00526 {
00527 oid searchfor[ MAX_OID_LEN];
00528 size_t searchfor_len = MAX_OID_LEN;
00529
00530 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00531 indexes);
00532 return netsnmp_tdata_compare_oid(row, searchfor, searchfor_len);
00533 }
00534
00536 int
00537 netsnmp_tdata_compare_oid(netsnmp_tdata_row *row,
00538 oid * compareto, size_t compareto_len)
00539 {
00540 netsnmp_index *index = (netsnmp_index *)row;
00541 return snmp_oid_compare( index->oids, index->len,
00542 compareto, compareto_len);
00543 }
00544
00545 int
00546 netsnmp_tdata_compare_subtree_idx(netsnmp_tdata_row *row,
00547 netsnmp_variable_list *indexes)
00548 {
00549 oid searchfor[ MAX_OID_LEN];
00550 size_t searchfor_len = MAX_OID_LEN;
00551
00552 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00553 indexes);
00554 return netsnmp_tdata_compare_subtree_oid(row, searchfor, searchfor_len);
00555 }
00556
00557 int
00558 netsnmp_tdata_compare_subtree_oid(netsnmp_tdata_row *row,
00559 oid * compareto, size_t compareto_len)
00560 {
00561 netsnmp_index *index = (netsnmp_index *)row;
00562 return snmp_oidtree_compare( index->oids, index->len,
00563 compareto, compareto_len);
00564 }
00565