diff options
Diffstat (limited to 'agent/mibgroup/if-mib/ifTable/ifTable_data_access.c')
-rw-r--r-- | agent/mibgroup/if-mib/ifTable/ifTable_data_access.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/agent/mibgroup/if-mib/ifTable/ifTable_data_access.c b/agent/mibgroup/if-mib/ifTable/ifTable_data_access.c new file mode 100644 index 0000000..327c3dc --- /dev/null +++ b/agent/mibgroup/if-mib/ifTable/ifTable_data_access.c @@ -0,0 +1,480 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 1.17 $ of : mfd-data-access.m2c,v $ + * + * $Id: ifTable_data_access.c 16790 2008-02-12 19:05:24Z hardaker $ + */ +/* + * standard Net-SNMP includes + */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +/* + * include our parent header + */ +#include "ifTable.h" +#include "ifTable_defs.h" + +#include "ifTable_data_access.h" + +#ifdef USING_IP_MIB_IPV4INTERFACETABLE_IPV4INTERFACETABLE_MODULE +# include "mibgroup/ip-mib/ipv4InterfaceTable/ipv4InterfaceTable.h" +#endif + +/* + * flag so we know not to set row/table last change times + * during startup. + */ +static int _first_load = 1; + +/** @ingroup interface + * @defgroup data_access data_access: Routines to access data + * + * These routines are used to locate the data used to satisfy + * requests. + * + * @{ + */ +/********************************************************************** + ********************************************************************** + *** + *** Table ifTable + *** + ********************************************************************** + **********************************************************************/ +/* + * IF-MIB::ifTable is subid 2 of interfaces. + * Its status is Current. + * OID: .1.3.6.1.2.1.2.2, length: 8 + */ + +/** + * initialization for ifTable data access + * + * This function is called during startup to allow you to + * allocate any resources you need for the data table. + * + * @param ifTable_reg + * Pointer to ifTable_registration + * + * @retval MFD_SUCCESS : success. + * @retval MFD_ERROR : unrecoverable error. + */ +int +ifTable_init_data(ifTable_registration * ifTable_reg) +{ + DEBUGMSGTL(("verbose:ifTable:ifTable_init_data", "called\n")); + + /* + * TODO:303:o: Initialize ifTable data. + */ + + return MFD_SUCCESS; +} /* ifTable_init_data */ + +/** + * container overview + * + */ + +/** + * container initialization + * + * @param container_ptr_ptr A pointer to a container pointer. If you + * create a custom container, use this parameter to return it + * to the MFD helper. If set to NULL, the MFD helper will + * allocate a container for you. + * @param cache A pointer to a cache structure. You can set the timeout + * and other cache flags using this pointer. + * + * This function is called at startup to allow you to customize certain + * aspects of the access method. For the most part, it is for advanced + * users. The default code should suffice for most cases. If no custom + * container is allocated, the MFD code will create one for your. + * + * This is also the place to set up cache behavior. The default, to + * simply set the cache timeout, will work well with the default + * container. If you are using a custom container, you may want to + * look at the cache helper documentation to see if there are any + * flags you want to set. + * + * @remark + * This would also be a good place to do any initialization needed + * for you data source. For example, opening a connection to another + * process that will supply the data, opening a database, etc. + */ +void +ifTable_container_init(netsnmp_container **container_ptr_ptr, + netsnmp_cache * cache) +{ + DEBUGMSGTL(("verbose:ifTable:ifTable_container_init", "called\n")); + + if (NULL == container_ptr_ptr) { + snmp_log(LOG_ERR, + "bad container param to ifTable_container_init\n"); + return; + } + + /* + * For advanced users, you can use a custom container. If you + * do not create one, one will be created for you. + */ + *container_ptr_ptr = NULL; + + if (NULL == cache) { + snmp_log(LOG_ERR, "bad cache param to ifTable_container_init\n"); + return; + } + + /* + * TODO:345:A: Set up ifTable cache properties. + * + * Also for advanced users, you can set parameters for the + * cache. Do not change the magic pointer, as it is used + * by the MFD helper. To completely disable caching, set + * cache->enabled to 0. + */ + /* + * since we set AUTO_RELOAD below, this timer controls how + * often the cache is reloaded. A 10 Mbps stream can wrap if*Octets in ~57 minutes. + * At 100 Mbps it is ~5 minutes, and at 1 Gbps, ~34 seconds. + */ + cache->timeout = IFTABLE_CACHE_TIMEOUT; /* seconds */ + + /* + * don't release resources + */ + cache->flags |= + (NETSNMP_CACHE_DONT_AUTO_RELEASE | NETSNMP_CACHE_DONT_FREE_EXPIRED + | NETSNMP_CACHE_DONT_FREE_BEFORE_LOAD | NETSNMP_CACHE_PRELOAD | + NETSNMP_CACHE_AUTO_RELOAD | NETSNMP_CACHE_DONT_INVALIDATE_ON_SET); +} /* ifTable_container_init */ + +/** + * check entry for update + * + */ +static void +_check_interface_entry_for_updates(ifTable_rowreq_ctx * rowreq_ctx, + netsnmp_container *ifcontainer) +{ + char oper_changed = 0; + u_long lastchange = rowreq_ctx->data.ifLastChange; + + /* + * check for matching entry. We can do this directly, since + * both containers use the same index. + */ + netsnmp_interface_entry *ifentry = + CONTAINER_FIND(ifcontainer, rowreq_ctx); + +#ifdef USING_IP_MIB_IPV4INTERFACETABLE_IPV4INTERFACETABLE_MODULE + /* + * give ipv4If table a crack at the entry + */ + ipv4InterfaceTable_check_entry_for_updates(rowreq_ctx, ifentry); +#endif + +#ifdef USING_IP_MIB_IPV6INTERFACETABLE_IPV6INTERFACETABLE_MODULE + /* + * give ipv6If table a crack at the entry + */ + ipv6InterfaceTable_check_entry_for_updates(rowreq_ctx, ifentry); +#endif + + if (NULL == ifentry) { + /* + * if this is the first time we detected that this interface is + * missing, set admin/oper status down, and set last change. + * + * yyy-rks: when, if ever, would we consider an entry + * deleted (and thus need to update ifTableLastChanged)? + */ + if (!rowreq_ctx->known_missing) { + DEBUGMSGTL(("ifTable:access", "updating missing entry\n")); + rowreq_ctx->known_missing = 1; + rowreq_ctx->data.ifAdminStatus = IFADMINSTATUS_DOWN; + if ((!(rowreq_ctx->data.ifentry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_LASTCHANGE)) + && (rowreq_ctx->data.ifOperStatus != IFOPERSTATUS_DOWN)) + oper_changed = 1; + rowreq_ctx->data.ifOperStatus = IFOPERSTATUS_DOWN; + } + } else { + DEBUGMSGTL(("ifTable:access", "updating existing entry\n")); + +#ifdef USING_IF_MIB_IFXTABLE_IFXTABLE_MODULE + { + int rc = strcmp(rowreq_ctx->data.ifName, + ifentry->name); + if (rc != 0) { + static int logged = 0; + if (!logged) { + snmp_log(LOG_ERR, "Name of an interface changed. Such " \ + "interfaces will keep its old name in IF-MIB.\n"); + logged = 1; + } + DEBUGMSGTL(("ifTable:access", "interface %s changed name to %s, ignoring\n", + rowreq_ctx->data.ifName, ifentry->name)); + } + } +#endif + /* + * if the interface was missing, but came back, clear the + * missing flag and set the discontinuity time. (if an os keeps + * persistent counters, tough cookies. We'll cross that + * bridge if we come to it). + */ + if (rowreq_ctx->known_missing) { + rowreq_ctx->known_missing = 0; +#ifdef USING_IF_MIB_IFXTABLE_IFXTABLE_MODULE + rowreq_ctx->data.ifCounterDiscontinuityTime = + netsnmp_get_agent_uptime(); +#endif + } + + /* + * Check for changes, then update + */ + if ((!(ifentry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_LASTCHANGE)) + && (rowreq_ctx->data.ifOperStatus != ifentry->oper_status)) + oper_changed = 1; + netsnmp_access_interface_entry_copy(rowreq_ctx->data.ifentry, + ifentry); + + /* + * remove entry from temporary ifcontainer + */ + CONTAINER_REMOVE(ifcontainer, ifentry); + netsnmp_access_interface_entry_free(ifentry); + } + + /* + * if ifOperStatus changed, update ifLastChange + */ + if (oper_changed) + rowreq_ctx->data.ifLastChange = netsnmp_get_agent_uptime(); + else + rowreq_ctx->data.ifLastChange = lastchange; +} + +/** + * add new entry + */ +static void +_add_new_interface(netsnmp_interface_entry *ifentry, + netsnmp_container *container) +{ + ifTable_rowreq_ctx *rowreq_ctx; + + DEBUGMSGTL(("ifTable:access", "creating new entry\n")); + + /* + * allocate an row context and set the index(es), then add it to + * the container and set ifTableLastChanged. + */ + rowreq_ctx = ifTable_allocate_rowreq_ctx(ifentry); + if ((NULL != rowreq_ctx) && + (MFD_SUCCESS == ifTable_indexes_set(rowreq_ctx, ifentry->index))) { + CONTAINER_INSERT(container, rowreq_ctx); + /* + * fix this when we hit an arch that reports its own last change + */ + netsnmp_assert(0 == (ifentry->ns_flags & + NETSNMP_INTERFACE_FLAGS_HAS_LASTCHANGE)); + if (0 == _first_load) { + rowreq_ctx->data.ifLastChange = netsnmp_get_agent_uptime(); + ifTable_lastChange_set(rowreq_ctx->data.ifLastChange); + } +#ifdef USING_IP_MIB_IPV4INTERFACETABLE_IPV4INTERFACETABLE_MODULE + /* + * give ipv4If table a crack at the entry + */ + ipv4InterfaceTable_check_entry_for_updates(rowreq_ctx, ifentry); +#endif +#ifdef USING_IP_MIB_IPV6INTERFACETABLE_IPV6INTERFACETABLE_MODULE + /* + * give ipv6If table a crack at the entry + */ + ipv6InterfaceTable_check_entry_for_updates(rowreq_ctx, ifentry); +#endif + } else { + if (rowreq_ctx) { + snmp_log(LOG_ERR, "error setting index while loading " + "ifTable cache.\n"); + ifTable_release_rowreq_ctx(rowreq_ctx); + } else { + snmp_log(LOG_ERR, "memory allocation failed while loading " + "ifTable cache.\n"); + netsnmp_access_interface_entry_free(ifentry); + } + } +} + +/** + * container shutdown + * + * @param container_ptr A pointer to the container. + * + * This function is called at shutdown to allow you to customize certain + * aspects of the access method. For the most part, it is for advanced + * users. The default code should suffice for most cases. + * + * This function is called before ifTable_container_free(). + * + * @remark + * This would also be a good place to do any cleanup needed + * for you data source. For example, closing a connection to another + * process that supplied the data, closing a database, etc. + */ +void +ifTable_container_shutdown(netsnmp_container *container_ptr) +{ + DEBUGMSGTL(("verbose:ifTable:ifTable_container_shutdown", "called\n")); + + if (NULL == container_ptr) { + snmp_log(LOG_ERR, "bad params to ifTable_container_shutdown\n"); + return; + } + +} /* ifTable_container_shutdown */ + +/** + * load initial data + * + * TODO:350:M: Implement ifTable data load + * This function will also be called by the cache helper to load + * the container again (after the container free function has been + * called to free the previous contents). + * + * @param container container to which items should be inserted + * + * @retval MFD_SUCCESS : success. + * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source + * @retval MFD_ERROR : other error. + * + * This function is called to load the index(es) (and data, optionally) + * for the every row in the data set. + * + * @remark + * While loading the data, the only important thing is the indexes. + * If access to your data is cheap/fast (e.g. you have a pointer to a + * structure in memory), it would make sense to update the data here. + * If, however, the accessing the data invovles more work (e.g. parsing + * some other existing data, or peforming calculations to derive the data), + * then you can limit yourself to setting the indexes and saving any + * information you will need later. Then use the saved information in + * ifTable_row_prep() for populating data. + * + * @note + * If you need consistency between rows (like you want statistics + * for each row to be from the same time frame), you should set all + * data here. + * + */ +int +ifTable_container_load(netsnmp_container *container) +{ + netsnmp_container *ifcontainer; + + DEBUGMSGTL(("verbose:ifTable:ifTable_container_load", "called\n")); + + /* + * TODO:351:M: |-> Load/update data in the ifTable container. + * loop over your ifTable data, allocate a rowreq context, + * set the index(es) [and data, optionally] and insert into + * the container. + */ + /* + * ifTable gets its data from the netsnmp_interface API. + */ + ifcontainer = + netsnmp_access_interface_container_load(NULL, + NETSNMP_ACCESS_INTERFACE_INIT_NOFLAGS); + if (NULL == ifcontainer) + return MFD_RESOURCE_UNAVAILABLE; /* msg already logged */ + + /* + * we just got a fresh copy of interface data. compare it to + * what we've already got, and make any adjustements... + */ + CONTAINER_FOR_EACH(container, (netsnmp_container_obj_func *) + _check_interface_entry_for_updates, ifcontainer); + + /* + * now add any new interfaces + */ + CONTAINER_FOR_EACH(ifcontainer, + (netsnmp_container_obj_func *) _add_new_interface, + container); + + /* + * free the container. we've either claimed each ifentry, or released it, + * so the dal function doesn't need to clear the container. + */ + netsnmp_access_interface_container_free(ifcontainer, + NETSNMP_ACCESS_INTERFACE_FREE_DONT_CLEAR); + + DEBUGMSGT(("verbose:ifTable:ifTable_cache_load", + "%d records\n", CONTAINER_SIZE(container))); + + if (_first_load) + _first_load = 0; + + return MFD_SUCCESS; +} /* ifTable_container_load */ + +/** + * container clean up + * + * @param container container with all current items + * + * This optional callback is called prior to all + * item's being removed from the container. If you + * need to do any processing before that, do it here. + * + * @note + * The MFD helper will take care of releasing all the row contexts. + * + */ +void +ifTable_container_free(netsnmp_container *container) +{ + DEBUGMSGTL(("verbose:ifTable:ifTable_container_free", "called\n")); + + /* + * TODO:380:M: Free ifTable container data. + */ +} /* ifTable_container_free */ + +/** + * prepare row for processing. + * + * When the agent has located the row for a request, this function is + * called to prepare the row for processing. If you fully populated + * the data context during the index setup phase, you may not need to + * do anything. + * + * @param rowreq_ctx pointer to a context. + * + * @retval MFD_SUCCESS : success. + * @retval MFD_ERROR : other error. + */ +int +ifTable_row_prep(ifTable_rowreq_ctx * rowreq_ctx) +{ + DEBUGMSGTL(("verbose:ifTable:ifTable_row_prep", "called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + /* + * TODO:390:o: Prepare row for request. + * If populating row data was delayed, this is the place to + * fill in the row for this request. + */ + + return MFD_SUCCESS; +} /* ifTable_row_prep */ + +/** @} */ |