#include <net-snmp/net-snmp-config.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"

/*
 * 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_iterator(
        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;


    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:
                        logh->enabled = 1;
                        break;
                    case RS_NOTINSERVICE:
                    case RS_CREATEANDWAIT:
                        logh->enabled = 0;
                        break;
		    case RS_DESTROY:
		        netsnmp_remove_loghandler( logh );
                        break;
		}
	        break;
	    }
	}
	break;
    }

    return SNMP_ERR_NOERROR;
}
