blob: 7c8a4c4865bfa9f48a3e7aac5b13648f6944c4de [file] [log] [blame]
/*
* 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>
#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>
/*
* 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 = netsnmp_memdup(row_oid, row_oid_len * sizeof(oid));
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 */
void *
netsnmp_table_row_extract(netsnmp_request_info *request)
{
return netsnmp_request_get_list_data(request, TABLE_ROW_DATA);
}
/** @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.
*
* ================================== */
/** @} */