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
00040
00041
00042
00043
00044
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 if (name)
00061 table->name = strdup(name);
00062 table->container = netsnmp_container_find( "table_container" );
00063 return table;
00064 }
00065
00067 void
00068 netsnmp_tdata_delete_table(netsnmp_tdata *table)
00069 {
00070 if (!table)
00071 return;
00072
00073 if (table->name)
00074 free(table->name);
00075 if (table->container)
00076 CONTAINER_FREE(table->container);
00077
00078 SNMP_FREE(table);
00079 return;
00080 }
00081
00083 netsnmp_tdata_row *
00084 netsnmp_tdata_create_row(void)
00085 {
00086 netsnmp_tdata_row *row = SNMP_MALLOC_TYPEDEF(netsnmp_tdata_row);
00087 return row;
00088 }
00089
00091 netsnmp_tdata_row *
00092 netsnmp_tdata_clone_row(netsnmp_tdata_row *row)
00093 {
00094 netsnmp_tdata_row *newrow = NULL;
00095 if (!row)
00096 return NULL;
00097
00098 memdup((u_char **) & newrow, (u_char *) row,
00099 sizeof(netsnmp_tdata_row));
00100 if (!newrow)
00101 return NULL;
00102
00103 if (row->indexes) {
00104 newrow->indexes = snmp_clone_varbind(newrow->indexes);
00105 if (!newrow->indexes) {
00106 SNMP_FREE(newrow);
00107 return NULL;
00108 }
00109 }
00110
00111 if (row->oid_index.oids) {
00112 memdup((u_char **) & newrow->oid_index.oids,
00113 (u_char *) row->oid_index.oids,
00114 row->oid_index.len * sizeof(oid));
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 memdup((u_char **) &dst_row->oid_index.oids,
00144 (u_char *) src_row->oid_index.oids,
00145 src_row->oid_index.len * sizeof(oid));
00146 if (!dst_row->oid_index.oids)
00147 return -1;
00148 }
00149
00150 return 0;
00151 }
00152
00156 void *
00157 netsnmp_tdata_delete_row(netsnmp_tdata_row *row)
00158 {
00159 void *data;
00160
00161 if (!row)
00162 return NULL;
00163
00164
00165
00166
00167 if (row->indexes)
00168 snmp_free_varbind(row->indexes);
00169 SNMP_FREE(row->oid_index.oids);
00170 data = row->data;
00171 free(row);
00172
00173
00174
00175
00176 return data;
00177 }
00178
00185 int
00186 netsnmp_tdata_add_row(netsnmp_tdata *table,
00187 netsnmp_tdata_row *row)
00188 {
00189 if (!row || !table)
00190 return SNMPERR_GENERR;
00191
00192 if (row->indexes)
00193 _netsnmp_tdata_generate_index_oid(row);
00194
00195 if (!row->oid_index.oids) {
00196 snmp_log(LOG_ERR,
00197 "illegal data attempted to be added to table %s (no index)\n",
00198 table->name);
00199 return SNMPERR_GENERR;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 if (table->flags & TDATA_FLAG_NO_STORE_INDEXES) {
00212 snmp_free_varbind(row->indexes);
00213 row->indexes = NULL;
00214 }
00215
00216
00217
00218
00219 CONTAINER_INSERT( table->container, row );
00220 DEBUGMSGTL(("tdata_add_row", "added row (%x)\n", row));
00221
00222 return SNMPERR_SUCCESS;
00223 }
00224
00226 void
00227 netsnmp_tdata_replace_row(netsnmp_tdata *table,
00228 netsnmp_tdata_row *origrow,
00229 netsnmp_tdata_row *newrow)
00230 {
00231 netsnmp_tdata_remove_row(table, origrow);
00232 netsnmp_tdata_add_row(table, newrow);
00233 }
00234
00241 netsnmp_tdata_row *
00242 netsnmp_tdata_remove_row(netsnmp_tdata *table,
00243 netsnmp_tdata_row *row)
00244 {
00245 if (!row || !table)
00246 return NULL;
00247
00248 CONTAINER_REMOVE( table->container, row );
00249 return row;
00250 }
00251
00259 void *
00260 netsnmp_tdata_remove_and_delete_row(netsnmp_tdata *table,
00261 netsnmp_tdata_row *row)
00262 {
00263 if (!row || !table)
00264 return NULL;
00265
00266
00267
00268
00269 netsnmp_tdata_remove_row(table, row);
00270 return netsnmp_tdata_delete_row(row);
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280 Netsnmp_Node_Handler _netsnmp_tdata_helper_handler;
00281
00283 netsnmp_mib_handler *
00284 netsnmp_get_tdata_handler(netsnmp_tdata *table)
00285 {
00286 netsnmp_mib_handler *ret = NULL;
00287
00288 if (!table) {
00289 snmp_log(LOG_INFO,
00290 "netsnmp_get_tdata_handler(NULL) called\n");
00291 return NULL;
00292 }
00293
00294 ret = netsnmp_create_handler(TABLE_TDATA_NAME,
00295 _netsnmp_tdata_helper_handler);
00296 if (ret) {
00297 ret->flags |= MIB_HANDLER_AUTO_NEXT;
00298 ret->myvoid = (void *) table;
00299 }
00300 return ret;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 int
00312 _netsnmp_tdata_helper_handler(netsnmp_mib_handler *handler,
00313 netsnmp_handler_registration *reginfo,
00314 netsnmp_agent_request_info *reqinfo,
00315 netsnmp_request_info *requests)
00316 {
00317 netsnmp_tdata *table = (netsnmp_tdata *) handler->myvoid;
00318 netsnmp_request_info *request;
00319 netsnmp_table_request_info *table_info;
00320 netsnmp_tdata_row *row;
00321
00322 switch ( reqinfo->mode ) {
00323 case MODE_GET:
00324 case MODE_SET_RESERVE1:
00325
00326 for (request = requests; request; request = request->next) {
00327 if (request->processed)
00328 continue;
00329
00330 table_info = netsnmp_extract_table_info(request);
00331 if (!table_info)
00332 continue;
00333 row = netsnmp_container_table_row_extract( request );
00334
00335 netsnmp_request_add_list_data(request,
00336 netsnmp_create_data_list(
00337 TABLE_TDATA_TABLE, table, NULL));
00338 netsnmp_request_add_list_data(request,
00339 netsnmp_create_data_list(
00340 TABLE_TDATA_ROW, row, NULL));
00341 }
00342 }
00343
00344
00345 return SNMP_ERR_NOERROR;
00346 }
00347
00348
00350 int
00351 netsnmp_tdata_register(netsnmp_handler_registration *reginfo,
00352 netsnmp_tdata *table,
00353 netsnmp_table_registration_info *table_info)
00354 {
00355 netsnmp_inject_handler(reginfo, netsnmp_get_tdata_handler(table));
00356 return netsnmp_container_table_register(reginfo, table_info,
00357 table->container, TABLE_CONTAINER_KEY_NETSNMP_INDEX);
00358 }
00359
00361 netsnmp_tdata *
00362 netsnmp_tdata_extract_table(netsnmp_request_info *request)
00363 {
00364 return (netsnmp_tdata *) netsnmp_request_get_list_data(request,
00365 TABLE_TDATA_TABLE);
00366 }
00367
00369 netsnmp_container *
00370 netsnmp_tdata_extract_container(netsnmp_request_info *request)
00371 {
00372 netsnmp_tdata *tdata = netsnmp_request_get_list_data(request,
00373 TABLE_TDATA_TABLE);
00374 return ( tdata ? tdata->container : NULL );
00375 }
00376
00378 netsnmp_tdata_row *
00379 netsnmp_tdata_extract_row(netsnmp_request_info *request)
00380 {
00381 return (netsnmp_tdata_row *) netsnmp_container_table_row_extract(request);
00382 }
00383
00386 void *
00387 netsnmp_tdata_extract_entry(netsnmp_request_info *request)
00388 {
00389 netsnmp_tdata_row *row =
00390 (netsnmp_tdata_row *) netsnmp_tdata_extract_row(request);
00391 if (row)
00392 return row->data;
00393 else
00394 return NULL;
00395 }
00396
00398 NETSNMP_INLINE void
00399 netsnmp_insert_tdata_row(netsnmp_request_info *request,
00400 netsnmp_tdata_row *row)
00401 {
00402 netsnmp_container_table_row_insert(request, (netsnmp_index *)row);
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00413 void *
00414 netsnmp_tdata_row_entry( netsnmp_tdata_row *row )
00415 {
00416 if (row)
00417 return row->data;
00418 else
00419 return NULL;
00420 }
00421
00423 netsnmp_tdata_row *
00424 netsnmp_tdata_row_first(netsnmp_tdata *table)
00425 {
00426 return (netsnmp_tdata_row *)CONTAINER_FIRST( table->container );
00427 }
00428
00430 netsnmp_tdata_row *
00431 netsnmp_tdata_row_get( netsnmp_tdata *table,
00432 netsnmp_tdata_row *row)
00433 {
00434 return CONTAINER_FIND( table->container, row );
00435 }
00436
00438 netsnmp_tdata_row *
00439 netsnmp_tdata_row_next( netsnmp_tdata *table,
00440 netsnmp_tdata_row *row)
00441 {
00442 return (netsnmp_tdata_row *)CONTAINER_NEXT( table->container, row );
00443 }
00444
00446 netsnmp_tdata_row *
00447 netsnmp_tdata_row_get_byidx(netsnmp_tdata *table,
00448 netsnmp_variable_list *indexes)
00449 {
00450 oid searchfor[ MAX_OID_LEN];
00451 size_t searchfor_len = MAX_OID_LEN;
00452
00453 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00454 indexes);
00455 return netsnmp_tdata_row_get_byoid(table, searchfor, searchfor_len);
00456 }
00457
00459 netsnmp_tdata_row *
00460 netsnmp_tdata_row_get_byoid(netsnmp_tdata *table,
00461 oid * searchfor, size_t searchfor_len)
00462 {
00463 netsnmp_index index;
00464 if (!table)
00465 return NULL;
00466
00467 index.oids = searchfor;
00468 index.len = searchfor_len;
00469 return CONTAINER_FIND( table->container, &index );
00470 }
00471
00474 netsnmp_tdata_row *
00475 netsnmp_tdata_row_next_byidx(netsnmp_tdata *table,
00476 netsnmp_variable_list *indexes)
00477 {
00478 oid searchfor[ MAX_OID_LEN];
00479 size_t searchfor_len = MAX_OID_LEN;
00480
00481 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00482 indexes);
00483 return netsnmp_tdata_row_next_byoid(table, searchfor, searchfor_len);
00484 }
00485
00488 netsnmp_tdata_row *
00489 netsnmp_tdata_row_next_byoid(netsnmp_tdata *table,
00490 oid * searchfor, size_t searchfor_len)
00491 {
00492 netsnmp_index index;
00493 if (!table)
00494 return NULL;
00495
00496 index.oids = searchfor;
00497 index.len = searchfor_len;
00498 return CONTAINER_NEXT( table->container, &index );
00499 }
00500
00501 int
00502 netsnmp_tdata_row_count(netsnmp_tdata *table)
00503 {
00504 if (!table)
00505 return 0;
00506 return CONTAINER_SIZE( table->container );
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00517 int
00518 netsnmp_tdata_compare_idx(netsnmp_tdata_row *row,
00519 netsnmp_variable_list *indexes)
00520 {
00521 oid searchfor[ MAX_OID_LEN];
00522 size_t searchfor_len = MAX_OID_LEN;
00523
00524 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00525 indexes);
00526 return netsnmp_tdata_compare_oid(row, searchfor, searchfor_len);
00527 }
00528
00530 int
00531 netsnmp_tdata_compare_oid(netsnmp_tdata_row *row,
00532 oid * compareto, size_t compareto_len)
00533 {
00534 netsnmp_index *index = (netsnmp_index *)row;
00535 return snmp_oid_compare( index->oids, index->len,
00536 compareto, compareto_len);
00537 }
00538
00539 int
00540 netsnmp_tdata_compare_subtree_idx(netsnmp_tdata_row *row,
00541 netsnmp_variable_list *indexes)
00542 {
00543 oid searchfor[ MAX_OID_LEN];
00544 size_t searchfor_len = MAX_OID_LEN;
00545
00546 build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00547 indexes);
00548 return netsnmp_tdata_compare_subtree_oid(row, searchfor, searchfor_len);
00549 }
00550
00551 int
00552 netsnmp_tdata_compare_subtree_oid(netsnmp_tdata_row *row,
00553 oid * compareto, size_t compareto_len)
00554 {
00555 netsnmp_index *index = (netsnmp_index *)row;
00556 return snmp_oidtree_compare( index->oids, index->len,
00557 compareto, compareto_len);
00558 }
00559