table_tdata.c

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     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      * free the memory we can 
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      * return the void * pointer 
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      * The individual index values probably won't be needed,
00204      *    so this memory can be released.
00205      * Note that this is purely internal to the helper.
00206      * The calling application can set this flag as
00207      *    a hint to the helper that these values aren't
00208      *    required, but it's up to the helper as to
00209      *    whether it takes any notice or not!
00210      */
00211     if (table->flags & TDATA_FLAG_NO_STORE_INDEXES) {
00212         snmp_free_varbind(row->indexes);
00213         row->indexes = NULL;
00214     }
00215 
00216     /*
00217      * add this row to the stored table
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      * remove it from the list 
00268      */
00269     netsnmp_tdata_remove_row(table, row);
00270     return netsnmp_tdata_delete_row(row);
00271 }
00272 
00273 
00274 /* ==================================
00275  *
00276  * TData API: MIB maintenance
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  * The helper handler that takes care of passing a specific row of
00305  * data down to the lower handler(s).  The table_container helper
00306  * has already taken care of identifying the appropriate row of the
00307  * table (and converting GETNEXT requests into an equivalent GET request)
00308  * So all we need to do here is make sure that the row is accessible
00309  * using tdata-style retrieval techniques as well.
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;           /* ack */
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     /* next handler called automatically - 'AUTO_NEXT' */
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  * Generic API: Row operations
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  * Generic API: Index operations on a 'tdata' table
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 

net-snmpに対してSat Sep 5 13:14:27 2009に生成されました。  doxygen 1.4.7