/*
 * The instrumentation of the COVALENT-ANTIVIRUS-MIB module.
 * $Id: antivirus-mib.c 8676 2008-01-17 23:11:17Z ispringer $
 */

#include <stdio.h>
#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.h>
#include <snmp_api.h>
#include <snmp_impl.h>
#include <snmp_client.h>
#include <snmp_vars.h>
#include <var_struct.h>
#include <agent_trap.h>

#include <covalent-snmp-config.h>
#include <covalent-snmp-sconfig.h>
#include <covalent-snmp-logging.h>

#include <ietf-mibs/snmp-generic.h>
#include <ietf-mibs/snmpv2-tc.h>
#include <covalent-mibs/antivirus-mib.h>

#include "log_config.h"

/* We need to have our own main server_rec and their amount.  */
server_rec *antivirus_www_services;
int antivirus_www_service_count;

static unsigned long local_long;
static unsigned char local_buf[256];

/* The SNMP logger function knows whereto the logging must go */
/* and is available in the server_config record of covalent-snmp. */
snmp_logger *av2snmp_logger;
notification *send_notification;

av_mib_service_stats_t  *av_mib_service_stats;
av_mib_update_activity_t *av_mib_update_activity;

#define CTAVDIRECTORY                    1
#define CTAVVERSION                      2
#define CTAVDBNAME                       3
#define CTAVSCANENABLE                   4

#define CTAVDETECTEDLASTTIME             1
#define CTAVDETECTEDLASTDOC              2
#define CTAVDETECTEDLASTVIRUS            3
#define CTAVDETECTEDCOUNTER              4

#define CTAVUPDATEAPPLNAME               1
#define CTAVUPDATEURL                    2
#define CTAVUPDATEUSER                   3
#define CTAVUPDATEPASSWORD               4
#define CTAVUPDATEPROXY                  5
#define CTAVUPDATESAFEDIR                6
#define CTAVUPDATERESTART                7

#define CTAVUPDATEACTIVITY               1
#define CTAVUPDATELASTTIME               2
#define CTAVUPDATELASTSUCCESSFULLTIME    3
#define CTAVUPDATEINTERVAL               4
#define CTAVUPDATECOUNTER                5
#define CTAVUPDATELASTSUCCESSFULLCOUNTER 6
#define CTAVUPDATELASTSTATUSMSG          7

/* The values used by ctAVUpdateActivity */
#define UPDATEACTIVITY_DISABLED	1
#define UPDATEACTIVITY_RUNNING	2
#define UPDATEACTIVITY_FORCE	3
#define UPDATEACTIVITY_TIMER	4

static int
write_ctAVDirectory(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVDBName(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVScanEnable(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

covalent_av_sconfig *
get_AntiVirus_Service_Admin_Entry(struct variable *vp,
        oid *name, size_t *namelength,
        oid *newname, size_t *newlength,
        int exact, server_rec *www_service)
{
oid *ptr;
int result;

    *newlength = vp->namelen;
    memcpy((char *)newname, (char *)vp->name, *newlength * sizeof(oid));
    ptr = &(newname[ (*newlength)++ ]);
    *ptr = 1;
    while (www_service) {
        result = snmp_oid_compare(name, *namelength, newname, *newlength);
        if ((exact && (result == 0)) || (!exact && (result < 0))) {
            return(ap_get_module_config(www_service->module_config, &covalent_av_module));
        }
        (*ptr)++;
        www_service = www_service->next;
    }
    return(NULL);
}


static unsigned char *
var_ctAVServiceEntry(struct variable *vp,
    oid *name, size_t *length, int exact,
    size_t *var_len, WriteMethod **write_method)
{
oid newname[ MAX_OID_LEN ];
size_t newlength;
covalent_av_sconfig *antivirus;
int fd;

    antivirus = get_AntiVirus_Service_Admin_Entry(vp, name, length,
                        newname, &newlength, exact, antivirus_www_services);
    if (!antivirus) {
        return(NULL);
    }
    *length = newlength;
    memcpy( (char *)name,(char *)newname, *length * sizeof(oid));
    *var_len = sizeof(long);

    switch (vp->magic) {
    case CTAVDIRECTORY:
        *write_method = write_ctAVDirectory;
        if (antivirus->datfiledir) {
            *var_len = strlen(antivirus->datfiledir);
            return (unsigned char *) antivirus->datfiledir;
        } else {
            *var_len = 0;
            return (unsigned char *) "";
        }
    case CTAVVERSION:
        *var_len = 0;
        if (antivirus->datfiledir) {
            strncpy(local_buf, antivirus->datfiledir, 255);
            strncat(local_buf, "/version", 255);
            fd = open(local_buf, O_RDONLY, 0);
            if (fd != -1) {
                *var_len = read(fd, local_buf, 255);
		close(fd);
                if (*var_len == -1) {
                    *var_len = 0;
                } else {
                    while (((local_buf[(*var_len - 1)] == '\r') ||
                                (local_buf[(*var_len - 1)] == '\n')) &&
                                *var_len) {
	                (*var_len)--;
                    }
                }
            }
        }
        return (unsigned char *) local_buf;
    case CTAVDBNAME:
        *write_method = write_ctAVDBName;
        if (antivirus->scandbfile) {
            *var_len = strlen(antivirus->scandbfile);
            return (unsigned char *) antivirus->scandbfile;
        } else {
            *var_len = 0;
            return (unsigned char *) "";
        }
    case CTAVSCANENABLE:
        *write_method = write_ctAVScanEnable;
        *var_len = sizeof(char);
        local_buf[ 0 ] = 0x80; /* (0x80 >> (1 % 8)) */
        return (unsigned char *) &local_buf;
    }
    return NULL;
}

int
get_AntiVirus_Service_Stats_Entry(struct variable *vp,
        oid *name, size_t *namelength,
        oid *newname, size_t *newlength,
        int exact)
{
oid *ptr;
int result;

    *newlength = vp->namelen;
    memcpy((char *)newname, (char *)vp->name, *newlength * sizeof(oid));
    ptr = &(newname[ (*newlength)++ ]);
    *ptr = 1;
    while (*ptr <= antivirus_www_service_count) {
        result = snmp_oid_compare(name, *namelength, newname, *newlength);
        if ((exact && (result == 0)) || (!exact && (result < 0))) {
            return(*ptr);
        }
        (*ptr)++;
    }
    return(0);
}


static unsigned char *
var_ctAVServiceStatEntry(struct variable *vp,
    oid *name, size_t *length, int exact,
    size_t *var_len, WriteMethod **write_method)
{
oid newname[ MAX_OID_LEN ];
size_t newlength;
int index;
av_mib_service_stats_t *stats_rec;

    index = get_AntiVirus_Service_Stats_Entry(vp, name, length,
			newname, &newlength, exact);
    if ((index == 0) || (av_mib_service_stats == NULL)) {
        return(NULL);
    }
    stats_rec = &(av_mib_service_stats[ (index - 1) ]);
    *length = newlength;
    memcpy( (char *)name,(char *)newname, *length * sizeof(oid));
    *write_method = 0;
    switch (vp->magic) {
    case CTAVDETECTEDLASTTIME:
        *var_len = snmp_time2DateAndTime(stats_rec->lastTime, local_buf);
        return (unsigned char *) local_buf;
    case CTAVDETECTEDLASTDOC:
        strcpy(local_buf, stats_rec->lastDoc);
        *var_len = strlen(local_buf);
        return (unsigned char *) local_buf;
    case CTAVDETECTEDLASTVIRUS:
        strcpy(local_buf, stats_rec->lastVirus);
        *var_len = strlen(local_buf);
        return (unsigned char *) local_buf;
    case CTAVDETECTEDCOUNTER:
        local_long = stats_rec->count;
        *var_len = sizeof(long);
        return (unsigned char *) &(local_long);
    }
    return NULL;
}

static int
write_ctAVUpdateApplName(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVUpdateUrl(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVUpdateUser(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVUpdatePassword(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVUpdateProxy(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVUpdateSafeDir(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVUpdateRestart(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}


static unsigned char *
var_ctAVUpdateApplEntry(struct variable *vp,
    oid *name, size_t *length, int exact,
    size_t *var_len, WriteMethod **write_method)
{
oid newname[ MAX_OID_LEN ];
size_t newlength;
covalent_av_sconfig *antivirus;
int result;

    newlength = vp->namelen;
    memcpy((char *)newname, (char *)vp->name, newlength * sizeof(oid));
    newname[ newlength++ ] = getppid();
    result = snmp_oid_compare(name, *length, newname, newlength);
    if (!((exact && (result == 0)) || (!exact && (result < 0)))) {
        return(NULL);
    }
    antivirus = ap_get_module_config(antivirus_www_services->module_config, &covalent_av_module);
    if (!antivirus) {
        return(NULL);
    }

    *length = newlength;
    memcpy( (char *)name,(char *)newname, *length * sizeof(oid));
    *write_method = 0;
    *var_len = sizeof(long);
    switch (vp->magic) {
    case CTAVUPDATEAPPLNAME:
        *write_method = write_ctAVUpdateApplName;
        if (antivirus->updateprog) {
            *var_len = strlen(antivirus->updateprog);
            return (unsigned char *) antivirus->updateprog;
        } else {
            *var_len = 0;
            return (unsigned char *) "";
        }
    case CTAVUPDATEURL:
        *write_method = write_ctAVUpdateUrl;
        if (0) {
            *var_len = strlen(antivirus->updateprog);
            return (unsigned char *) antivirus->updateprog;
        } else {
            *var_len = 0;
            return (unsigned char *) "";
        }
    case CTAVUPDATEUSER:
        *write_method = write_ctAVUpdateUser;
        if (antivirus->username) {
            *var_len = strlen(antivirus->username);
            return (unsigned char *) antivirus->username;
        } else {
            *var_len = 0;
            return (unsigned char *) "";
        }
    case CTAVUPDATEPASSWORD:
        *write_method = write_ctAVUpdatePassword;
        if (antivirus->password) {
            *var_len = strlen(antivirus->password);
            return (unsigned char *) antivirus->password;
        } else {
            *var_len = 0;
            return (unsigned char *) "";
        }
    case CTAVUPDATEPROXY:
        *write_method = write_ctAVUpdateProxy;
        if (antivirus->proxy) {
            *var_len = strlen(antivirus->proxy);
            return (unsigned char *) antivirus->proxy;
        } else {
            *var_len = 0;
            return (unsigned char *) "";
        }
    case CTAVUPDATESAFEDIR:
        *write_method = write_ctAVUpdateSafeDir;
        if (antivirus->safedir) {
            *var_len = strlen(antivirus->safedir);
            return (unsigned char *) antivirus->safedir;
        } else {
            *var_len = 0;
            return (unsigned char *) "";
        }
    case CTAVUPDATERESTART:
        *write_method = write_ctAVUpdateRestart;
	local_long = antivirus->restart;
        return (unsigned char *) &local_long;
    }
    return NULL;
}

static int
write_ctAVUpdateActivity(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static int
write_ctAVUpdateInterval(int action,
    unsigned char *var_val, unsigned char var_val_type, size_t var_val_len,
    unsigned char *statP, oid *name, size_t name_len)
{
    return SNMP_ERR_NOTWRITABLE;
}

static unsigned char *
var_ctAVUpdateActivityEntry(struct variable *vp,
    oid *name, size_t *length, int exact,
    size_t *var_len, WriteMethod **write_method)
{
oid newname[ MAX_OID_LEN ];
size_t newlength;
int result;

    newlength = vp->namelen;
    memcpy((char *)newname, (char *)vp->name, newlength * sizeof(oid));
    newname[ newlength++ ] = getppid();
    result = snmp_oid_compare(name, *length, newname, newlength);
    if (!((exact && (result == 0)) || (!exact && (result < 0)))) {
        return(NULL);
    }
    if (av_mib_update_activity == NULL) {
        return(NULL);
    }

    *length = newlength;
    memcpy( (char *)name,(char *)newname, *length * sizeof(oid));
    *var_len = sizeof(long);
    switch (vp->magic) {
    case CTAVUPDATEACTIVITY:
        *write_method = write_ctAVUpdateActivity;
        local_long = av_mib_update_activity->activity;
        return (unsigned char *) &local_long;
    case CTAVUPDATELASTTIME:
        *var_len = snmp_time2DateAndTime(av_mib_update_activity->lastTime, local_buf);
        return (unsigned char *) local_buf;
    case CTAVUPDATELASTSUCCESSFULLTIME:
        *var_len = snmp_time2DateAndTime(av_mib_update_activity->lastSuccessfullTime, local_buf);
        return (unsigned char *) local_buf;
    case CTAVUPDATEINTERVAL:
        *write_method = write_ctAVUpdateInterval;
        local_long = av_mib_update_activity->timeInterval;
        return (unsigned char *) &local_long;
    case CTAVUPDATECOUNTER:
        local_long = av_mib_update_activity->updateCounter;
        return (unsigned char *) &local_long;
    case CTAVUPDATELASTSUCCESSFULLCOUNTER:
        local_long = av_mib_update_activity->sinceLastSuccessfullCounter;
        return (unsigned char *) &local_long;
    case CTAVUPDATELASTSTATUSMSG:
        *var_len = strlen(av_mib_update_activity->statusMsg);
        return (unsigned char *) av_mib_update_activity->statusMsg;
    }
    return NULL;
}

static oid ctAVServiceEntry_oid[] = {1, 3, 6, 1, 4, 1, 6100, 7, 1, 1, 1};
static struct variable2 ctAVServiceEntry_variables[] = {
    { CTAVDIRECTORY, ASN_OCTET_STR, RWRITE, var_ctAVServiceEntry, 1, {1}},
    { CTAVVERSION, ASN_OCTET_STR, RONLY, var_ctAVServiceEntry, 1, {2}},
    { CTAVDBNAME, ASN_OCTET_STR, RWRITE, var_ctAVServiceEntry, 1, {3}},
    { CTAVSCANENABLE, ASN_OCTET_STR, RWRITE, var_ctAVServiceEntry, 1, {4}}
};

static oid ctAVServiceStatEntry_oid[] = {1, 3, 6, 1, 4, 1, 6100, 7, 1, 2, 1};
static struct variable2 ctAVServiceStatEntry_variables[] = {
    { CTAVDETECTEDLASTTIME, ASN_OCTET_STR, RONLY, var_ctAVServiceStatEntry, 1, {1}},
    { CTAVDETECTEDLASTDOC, ASN_OCTET_STR, RONLY, var_ctAVServiceStatEntry, 1, {2}},
    { CTAVDETECTEDLASTVIRUS, ASN_OCTET_STR, RONLY, var_ctAVServiceStatEntry, 1, {3}},
    { CTAVDETECTEDCOUNTER, ASN_COUNTER, RONLY, var_ctAVServiceStatEntry, 1, {4}}
};

static oid ctAVUpdateApplEntry_oid[] = {1, 3, 6, 1, 4, 1, 6100, 7, 2, 1, 1};
static struct variable2 ctAVUpdateApplEntry_variables[] = {
    { CTAVUPDATEAPPLNAME, ASN_OCTET_STR, RWRITE, var_ctAVUpdateApplEntry, 1, {1}},
    { CTAVUPDATEURL, ASN_OCTET_STR, RWRITE, var_ctAVUpdateApplEntry, 1, {2}},
    { CTAVUPDATEUSER, ASN_OCTET_STR, RWRITE, var_ctAVUpdateApplEntry, 1, {3}},
    { CTAVUPDATEPASSWORD, ASN_OCTET_STR, RWRITE, var_ctAVUpdateApplEntry, 1, {4}},
    { CTAVUPDATEPROXY, ASN_OCTET_STR, RWRITE, var_ctAVUpdateApplEntry, 1, {5}},
    { CTAVUPDATESAFEDIR, ASN_OCTET_STR, RWRITE, var_ctAVUpdateApplEntry, 1, {6}},
    { CTAVUPDATERESTART, ASN_INTEGER, RWRITE, var_ctAVUpdateApplEntry, 1, {7}}
};

static oid ctAVUpdateActivityEntry_oid[] = {1, 3, 6, 1, 4, 1, 6100, 7, 2, 2, 1};
static struct variable2 ctAVUpdateActivityEntry_variables[] = {
    { CTAVUPDATEACTIVITY, ASN_INTEGER, RWRITE, var_ctAVUpdateActivityEntry, 1, {1}},
    { CTAVUPDATELASTTIME, ASN_OCTET_STR, RONLY, var_ctAVUpdateActivityEntry, 1, {2}},
    { CTAVUPDATELASTSUCCESSFULLTIME, ASN_OCTET_STR, RONLY, var_ctAVUpdateActivityEntry, 1, {3}},
    { CTAVUPDATEINTERVAL, ASN_INTEGER, RWRITE, var_ctAVUpdateActivityEntry, 1, {4}},
    { CTAVUPDATECOUNTER, ASN_COUNTER, RONLY, var_ctAVUpdateActivityEntry, 1, {5}},
    { CTAVUPDATELASTSUCCESSFULLCOUNTER, ASN_COUNTER, RONLY, var_ctAVUpdateActivityEntry, 1, {6}},
    { CTAVUPDATELASTSTATUSMSG, ASN_OCTET_STR, RONLY, var_ctAVUpdateActivityEntry, 1, {7}}
};

int
get_wwwServiceIndex(server_rec *s)
{
module *mod_ptr;
covalent_snmp_sconfig *sconf_ptr;

    mod_ptr = ap_find_linked_module(CONDUCTOR_MODULE_NAME);
    if (mod_ptr == NULL) {
        /* The Covalent SNMP Conductor module is not there */
        return(-1);
    }
    sconf_ptr = (covalent_snmp_sconfig *)
                ap_get_module_config(s->module_config, mod_ptr);
    if (sconf_ptr == NULL) {
        /* server config record is not there */
        return(-1);
    }
    return(sconf_ptr->wwwServiceIndex);
}

/* Oid definition of the Notification */
static oid ctAVNotification_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 7, 4, 0 };
/* Oid definition of the Notification Objects */
static oid ctAVDetectedLastDoc_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 7, 1, 2, 1, 2, 0 };
static oid ctAVDetectedLastVirus_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 7, 1, 2, 1, 3, 0 };
static oid ctAVUpdateLastStatusMsg_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 7, 2, 2, 1, 7, 0 };

void
generate_ctAVNotification(int type, int index,
                                    char *str1, oid *objid1, int objidlen1,
                                    char *str2, oid *objid2, int objidlen2)
{
/* varbind variables of the Notification Objects */
struct variable_list ctAVNotification_var1;
struct variable_list ctAVNotification_var2;

    PRINT_AVMIB("generate_ctAVNotification");
    if (send_notification) {
        ctAVNotification_oid[9] = type;
        objid1[ 12 ] = index;
        memset(&ctAVNotification_var1, 0, sizeof(ctAVNotification_var1));
        snmp_set_var_objid(&ctAVNotification_var1, objid1, objidlen1);
        snmp_set_var_value(&ctAVNotification_var1, str1, strlen(str1));
        ctAVNotification_var1.type = ASN_OCTET_STR;
        if (str2 == NULL) { /* This notification has no second varbind */
            ctAVNotification_var1.next_variable = NULL;
        } else { 
            objid2[ 12 ] = index;
            memset(&ctAVNotification_var2, 0, sizeof(ctAVNotification_var2));
            snmp_set_var_objid(&ctAVNotification_var2, objid2, objidlen2);
            snmp_set_var_value(&ctAVNotification_var2, str2, strlen(str2));
            ctAVNotification_var2.type = ASN_OCTET_STR;
            ctAVNotification_var2.next_variable = NULL;
        }
        send_notification(6, type, ctAVNotification_oid,
                                sizeof(ctAVNotification_oid)/sizeof(oid),
                                                &ctAVNotification_var1);
    }
}

void
invoke_av_detected_log(request_rec *r)
{
snmp_generic_log_record log_record;

    PRINT_AVMIB("invoke_av_detected_log");
    if ((av2snmp_logger) && (r)) {
        PRINT_AVMIB("We invoke a log");
        log_record.type = CONDUCTOR_ANTIVIRUS_SERVICE_STATS;
        log_record.data.detected.wwwServiceIndex = get_wwwServiceIndex(r->server);
        log_record.data.detected.time = time(NULL);
        strncpy(log_record.data.detected.wwwDocName, r->uri, MAX_SNMPADMINSTRING);
        strncpy(log_record.data.detected.virusName, "", MAX_SNMPADMINSTRING);
        av2snmp_logger(&log_record);
        PRINT_AVMIB("We have logged");
    }
}

int
log_av_detected_info(snmp_generic_log_record *data)
{
av_mib_service_stats_t *stats_rec;

    PRINT_AVMIB("log_av_datected_info");
    if (data->type == CONDUCTOR_ANTIVIRUS_SERVICE_STATS) {
        PRINT_AVMIB("We have the correct type");
        if ((av_mib_service_stats) && (data->data.detected.wwwServiceIndex < antivirus_www_service_count)) {
            PRINT_AVMIB("We have data to store it and correct index");
            stats_rec = &(av_mib_service_stats[ data->data.detected.wwwServiceIndex ]);
            if (strcmp(stats_rec->lastDoc, data->data.detected.wwwDocName)) {
                PRINT_AVMIB("We now generate the notification");
                generate_ctAVNotification(1 /* infected document */,
                                (data->data.detected.wwwServiceIndex + 1),
                                data->data.detected.wwwDocName,
                                ctAVDetectedLastDoc_oid,
                                sizeof(ctAVDetectedLastDoc_oid)/sizeof(oid),
                                data->data.detected.virusName,
                                ctAVDetectedLastVirus_oid,
                                sizeof(ctAVDetectedLastVirus_oid)/sizeof(oid));
            }
            stats_rec->lastTime = data->data.detected.time;
            strncpy(stats_rec->lastDoc, data->data.detected.wwwDocName, MAX_SNMPADMINSTRING);
            strncpy(stats_rec->lastVirus, data->data.detected.virusName, MAX_SNMPADMINSTRING);
            stats_rec->count++;
        }
        return(1);
    }
    return(0);
}

void
invoke_av_update_log(int result)
{
snmp_generic_log_record log_record;

    if (av2snmp_logger) {
        log_record.type = CONDUCTOR_ANTIVIRUS_UPDATE_STATS;
        log_record.data.update.result = result;
        log_record.data.update.time = time(NULL);
        log_record.data.update.interval = 0;
        strncpy(log_record.data.update.statusMsg, "", MAX_SNMPADMINSTRING);
        av2snmp_logger(&log_record);
    }
}

int
log_av_update_info(snmp_generic_log_record *data)
{
    if (data->type == CONDUCTOR_ANTIVIRUS_UPDATE_STATS) {
        if (av_mib_update_activity) {
            if (data->data.update.result == UPDATE_SUCCESS) {
                av_mib_update_activity->sinceLastSuccessfullCounter = 0;
                av_mib_update_activity->lastSuccessfullTime = data->data.update.time;
                generate_ctAVNotification(2 /* update succeeded */, getppid(),
                                data->data.update.statusMsg,
                                ctAVUpdateLastStatusMsg_oid,
                                sizeof(ctAVUpdateLastStatusMsg_oid)/sizeof(oid),
                                NULL, NULL, 0);

            } else {
                av_mib_update_activity->sinceLastSuccessfullCounter++;
                generate_ctAVNotification(3 /* update failed */, getppid(),
                                data->data.update.statusMsg, 
                                ctAVUpdateLastStatusMsg_oid,
                                sizeof(ctAVUpdateLastStatusMsg_oid)/sizeof(oid),
                                NULL, NULL, 0);
            }
            av_mib_update_activity->lastTime = data->data.update.time;
            av_mib_update_activity->updateCounter++;
            av_mib_update_activity->timeInterval = data->data.update.interval;
            strcpy(av_mib_update_activity->statusMsg, data->data.update.statusMsg);
        }
        return(1);
    }
    return(0);
}

int
init_subtree_av_service_stats(server_rec *s, pool *p)
{
    antivirus_www_service_count = count_services(s);
    av_mib_service_stats = (av_mib_service_stats_t *)
               ap_pcalloc(p, (sizeof(av_mib_service_stats_t) *
                                        antivirus_www_service_count));
    return(0);
}

int
init_subtree_av_update_activity(server_rec *s, pool *p)
{
    av_mib_update_activity = (av_mib_update_activity_t *)
               ap_pcalloc(p, sizeof(av_mib_update_activity));
    return(0);
}


void init_covalent_antivirus_mib(server_rec *s, pool *p)
{
module *covalent_snmp_module;
covalent_snmp_sconfig *covalent_snmp_sconf;
external_mib_subtree *subtree;

    covalent_snmp_module = ap_find_linked_module(CONDUCTOR_MODULE_NAME);
    if (covalent_snmp_module == NULL) {
        /* The Covalent SNMP Conductor module is not there */
	return;
    }
    antivirus_www_services = s;
    covalent_snmp_sconf = ap_get_module_config(antivirus_www_services->module_config,
                                                covalent_snmp_module);
    if (covalent_snmp_sconf == NULL) {
        /* The Covalent SNMP Conductor sconfig is not there */
        return;
    }
    av2snmp_logger = covalent_snmp_sconf->snmp_logger;
    send_notification = covalent_snmp_sconf->invoke_notification;

    /* This subtree is always there. Just info from the server config. */
    subtree = (external_mib_subtree *)
                        ap_push_array(covalent_snmp_sconf->external_mib_subtrees);
    if (subtree) {
        subtree->base_oid = ctAVServiceEntry_oid;
        subtree->base_oid_length = sizeof(ctAVServiceEntry_oid) /
                                                sizeof(ctAVServiceEntry_oid[0]);
        subtree->variables = (struct variables *)ctAVServiceEntry_variables;
        subtree->variable_size = sizeof(ctAVServiceEntry_variables[0]);
        subtree->variables_amount = sizeof(ctAVServiceEntry_variables) /
                                sizeof(ctAVServiceEntry_variables[0]);
	subtree->init = NULL;
        subtree->logging_sink = NULL;
    }

    subtree = (external_mib_subtree *)
                        ap_push_array(covalent_snmp_sconf->external_mib_subtrees);
    if (subtree) {
        subtree->base_oid = ctAVServiceStatEntry_oid;
        subtree->base_oid_length = sizeof(ctAVServiceStatEntry_oid) /
                                                sizeof(ctAVServiceStatEntry_oid[0]);
        subtree->variables = (struct variables *) ctAVServiceStatEntry_variables;
        subtree->variable_size = sizeof(ctAVServiceStatEntry_variables[0]);
        subtree->variables_amount = sizeof(ctAVServiceStatEntry_variables) /
                        sizeof(ctAVServiceStatEntry_variables[0]);
	subtree->init = init_subtree_av_service_stats;
        subtree->logging_sink = log_av_detected_info;
    }

    /* This subtree is always there. Just info from the server config. */
    subtree = (external_mib_subtree *)
                        ap_push_array(covalent_snmp_sconf->external_mib_subtrees);
    if (subtree) {
        subtree->base_oid = ctAVUpdateApplEntry_oid;
        subtree->base_oid_length = sizeof(ctAVUpdateApplEntry_oid) /
                                                sizeof(ctAVUpdateApplEntry_oid[0]);
        subtree->variables = (struct variables *) ctAVUpdateApplEntry_variables;
        subtree->variable_size = sizeof(ctAVUpdateApplEntry_variables[0]);
        subtree->variables_amount = sizeof(ctAVUpdateApplEntry_variables) /
                                sizeof(ctAVUpdateApplEntry_variables[0]);
	subtree->init = NULL;
        subtree->logging_sink = NULL;
    }

    subtree = (external_mib_subtree *)
                        ap_push_array(covalent_snmp_sconf->external_mib_subtrees);
    if (subtree) {
        subtree->base_oid = ctAVUpdateActivityEntry_oid;
        subtree->base_oid_length = sizeof(ctAVUpdateActivityEntry_oid) /
                                                sizeof(ctAVUpdateActivityEntry_oid[0]);
        subtree->variables = (struct variables *) ctAVUpdateActivityEntry_variables;
        subtree->variable_size = sizeof(ctAVUpdateActivityEntry_variables[0]);
        subtree->variables_amount = sizeof(ctAVUpdateActivityEntry_variables) /
                        sizeof(ctAVUpdateActivityEntry_variables[0]);
	subtree->init = init_subtree_av_update_activity;
        subtree->logging_sink = log_av_update_info;
    }
}

