/*
 * This file implements the WWW-RESP-NOTIFY-MIB module.
 * $Id: resp-notify-mib.c 8676 2008-01-17 23:11:17Z ispringer $
 */
/* Includes */
#include <sys/types.h>

/* Apache includes */
#include "httpd.h"
#include "http_config.h"

/* UCD-SNMP includes */
#include "ucd-snmp-config.h"
#include "asn1.h"
#include "snmp_api.h"
#include "snmp_impl.h"
#include "snmp_client.h"
#include "snmp_debug.h"
#include "snmp_vars.h"
#include "var_struct.h"
#include "agent_trap.h"

/* Conductor includes */
#include "covalent-snmp-config.h"
#include "ietf-mibs/snmp-generic.h"
#include "covalent-snmp-logging.h"
#include "covalent-snmp.h"
#include "ietf-mibs/snmpv2-tc.h"
#include "resp-notify-mib.h"

#ifndef SNMP_MIN
#define SNMP_MIN(a,b)   (((a)<(b)) ? (a) : (b))
#endif

#define NEXT    FALSE
#define EXACT   TRUE

#define CTNOTIFYENABLEVALUE              2

#ifdef COVALENT_RESP_NOTIFY_MIB
extern int nr_www_services; /* number of www services */

/*
 * Function:
 *       ctNotifyResponse_enabled
 * Parameters:
 *       int wwwServiceIndex - The service index from which this response was
 *                             send.
 *       int responseType    - The response that was returned to the client.
 * Returns: int - '0' meaning notify disabled for this response type.
 *                '1' meaning notify enabled for this response type.
 * Description:
 *       This function should filter the notification send.
 *       It should filter on the ctNotifyResponseTable, but is
 *       currently implemented only to return all 4xx and 5xx
 *       response codes. (See HTTP/1.1 standard)
 */
int
ctNotifyResponse_enabled(int wwwServiceIndex, int responseType)
{
    if (responseType >= 400) {
	return(1);
    }
    return(0);
}


int
get_ctResponseNotifyEnable_wwwServiceIndex(struct variable *vp,
        oid *name, size_t *namelength,
        oid *newname, size_t *newname_length,
        int *index)
{
oid *ptr;

    *newname_length = vp->namelen;
    memcpy((char *)newname, (char *)vp->name, *newname_length * sizeof(oid));
    ptr = &(newname[ (*newname_length)++ ]);
    while (*index <= nr_www_services) {
        *ptr = *index;
        if ( 0 >= snmp_oid_compare(name, SNMP_MIN(*namelength,*newname_length),
                                newname, SNMP_MIN(*namelength, *newname_length))) {
            return(*index);
        }
        (*index)++;
    }
    return(0);
}



int
get_ctResponseNotifyEnableIndex(oid *name, size_t *name_length, oid *newname, size_t *newname_length, int exact)
{
int     responseArrayIndex;
int     result;
int     newnameLen = (*newname_length)++;

    responseArrayIndex = 0;
    while (responseTypes[ responseArrayIndex ] > 0) {
        newname[ newnameLen ] = responseTypes[responseArrayIndex];
        result = snmp_oid_compare(name, *name_length, newname, *newname_length);
        if (((exact == EXACT) && (result == 0)) || ((exact == NEXT) && (0 > result))) {
            return(responseTypes[responseArrayIndex]);
        } /* if */
        responseArrayIndex++;
    } /* for */
return(-1);
}


static unsigned char *
read_ctNotifyEnableEntry(struct variable *vp,
    oid     *name,
    size_t  *length,
    int     exact,
    size_t  *var_len,
    WriteMethod **write_method)
{
oid newname[ MAX_OID_LEN ];
size_t newname_length;
int wwwServiceIndex = 1;
int responseTypeIndex;

    do {
        wwwServiceIndex++;
        if (get_ctResponseNotifyEnable_wwwServiceIndex(vp, name, length, newname, &newname_length, &wwwServiceIndex)) {
            responseTypeIndex = get_ctResponseNotifyEnableIndex(name, length, newname, &newname_length, exact);
        } else {
            return(NULL);
        }
    } while ( responseTypeIndex < 0 );

    *length = newname_length;
    memcpy( (char *)name,(char *)newname, *length * sizeof(oid));
    *write_method = NULL;

    /* This could be optimised, but left in place for similarity for nono's. */
    switch (vp->magic) {
    case CTNOTIFYENABLEVALUE:
        *var_len = sizeof(long);
        long_return = (ctNotifyResponse_enabled(wwwServiceIndex, responseTypeIndex) + 1);
        return (unsigned char *) &long_return;
    }
    return NULL;
}

static oid ctNotifyEnableEntry_oid[] = {1, 3, 6, 1, 4, 1, 6100, 3, 1, 1, 1};
struct variable2 ctNotifyEnableEntry_variables[] = {
    { CTNOTIFYENABLEVALUE, ASN_INTEGER, RWRITE, read_ctNotifyEnableEntry, 1, {2} },
};

void init_www_resp_notify_mib()
{
    REGISTER_MIB("www-resp-notify-mib/ctNotifyEnableEntry", ctNotifyEnableEntry_variables,
         variable2, ctNotifyEnableEntry_oid);
};

#endif /* COVALENT_RESP_NOTIFY_MIB */

void
generate_ctNotifyResponse_notification(www_log_record *logrec)
{
#ifdef COVALENT_RESP_NOTIFY_MIB
/* Oid definition of the Notification */
static oid ctNotifyResponse_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 3, 3, 1 };
/* Oid definition of the Notification Objects */
static oid ctNotifyWwwService_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 3, 2, 1, 0 };
static oid ctNotifyWwwDocName_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 3, 2, 2, 0 };
static oid ctNotifyWwwTimeStamp_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 3, 2, 3, 0 };
static oid ctNotifyWwwRequestType_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 3, 2, 4, 0 };
static oid ctNotifyWwwResponseType_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 3, 2, 5, 0 };
static oid ctNotifyWwwStatusMessage_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 3, 2, 6, 0 };
/* varbind variables of the Notification Objects */
struct variable_list ctNotifyWwwService_var;
struct variable_list ctNotifyWwwDocName_var;
struct variable_list ctNotifyWwwTimeStamp_var;
struct variable_list ctNotifyWwwRequestType_var;
struct variable_list ctNotifyWwwResponseType_var;
struct variable_list ctNotifyWwwStatusMessage_var;
char *request_type;

    DEBUGMSGTL(("resp-notify-mib", "generate_ctNotifyResponse_notification"));

    if (ctNotifyResponse_enabled(logrec->wwwServiceIndex, logrec->wwwResponseOutType)) {
        memset(&ctNotifyWwwService_var, 0, sizeof(ctNotifyWwwService_var));
        snmp_set_var_objid(&ctNotifyWwwService_var, ctNotifyWwwService_oid,
				sizeof(ctNotifyWwwService_oid)/sizeof(oid));
        long_return = logrec->wwwServiceIndex + 1;
        snmp_set_var_value(&ctNotifyWwwService_var, (u_char *)&(long_return),
				sizeof(long_return));
        ctNotifyWwwService_var.type = ASN_UNSIGNED;
        ctNotifyWwwService_var.next_variable = &ctNotifyWwwDocName_var;

        memset(&ctNotifyWwwDocName_var, 0, sizeof(ctNotifyWwwDocName_var));
        snmp_set_var_objid(&ctNotifyWwwDocName_var, ctNotifyWwwDocName_oid,
				sizeof(ctNotifyWwwDocName_oid)/sizeof(oid));
        snmp_set_var_value(&ctNotifyWwwDocName_var, logrec->wwwDocName,
				strlen(logrec->wwwDocName));
        ctNotifyWwwDocName_var.type = ASN_OCTET_STR;
        ctNotifyWwwDocName_var.next_variable = &ctNotifyWwwTimeStamp_var;

        memset(&ctNotifyWwwTimeStamp_var, 0, sizeof(ctNotifyWwwTimeStamp_var));
        snmp_set_var_objid(&ctNotifyWwwTimeStamp_var, ctNotifyWwwTimeStamp_oid,
				sizeof(ctNotifyWwwTimeStamp_oid)/sizeof(oid));
        snmp_set_var_value(&ctNotifyWwwTimeStamp_var, return_buf,
				snmp_time2DateAndTime(logrec->wwwRequestTime, return_buf));
        ctNotifyWwwTimeStamp_var.type = ASN_OCTET_STR;
        ctNotifyWwwTimeStamp_var.next_variable = &ctNotifyWwwRequestType_var;

        request_type = (logrec->wwwRequestInType < 0) ? requestTypes[ logrec->wwwRequestInType ] : "";
        memset(&ctNotifyWwwRequestType_var, 0, sizeof(ctNotifyWwwRequestType_var));
        snmp_set_var_objid(&ctNotifyWwwRequestType_var, ctNotifyWwwRequestType_oid,
				sizeof(ctNotifyWwwRequestType_oid)/sizeof(oid));
        snmp_set_var_value(&ctNotifyWwwRequestType_var, request_type,
				strlen(request_type));
        ctNotifyWwwRequestType_var.type = ASN_OCTET_STR;
        ctNotifyWwwRequestType_var.next_variable = &ctNotifyWwwResponseType_var;

        memset(&ctNotifyWwwResponseType_var, 0, sizeof(ctNotifyWwwResponseType_var));
        snmp_set_var_objid(&ctNotifyWwwResponseType_var, ctNotifyWwwResponseType_oid,
				sizeof(ctNotifyWwwResponseType_oid)/sizeof(oid));
        snmp_set_var_value(&ctNotifyWwwResponseType_var, (u_char *)&logrec->wwwResponseOutType,
				sizeof(logrec->wwwResponseOutType));
        ctNotifyWwwResponseType_var.type = ASN_INTEGER;
        ctNotifyWwwResponseType_var.next_variable = &ctNotifyWwwStatusMessage_var;

        memset(&ctNotifyWwwStatusMessage_var, 0, sizeof(ctNotifyWwwStatusMessage_var));
        snmp_set_var_objid(&ctNotifyWwwStatusMessage_var, ctNotifyWwwStatusMessage_oid,
				sizeof(ctNotifyWwwStatusMessage_oid)/sizeof(oid));
        snmp_set_var_value(&ctNotifyWwwStatusMessage_var, logrec->wwwStatusMsg,
				strlen(logrec->wwwStatusMsg));
        ctNotifyWwwStatusMessage_var.type = ASN_OCTET_STR;
        ctNotifyWwwStatusMessage_var.next_variable = NULL;

        send_enterprise_trap_vars(6, logrec->wwwResponseOutType, ctNotifyResponse_oid,
				sizeof(ctNotifyResponse_oid)/sizeof(oid),
							&ctNotifyWwwService_var);
    }
    return;
#endif /* COVALENT_RESP_NOTIFY_MIB */
}

