diff options
Diffstat (limited to 'agent/helpers/table_row.c')
-rw-r--r-- | agent/helpers/table_row.c | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/agent/helpers/table_row.c b/agent/helpers/table_row.c new file mode 100644 index 0000000..2a33f23 --- /dev/null +++ b/agent/helpers/table_row.c @@ -0,0 +1,264 @@ +/* + * table_row.c + * + * Helper for registering single row slices of a shared table + * + * $Id$ + */ +#define TABLE_ROW_DATA "table_row" + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-features.h> + +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif + +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include <net-snmp/agent/table.h> +#include <net-snmp/agent/table_container.h> +#include <net-snmp/library/container.h> +#include <net-snmp/library/snmp_assert.h> + +netsnmp_feature_child_of(table_row_all, mib_helpers) + +netsnmp_feature_child_of(table_row_extract, table_row_all) + + +/* + * snmp.h:#define SNMP_MSG_INTERNAL_SET_BEGIN -1 + * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE1 0 + * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE2 1 + * snmp.h:#define SNMP_MSG_INTERNAL_SET_ACTION 2 + * snmp.h:#define SNMP_MSG_INTERNAL_SET_COMMIT 3 + * snmp.h:#define SNMP_MSG_INTERNAL_SET_FREE 4 + * snmp.h:#define SNMP_MSG_INTERNAL_SET_UNDO 5 + */ + +/** @defgroup table_row table_row + * Helps you implement a table shared across two or more subagents, + * or otherwise split into individual row slices. + * @ingroup table + * + * @{ + */ + +static Netsnmp_Node_Handler _table_row_handler; +static Netsnmp_Node_Handler _table_row_default_handler; + +/********************************************************************** + ********************************************************************** + * * + * * + * PUBLIC Registration functions * + * * + * * + ********************************************************************** + **********************************************************************/ + +/* ================================== + * + * Table Row API: Table maintenance + * + * This helper doesn't operate with the complete + * table, so these routines are not relevant. + * + * ================================== */ + + +/* ================================== + * + * Table Row API: MIB maintenance + * + * ================================== */ + +/** returns a netsnmp_mib_handler object for the table_container helper */ +netsnmp_mib_handler * +netsnmp_table_row_handler_get(void *row) +{ + netsnmp_mib_handler *handler; + + handler = netsnmp_create_handler("table_row", + _table_row_handler); + if(NULL == handler) { + snmp_log(LOG_ERR, + "malloc failure in netsnmp_table_row_register\n"); + return NULL; + } + + handler->myvoid = (void*)row; + handler->flags |= MIB_HANDLER_INSTANCE; + /* handler->flags |= MIB_HANDLER_AUTO_NEXT; ??? */ + + return handler; +} + +int +netsnmp_table_row_register(netsnmp_handler_registration *reginfo, + netsnmp_table_registration_info *tabreg, + void *row, netsnmp_variable_list *index) +{ + netsnmp_handler_registration *reg2; + netsnmp_mib_handler *handler; + oid row_oid[MAX_OID_LEN]; + size_t row_oid_len, len; + char tmp[SNMP_MAXBUF_MEDIUM]; + + if ((NULL == reginfo) || (NULL == reginfo->handler) || (NULL == tabreg)) { + snmp_log(LOG_ERR, "bad param in netsnmp_table_row_register\n"); + return SNMPERR_GENERR; + } + + /* + * The first table_row invoked for a particular table should + * register the full table as well, with a default handler to + * process requests for non-existent (or incomplete) rows. + * + * Subsequent table_row registrations attempting to set up + * this default handler would fail - preferably silently! + */ + snprintf(tmp, sizeof(tmp), "%s_table", reginfo->handlerName); + reg2 = netsnmp_create_handler_registration( + tmp, _table_row_default_handler, + reginfo->rootoid, reginfo->rootoid_len, + reginfo->modes); + netsnmp_register_table(reg2, tabreg); /* Ignore return value */ + + /* + * Adjust the OID being registered, to take account + * of the indexes and column range provided.... + */ + row_oid_len = reginfo->rootoid_len; + memcpy( row_oid, (u_char *) reginfo->rootoid, row_oid_len * sizeof(oid)); + row_oid[row_oid_len++] = 1; /* tableEntry */ + row_oid[row_oid_len++] = tabreg->min_column; + reginfo->range_ubound = tabreg->max_column; + reginfo->range_subid = row_oid_len-1; + build_oid_noalloc(&row_oid[row_oid_len], + MAX_OID_LEN-row_oid_len, &len, NULL, 0, index); + row_oid_len += len; + free(reginfo->rootoid); + reginfo->rootoid = snmp_duplicate_objid(row_oid, row_oid_len); + reginfo->rootoid_len = row_oid_len; + + + /* + * ... insert a minimal handler ... + */ + handler = netsnmp_table_row_handler_get(row); + netsnmp_inject_handler(reginfo, handler ); + + /* + * ... and register the row + */ + return netsnmp_register_handler(reginfo); +} + + +/** return the row data structure supplied to the table_row helper */ +#ifndef NETSNMP_FEATURE_REMOVE_TABLE_ROW_EXTRACT +void * +netsnmp_table_row_extract(netsnmp_request_info *request) +{ + return netsnmp_request_get_list_data(request, TABLE_ROW_DATA); +} +#endif /* NETSNMP_FEATURE_REMOVE_TABLE_ROW_EXTRACT */ +/** @cond */ + +/********************************************************************** + ********************************************************************** + * * + * * + * netsnmp_table_row_helper_handler() * + * * + * * + ********************************************************************** + **********************************************************************/ + +static int +_table_row_handler(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + int rc = SNMP_ERR_NOERROR; + netsnmp_request_info *req; + void *row; + + /** sanity checks */ + netsnmp_assert((NULL != handler) && (NULL != handler->myvoid)); + netsnmp_assert((NULL != reginfo) && (NULL != reqinfo)); + + DEBUGMSGTL(("table_row", "Mode %s, Got request:\n", + se_find_label_in_slist("agent_mode",reqinfo->mode))); + + /* + * First off, get our pointer from the handler. + * This contains the row that was actually registered. + * Make this available for each of the requests passed in. + */ + row = handler->myvoid; + for (req = requests; req; req=req->next) + netsnmp_request_add_list_data(req, + netsnmp_create_data_list(TABLE_ROW_DATA, row, NULL)); + + /* + * Then call the next handler, to actually process the request + */ + rc = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests); + if (rc != SNMP_ERR_NOERROR) { + DEBUGMSGTL(("table_row", "next handler returned %d\n", rc)); + } + + return rc; +} + +static int +_table_row_default_handler(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + netsnmp_request_info *req; + netsnmp_table_request_info *table_info; + netsnmp_table_registration_info *tabreg; + + tabreg = netsnmp_find_table_registration_info(reginfo); + for ( req=requests; req; req=req->next ) { + table_info = netsnmp_extract_table_info( req ); + if (( table_info->colnum >= tabreg->min_column ) || + ( table_info->colnum <= tabreg->max_column )) { + netsnmp_set_request_error( reqinfo, req, SNMP_NOSUCHINSTANCE ); + } else { + netsnmp_set_request_error( reqinfo, req, SNMP_NOSUCHOBJECT ); + } + } + return SNMP_ERR_NOERROR; +} +/** @endcond */ + + +/* ================================== + * + * Table Row API: Row operations + * + * This helper doesn't operate with the complete + * table, so these routines are not relevant. + * + * ================================== */ + + +/* ================================== + * + * Table Row API: Index operations + * + * This helper doesn't operate with the complete + * table, so these routines are not relevant. + * + * ================================== */ + +/** @} */ |