/*
 * This file was generated by mib2c and is intended for use as
 * a mib module for the ucd-snmp snmpd agent. 
 */


/*
 * This should always be included first before anything else 
 */
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-features.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif

netsnmp_feature_require(mib_snprint_variable);
netsnmp_feature_require(tdomain_support);
netsnmp_feature_require(check_vb_uint);
netsnmp_feature_require(string_time_to_secs);
#ifndef NETSNMP_NO_WRITE_SUPPORT
netsnmp_feature_require(header_complex_find_entry);
#endif /* NETSNMP_NO_WRITE_SUPPORT */

/*
 * minimal include directives 
 */
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>

#include "header_complex.h"
#include "mteTriggerTable.h"
#include "mteTriggerBooleanTable.h"
#include "mteTriggerDeltaTable.h"
#include "mteTriggerExistenceTable.h"
#include "mteTriggerThresholdTable.h"
#include "mteEventTable.h"
#include "mteObjectsTable.h"

/*
 * mteTriggerTable_variables_oid:
 *   this is the top level oid that we want to register under.  This
 *   is essentially a prefix, with the suffix appearing in the
 *   variable below.
 */

/*
 * trap definitions 
 */
oid             mteTriggerFired[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 1 };
oid             mteTriggerRising[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 2 };
oid             mteTriggerFalling[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 3 };
oid             mteTriggerFailure[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 4 };
oid             mteEventSetFailure[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 5 };

/*
 * trap objects 
 */
oid             mteHotTrigger[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 1 };
oid             mteHotTargetName[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 2 };
oid             mteHotContextName[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 3 };
oid             mteHotOID[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 4 };
oid             mteHotValue[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 5 };
oid             mteFailedReason[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 6 };

/*
 * For discontinuity checking.  
 */
oid             sysUpTimeInstance[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };

oid             mteTriggerTable_variables_oid[] =
    { 1, 3, 6, 1, 2, 1, 88, 1, 2, 2 };


/*
 * variable2 mteTriggerTable_variables:
 *   this variable defines function callbacks and type return information 
 *   for the mteTriggerTable mib section 
 */


#ifndef NETSNMP_NO_WRITE_SUPPORT
struct variable2 mteTriggerTable_variables[] = {
    /*
     * magic number        , variable type , ro/rw , callback fn  , L, oidsuffix 
     */
#define   MTETRIGGERCOMMENT     5
    {MTETRIGGERCOMMENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 3}},
#define   MTETRIGGERTEST        6
    {MTETRIGGERTEST, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 4}},
#define   MTETRIGGERSAMPLETYPE  7
    {MTETRIGGERSAMPLETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 5}},
#define   MTETRIGGERVALUEID     8
    {MTETRIGGERVALUEID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 6}},
#define   MTETRIGGERVALUEIDWILDCARD  9
    {MTETRIGGERVALUEIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 7}},
#define   MTETRIGGERTARGETTAG   10
    {MTETRIGGERTARGETTAG, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 8}},
#define   MTETRIGGERCONTEXTNAME  11
    {MTETRIGGERCONTEXTNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 9}},
#define   MTETRIGGERCONTEXTNAMEWILDCARD  12
    {MTETRIGGERCONTEXTNAMEWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 10}},
#define   MTETRIGGERFREQUENCY   13
    {MTETRIGGERFREQUENCY, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 11}},
#define   MTETRIGGEROBJECTSOWNER  14
    {MTETRIGGEROBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 12}},
#define   MTETRIGGEROBJECTS     15
    {MTETRIGGEROBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 13}},
#define   MTETRIGGERENABLED     16
    {MTETRIGGERENABLED, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 14}},
#define   MTETRIGGERENTRYSTATUS  17
    {MTETRIGGERENTRYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_mteTriggerTable, 2, {1, 15}},
};
#else /* !NETSNMP_NO_WRITE_SUPPORT */
struct variable2 mteTriggerTable_variables[] = {
    /*
     * magic number        , variable type , ro/rw , callback fn  , L, oidsuffix 
     */
#define   MTETRIGGERCOMMENT     5
    {MTETRIGGERCOMMENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 3}},
#define   MTETRIGGERTEST        6
    {MTETRIGGERTEST, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 4}},
#define   MTETRIGGERSAMPLETYPE  7
    {MTETRIGGERSAMPLETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 5}},
#define   MTETRIGGERVALUEID     8
    {MTETRIGGERVALUEID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 6}},
#define   MTETRIGGERVALUEIDWILDCARD  9
    {MTETRIGGERVALUEIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 7}},
#define   MTETRIGGERTARGETTAG   10
    {MTETRIGGERTARGETTAG, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 8}},
#define   MTETRIGGERCONTEXTNAME  11
    {MTETRIGGERCONTEXTNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 9}},
#define   MTETRIGGERCONTEXTNAMEWILDCARD  12
    {MTETRIGGERCONTEXTNAMEWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 10}},
#define   MTETRIGGERFREQUENCY   13
    {MTETRIGGERFREQUENCY, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 11}},
#define   MTETRIGGEROBJECTSOWNER  14
    {MTETRIGGEROBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 12}},
#define   MTETRIGGEROBJECTS     15
    {MTETRIGGEROBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 13}},
#define   MTETRIGGERENABLED     16
    {MTETRIGGERENABLED, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 14}},
#define   MTETRIGGERENTRYSTATUS  17
    {MTETRIGGERENTRYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
     var_mteTriggerTable, 2, {1, 15}},
};
#endif /* !NETSNMP_NO_WRITE_SUPPORT */

/*
 * (L = length of the oidsuffix) 
 */


/*
 * global storage of our data, saved in and configured by header_complex() 
 */
struct header_complex_index *mteTriggerTableStorage = NULL;

netsnmp_session *mte_callback_sess = NULL;

/*
 * init_mteTriggerTable():
 *   Initialization routine.  This is called when the agent starts up.
 *   At a minimum, registration of your variables should take place here.
 */
void
init_mteTriggerTable(void)
{
    DEBUGMSGTL(("mteTriggerTable", "initializing...  "));

#ifndef NETSNMP_TRANSPORT_CALLBACK_DOMAIN
    snmp_log(LOG_WARNING,"mteTriggerTable has been disabled because "
               "the callback transport is not available.\n");
    return;
#endif

    /*
     * register ourselves with the agent to handle our mib tree 
     */
    REGISTER_MIB("mteTriggerTable", mteTriggerTable_variables, variable2,
                 mteTriggerTable_variables_oid);


    /*
     * register our config handler(s) to deal with registrations 
     */
    snmpd_register_config_handler("mteTriggerTable", parse_mteTriggerTable,
                                  NULL, NULL);

    snmpd_register_config_handler("monitor", parse_simple_monitor, NULL,
                                  "[options] monitor_expression [see \"man snmpd.conf\"]");
    snmpd_register_config_handler("defaultMonitors",
                                  parse_default_monitors, NULL, "yes|no");

    /*
     * we need to be called back later to store our data 
     */
    snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
                           store_mteTriggerTable, NULL);


    /*
     * place any other initialization junk you need here 
     */
    se_add_pair_to_slist("mteBooleanOperators", strdup("!="),
                         MTETRIGGERBOOLEANCOMPARISON_UNEQUAL);
    se_add_pair_to_slist("mteBooleanOperators", strdup("=="),
                         MTETRIGGERBOOLEANCOMPARISON_EQUAL);
    se_add_pair_to_slist("mteBooleanOperators", strdup("<"),
                         MTETRIGGERBOOLEANCOMPARISON_LESS);
    se_add_pair_to_slist("mteBooleanOperators", strdup("<="),
                         MTETRIGGERBOOLEANCOMPARISON_LESSOREQUAL);
    se_add_pair_to_slist("mteBooleanOperators", strdup(">"),
                         MTETRIGGERBOOLEANCOMPARISON_GREATER);
    se_add_pair_to_slist("mteBooleanOperators", strdup(">="),
                         MTETRIGGERBOOLEANCOMPARISON_GREATEROREQUAL);

    DEBUGMSGTL(("mteTriggerTable", "done.\n"));
}

struct mteTriggerTable_data *
create_mteTriggerTable_data(void)
{
    struct mteTriggerTable_data *StorageNew;

    StorageNew = SNMP_MALLOC_STRUCT(mteTriggerTable_data);

    /*
     * fill in default row values here into StorageNew 
     */
    /*
     * fill in values for all tables (even if not
     * appropriate), since its easier to do here than anywhere
     * else 
     */
    StorageNew->mteTriggerComment = strdup("");
    StorageNew->mteTriggerTest = strdup("");
    StorageNew->mteTriggerTest[0] |= (char) MTETRIGGERTEST_BOOLEAN;
    StorageNew->mteTriggerTestLen = 1;
    StorageNew->mteTriggerSampleType = MTETRIGGERSAMPLETYPE_ABSOLUTEVALUE;
    StorageNew->mteTriggerValueID = calloc(1, sizeof(oid) * sizeof(2)); /* 0.0 */
    StorageNew->mteTriggerValueIDLen = 2;
    StorageNew->mteTriggerValueIDWildcard =
        MTETRIGGERVALUEIDWILDCARD_FALSE;
    StorageNew->mteTriggerTargetTag = strdup("");
    StorageNew->mteTriggerContextName = strdup("");
    StorageNew->mteTriggerContextNameWildcard =
        MTETRIGGERCONTEXTNAMEWILDCARD_FALSE;
    StorageNew->mteTriggerFrequency = 600;
    StorageNew->mteTriggerObjectsOwner = strdup("");
    StorageNew->mteTriggerObjects = strdup("");
    StorageNew->mteTriggerEnabled = MTETRIGGERENABLED_FALSE;
    StorageNew->mteTriggerDeltaDiscontinuityID =
        netsnmp_memdup(sysUpTimeInstance, sizeof(sysUpTimeInstance));
    StorageNew->mteTriggerDeltaDiscontinuityIDLen =
        sizeof(sysUpTimeInstance) / sizeof(oid);
    StorageNew->mteTriggerDeltaDiscontinuityIDWildcard = TV_FALSE;
    StorageNew->mteTriggerDeltaDiscontinuityIDType =
        MTETRIGGERDELTADISCONTINUITYIDTYPE_TIMETICKS;
    StorageNew->mteTriggerExistenceTest = strdup("");
    StorageNew->mteTriggerExistenceTest[0] =
        (char) (MTETRIGGEREXISTENCETEST_PRESENT |
                MTETRIGGEREXISTENCETEST_ABSENT);
    StorageNew->mteTriggerExistenceTestLen = 1;
    StorageNew->mteTriggerExistenceStartup = strdup("");
    StorageNew->mteTriggerExistenceStartup[0] =
        (char) (MTETRIGGEREXISTENCESTARTUP_PRESENT);
    StorageNew->mteTriggerExistenceStartupLen = 1;
    StorageNew->mteTriggerExistenceObjectsOwner = strdup("");
    StorageNew->mteTriggerExistenceObjects = strdup("");
    StorageNew->mteTriggerExistenceEventOwner = strdup("");
    StorageNew->mteTriggerExistenceEvent = strdup("");
    StorageNew->mteTriggerBooleanComparison =
        MTETRIGGERBOOLEANCOMPARISON_UNEQUAL;
    StorageNew->mteTriggerBooleanStartup = MTETRIGGERBOOLEANSTARTUP_TRUE;
    StorageNew->mteTriggerBooleanObjectsOwner = strdup("");
    StorageNew->mteTriggerBooleanObjects = strdup("");
    StorageNew->mteTriggerBooleanEventOwner = strdup("");
    StorageNew->mteTriggerBooleanEvent = strdup("");
    StorageNew->mteTriggerThresholdStartup =
        MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING;
    StorageNew->mteTriggerThresholdObjectsOwner = strdup("");
    StorageNew->mteTriggerThresholdObjects = strdup("");
    StorageNew->mteTriggerThresholdRisingEventOwner = strdup("");
    StorageNew->mteTriggerThresholdRisingEvent = strdup("");
    StorageNew->mteTriggerThresholdFallingEventOwner = strdup("");
    StorageNew->mteTriggerThresholdFallingEvent = strdup("");
    StorageNew->mteTriggerThresholdDeltaRisingEventOwner = strdup("");
    StorageNew->mteTriggerThresholdDeltaRisingEvent = strdup("");
    StorageNew->mteTriggerThresholdDeltaFallingEventOwner = strdup("");
    StorageNew->mteTriggerThresholdDeltaFallingEvent = strdup("");
    StorageNew->lastboolresult = -1;
    StorageNew->storageType = ST_NONVOLATILE;
    StorageNew->prevDiscoTicks = 0;
    StorageNew->prevUptimeTicks = 0;
    return StorageNew;
}

/*
 * mteTriggerTable_add(): adds a structure node to our data set 
 */
int
mteTriggerTable_add(struct mteTriggerTable_data *thedata)
{
    netsnmp_variable_list *vars = NULL;


    DEBUGMSGTL(("mteTriggerTable", "adding data...  "));
    /*
     * add the index variables to the varbind list, which is 
     * used by header_complex to index the data 
     */


    snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->mteOwner, thedata->mteOwnerLen); /* mteOwner */
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OCTET_STR, (char *) thedata->mteTriggerName, thedata->mteTriggerNameLen);        /* mteTriggerName */



    header_complex_add_data(&mteTriggerTableStorage, vars, thedata);
    DEBUGMSGTL(("mteTriggerTable", "registered an entry\n"));


    DEBUGMSGTL(("mteTriggerTable", "done.\n"));
    return SNMPERR_SUCCESS;
}


#define MTE_PROCESS_LINE(line) \
  snprintf(buf, SPRINT_MAX_LEN, "-u %s %s", mte_default_user, line); \
  parse_simple_monitor("monitor", buf);

void
parse_default_monitors(const char *token, char *line)
{
    char            buf[SPRINT_MAX_LEN];
    char           *mte_default_user =
        netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_INTERNAL_SECNAME);

    if (strncmp(line, "yes", 3) == 0) {

        DEBUGMSGTL(("mteTriggerTable", "registering default monitors\n"));

        if (mte_default_user == NULL) {
            config_perror
                ("You must specify a user name first using the agentSecName token\n");
            return;
        }

        /*
         * we don't include many additional objects here as most of
         * the error messages are complete with the needed
         * information 
         */
        MTE_PROCESS_LINE
            ("-o prNames -o prErrMessage \"process table\" prErrorFlag != 0");
        MTE_PROCESS_LINE
            ("-o memErrorName -o memSwapErrorMsg \"memory\" memSwapError != 0");
        MTE_PROCESS_LINE
            ("-o extNames -o extOutput \"extTable\" extResult != 0");
        MTE_PROCESS_LINE
            ("-o dskPath -o dskErrorMsg \"dskTable\" dskErrorFlag != 0");
        MTE_PROCESS_LINE
            ("-o laNames -o laErrMessage  \"laTable\" laErrorFlag != 0");
        MTE_PROCESS_LINE
            ("-o fileName -o fileErrorMsg  \"fileTable\" fileErrorFlag != 0");
        /*
         * this one is not *all* that useful, because the error is
         * only kept for 30 seconds at most.  Maybe scan it every 30
         * seconds, but I'm not doing so without seeking other peoples
         * opinions first. 
         */
        MTE_PROCESS_LINE
            ("-o snmperrErrMessage  \"snmperrs\" snmperrErrorFlag != 0");
    }
}

static int      monitor_call_count = 0;
void
parse_simple_monitor(const char *token, char *line)
{
    char            buf[SPRINT_MAX_LEN], *cp, eventname[64];
    oid             obuf[MAX_OID_LEN];
    size_t          obufLen;
    struct mteTriggerTable_data *StorageNew;

    monitor_call_count++;
    eventname[0] = '\0';

    StorageNew = create_mteTriggerTable_data();
    StorageNew->storageType = ST_READONLY;
    StorageNew->mteTriggerEnabled = MTETRIGGERENABLED_TRUE;
    StorageNew->mteTriggerEntryStatus = RS_ACTIVE;
    StorageNew->mteTriggerValueIDWildcard = MTETRIGGERVALUEIDWILDCARD_TRUE;
    StorageNew->mteTriggerBooleanStartup = MTETRIGGERBOOLEANSTARTUP_TRUE;
    StorageNew->mteTriggerThresholdStartup =
        MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING;
    StorageNew->mteTriggerExistenceTest[0] = 0;

    /*
     * owner = snmpd.conf, why not? 
     */
    StorageNew->mteOwner = strdup("snmpd.conf");
    StorageNew->mteOwnerLen = strlen(StorageNew->mteOwner);
    StorageNew->pdu_version = SNMP_VERSION_3;
    StorageNew->pdu_securityModel = SNMP_SEC_MODEL_USM;
    StorageNew->pdu_securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;

    cp = line;

    while (cp && *cp == '-') {
        cp = copy_nword(cp, buf, sizeof(buf));
        switch (buf[1]) {
        case 't':
           /*
            * Threshold toggle
            */
           StorageNew->mteTriggerTest[0] = MTETRIGGERTEST_THRESHOLD;
           break;
        case 'i':
           /*
            * Single instance
            */
           StorageNew->mteTriggerValueIDWildcard = MTETRIGGERVALUEIDWILDCARD_FALSE;
           break;
        case 'r':
            if (cp) {
                int freq;
                cp = copy_nword(cp, buf, sizeof(buf));
                freq = netsnmp_string_time_to_secs(buf);
                if (freq == -1) {
                    config_perror("Invalid -r value\n");
                    /*
                     * XXX: free StorageNew 
                     */
                    return;
                }
                StorageNew->mteTriggerFrequency = (unsigned long) freq;
            } else {
                config_perror("No parameter after -r given\n");
                /*
                 * XXX: free StorageNew 
                 */
                return;
            }
            break;
        case 'u':
            if (cp) {
                cp = copy_nword(cp, buf, sizeof(buf));
                StorageNew->pdu_securityName = strdup(buf);
                StorageNew->pdu_securityNameLen = strlen(buf);
            } else {
                config_perror("No parameter after -u given\n");
                /*
                 * XXX: free StorageNew 
                 */
                return;
            }
            break;
        case 'e':
            if (cp) {
                cp = copy_nword(cp, eventname, sizeof(eventname));
            } else {
                config_perror("No parameter after -e given\n");
                /*
                 * XXX: free StorageNew 
                 */
                return;
            }
            break;
        case 'o':
            /*
             * oid 
             */
            cp = copy_nword(cp, buf, sizeof(buf));
            obufLen = MAX_OID_LEN;
            if (!snmp_parse_oid(buf, obuf, &obufLen)) {
		netsnmp_config_error("unable to parse oid: %s", buf);
                /*
                 * XXX: free StorageNew 
                 */
                return;
            }
            sprintf(buf, "snmpd.conf%d", monitor_call_count);
            mte_add_object_to_table("snmpd.conf", buf, obuf, obufLen, 1);

            if (StorageNew->mteTriggerObjectsOwnerLen == 0) {
                SNMP_FREE(StorageNew->mteTriggerObjectsOwner);
                StorageNew->mteTriggerObjectsOwner = strdup("snmpd.conf");
                StorageNew->mteTriggerObjectsOwnerLen =
                    strlen("snmpd.conf");
            }

            if (StorageNew->mteTriggerObjectsLen == 0) {
                SNMP_FREE(StorageNew->mteTriggerObjects);
                StorageNew->mteTriggerObjects = strdup(buf);
                StorageNew->mteTriggerObjectsLen = strlen(buf);
            }
            break;
        }
    }

    if (StorageNew->pdu_securityNameLen == 0) {
        char           *mte_default_user =
            netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_INTERNAL_SECNAME);
        if (mte_default_user) {
            StorageNew->pdu_securityName = strdup(mte_default_user);
            StorageNew->pdu_securityNameLen = strlen(mte_default_user);
        } else {
            config_perror("-u USER parameter required\n");
            /*
             * XXX: free StorageNew 
             */
            return;
        }
    }

    /*
     * name 
     */
    cp = copy_nword(cp, buf, sizeof(buf));
    if (!cp) {
        config_perror("illegal monitor: no name specified");
        /*
         * XXX: free StorageNew 
         */
        return;
    }

    StorageNew->mteTriggerName = strdup(buf);
    StorageNew->mteTriggerNameLen = strlen(StorageNew->mteTriggerName);

    /*
     * oid 
     */
    cp = copy_nword(cp, buf, sizeof(buf));
    obufLen = MAX_OID_LEN;
    if (!snmp_parse_oid(buf, obuf, &obufLen)) {
	netsnmp_config_error("unable to parse oid: %s", buf);
        /*
         * XXX: free StorageNew 
         */
        return;
    }
    if (StorageNew->mteTriggerValueID)
        free(StorageNew->mteTriggerValueID);
    StorageNew->mteTriggerValueID = snmp_duplicate_objid(obuf, obufLen);
    StorageNew->mteTriggerValueIDLen = obufLen;

    if (StorageNew->mteTriggerTest[0] == MTETRIGGERTEST_THRESHOLD) {
       /*
        * it's a threshold
        * grab 'low' and 'high' params
        */
        if (!cp) {
            config_perror("no lower threshold value specified");
       }
       cp = copy_nword(cp, buf, sizeof(buf));
       StorageNew->mteTriggerThresholdFalling = strtol(buf, NULL, 0);

        if (!cp) {
            config_perror("no upper threshold value specified");
       }
       cp = copy_nword(cp, buf, sizeof(buf));
       StorageNew->mteTriggerThresholdRising = strtol(buf, NULL, 0);
    } else {
        /*
         * if nothing beyond here, it's an existence test 
         */
        if (!cp) {
            StorageNew->mteTriggerTest[0] = (u_char)MTETRIGGERTEST_EXISTENCE;
            if (eventname[0] != '\0') {
                StorageNew->mteTriggerExistenceEventOwner =
                    strdup("snmpd.conf");
                StorageNew->mteTriggerExistenceEventOwnerLen =
                    strlen(StorageNew->mteTriggerExistenceEventOwner);
                StorageNew->mteTriggerExistenceEvent =
                    strdup(eventname);
                StorageNew->mteTriggerExistenceEventLen =
                    strlen(eventname);
            }
            mteTriggerTable_add(StorageNew);
            return;
        }

        /*
         * assume boolean (need to deal with threshold statements) 
         */
        cp = copy_nword(cp, buf, sizeof(buf));
        if ((StorageNew->mteTriggerBooleanComparison =
             se_find_value_in_slist("mteBooleanOperators", buf)) == -1) {
            config_perror("illegal boolean operator");
            return;
        }

        /*
         * XXX: add threshold 
         */
        StorageNew->mteTriggerTest[0] = MTETRIGGERTEST_BOOLEAN;
        if (!cp) {
            config_perror("no comparison value specified");
            /*
             * XXX: free StorageNew 
             */
            return;
        }

        cp = copy_nword(cp, buf, sizeof(buf));
        StorageNew->mteTriggerBooleanValue = strtol(buf, NULL, 0);

        if (eventname[0] != '\0') {
            StorageNew->mteTriggerBooleanEventOwner =
                strdup("snmpd.conf");
            StorageNew->mteTriggerBooleanEventOwnerLen =
                strlen(StorageNew->mteTriggerBooleanEventOwner);
            StorageNew->mteTriggerBooleanEvent =
                strdup(eventname);
            StorageNew->mteTriggerBooleanEventLen =
                strlen(eventname);
        }
    }
    mteTriggerTable_add(StorageNew);
    mte_enable_trigger(StorageNew);

    DEBUGMSGTL(("mteTriggerTable", "added simple monitor: %s\n",
                StorageNew->mteTriggerName));
} /* parse_simple_monitor */


/*
 * parse_mteTriggerTable():
 *   parses .conf file entries needed to configure the mib.
 */
void
parse_mteTriggerTable(const char *token, char *line)
{
    size_t          tmpint;
    oid            *tmpoid = NULL;
    struct mteTriggerTable_data *StorageTmp =
        SNMP_MALLOC_STRUCT(mteTriggerTable_data);

    DEBUGMSGTL(("mteTriggerTable", "parsing config...  "));

    if (StorageTmp == NULL) {
        config_perror("malloc failure");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line, &StorageTmp->mteOwner,
                              &StorageTmp->mteOwnerLen);
    if (StorageTmp->mteOwner == NULL) {
        config_perror("invalid specification for mteOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerName,
                              &StorageTmp->mteTriggerNameLen);
    if (StorageTmp->mteTriggerName == NULL) {
        config_perror("invalid specification for mteTriggerName");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerComment,
                              &StorageTmp->mteTriggerCommentLen);
    if (StorageTmp->mteTriggerComment == NULL) {
        config_perror("invalid specification for mteTriggerComment");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerTest,
                              &StorageTmp->mteTriggerTestLen);
    if (StorageTmp->mteTriggerTest == NULL) {
        config_perror("invalid specification for mteTriggerTest");
        return;
    }

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerSampleType, &tmpint);

    line =
        read_config_read_data(ASN_OBJECT_ID, line,
                              &StorageTmp->mteTriggerValueID,
                              &StorageTmp->mteTriggerValueIDLen);
    if (StorageTmp->mteTriggerValueID == NULL) {
        config_perror("invalid specification for mteTriggerValueID");
        return;
    }

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerValueIDWildcard,
                              &tmpint);

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerTargetTag,
                              &StorageTmp->mteTriggerTargetTagLen);
    if (StorageTmp->mteTriggerTargetTag == NULL) {
        config_perror("invalid specification for mteTriggerTargetTag");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerContextName,
                              &StorageTmp->mteTriggerContextNameLen);
    if (StorageTmp->mteTriggerContextName == NULL) {
        config_perror("invalid specification for mteTriggerContextName");
        return;
    }

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerContextNameWildcard,
                              &tmpint);

    line =
        read_config_read_data(ASN_UNSIGNED, line,
                              &StorageTmp->mteTriggerFrequency, &tmpint);

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerObjectsOwner,
                              &StorageTmp->mteTriggerObjectsOwnerLen);
    if (StorageTmp->mteTriggerObjectsOwner == NULL) {
        config_perror("invalid specification for mteTriggerObjectsOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerObjects,
                              &StorageTmp->mteTriggerObjectsLen);
    if (StorageTmp->mteTriggerObjects == NULL) {
        config_perror("invalid specification for mteTriggerObjects");
        return;
    }

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerEnabled, &tmpint);

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerEntryStatus, &tmpint);

    /*
     * delta table 
     */
    line =
        read_config_read_data(ASN_OBJECT_ID, line,
                              &StorageTmp->mteTriggerDeltaDiscontinuityID,
                              &StorageTmp->
                              mteTriggerDeltaDiscontinuityIDLen);
    if (StorageTmp->mteTriggerDeltaDiscontinuityID == NULL) {
        config_perror
            ("invalid specification for mteTriggerDeltaDiscontinuityID");
        return;
    }

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->
                              mteTriggerDeltaDiscontinuityIDWildcard,
                              &tmpint);

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->
                              mteTriggerDeltaDiscontinuityIDType, &tmpint);

    /*
     * existence table 
     */
    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerExistenceTest,
                              &StorageTmp->mteTriggerExistenceTestLen);
    if (StorageTmp->mteTriggerExistenceTest == NULL) {
        config_perror("invalid specification for mteTriggerExistenceTest");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerExistenceStartup,
                              &StorageTmp->mteTriggerExistenceStartupLen);
    if (StorageTmp->mteTriggerExistenceStartup == NULL) {
        config_perror
            ("invalid specification for mteTriggerExistenceStartup");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerExistenceObjectsOwner,
                              &StorageTmp->
                              mteTriggerExistenceObjectsOwnerLen);
    if (StorageTmp->mteTriggerExistenceObjectsOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerExistenceObjectsOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerExistenceObjects,
                              &StorageTmp->mteTriggerExistenceObjectsLen);
    if (StorageTmp->mteTriggerExistenceObjects == NULL) {
        config_perror
            ("invalid specification for mteTriggerExistenceObjects");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerExistenceEventOwner,
                              &StorageTmp->
                              mteTriggerExistenceEventOwnerLen);
    if (StorageTmp->mteTriggerExistenceEventOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerExistenceEventOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerExistenceEvent,
                              &StorageTmp->mteTriggerExistenceEventLen);
    if (StorageTmp->mteTriggerExistenceEvent == NULL) {
        config_perror
            ("invalid specification for mteTriggerExistenceEvent");
        return;
    }

    /*
     * boolean table 
     */
    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerBooleanComparison,
                              &tmpint);

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerBooleanValue,
                              &tmpint);

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerBooleanStartup,
                              &tmpint);

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerBooleanObjectsOwner,
                              &StorageTmp->
                              mteTriggerBooleanObjectsOwnerLen);
    if (StorageTmp->mteTriggerBooleanObjectsOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerBooleanObjectsOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerBooleanObjects,
                              &StorageTmp->mteTriggerBooleanObjectsLen);
    if (StorageTmp->mteTriggerBooleanObjects == NULL) {
        config_perror
            ("invalid specification for mteTriggerBooleanObjects");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerBooleanEventOwner,
                              &StorageTmp->mteTriggerBooleanEventOwnerLen);
    if (StorageTmp->mteTriggerBooleanEventOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerBooleanEventOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerBooleanEvent,
                              &StorageTmp->mteTriggerBooleanEventLen);
    if (StorageTmp->mteTriggerBooleanEvent == NULL) {
        config_perror("invalid specification for mteTriggerBooleanEvent");
        return;
    }

    /*
     * threshold table 
     */
    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerThresholdStartup,
                              &tmpint);

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerThresholdRising,
                              &tmpint);

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerThresholdFalling,
                              &tmpint);

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerThresholdDeltaRising,
                              &tmpint);

    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->mteTriggerThresholdDeltaFalling,
                              &tmpint);

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerThresholdObjectsOwner,
                              &StorageTmp->
                              mteTriggerThresholdObjectsOwnerLen);
    if (StorageTmp->mteTriggerThresholdObjectsOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdObjectsOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerThresholdObjects,
                              &StorageTmp->mteTriggerThresholdObjectsLen);
    if (StorageTmp->mteTriggerThresholdObjects == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdObjects");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->
                              mteTriggerThresholdRisingEventOwner,
                              &StorageTmp->
                              mteTriggerThresholdRisingEventOwnerLen);
    if (StorageTmp->mteTriggerThresholdRisingEventOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdRisingEventOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerThresholdRisingEvent,
                              &StorageTmp->
                              mteTriggerThresholdRisingEventLen);
    if (StorageTmp->mteTriggerThresholdRisingEvent == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdRisingEvent");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->
                              mteTriggerThresholdFallingEventOwner,
                              &StorageTmp->
                              mteTriggerThresholdFallingEventOwnerLen);
    if (StorageTmp->mteTriggerThresholdFallingEventOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdFallingEventOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->mteTriggerThresholdFallingEvent,
                              &StorageTmp->
                              mteTriggerThresholdFallingEventLen);
    if (StorageTmp->mteTriggerThresholdFallingEvent == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdFallingEvent");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->
                              mteTriggerThresholdDeltaRisingEventOwner,
                              &StorageTmp->
                              mteTriggerThresholdDeltaRisingEventOwnerLen);
    if (StorageTmp->mteTriggerThresholdDeltaRisingEventOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdDeltaRisingEventOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->
                              mteTriggerThresholdDeltaRisingEvent,
                              &StorageTmp->
                              mteTriggerThresholdDeltaRisingEventLen);
    if (StorageTmp->mteTriggerThresholdDeltaRisingEvent == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdDeltaRisingEvent");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->
                              mteTriggerThresholdDeltaFallingEventOwner,
                              &StorageTmp->
                              mteTriggerThresholdDeltaFallingEventOwnerLen);
    if (StorageTmp->mteTriggerThresholdDeltaFallingEventOwner == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdDeltaFallingEventOwner");
        return;
    }

    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &StorageTmp->
                              mteTriggerThresholdDeltaFallingEvent,
                              &StorageTmp->
                              mteTriggerThresholdDeltaFallingEventLen);
    if (StorageTmp->mteTriggerThresholdDeltaFallingEvent == NULL) {
        config_perror
            ("invalid specification for mteTriggerThresholdDeltaFallingEvent");
        return;
    }

    /*
     * local internal variables 
     */
    line =
        read_config_read_data(ASN_INTEGER, line,
                              &StorageTmp->have_copied_auth_info, &tmpint);
    if (StorageTmp->have_copied_auth_info) {
        line =
            read_config_read_data(ASN_INTEGER, line,
                                  &StorageTmp->pdu_version, &tmpint);
        line =
            read_config_read_data(ASN_INTEGER, line,
                                  &StorageTmp->pdu_securityModel, &tmpint);
        line =
            read_config_read_data(ASN_INTEGER, line,
                                  &StorageTmp->pdu_securityLevel, &tmpint);
        line =
            read_config_read_data(ASN_OBJECT_ID, line, &tmpoid, &tmpint);
        if (!netsnmp_tdomain_support
            (tmpoid, tmpint, &StorageTmp->pdu_tDomain,
             &StorageTmp->pdu_tDomainLen)) {
            config_perror
                ("unsupported transport domain for mteTriggerEntry");
            return;
        }
        if (tmpoid != NULL) {
            free(tmpoid);
        }

        /*
         * can be NULL?  Yes.  
         */
        line = read_config_read_data(ASN_OCTET_STR, line,
                                     &(StorageTmp->pdu_transport),
                                     &StorageTmp->pdu_transportLen);

        line =
            read_config_read_data(ASN_OCTET_STR, line,
                                  &StorageTmp->pdu_community,
                                  &StorageTmp->pdu_community_len);
        if (StorageTmp->pdu_community == NULL) {
            config_perror("invalid specification for pdu_community");
            return;
        }
        line =
            read_config_read_data(ASN_OCTET_STR, line,
                                  &StorageTmp->pdu_securityName,
                                  &StorageTmp->pdu_securityNameLen);
        if (StorageTmp->pdu_securityName == NULL) {
            config_perror("invalid specification for pdu_securityName");
            return;
        }
    }
    StorageTmp->storageType = ST_NONVOLATILE;   /* the only type stored */

    mteTriggerTable_add(StorageTmp);

    /*
     * technically this is too early 
     */
    if (StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_TRUE &&
        StorageTmp->mteTriggerEntryStatus == RS_ACTIVE)
        mte_enable_trigger(StorageTmp);

    DEBUGMSGTL(("mteTriggerTable", "done.\n"));
} /* parse_mteTriggerTable */


/*
 * store_mteTriggerTable():
 *   stores .conf file entries needed to configure the mib.
 */
int
store_mteTriggerTable(int majorID, int minorID, void *serverarg,
                      void *clientarg)
{
    char            line[SNMP_MAXBUF];
    char           *cptr;
    size_t          tmpint;
    struct mteTriggerTable_data *StorageTmp;
    struct header_complex_index *hcindex;

    DEBUGMSGTL(("mteTriggerTable", "storing data...  "));

    for (hcindex = mteTriggerTableStorage; hcindex != NULL;
         hcindex = hcindex->next) {
        StorageTmp = (struct mteTriggerTable_data *) hcindex->data;


        if (StorageTmp->storageType == ST_NONVOLATILE) {

            memset(line, 0, sizeof(line));
            strcat(line, "mteTriggerTable ");
            cptr = line + strlen(line);

            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteOwner,
                                       &StorageTmp->mteOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteTriggerName,
                                       &StorageTmp->mteTriggerNameLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteTriggerComment,
                                       &StorageTmp->mteTriggerCommentLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteTriggerTest,
                                       &StorageTmp->mteTriggerTestLen);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->mteTriggerSampleType,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_OBJECT_ID, cptr,
                                       &StorageTmp->mteTriggerValueID,
                                       &StorageTmp->mteTriggerValueIDLen);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerValueIDWildcard, &tmpint);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteTriggerTargetTag,
                                       &StorageTmp->
                                       mteTriggerTargetTagLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteTriggerContextName,
                                       &StorageTmp->
                                       mteTriggerContextNameLen);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerContextNameWildcard,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_UNSIGNED, cptr,
                                       &StorageTmp->mteTriggerFrequency,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteTriggerObjectsOwner,
                                       &StorageTmp->
                                       mteTriggerObjectsOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteTriggerObjects,
                                       &StorageTmp->mteTriggerObjectsLen);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->mteTriggerEnabled,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->mteTriggerEntryStatus,
                                       &tmpint);

            /*
             * delta table 
             */
            cptr =
                read_config_store_data(ASN_OBJECT_ID, cptr,
                                       &StorageTmp->
                                       mteTriggerDeltaDiscontinuityID,
                                       &StorageTmp->
                                       mteTriggerDeltaDiscontinuityIDLen);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerDeltaDiscontinuityIDWildcard,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerDeltaDiscontinuityIDType,
                                       &tmpint);

            /*
             * existence table 
             */
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerExistenceTest,
                                       &StorageTmp->
                                       mteTriggerExistenceTestLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerExistenceStartup,
                                       &StorageTmp->
                                       mteTriggerExistenceStartupLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerExistenceObjectsOwner,
                                       &StorageTmp->
                                       mteTriggerExistenceObjectsOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerExistenceObjects,
                                       &StorageTmp->
                                       mteTriggerExistenceObjectsLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerExistenceEventOwner,
                                       &StorageTmp->
                                       mteTriggerExistenceEventOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerExistenceEvent,
                                       &StorageTmp->
                                       mteTriggerExistenceEventLen);

            /*
             * boolean table 
             */
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerBooleanComparison,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->mteTriggerBooleanValue,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerBooleanStartup, &tmpint);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerBooleanObjectsOwner,
                                       &StorageTmp->
                                       mteTriggerBooleanObjectsOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerBooleanObjects,
                                       &StorageTmp->
                                       mteTriggerBooleanObjectsLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerBooleanEventOwner,
                                       &StorageTmp->
                                       mteTriggerBooleanEventOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->mteTriggerBooleanEvent,
                                       &StorageTmp->
                                       mteTriggerBooleanEventLen);

            /*
             * threshold table 
             */
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdStartup,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdRising, &tmpint);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdFalling,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaRising,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaFalling,
                                       &tmpint);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdObjectsOwner,
                                       &StorageTmp->
                                       mteTriggerThresholdObjectsOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdObjects,
                                       &StorageTmp->
                                       mteTriggerThresholdObjectsLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdRisingEventOwner,
                                       &StorageTmp->
                                       mteTriggerThresholdRisingEventOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdRisingEvent,
                                       &StorageTmp->
                                       mteTriggerThresholdRisingEventLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdFallingEventOwner,
                                       &StorageTmp->
                                       mteTriggerThresholdFallingEventOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdFallingEvent,
                                       &StorageTmp->
                                       mteTriggerThresholdFallingEventLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaRisingEventOwner,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaRisingEventOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaRisingEvent,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaRisingEventLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaFallingEventOwner,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaFallingEventOwnerLen);
            cptr =
                read_config_store_data(ASN_OCTET_STR, cptr,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaFallingEvent,
                                       &StorageTmp->
                                       mteTriggerThresholdDeltaFallingEventLen);

            /*
             * local internal variables 
             */
            cptr =
                read_config_store_data(ASN_INTEGER, cptr,
                                       &StorageTmp->have_copied_auth_info,
                                       &tmpint);
            if (StorageTmp->have_copied_auth_info) {
                cptr =
                    read_config_store_data(ASN_INTEGER, cptr,
                                           &StorageTmp->pdu_version,
                                           &tmpint);
                cptr =
                    read_config_store_data(ASN_INTEGER, cptr,
                                           &StorageTmp->pdu_securityModel,
                                           &tmpint);
                cptr =
                    read_config_store_data(ASN_INTEGER, cptr,
                                           &StorageTmp->pdu_securityLevel,
                                           &tmpint);
                cptr =
                    read_config_store_data(ASN_OBJECT_ID, cptr,
                                           (void *)(&StorageTmp->pdu_tDomain),
                                           &StorageTmp->pdu_tDomainLen);
                cptr =
                    read_config_store_data(ASN_OCTET_STR, cptr,
                                           &StorageTmp->pdu_transport,
                                           &StorageTmp->pdu_transportLen);
                cptr =
                    read_config_store_data(ASN_OCTET_STR, cptr,
                                           &StorageTmp->pdu_community,
                                           &StorageTmp->pdu_community_len);
                cptr =
                    read_config_store_data(ASN_OCTET_STR, cptr,
                                           &StorageTmp->pdu_securityName,
                                           &StorageTmp->
                                           pdu_securityNameLen);
            }

            snmpd_store_config(line);
        }
    }
    DEBUGMSGTL(("mteTriggerTable", "done.\n"));
    return SNMPERR_SUCCESS;
}




/*
 * var_mteTriggerTable():
 *   Handle this table separately from the scalar value case.
 *   The workings of this are basically the same as for var_mteTriggerTable above.
 */
unsigned char  *
var_mteTriggerTable(struct variable *vp,
                    oid * name,
                    size_t * length,
                    int exact,
                    size_t * var_len, WriteMethod ** write_method)
{


    struct mteTriggerTable_data *StorageTmp = NULL;


    DEBUGMSGTL(("mteTriggerTable",
                "var_mteTriggerTable: Entering...  \n"));

	/* set default value */
	*write_method = NULL;

    /*
     * this assumes you have registered all your data properly
     */
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, vp, name, length, exact,
                        var_len, write_method)) == NULL) {
#ifndef NETSNMP_NO_WRITE_SUPPORT
        if (vp->magic == MTETRIGGERENTRYSTATUS)
            *write_method = write_mteTriggerEntryStatus;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        return NULL;
    }


    /*
     * this is where we do the value assignments for the mib results.
     */
    switch (vp->magic) {


    case MTETRIGGERCOMMENT:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerComment;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = StorageTmp->mteTriggerCommentLen;
        return (u_char *) StorageTmp->mteTriggerComment;

    case MTETRIGGERTEST:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerTest;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = StorageTmp->mteTriggerTestLen;
        return (u_char *) StorageTmp->mteTriggerTest;

    case MTETRIGGERSAMPLETYPE:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerSampleType;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = sizeof(StorageTmp->mteTriggerSampleType);
        return (u_char *) & StorageTmp->mteTriggerSampleType;

    case MTETRIGGERVALUEID:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerValueID;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = StorageTmp->mteTriggerValueIDLen * sizeof(oid);
        return (u_char *) StorageTmp->mteTriggerValueID;

    case MTETRIGGERVALUEIDWILDCARD:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerValueIDWildcard;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = sizeof(StorageTmp->mteTriggerValueIDWildcard);
        return (u_char *) & StorageTmp->mteTriggerValueIDWildcard;

    case MTETRIGGERTARGETTAG:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerTargetTag;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = StorageTmp->mteTriggerTargetTagLen;
        return (u_char *) StorageTmp->mteTriggerTargetTag;

    case MTETRIGGERCONTEXTNAME:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerContextName;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = StorageTmp->mteTriggerContextNameLen;
        return (u_char *) StorageTmp->mteTriggerContextName;

    case MTETRIGGERCONTEXTNAMEWILDCARD:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerContextNameWildcard;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = sizeof(StorageTmp->mteTriggerContextNameWildcard);
        return (u_char *) & StorageTmp->mteTriggerContextNameWildcard;

    case MTETRIGGERFREQUENCY:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerFrequency;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = sizeof(StorageTmp->mteTriggerFrequency);
        return (u_char *) & StorageTmp->mteTriggerFrequency;

    case MTETRIGGEROBJECTSOWNER:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerObjectsOwner;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = StorageTmp->mteTriggerObjectsOwnerLen;
        return (u_char *) StorageTmp->mteTriggerObjectsOwner;

    case MTETRIGGEROBJECTS:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerObjects;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = StorageTmp->mteTriggerObjectsLen;
        return (u_char *) StorageTmp->mteTriggerObjects;

    case MTETRIGGERENABLED:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerEnabled;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = sizeof(StorageTmp->mteTriggerEnabled);
        return (u_char *) & StorageTmp->mteTriggerEnabled;

    case MTETRIGGERENTRYSTATUS:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        *write_method = write_mteTriggerEntryStatus;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        *var_len = sizeof(StorageTmp->mteTriggerEntryStatus);
        return (u_char *) & StorageTmp->mteTriggerEntryStatus;


    default:
        ERROR_MSG("");
    }
    return NULL;
}



#ifndef NETSNMP_NO_WRITE_SUPPORT
int
write_mteTriggerComment(int action,
                        u_char * var_val,
                        u_char var_val_type,
                        size_t var_val_len,
                        u_char * statP, oid * name, size_t name_len)
{
    static char    *tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    static size_t   tmplen;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerComment entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_OCTET_STR) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerComment not ASN_OCTET_STR\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;

        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in string for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerComment;
        tmplen = StorageTmp->mteTriggerCommentLen;
        StorageTmp->mteTriggerComment = netsnmp_memdup(var_val, var_val_len);
        StorageTmp->mteTriggerCommentLen = var_val_len;
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        SNMP_FREE(StorageTmp->mteTriggerComment);
        StorageTmp->mteTriggerComment = tmpvar;
        StorageTmp->mteTriggerCommentLen = tmplen;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        SNMP_FREE(tmpvar);
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerComment */



int
write_mteTriggerTest(int action,
                     u_char * var_val,
                     u_char var_val_type,
                     size_t var_val_len,
                     u_char * statP, oid * name, size_t name_len)
{
    static char    *tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    static size_t   tmplen;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerTest entering action=%d...  \n", action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_OCTET_STR) {
            snmp_log(LOG_ERR, "write to mteTriggerTest not ASN_OCTET_STR\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in string for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerTest;
        tmplen = StorageTmp->mteTriggerTestLen;
        StorageTmp->mteTriggerTest = netsnmp_memdup(var_val, var_val_len);
        StorageTmp->mteTriggerTestLen = var_val_len;
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        SNMP_FREE(StorageTmp->mteTriggerTest);
        StorageTmp->mteTriggerTest = tmpvar;
        StorageTmp->mteTriggerTestLen = tmplen;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        SNMP_FREE(tmpvar);
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerTest */



int
write_mteTriggerSampleType(int action,
                           u_char * var_val,
                           u_char var_val_type,
                           size_t var_val_len,
                           u_char * statP, oid * name, size_t name_len)
{
    static int      tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerSampleType entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_INTEGER) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerSampleType not ASN_INTEGER\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in long_ret for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerSampleType;
        StorageTmp->mteTriggerSampleType = *((long *) var_val);
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        StorageTmp->mteTriggerSampleType = tmpvar;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerSampleType */



int
write_mteTriggerValueID(int action,
                        u_char * var_val,
                        u_char var_val_type,
                        size_t var_val_len,
                        u_char * statP, oid * name, size_t name_len)
{
    static oid     *tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    static size_t   tmplen;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerValueID entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_OBJECT_ID) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerValueID not ASN_OBJECT_ID\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in objid for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerValueID;
        tmplen = StorageTmp->mteTriggerValueIDLen;
        StorageTmp->mteTriggerValueID = netsnmp_memdup(var_val, var_val_len);
        StorageTmp->mteTriggerValueIDLen = var_val_len / sizeof(oid);
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        SNMP_FREE(StorageTmp->mteTriggerValueID);
        StorageTmp->mteTriggerValueID = tmpvar;
        StorageTmp->mteTriggerValueIDLen = tmplen;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */

        /*
         * XXX: if the valueID has actually changed, shouldn't we dump any
         * previous values, as these are from a different object?  
         */
        SNMP_FREE(tmpvar);
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerValueID */



int
write_mteTriggerValueIDWildcard(int action,
                                u_char * var_val,
                                u_char var_val_type,
                                size_t var_val_len,
                                u_char * statP,
                                oid * name, size_t name_len)
{
    static int      tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerValueIDWildcard entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_INTEGER) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerValueIDWildcard not ASN_INTEGER\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in long_ret for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerValueIDWildcard;
        StorageTmp->mteTriggerValueIDWildcard = *((long *) var_val);
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        StorageTmp->mteTriggerValueIDWildcard = tmpvar;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerValueIDWildcard */



int
write_mteTriggerTargetTag(int action,
                          u_char * var_val,
                          u_char var_val_type,
                          size_t var_val_len,
                          u_char * statP, oid * name, size_t name_len)
{
    static char    *tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    static size_t   tmplen;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerTargetTag entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_OCTET_STR) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerTargetTag not ASN_OCTET_STR\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in string for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerTargetTag;
        tmplen = StorageTmp->mteTriggerTargetTagLen;
        StorageTmp->mteTriggerTargetTag = netsnmp_memdup(var_val, var_val_len);
        StorageTmp->mteTriggerTargetTagLen = var_val_len;
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        SNMP_FREE(StorageTmp->mteTriggerTargetTag);
        StorageTmp->mteTriggerTargetTag = tmpvar;
        StorageTmp->mteTriggerTargetTagLen = tmplen;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        SNMP_FREE(tmpvar);
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerTargetTag */



int
write_mteTriggerContextName(int action,
                            u_char * var_val,
                            u_char var_val_type,
                            size_t var_val_len,
                            u_char * statP, oid * name, size_t name_len)
{
    static char    *tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    static size_t   tmplen;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerContextName entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_OCTET_STR) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerContextName not ASN_OCTET_STR\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in string for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerContextName;
        tmplen = StorageTmp->mteTriggerContextNameLen;
        StorageTmp->mteTriggerContextName =
            netsnmp_memdup(var_val, var_val_len);
        StorageTmp->mteTriggerContextNameLen = var_val_len;
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        SNMP_FREE(StorageTmp->mteTriggerContextName);
        StorageTmp->mteTriggerContextName = tmpvar;
        StorageTmp->mteTriggerContextNameLen = tmplen;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        SNMP_FREE(tmpvar);
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerContextName */



int
write_mteTriggerContextNameWildcard(int action,
                                    u_char * var_val,
                                    u_char var_val_type,
                                    size_t var_val_len,
                                    u_char * statP,
                                    oid * name, size_t name_len)
{
    static int      tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerContextNameWildcard entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_INTEGER) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerContextNameWildcard not ASN_INTEGER\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in long_ret for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerContextNameWildcard;
        StorageTmp->mteTriggerContextNameWildcard = *((long *) var_val);
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        StorageTmp->mteTriggerContextNameWildcard = tmpvar;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerContextNameWildcard */



int
write_mteTriggerFrequency(int action,
                          u_char * var_val,
                          u_char var_val_type,
                          size_t var_val_len,
                          u_char * statP, oid * name, size_t name_len)
{
    static int      tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerFrequency entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_UNSIGNED) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerFrequency not ASN_UNSIGNED\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in ulong_ret for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerFrequency;
        StorageTmp->mteTriggerFrequency = *((unsigned long *) var_val);
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        StorageTmp->mteTriggerFrequency = tmpvar;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        if (StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_TRUE &&
            StorageTmp->mteTriggerEntryStatus == RS_ACTIVE)
            mte_enable_trigger(StorageTmp);

        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerFrequency */



int
write_mteTriggerObjectsOwner(int action,
                             u_char * var_val,
                             u_char var_val_type,
                             size_t var_val_len,
                             u_char * statP, oid * name, size_t name_len)
{
    static char    *tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    static size_t   tmplen;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerObjectsOwner entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_OCTET_STR) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerObjectsOwner not ASN_OCTET_STR\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in string for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerObjectsOwner;
        tmplen = StorageTmp->mteTriggerObjectsOwnerLen;
        StorageTmp->mteTriggerObjectsOwner =
            netsnmp_memdup(var_val, var_val_len);
        StorageTmp->mteTriggerObjectsOwnerLen = var_val_len;
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        SNMP_FREE(StorageTmp->mteTriggerObjectsOwner);
        StorageTmp->mteTriggerObjectsOwner = tmpvar;
        StorageTmp->mteTriggerObjectsOwnerLen = tmplen;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        SNMP_FREE(tmpvar);
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerObjectsOwner */



int
write_mteTriggerObjects(int action,
                        u_char * var_val,
                        u_char var_val_type,
                        size_t var_val_len,
                        u_char * statP, oid * name, size_t name_len)
{
    static char    *tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    static size_t   tmplen;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerObjects entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_OCTET_STR) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerObjects not ASN_OCTET_STR\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in string for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerObjects;
        tmplen = StorageTmp->mteTriggerObjectsLen;
        StorageTmp->mteTriggerObjects = netsnmp_memdup(var_val, var_val_len);
        StorageTmp->mteTriggerObjectsLen = var_val_len;
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        SNMP_FREE(StorageTmp->mteTriggerObjects);
        StorageTmp->mteTriggerObjects = tmpvar;
        StorageTmp->mteTriggerObjectsLen = tmplen;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        SNMP_FREE(tmpvar);
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerObjects */



int
write_mteTriggerEnabled(int action,
                        u_char * var_val,
                        u_char var_val_type,
                        size_t var_val_len,
                        u_char * statP, oid * name, size_t name_len)
{
    static int      tmpvar;
    struct mteTriggerTable_data *StorageTmp = NULL;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);


    DEBUGMSGTL(("mteTriggerTable",
                "write_mteTriggerEnabled entering action=%d...  \n",
                action));
    if ((StorageTmp =
         header_complex(mteTriggerTableStorage, NULL,
                        &name[sizeof(mteTriggerTable_variables_oid) /
                              sizeof(oid) + 3 - 1], &newlen, 1, NULL,
                        NULL)) == NULL)
        return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */


    switch (action) {
    case RESERVE1:
        if (var_val_type != ASN_INTEGER) {
            snmp_log(LOG_ERR,
                     "write to mteTriggerEnabled not ASN_INTEGER\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (StorageTmp->storageType != ST_NONVOLATILE)
            return SNMP_ERR_NOTWRITABLE;
        break;


    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        break;


    case FREE:
        /*
         * Release any resources that have been allocated 
         */
        break;


    case ACTION:
        /*
         * The variable has been stored in long_ret for
         * you to use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in the UNDO case 
         */
        tmpvar = StorageTmp->mteTriggerEnabled;
        StorageTmp->mteTriggerEnabled = *((long *) var_val);
        break;


    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        StorageTmp->mteTriggerEnabled = tmpvar;
        break;


    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        if (StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_TRUE &&
            StorageTmp->mteTriggerEntryStatus == RS_ACTIVE)
            mte_enable_trigger(StorageTmp);
        else if (StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_FALSE)
            mte_disable_trigger(StorageTmp);

        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerEnabled */



int
write_mteTriggerEntryStatus(int action,
                            u_char * var_val,
                            u_char var_val_type,
                            size_t var_val_len,
                            u_char * statP, oid * name, size_t name_len)
{
    struct mteTriggerTable_data *StorageTmp = NULL;
    static struct mteTriggerTable_data *StorageNew, *StorageDel;
    size_t          newlen =
        name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                    3 - 1);
    static int      old_value;
    int             set_value;
    static netsnmp_variable_list *vars, *vp;
    struct header_complex_index *hciptr;

    StorageTmp =
        header_complex(mteTriggerTableStorage, NULL,
                       &name[sizeof(mteTriggerTable_variables_oid) /
                             sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);




    if (var_val_type != ASN_INTEGER || var_val == NULL) {
        snmp_log(LOG_ERR,
                 "write to mteTriggerEntryStatus not ASN_INTEGER\n");
        return SNMP_ERR_WRONGTYPE;
    }
    set_value = *((long *) var_val);


    /*
     * check legal range, and notReady is reserved for us, not a user 
     */
    if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
        return SNMP_ERR_INCONSISTENTVALUE;


    switch (action) {
    case RESERVE1:
        /*
         * stage one: test validity 
         */
        if (StorageTmp == NULL) {
            /*
             * create the row now? 
             */


            /*
             * ditch illegal values now 
             */
            if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE)
                return SNMP_ERR_INCONSISTENTVALUE;


            /*
             * destroying a non-existent row is actually legal 
             */
            if (set_value == RS_DESTROY) {
                return SNMP_ERR_NOERROR;
            }


            /*
             * illegal creation values 
             */
            if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
                return SNMP_ERR_INCONSISTENTVALUE;
            }
        } else {
            /*
             * row exists.  Check for a valid state change 
             */
            if (set_value == RS_CREATEANDGO
                || set_value == RS_CREATEANDWAIT) {
                /*
                 * can't create a row that exists 
                 */
                return SNMP_ERR_INCONSISTENTVALUE;
            }

            if (StorageTmp->mteTriggerEntryStatus == RS_ACTIVE &&
                set_value != RS_DESTROY) {
                /*
                 * "Once made active an entry may not be modified except to 
                 * delete it."  XXX: doesn't this in fact apply to ALL
                 * columns of the table and not just this one?  
                 */
                return SNMP_ERR_INCONSISTENTVALUE;
            }
            if (StorageTmp->storageType != ST_NONVOLATILE)
                return SNMP_ERR_NOTWRITABLE;
        }
        break;




    case RESERVE2:
        /*
         * memory reseveration, final preparation... 
         */
        if (StorageTmp == NULL) {
            /*
             * creation 
             */
            vars = NULL;


            snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0);  /* mteOwner */
            snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OCTET_STR, NULL, 0);     /* mteTriggerName */



            if (header_complex_parse_oid
                (&
                 (name
                  [sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
                   2]), newlen, vars) != SNMPERR_SUCCESS) {
                /*
                 * XXX: free, zero vars 
                 */
                return SNMP_ERR_INCONSISTENTNAME;
            }
            vp = vars;


            StorageNew = create_mteTriggerTable_data();

            StorageNew->mteOwner = malloc(vp->val_len + 1);
            memcpy(StorageNew->mteOwner, vp->val.string, vp->val_len);
            StorageNew->mteOwner[vp->val_len] = '\0';
            StorageNew->mteOwnerLen = vp->val_len;

            vp = vp->next_variable;
            StorageNew->mteTriggerName = malloc(vp->val_len + 1);
            memcpy(StorageNew->mteTriggerName, vp->val.string,
                   vp->val_len);
            StorageNew->mteTriggerName[vp->val_len] = '\0';
            StorageNew->mteTriggerNameLen = vp->val_len;

            vp = vp->next_variable;

            StorageNew->mteTriggerEntryStatus = set_value;

        }


        break;




    case FREE:
        /*
         * XXX: free, zero vars 
         */
        /*
         * Release any resources that have been allocated 
         */
        break;




    case ACTION:
        /*
         * The variable has been stored in set_value for you to
         * use, and you have just been asked to do something with
         * it.  Note that anything done here must be reversable in
         * the UNDO case 
         */


        if (StorageTmp == NULL) {
            /*
             * row creation, so add it 
             */
            if (StorageNew != NULL)
                mteTriggerTable_add(StorageNew);
            /*
             * XXX: ack, and if it is NULL? 
             */
        } else if (set_value != RS_DESTROY) {
            /*
             * set the flag? 
             */
            old_value = StorageTmp->mteTriggerEntryStatus;
            StorageTmp->mteTriggerEntryStatus = *((long *) var_val);
        } else {
            /*
             * destroy...  extract it for now 
             */
            hciptr =
                header_complex_find_entry(mteTriggerTableStorage,
                                          StorageTmp);
            StorageDel =
                header_complex_extract_entry(&mteTriggerTableStorage,
                                             hciptr);
        }
        break;




    case UNDO:
        /*
         * Back out any changes made in the ACTION case 
         */
        if (StorageTmp == NULL) {
            /*
             * row creation, so remove it again 
             */
            hciptr =
                header_complex_find_entry(mteTriggerTableStorage,
                                          StorageTmp);
            StorageDel =
                header_complex_extract_entry(&mteTriggerTableStorage,
                                             hciptr);
            /*
             * XXX: free it 
             */
        } else if (StorageDel != NULL) {
            /*
             * row deletion, so add it again 
             */
            mteTriggerTable_add(StorageDel);
        } else {
            StorageTmp->mteTriggerEntryStatus = old_value;
        }
        break;




    case COMMIT:
        /*
         * Things are working well, so it's now safe to make the change
         * permanently.  Make sure that anything done here can't fail! 
         */
        if (StorageDel != NULL) {
            mte_disable_trigger(StorageDel);
            StorageDel = NULL;
            /*
             * XXX: free it, its dead 
             */
        } else {
            if (StorageTmp
                && StorageTmp->mteTriggerEntryStatus == RS_CREATEANDGO) {
                StorageTmp->mteTriggerEntryStatus = RS_ACTIVE;
            } else if (StorageTmp &&
                       StorageTmp->mteTriggerEntryStatus ==
                       RS_CREATEANDWAIT) {
                StorageTmp->mteTriggerEntryStatus = RS_NOTINSERVICE;
            }
        }
        if (StorageTmp &&
            StorageTmp->mteTriggerEntryStatus == RS_ACTIVE &&
            !StorageTmp->have_copied_auth_info) {

            netsnmp_agent_session *asp =
                netsnmp_get_current_agent_session();
            netsnmp_pdu    *pdu = NULL;

            if (!asp) {
                snmp_log(LOG_ERR,
                         "snmpTriggerTable: can't get master session for authentication params\n");
            } else {
                pdu = asp->orig_pdu;
                if (!pdu) {
                    snmp_log(LOG_ERR,
                             "snmpTriggerTable: can't get master pdu for authentication params\n");
                }
            }

            if (pdu) {
                DEBUGMSGTL(("mteTriggerTest", "copying PDU auth info\n"));
                StorageTmp->pdu_version = pdu->version;
                StorageTmp->pdu_securityModel = pdu->securityModel;
                StorageTmp->pdu_securityLevel = pdu->securityLevel;
                StorageTmp->pdu_tDomain = pdu->tDomain;
                StorageTmp->pdu_tDomainLen = pdu->tDomainLen;
                if (pdu->transport_data != NULL) {
                    StorageTmp->pdu_transport =
                        malloc(pdu->transport_data_length);
                    memcpy(StorageTmp->pdu_transport, pdu->transport_data,
                           pdu->transport_data_length);
                }
                StorageTmp->pdu_transportLen = pdu->transport_data_length;
                if (pdu->community) {
                    StorageTmp->pdu_community =
                        calloc(1, pdu->community_len + 1);
                    memcpy(StorageTmp->pdu_community, pdu->community,
                           pdu->community_len);
                    StorageTmp->pdu_community_len = pdu->community_len;
                } else {
                    StorageTmp->pdu_community = NULL;
                    StorageTmp->pdu_community_len = 0;
                }
                if (pdu->securityName) {
                    StorageTmp->pdu_securityName =
                        netsnmp_memdup(pdu->securityName,
                                       pdu->securityNameLen + 1);
                    StorageTmp->pdu_securityNameLen = pdu->securityNameLen;
                } else {
                    StorageTmp->pdu_securityName = NULL;
                    StorageTmp->pdu_securityNameLen = 0;
                }
                StorageTmp->have_copied_auth_info = 1;
            }
        }

        if (StorageTmp &&
            StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_TRUE &&
            StorageTmp->mteTriggerEntryStatus == RS_ACTIVE)
            mte_enable_trigger(StorageTmp);
        snmp_store_needed(NULL);
        break;
    }
    return SNMP_ERR_NOERROR;
} /* write_mteTriggerEntryStatus */

#endif /* !NETSNMP_NO_WRITE_SUPPORT */



/*
 * send trap 
 */
void
send_mte_trap(struct mteTriggerTable_data *item,
              oid * trap_oid, size_t trap_oid_len,
              oid * name_oid, size_t name_oid_len,
              long *value, const char *objowner, const char *objname,
              const char *reason)
{
    static oid      objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };     /* snmpTrapIOD.0 */

    netsnmp_variable_list *var_list = NULL;

    /*
     * snmpTrap oid 
     */
    snmp_varlist_add_variable(&var_list, objid_snmptrap,
                              sizeof(objid_snmptrap) / sizeof(oid),
                              ASN_OBJECT_ID, (u_char *) trap_oid,
                              trap_oid_len * sizeof(oid));

    /*
     * mteHotTrigger 
     */
    snmp_varlist_add_variable(&var_list, mteHotTrigger,
                              sizeof(mteHotTrigger) / sizeof(oid),
                              ASN_OCTET_STR,
                              (u_char *) item->mteTriggerName,
                              item->mteTriggerNameLen);

    /*
     * mteHotTargetName 
     */
    snmp_varlist_add_variable(&var_list, mteHotTargetName, sizeof(mteHotTargetName) / sizeof(oid), ASN_OCTET_STR, (u_char *) item->mteTriggerTargetTag, /*XXX: targetName,not tag */
                              item->mteTriggerTargetTagLen);    /*XXX */

    /*
     * mteHotContextName 
     */
    snmp_varlist_add_variable(&var_list, mteHotContextName,
                              sizeof(mteHotContextName) / sizeof(oid),
                              ASN_OCTET_STR,
                              (u_char *) item->mteTriggerContextName,
                              item->mteTriggerContextNameLen);

    snmp_varlist_add_variable(&var_list, mteHotOID,
                              sizeof(mteHotOID) / sizeof(oid),
                              ASN_OBJECT_ID, (u_char *) name_oid,
                              sizeof(oid) * name_oid_len);

    if (trap_oid == mteTriggerFailure || trap_oid == mteEventSetFailure) {
        /*
         * mteFailedReason  
         */
        snmp_varlist_add_variable(&var_list, mteFailedReason,
                                  sizeof(mteFailedReason) / sizeof(oid),
                                  ASN_INTEGER, (u_char *) value,
                                  sizeof(value));
    } else {
        /*
         * mteHotValue  
         */
        snmp_varlist_add_variable(&var_list, mteHotValue,
                                  sizeof(mteHotValue) / sizeof(oid),
                                  ASN_INTEGER, (u_char *) value,
                                  sizeof(value));
    }

    /*
     * add in traps from main table 
     */
    mte_add_objects(var_list, item, item->mteTriggerObjectsOwner,
                    item->mteTriggerObjects,
                    name_oid + item->mteTriggerValueIDLen,
                    name_oid_len - item->mteTriggerValueIDLen);
    /*
     * add in traps from sub table 
     */
    mte_add_objects(var_list, item, objowner, objname,
                    name_oid + item->mteTriggerValueIDLen,
                    name_oid_len - item->mteTriggerValueIDLen);

    /*
     * XXX: stuff based on event table 
     */
    DEBUGMSGTL(("mteTriggerTest:send_mte_trap", "sending the trap (%s): ",
                reason));
    DEBUGMSGOID(("mteTriggerTest:send_mte_trap", name_oid, name_oid_len));
    DEBUGMSG(("mteTriggerTest:send_mte_trap", " = %ld\n", *value));

    send_v2trap(var_list);
    snmp_free_varbind(var_list);
} /* send_mte_trap */


void
last_state_clean(void *data)
{
    struct last_state *cleanme = (struct last_state *) data;
    SNMP_FREE(cleanme->value);
    SNMP_FREE(cleanme);
}


/*
 * retrieves requested info in pdu from the current target 
 */
netsnmp_pdu    *
mte_get_response(struct mteTriggerTable_data *item, netsnmp_pdu *pdu)
{
    netsnmp_pdu    *response = NULL;
    int             status = 0;
    char            buf[SPRINT_MAX_LEN];

    /*
     * local agent check 
     */
    pdu->errstat = SNMPERR_SUCCESS;
    pdu->errindex = 0;
    pdu->version = item->pdu_version;
    pdu->securityModel = item->pdu_securityModel;
    pdu->securityLevel = item->pdu_securityLevel;
    pdu->tDomain = item->pdu_tDomain;
    pdu->tDomainLen = item->pdu_tDomainLen;
    pdu->transport_data = netsnmp_memdup(item->pdu_transport,
                                         item->pdu_transportLen);
    pdu->transport_data_length = item->pdu_transportLen;
    pdu->community = netsnmp_memdup(item->pdu_community,
                                    item->pdu_community_len);
    pdu->community_len = item->pdu_community_len;
    pdu->contextName = netsnmp_memdup(item->mteTriggerContextName,
                                      item->mteTriggerContextNameLen);
    pdu->contextNameLen = item->mteTriggerContextNameLen;
    pdu->securityName = netsnmp_memdup(item->pdu_securityName,
                                       item->pdu_securityNameLen + 1);
    pdu->securityNameLen = item->pdu_securityNameLen;
    DEBUGMSGTL(("mteTriggerTable",
                "accessing locally with secName \"%s\" community \"%s\"\n",
                item->pdu_securityName ? (char *) item->
                pdu_securityName : "[NIL]",
                item->pdu_community ? (char *) item->
                pdu_community : "[NIL]"));

    if (item->mteTriggerTargetTagLen == 0) {
        /*
         * send to the local agent 
         */

        if (mte_callback_sess == NULL)
            mte_callback_sess =  netsnmp_query_get_default_session();
        if (!mte_callback_sess)
            return NULL;

        status = snmp_synch_response(mte_callback_sess, pdu, &response);

        if (status != SNMP_ERR_NOERROR ||
            response->errstat != SNMP_ERR_NOERROR) {
            /*
             * xxx 
             */
            char           *errstr;
            snmp_error(mte_callback_sess, NULL, NULL, &errstr);
            if (response) {
                DEBUGMSGTL(("mteTriggerTable",
                            "Error received: status=%d, sess_error=%s, pduerr=%d/%s, pdu version=%d\n",
                            status, errstr,
                            response->errstat,
                            snmp_api_errstring(response->errstat),
                            response->version));
            } else {
                DEBUGMSGTL(("mteTriggerTable",
                            "Error received: status=%d, sess_error=%s [no response pointer]\n",
                            status, errstr));
            }
            if (errstr)
                free(errstr);
            return NULL;        /* XXX: proper failure, trap sent, etc */
        }
    } else {
        /*
         * remote target list 
         */
        /*
         * XXX 
         */
    }
    if (response->variables)
        snprint_variable(buf, sizeof(buf), response->variables->name,
                         response->variables->name_length,
                         response->variables);
    else
        strcpy(buf, "empty");
    buf[sizeof(buf) - 1] = '\0';
    DEBUGMSGTL(("mteTriggerTable", "got a variables: %s\n", buf));
    return response;
} /* mte_get_response */


/*
 * Return 1 if `type' is an integer type; specifically, to quote RFC 2981,
 * p. 13, "anything that ends up encoded for transmission (that is, in BER,
 * not ASN.1) as an integer".  Return 0 for all other types.  
 */

int
mte_is_integer_type(unsigned char type)
{
    switch (type) {
    case ASN_INTEGER:
    case ASN_COUNTER:
    case ASN_GAUGE:
    case ASN_TIMETICKS:
    case ASN_UINTEGER:
    case ASN_COUNTER64:
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
    case ASN_OPAQUE_COUNTER64:
    case ASN_OPAQUE_U64:
    case ASN_OPAQUE_I64:
#endif                          /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
        return 1;
    default:
        return 0;
    }
}


/*
 * Return 0 if the discontinuity object was checked and no discontinuity has
 * occurred, 1 if the discontinuity object was checked and a discontinuity
 * has occurred or -1 if the discontinuity object is not accessible.  
 */

int
mte_discontinuity_occurred(struct mteTriggerTable_data *item)
{
    netsnmp_pdu    *pdu = NULL, *response = NULL;
    unsigned long   discoTicks = 0;     /*  cool var name  */

    if (item->mteTriggerDeltaDiscontinuityIDLen == 0 ||
        (snmp_oid_compare(item->mteTriggerDeltaDiscontinuityID,
                          item->mteTriggerDeltaDiscontinuityIDLen,
                          sysUpTimeInstance,
                          sizeof(sysUpTimeInstance) / sizeof(oid)) == 0)) {
        DEBUGMSGTL(("mte_disco",
                    "discoID either zero-length or sysUpTimeInstance\n"));
    } else {
        if (item->mteTriggerValueIDWildcard == TV_TRUE) {
            pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
        } else {
            pdu = snmp_pdu_create(SNMP_MSG_GET);
        }
        snmp_add_null_var(pdu, item->mteTriggerDeltaDiscontinuityID,
                          item->mteTriggerDeltaDiscontinuityIDLen);
        response = mte_get_response(item, pdu);
        if (response == NULL) {
            /*
             * XXX:  send a mteTriggerFailure notification with the appropriate
             * error code here.  
             */
            /*
             * "If the object identified is not accessible the sample attempt is in 
             * error, with the error code as from an SNMP request."  
             */
            DEBUGMSGTL(("mte_disco", "failure (auth?) getting discoID\n"));
            return -1;
        } else {
            if (item->mteTriggerDeltaDiscontinuityIDType ==
                MTETRIGGERDELTADISCONTINUITYIDTYPE_TIMETICKS ||
                item->mteTriggerDeltaDiscontinuityIDType ==
                MTETRIGGERDELTADISCONTINUITYIDTYPE_TIMESTAMP) {
                if (response->errstat == SNMPERR_SUCCESS) {
                    if (response->variables != NULL &&
                        response->variables->type == ASN_TIMETICKS) {
                        DEBUGMSGTL(("mte_disco",
                                    "got ASN_TIMETICKS-valued variable\n"));
                        discoTicks =
                            *((unsigned long *) response->variables->val.
                              integer);
                        if (item->prevDiscoTicks != 0) {
                            if (discoTicks != item->prevDiscoTicks) {
                                /*
                                 * Danger Will Robinson: there has been a discontinuity!  
                                 */
                                DEBUGMSGTL(("mte_disco",
                                            "a discontinuity has occurred\n"));
                                item->prevDiscoTicks = discoTicks;
                                snmp_free_pdu(response);
                                return 1;
                            }
                        }
                        item->prevDiscoTicks = discoTicks;
                    } else {
                        /*
                         * XXX: send a mteTriggerFailure notification with the
                         * appropriate error code here.  
                         */
                        if (response->variables != NULL &&
                            (response->variables->type == SNMP_NOSUCHOBJECT
                             || response->variables->type ==
                             SNMP_NOSUCHINSTANCE
                             || response->variables->type ==
                             SNMP_ENDOFMIBVIEW)) {
                            /*
                             * noSuchName I guess.  
                             */
                        } else {
                            /*
                             * badType.  
                             */
                        }
                        DEBUGMSGTL(("mte_disco",
                                    "failure getting discoID\n"));
                        snmp_free_pdu(response);
                        return -1;
                    }
                } else {
                    /*
                     * XXX: send a mteTriggerFailure notification with the appropriate
                     * error code (just use response->errstat) here.  
                     */
                    DEBUGMSGTL(("mte_disco", "failure getting discoID\n"));
                    snmp_free_pdu(response);
                    return -1;
                }
            } else {
                /*
                 * Don't handle dateAndTime type queries yet.  
                 */
                DEBUGMSGTL(("mte_disco",
                            "dateAndTime query UNIMPLEMENTED\n"));
            }
            snmp_free_pdu(response);
        }
    }

    /*
     * "...if this object does not point to sysUpTime discontinuity checking
     * MUST still check sysUpTime for an overall discontinuity."  
     */
    if (snmp_oid_compare(item->mteTriggerDeltaDiscontinuityID,
                         item->mteTriggerDeltaDiscontinuityIDLen,
                         sysUpTimeInstance,
                         sizeof(sysUpTimeInstance) / sizeof(oid)) != 0) {
        DEBUGMSGTL(("mte_disco", "discoID != sysUpTimeInstance\n"));
        /*
         * At the moment we only support checking the local system so there's no
         * point doing anything extra here.  
         */
    }

    /*
     * Well if we got all the way to here, then there has been neither a
     * discontinuity nor an error.  
     */
    DEBUGMSGTL(("mte_disco", "no discontinuity\n"));
    return 0;
} /* mte_discontinuity_occurred */


void
mte_run_trigger(unsigned int clientreg, void *clientarg)
{

    struct mteTriggerTable_data *item =
        (struct mteTriggerTable_data *) clientarg;
    netsnmp_pdu    *pdu = NULL, *response = NULL;
    char            buf[SPRINT_MAX_LEN];
    int             msg_type = SNMP_MSG_GET, disco;

    oid            *next_oid;
    size_t          next_oid_len;
    long           *value, *old_value, x;
    struct last_state *laststate;
    char            lastbool = 0, boolresult = 0, lastthresh = 0;

    if (!item) {
        /*
         * ack 
         */
        snmp_alarm_unregister(clientreg);
        return;
    }
    DEBUGMSGTL(("mteTriggertable", "Running trigger for %s/%s\n",
                item->mteOwner, item->mteTriggerName));

    next_oid = item->mteTriggerValueID;
    next_oid_len = item->mteTriggerValueIDLen;
    if (item->mteTriggerValueIDWildcard == TV_TRUE)
        msg_type = SNMP_MSG_GETNEXT;

    item->hc_storage_old = item->hc_storage;
    item->hc_storage = NULL;
    do {
        pdu = snmp_pdu_create(msg_type);
        snmp_add_null_var(pdu, next_oid, next_oid_len);

        if(response)
            snmp_free_pdu(response);
		
        response = mte_get_response(item, pdu);
        if (!response)
            break;              /* XXX: proper failure */

        if (item->mteTriggerValueIDWildcard == TV_TRUE &&
            ((response->variables->type >= SNMP_NOSUCHOBJECT &&
              response->variables->type <= SNMP_ENDOFMIBVIEW) ||
             snmp_oid_compare(item->mteTriggerValueID,
                              item->mteTriggerValueIDLen,
                              response->variables->name,
                              item->mteTriggerValueIDLen) != 0)) {
            DEBUGMSGTL(("mteTriggerTable",
                        "DONE, last varbind processed\n"));
            break;
        }

        /*
         * shorter pointers 
         */
        next_oid = response->variables->name;
        next_oid_len = response->variables->name_length;

        /*
         * Send a "bad type" notification if the type of the target object is 
         * non-INTEGER and the test type is either `boolean' or `threshold'
         * (which want to do arithmetic).  
         */
        if (((item->mteTriggerTest[0] & MTETRIGGERTEST_BOOLEAN) ||
             (item->mteTriggerTest[0] & MTETRIGGERTEST_THRESHOLD)) &&
            response->errstat == SNMPERR_SUCCESS &&
            !mte_is_integer_type(response->variables->type)) {
            long            failure = MTE_FAILURE_BADTYPE;
            send_mte_trap(item, mteTriggerFailure,
                          sizeof(mteTriggerFailure) / sizeof(oid),
                          next_oid, next_oid_len, &failure,
                          NULL, NULL, "failure: bad type");
            /*
             * RFC2981, p.15: "If the value syntax of those objects
             * [returned by a getNext-style match] is not usable, that
             * results in a `badType' error THAT TERMINATES THE SCAN."
             * (my emphasis).  
             */
            break;
        }

        /*
         * Clone the value.  XXX: What happens if it's an unsigned type? Or a
         * 64-bit type, or an OCTET STRING for the sake of argument.  Do
         * everything in 64-bit arithmetic perhaps?  Generate "bad type"
         * notifications for non-INTEGER cases (except for existence).  
         */
        if (response->errstat == SNMPERR_SUCCESS &&
            response->variables->val.integer)
            value = netsnmp_memdup(response->variables->val.integer,
                                   sizeof(*response->variables->val.integer));
        else
            value = NULL;

        snprint_variable(buf, sizeof(buf),
                         next_oid, next_oid_len, response->variables);
        buf[sizeof(buf) - 1] = '\0';
        DEBUGMSGTL(("mteTriggerTable", "received %s (type %d)\n", buf,
                    response->variables->type));

        /*
         * see if we have old values for this 
         */
        laststate = header_complex_get_from_oid(item->hc_storage_old,
                                                next_oid, next_oid_len);
        if (laststate) {
            old_value = laststate->value;
            lastbool = laststate->lastbool;
            lastthresh = laststate->lastthreshold;
        } else {
            old_value = NULL;
            lastthresh = MTE_THRESHOLD_BEGIN;
        }

        /*
         * deal with existence tests 
         */
        if (item->mteTriggerTest[0] & MTETRIGGERTEST_EXISTENCE) {
            if ((item->mteTriggerExistenceTest[0] &
                 MTETRIGGEREXISTENCETEST_PRESENT)
                && value && !old_value &&
                (item->started ||
                 (item->mteTriggerExistenceStartup[0] &
                  MTETRIGGEREXISTENCESTARTUP_PRESENT))) {
                /*
                 * XXX: if mteTriggerExistenceTest is not "present", for
                 * example, and then turned on when has been previously
                 * off, do we respect the value of the last known
                 * existence status? 
                 */
                send_mte_trap(item, mteTriggerFired,
                              sizeof(mteTriggerFired) / sizeof(oid),
                              next_oid, next_oid_len,
                              value, item->mteTriggerExistenceObjectsOwner,
                              item->mteTriggerExistenceObjects,
                              "existence: present");
                run_mte_events(item, next_oid, next_oid_len,
                               item->mteTriggerExistenceEventOwner,
                               item->mteTriggerExistenceEvent);
            }

            if ((item->mteTriggerExistenceTest[0] &
                 MTETRIGGEREXISTENCETEST_CHANGED)
                && value && old_value && *old_value != *value) {
                /*
                 * XXX: if mteTriggerExistenceTest is not "present", for
                 * example, and then turned on when has been previously
                 * off, do we respect the value of the last known
                 * existence status? 
                 */
                send_mte_trap(item, mteTriggerFired,
                              sizeof(mteTriggerFired) / sizeof(oid),
                              next_oid, next_oid_len,
                              value, item->mteTriggerExistenceObjectsOwner,
                              item->mteTriggerExistenceObjects,
                              "existence: changed");
                run_mte_events(item, next_oid, next_oid_len,
                               item->mteTriggerExistenceEventOwner,
                               item->mteTriggerExistenceEvent);
            }
        }

        /*
         * Deal with boolean tests.  
         */
        if ((item->mteTriggerTest[0] & MTETRIGGERTEST_BOOLEAN) &&
            ((item->mteTriggerSampleType ==
              MTETRIGGERSAMPLETYPE_ABSOLUTEVALUE && value)
             || (item->mteTriggerSampleType ==
                 MTETRIGGERSAMPLETYPE_DELTAVALUE && value && old_value))) {
            if (item->mteTriggerSampleType ==
                MTETRIGGERSAMPLETYPE_DELTAVALUE) {
                /*
                 * XXX: Must check the discontinuity OID here.  
                 */
                disco = mte_discontinuity_occurred(item);
                if (disco == -1) {
                    /*
                     * An error notification has already been sent; just bail
                     * out now.  
                     */
                    /*
                     * XXX: should save values here?  
                     */
                    return;
                } else if (disco == 1) {
                    /*
                     * A discontinuity has occurred; the right thing to do here
                     * depends on the exact type.  FOR NOW, assume long.  
                     */
                    x = *((long *) value) + (INT_MAX -
                                             *((long *) old_value));
                } else {
                    x = *((long *) value) - *((long *) old_value);
                }
            } else {
                x = *((long *) value);
            }

            switch (item->mteTriggerBooleanComparison) {
            case MTETRIGGERBOOLEANCOMPARISON_UNEQUAL:
                boolresult = (x != item->mteTriggerBooleanValue);
                break;

            case MTETRIGGERBOOLEANCOMPARISON_EQUAL:
                boolresult = (x == item->mteTriggerBooleanValue);
                break;

            case MTETRIGGERBOOLEANCOMPARISON_LESS:
                boolresult = (x < item->mteTriggerBooleanValue);
                break;

            case MTETRIGGERBOOLEANCOMPARISON_LESSOREQUAL:
                boolresult = (x <= item->mteTriggerBooleanValue);
                break;

            case MTETRIGGERBOOLEANCOMPARISON_GREATER:
                boolresult = (x > item->mteTriggerBooleanValue);
                break;

            case MTETRIGGERBOOLEANCOMPARISON_GREATEROREQUAL:
                boolresult = (x >= item->mteTriggerBooleanValue);
                break;

            default:
                snmp_log(LOG_WARNING,
                         "illegal value in mteTriggerBooleanComparison object: %ld",
                         item->mteTriggerBooleanComparison);
                boolresult = item->lastboolresult;      /* to fail next test */
            }

            if (boolresult &&
                ((item->mteTriggerBooleanStartup ==
                  MTETRIGGERBOOLEANSTARTUP_TRUE
                  && lastbool == (char)-1) || lastbool != boolresult)) {
                send_mte_trap(item, mteTriggerFired,
                              sizeof(mteTriggerFired) / sizeof(oid),
                              next_oid, next_oid_len,
                              &x, item->mteTriggerBooleanObjectsOwner,
                              item->mteTriggerBooleanObjects,
                              "boolean: true");
                run_mte_events(item, next_oid, next_oid_len,
                               item->mteTriggerBooleanEventOwner,
                               item->mteTriggerBooleanEvent);
            }

            DEBUGMSGTL(("mteTriggerTable",
                        "value: %d %ld %lu x: %d %ld %lu\n", *value,
                        *value, *value, x, x, x));

            DEBUGMSGTL(("mteTriggerTable",
                        "boolean result: x=%d %s configured=%d = %d\n",
                        x,
                        se_find_label_in_slist("mteBooleanOperators",
                                               item->
                                               mteTriggerBooleanComparison),
                        item->mteTriggerBooleanValue, boolresult));
        }

        /*
         * Deal with threshold tests.  XXX: doesn't handle "delta-type"
         * sampling.  
         */
        if ((item->mteTriggerTest[0] & MTETRIGGERTEST_THRESHOLD) &&
            ((item->mteTriggerSampleType ==
              MTETRIGGERSAMPLETYPE_ABSOLUTEVALUE && value)
             || (item->mteTriggerSampleType ==
                 MTETRIGGERSAMPLETYPE_DELTAVALUE && value && old_value))) {
            /*
             * XXX: correct intepretation of mteTriggerThresholdStartup? 
             */
            /*
             * only fires when passed and just set to active?  What
             * about a newly discovered node that is past a
             * threshold once we've been active for a turn at least? 
             */
            /*
             * XXX: Check notions of > vs >= 
             */
            if (((item->started == MTE_STARTED && laststate &&
                  lastthresh == MTE_THRESHOLD_LOW) ||
                 (item->started != MTE_STARTED &&
                  (item->mteTriggerThresholdStartup ==
                   MTETRIGGERTHRESHOLDSTARTUP_RISING
                   || item->mteTriggerThresholdStartup ==
                   MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING)))
                && (*value >= item->mteTriggerThresholdRising)) {
                send_mte_trap(item, mteTriggerRising,
                              sizeof(mteTriggerRising) / sizeof(oid),
                              next_oid, next_oid_len, value,
                              item->mteTriggerThresholdObjectsOwner,
                              item->mteTriggerThresholdObjects,
                              "threshold: rising");
                run_mte_events(item, next_oid, next_oid_len,
                               item->mteTriggerThresholdRisingEventOwner,
                               item->mteTriggerThresholdRisingEvent);
            }
            if (((item->started == MTE_STARTED && laststate &&
                  lastthresh == MTE_THRESHOLD_HIGH) ||
                 (item->started != MTE_STARTED &&
                  (item->mteTriggerThresholdStartup ==
                   MTETRIGGERTHRESHOLDSTARTUP_FALLING
                   || item->mteTriggerThresholdStartup ==
                   MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING)))
                && (*value <= item->mteTriggerThresholdFalling)) {
                send_mte_trap(item, mteTriggerFalling,
                              sizeof(mteTriggerFalling) / sizeof(oid),
                              next_oid, next_oid_len, value,
                              item->mteTriggerThresholdObjectsOwner,
                              item->mteTriggerThresholdObjects,
                              "threshold: falling");
                run_mte_events(item, next_oid, next_oid_len,
                               item->mteTriggerThresholdFallingEventOwner,
                               item->mteTriggerThresholdFallingEvent);
            }

        }

        if (value) {
            struct last_state *new_last_state =
                SNMP_MALLOC_STRUCT(last_state);
            new_last_state->value = value;
            new_last_state->lastbool = boolresult;
            header_complex_add_data_by_oid(&item->hc_storage, next_oid,
                                           next_oid_len, new_last_state);

            /*
             * set our notion of the current known threshold state 
             */
            if (lastthresh == MTE_THRESHOLD_LOW &&
                *value >= item->mteTriggerThresholdRising &&
                *value > item->mteTriggerThresholdFalling)
                new_last_state->lastthreshold = MTE_THRESHOLD_HIGH;
            else if (lastthresh == MTE_THRESHOLD_HIGH &&
                     *value < item->mteTriggerThresholdRising &&
                     *value <= item->mteTriggerThresholdFalling)
                new_last_state->lastthreshold = MTE_THRESHOLD_LOW;
            else if (lastthresh == MTE_THRESHOLD_BEGIN) {
                if (*value >= item->mteTriggerThresholdRising)
                    new_last_state->lastthreshold = MTE_THRESHOLD_HIGH;
                else if (*value <= item->mteTriggerThresholdFalling)
                    new_last_state->lastthreshold = MTE_THRESHOLD_LOW;
                /*
                 * XXX: else???  in between?  undefined? 
                 */
            } else {
                new_last_state->lastthreshold = lastthresh;
            }
        }

        /*
         * extract from old hc storage 
         */
        if (laststate) {
            header_complex_extract_entry(&item->hc_storage_old,
                                         header_complex_find_entry(item->
                                                                   hc_storage_old,
                                                                   (void *)
                                                                   laststate));
            last_state_clean(laststate);
        }

    } while (item->mteTriggerValueIDWildcard == TV_TRUE);

    if(response)
        snmp_free_pdu(response);

    /*
     * loop through old values for DNE cases 
     */
    if (item->mteTriggerExistenceTest[0] & MTETRIGGEREXISTENCETEST_ABSENT) {

        struct header_complex_index *iter;

        /*
         * XXX: broken 
         */
        if ((item->mteTriggerExistenceStartup[0] &
             MTETRIGGEREXISTENCESTARTUP_ABSENT)) {
            /*
             * XXX: send trap that nothing was found? 
             */
            /*
             * only if !wild? (see mib)
             */
        }
        for (iter = item->hc_storage_old; iter; iter = iter->next) {
            laststate = (struct last_state *) iter->data;
            send_mte_trap(item, mteTriggerFired,
                          sizeof(mteTriggerFired) / sizeof(oid),
                          iter->name, iter->namelen, laststate->value,
                          item->mteTriggerExistenceObjectsOwner,
                          item->mteTriggerExistenceObjects,
                          "existence: absent");
        }
        header_complex_free_all(item->hc_storage_old, last_state_clean);
        item->hc_storage_old = NULL;
    }

    item->started = MTE_STARTED;
} /* mte_run_trigger */



/*
 * handling routines 
 */
void
mte_enable_trigger(struct mteTriggerTable_data *item)
{
    if (!item)
        return;

    if (item->alarmreg)
        snmp_alarm_unregister(item->alarmreg);

    if (item->mteTriggerFrequency > 0) {
        DEBUGMSGTL(("mteTriggertable", "Enabling trigger for %s/%s @ %u\n",
                    item->mteOwner, item->mteTriggerName,
                    item->mteTriggerFrequency));
        item->alarmreg =
            snmp_alarm_register(item->mteTriggerFrequency, SA_REPEAT,
                                mte_run_trigger, item);
    }
}

void
mte_disable_trigger(struct mteTriggerTable_data *item)
{
    if (!item)
        return;

    if (item->alarmreg) {
        DEBUGMSGTL(("mteTriggertable", "Disabling trigger for %s/%s\n",
                    item->mteOwner, item->mteTriggerName));
        snmp_alarm_unregister(item->alarmreg);
        item->alarmreg = 0;
    }
    item->started = MTE_NOTSTARTED;
}
