summaryrefslogtreecommitdiff
path: root/agent/mibgroup/agent/nsLogging.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/agent/nsLogging.c')
-rw-r--r--agent/mibgroup/agent/nsLogging.c472
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;
+}