diff options
Diffstat (limited to 'agent/mibgroup/agent/nsLogging.c')
-rw-r--r-- | agent/mibgroup/agent/nsLogging.c | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/agent/mibgroup/agent/nsLogging.c b/agent/mibgroup/agent/nsLogging.c new file mode 100644 index 0000000..7f20bdb --- /dev/null +++ b/agent/mibgroup/agent/nsLogging.c @@ -0,0 +1,472 @@ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-features.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include <net-snmp/agent/scalar.h> + +#ifdef HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif + +#include <net-snmp/library/snmp_logging.h> +#include "agent/nsLogging.h" + +netsnmp_feature_require(logging_external) +#ifndef NETSNMP_NO_WRITE_SUPPORT +netsnmp_feature_require(table_iterator_insert_context) +#endif /* NETSNMP_NO_WRITE_SUPPORT */ + +/* + * OID and columns for the logging table. + */ + +#define NSLOGGING_TYPE 3 +#define NSLOGGING_MAXLEVEL 4 +#define NSLOGGING_STATUS 5 + +void +init_nsLogging(void) +{ + netsnmp_table_registration_info *table_info; + netsnmp_iterator_info *iinfo; + + const oid nsLoggingTable_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 1, 7, 2, 1}; + + /* + * Register the table. + * We need to define the column structure and indexing.... + */ + + table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); + if (!table_info) { + return; + } + netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, + ASN_PRIV_IMPLIED_OCTET_STR, 0); + table_info->min_column = NSLOGGING_TYPE; + table_info->max_column = NSLOGGING_STATUS; + + + /* + * .... and the iteration information .... + */ + iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info); + if (!iinfo) { + return; + } + iinfo->get_first_data_point = get_first_logging_entry; + iinfo->get_next_data_point = get_next_logging_entry; + iinfo->table_reginfo = table_info; + + + /* + * .... and register the table with the agent. + */ + netsnmp_register_table_iterator2( + netsnmp_create_handler_registration( + "tzLoggingTable", handle_nsLoggingTable, + nsLoggingTable_oid, OID_LENGTH(nsLoggingTable_oid), + HANDLER_CAN_RWRITE), + iinfo); +} + + +/* + * nsLoggingTable handling + */ + +netsnmp_variable_list * +get_first_logging_entry(void **loop_context, void **data_context, + netsnmp_variable_list *index, + netsnmp_iterator_info *data) +{ + long temp; + netsnmp_log_handler *logh_head = get_logh_head(); + if ( !logh_head ) + return NULL; + + temp = logh_head->priority; + snmp_set_var_value(index, (u_char*)&temp, + sizeof(temp)); + if ( logh_head->token ) + snmp_set_var_value(index->next_variable, (const u_char*)logh_head->token, + strlen(logh_head->token)); + else + snmp_set_var_value(index->next_variable, NULL, 0); + *loop_context = (void*)logh_head; + *data_context = (void*)logh_head; + return index; +} + +netsnmp_variable_list * +get_next_logging_entry(void **loop_context, void **data_context, + netsnmp_variable_list *index, + netsnmp_iterator_info *data) +{ + long temp; + netsnmp_log_handler *logh = (netsnmp_log_handler *)*loop_context; + logh = logh->next; + + if ( !logh ) + return NULL; + + temp = logh->priority; + snmp_set_var_value(index, (u_char*)&temp, + sizeof(temp)); + if ( logh->token ) + snmp_set_var_value(index->next_variable, (const u_char*)logh->token, + strlen(logh->token)); + else + snmp_set_var_value(index->next_variable, NULL, 0); + *loop_context = (void*)logh; + *data_context = (void*)logh; + return index; +} + + +int +handle_nsLoggingTable(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + long temp; + netsnmp_request_info *request = NULL; + netsnmp_table_request_info *table_info = NULL; + netsnmp_log_handler *logh = NULL; + netsnmp_variable_list *idx = NULL; + + switch (reqinfo->mode) { + + case MODE_GET: + for (request=requests; request; request=request->next) { + if (request->processed != 0) + continue; + logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); + table_info = netsnmp_extract_table_info(request); + + switch (table_info->colnum) { + case NSLOGGING_TYPE: + if (!logh) { + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + temp = logh->type; + snmp_set_var_typed_value(request->requestvb, ASN_INTEGER, + (u_char*)&temp, + sizeof(temp)); + break; + + case NSLOGGING_MAXLEVEL: + if (!logh) { + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + temp = logh->pri_max; + snmp_set_var_typed_value(request->requestvb, ASN_INTEGER, + (u_char*)&temp, + sizeof(temp)); + break; + + case NSLOGGING_STATUS: + if (!logh) { + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + temp = (logh->type ? + (logh->enabled ? + RS_ACTIVE: + RS_NOTINSERVICE) : + RS_NOTREADY); + snmp_set_var_typed_value(request->requestvb, ASN_INTEGER, + (u_char*)&temp, sizeof(temp)); + break; + + default: + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); + continue; + } + } + break; + + +#ifndef NETSNMP_NO_WRITE_SUPPORT + case MODE_SET_RESERVE1: + for (request=requests; request; request=request->next) { + if ( request->status != 0 ) { + return SNMP_ERR_NOERROR; /* Already got an error */ + } + logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); + table_info = netsnmp_extract_table_info(request); + + switch (table_info->colnum) { + case NSLOGGING_TYPE: + if ( request->requestvb->type != ASN_INTEGER ) { + netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); + return SNMP_ERR_WRONGTYPE; + } + if (*request->requestvb->val.integer < 0 ) { + netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE); + return SNMP_ERR_WRONGVALUE; + } + /* + * It's OK to create a new logging entry + * (either in one go, or built up using createAndWait) + * but it's not possible to change the type of an entry + * once it's been created. + */ + if (logh && logh->type) { + netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOTWRITABLE); + return SNMP_ERR_NOTWRITABLE; + } + break; + + case NSLOGGING_MAXLEVEL: + if ( request->requestvb->type != ASN_INTEGER ) { + netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); + return SNMP_ERR_WRONGTYPE; + } + if (*request->requestvb->val.integer < 0 || + *request->requestvb->val.integer > 7 ) { + netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE); + return SNMP_ERR_WRONGVALUE; + } + break; + + case NSLOGGING_STATUS: + if ( request->requestvb->type != ASN_INTEGER ) { + netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); + return SNMP_ERR_WRONGTYPE; + } + switch ( *request->requestvb->val.integer ) { + case RS_ACTIVE: + case RS_NOTINSERVICE: + /* + * Can only work on existing rows + */ + if (!logh) { + netsnmp_set_request_error(reqinfo, request, + SNMP_ERR_INCONSISTENTVALUE); + return SNMP_ERR_INCONSISTENTVALUE; + } + break; + + case RS_CREATEANDWAIT: + case RS_CREATEANDGO: + /* + * Can only work with new rows + */ + if (logh) { + netsnmp_set_request_error(reqinfo, request, + SNMP_ERR_INCONSISTENTVALUE); + return SNMP_ERR_INCONSISTENTVALUE; + } + + /* + * Normally, we'd create the row at a later stage + * (probably during the RESERVE2 or ACTION passes) + * + * But we need to check that the values are + * consistent during the ACTION pass (which is the + * latest that an error can be safely handled), + * so the values all need to be set up before this + * (i.e. during the RESERVE2 pass) + * So the new row needs to be created before that + * in order to have somewhere to put them. + * + * That's why we're doing this here. + */ + idx = table_info->indexes; + logh = netsnmp_register_loghandler( + /* not really, but we need a valid type */ + NETSNMP_LOGHANDLER_STDOUT, + *idx->val.integer); + if (!logh) { + netsnmp_set_request_error(reqinfo, request, + SNMP_ERR_GENERR); /* ??? */ + return SNMP_ERR_GENERR; + } + idx = idx->next_variable; + logh->type = 0; + logh->token = strdup((char *) idx->val.string); + netsnmp_insert_iterator_context(request, (void*)logh); + break; + + case RS_DESTROY: + /* + * Can work with new or existing rows + */ + break; + + case RS_NOTREADY: + default: + netsnmp_set_request_error(reqinfo, request, + SNMP_ERR_WRONGVALUE); + return SNMP_ERR_WRONGVALUE; + } + break; + + default: + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); + return SNMP_NOSUCHOBJECT; + } + } + break; + + + case MODE_SET_RESERVE2: + for (request=requests; request; request=request->next) { + if ( request->status != 0 ) { + return SNMP_ERR_NOERROR; /* Already got an error */ + } + logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); + table_info = netsnmp_extract_table_info(request); + + switch (table_info->colnum) { + case NSLOGGING_TYPE: + /* + * If we're creating a row using createAndGo, + * we need to set the type early, so that we + * can validate it in the ACTION pass. + * + * Remember that we need to be able to reverse this + */ + if ( logh ) + logh->type = *request->requestvb->val.integer; + break; + /* + * Don't need to handle nsLogToken or nsLogStatus in this pass + */ + } + } + break; + + case MODE_SET_ACTION: + for (request=requests; request; request=request->next) { + if (request->processed != 0) + continue; + if ( request->status != 0 ) { + return SNMP_ERR_NOERROR; /* Already got an error */ + } + logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); + table_info = netsnmp_extract_table_info(request); + + switch (table_info->colnum) { + case NSLOGGING_STATUS: + /* + * This is where we can check the internal consistency + * of the request. Basically, for a row to be marked + * 'active', then there needs to be a valid type value. + */ + switch ( *request->requestvb->val.integer ) { + case RS_ACTIVE: + case RS_CREATEANDGO: + if ( !logh || !logh->type ) { + netsnmp_set_request_error(reqinfo, request, + SNMP_ERR_INCONSISTENTVALUE); + return SNMP_ERR_INCONSISTENTVALUE; + } + break; + } + break; + /* + * Don't need to handle nsLogToken or nsLogType in this pass + */ + } + } + break; + + case MODE_SET_FREE: + case MODE_SET_UNDO: + /* + * If any resources were allocated in either of the + * two RESERVE passes, they need to be released here, + * and any assignments (in RESERVE2) reversed. + * + * Nothing additional will have been done during ACTION + * so this same code can do for UNDO as well. + */ + for (request=requests; request; request=request->next) { + if (request->processed != 0) + continue; + logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); + table_info = netsnmp_extract_table_info(request); + + switch (table_info->colnum) { + case NSLOGGING_TYPE: + /* + * If we've been setting the type, and the request + * has failed, then revert to an unset type. + * + * We need to be careful here - if the reason it failed is + * that the type was already set, then we shouldn't "undo" + * the assignment (since it won't actually have been made). + * + * Check the current value against the 'new' one. If they're + * the same, then this is probably a successful assignment, + * and the failure was elsewhere, so we need to undo it. + * (Or else there was an attempt to write the same value!) + */ + if ( logh && logh->type == *request->requestvb->val.integer ) + logh->type = 0; + break; + + case NSLOGGING_STATUS: + temp = *request->requestvb->val.integer; + if ( logh && ( temp == RS_CREATEANDGO || + temp == RS_CREATEANDWAIT)) { + netsnmp_remove_loghandler( logh ); + } + break; + /* + * Don't need to handle nsLogToken in this pass + */ + } + } + break; + + + case MODE_SET_COMMIT: + for (request=requests; request; request=request->next) { + if (request->processed != 0) + continue; + if ( request->status != 0 ) { + return SNMP_ERR_NOERROR; /* Already got an error */ + } + logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); + if (!logh) { + netsnmp_set_request_error(reqinfo, request, SNMP_ERR_COMMITFAILED); + return SNMP_ERR_COMMITFAILED; /* Shouldn't happen! */ + } + table_info = netsnmp_extract_table_info(request); + + switch (table_info->colnum) { + case NSLOGGING_MAXLEVEL: + logh->pri_max = *request->requestvb->val.integer; + break; + + case NSLOGGING_STATUS: + switch (*request->requestvb->val.integer) { + case RS_ACTIVE: + case RS_CREATEANDGO: + netsnmp_enable_this_loghandler(logh); + break; + case RS_NOTINSERVICE: + case RS_CREATEANDWAIT: + netsnmp_disable_this_loghandler(logh); + break; + case RS_DESTROY: + netsnmp_remove_loghandler( logh ); + break; + } + break; + } + } + break; +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + } + + return SNMP_ERR_NOERROR; +} |