| /* |
| * 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. |
| * |
| * ================================== */ |
| |
| /** @} */ |