/*
 * TargetParamTable MIB
 * 
 * This file was generated by mib2c and is intended for use as a mib module
 * for the ucd-snmp snmpd agent. Edited by Michael Baer 
 * 
 * Portions of this file are copyrighted by:
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
 * Use is subject to license terms specified in the COPYING file
 * distributed with the Net-SNMP package.
 */

#include <net-snmp/net-snmp-config.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <stdlib.h>
#include <ctype.h>

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

#include "snmpTargetParamsEntry.h"
#include "snmpTargetParamsEntry_data.h"

#define snmpTargetParamsOIDLen 11       /*This is base+column, 
                                         * i.e. everything but index */

oid             snmpTargetParamsOID[snmpTargetParamsOIDLen] =
    { 1, 3, 6, 1, 6, 3, 12, 1, 3, 1, 0 };


/*
 * Utility routines 
 */


/*
 * snmpTargetParams_rowStatusCheck is boolean funciton that  checks 
 * the status of a row's values in order to determine whether
 * the row should be notReady or notInService  
 */
int
snmpTargetParams_rowStatusCheck(struct targetParamTable_struct *entry)
{
    if ((entry->mpModel < 0) || (entry->secModel < 0) ||
        (entry->secLevel < 0) || (entry->secNameData == NULL))
        return 0;
    else
        return 1;
}                               /* snmtpTargetParamTable_rowStatusCheck */


/*
 * initialization routines 
 */


/*
 * this variable defines function callbacks and type return information 
 * for the snmpTargetAddrEntry mib 
 */

struct variable2 snmpTargetParamsEntry_variables[] = {
    {SNMPTARGETPARAMSMPMODEL, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_snmpTargetParamsEntry, 1, {SNMPTARGETPARAMSMPMODELCOLUMN}},
    {SNMPTARGETPARAMSSECURITYMODEL, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_snmpTargetParamsEntry, 1, {SNMPTARGETPARAMSSECURITYMODELCOLUMN}},
    {SNMPTARGETPARAMSSECURITYNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
     var_snmpTargetParamsEntry, 1, {SNMPTARGETPARAMSSECURITYNAMECOLUMN}},
    {SNMPTARGETPARAMSSECURITYLEVEL, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_snmpTargetParamsEntry, 1, {SNMPTARGETPARAMSSECURITYLEVELCOLUMN}},
    {SNMPTARGETPARAMSSTORAGETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_snmpTargetParamsEntry, 1, {SNMPTARGETPARAMSSTORAGETYPECOLUMN}},
    {SNMPTARGETPARAMSROWSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
     var_snmpTargetParamsEntry, 1, {SNMPTARGETPARAMSROWSTATUSCOLUMN}}
};

/*
 * now load this mib into the agents mib table 
 */
oid             snmpTargetParamsEntry_variables_oid[] =
    { 1, 3, 6, 1, 6, 3, 12, 1, 3, 1 };


void
init_snmpTargetParamsEntry(void)
{
    init_snmpTargetParamsEntry_data();

    REGISTER_MIB("target/snmpTargetParamsEntry",
                 snmpTargetParamsEntry_variables, variable2,
                 snmpTargetParamsEntry_variables_oid);

    snmpd_register_config_handler("targetParams",
                                  snmpd_parse_config_targetParams,
                                  NULL, NULL);

}                               /*  init_snmpTargetParmsEntry  */

void
shutdown_snmpTargetParamsEntry(void)
{
    shutdown_snmpTargetParamsEntry_data();
}


int
snmpTargetParams_addParamName(struct targetParamTable_struct *entry,
                              char *cptr)
{
    size_t          len;
    if (cptr == NULL) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: no param name in config string\n"));
        return (0);
    } else {
        len = strlen(cptr);
        /*
         * spec check for string 1-32 
         */
        if (len < 1 || len > 32) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "ERROR snmpTargetParamsEntry: param name out of range in config string\n"));
            return (0);
        }
        entry->paramNameData = strdup(cptr);
        entry->paramNameLen = strlen(cptr);
    }
    return (1);
}


int
snmpTargetParams_addMPModel(struct targetParamTable_struct *entry,
                            char *cptr)
{
    if (cptr == NULL) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: no mp model in config string\n"));
        return (0);
    } else if (!(isdigit((unsigned char)(*cptr)))) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargeParamsEntry: mp model is not digit in config string\n"));
        return (0);
    }
    /*
     * spec check MP Model >= 0 
     */
    else if ((entry->mpModel = (int) strtol(cptr, (char **) NULL, 0)) < 0) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargeParamsEntry: mp model out of range in config string\n"));
        return (0);
    }
    return (1);
}                               /* snmpTargetParams_addMPModel  */


int
snmpTargetParams_addSecModel(struct targetParamTable_struct *entry,
                             char *cptr)
{
    if (cptr == NULL) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: no sec model in config string\n"));
        return (0);
    } else if (!(isdigit((unsigned char)(*cptr)))) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargeParamsEntry: security model is not digit in config string\n"));
        return (0);
    }
    /*
     * spec check Sec. Model > 0 
     */
    else if ((entry->secModel =
              (int) strtol(cptr, (char **) NULL, 0)) <= 0) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: security model out of range in config string\n"));
        return (0);
    }
    return (1);
}                               /*  snmpTargetParams_addSecModel  */


int
snmpTargetParams_addSecName(struct targetParamTable_struct *entry,
                            char *cptr)
{
    if (cptr == NULL) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: no security name in config string\n"));
        return (0);
    } else {
        entry->secNameData = strdup(cptr);
        entry->secNameLen = strlen(cptr);
    }
    return (1);
}                               /* snmpTargetParams_addSecName  */


int
snmpTargetParams_addSecLevel(struct targetParamTable_struct *entry,
                             char *cptr)
{
    if (cptr == NULL) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: no security level in config string\n"));
        return (0);
    } else if (!(isdigit((unsigned char)(*cptr)))) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargeParamsEntry: security level is not digit in config string\n"));
        return (0);
    }
    /*
     * no spec range check, but noAuthNoPriv is 1 so... 
     */
    else if ((entry->secLevel =
              (int) strtol(cptr, (char **) NULL, 0)) <= 0) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargeParamsEntry: security level is not greater than 0 in config string\n"));
        return (0);
    }
    return (1);
}                               /*  snmpTargetParams_addSecLevel  */


int
snmpTargetParams_addStorageType(struct targetParamTable_struct *entry,
                                char *cptr)
{
    if (cptr == NULL) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: no storage type in config string\n"));
        return (0);
    } else if (!(isdigit((unsigned char)(*cptr)))) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargeParamsEntry: storage type is not digit in config string\n"));
        return (0);
    }
    /*
     * check that storage type is a possible value 
     */
    else if (((entry->storageType = (int) strtol(cptr, (char **) NULL, 0))
              != SNMP_STORAGE_OTHER) &&
             (entry->storageType != SNMP_STORAGE_VOLATILE) &&
             (entry->storageType != SNMP_STORAGE_NONVOLATILE) &&
             (entry->storageType != SNMP_STORAGE_PERMANENT) &&
             (entry->storageType != SNMP_STORAGE_READONLY)) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargeParamsEntry: storage type is not a valid value of"));
        DEBUGMSG(("snmpTargetParamsEntry",
                  " other(%d), volatile(%d), nonvolatile(%d), permanent(%d), or ",
                  SNMP_STORAGE_OTHER, SNMP_STORAGE_VOLATILE,
                  SNMP_STORAGE_NONVOLATILE, SNMP_STORAGE_PERMANENT));
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "readonly(%d) in config string.\n",
                    SNMP_STORAGE_READONLY));

        return (0);
    }
    return (1);
}                               /* snmpTargetParams_addStorageType  */


int
snmpTargetParams_addRowStatus(struct targetParamTable_struct *entry,
                              char *cptr)
{
    if (cptr == NULL) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: no row status in config string\n"));
        return (0);
    } else if (!(isdigit((unsigned char)(*cptr)))) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargeParamsEntry: row status is not digit in config string\n"));
        return (0);
    }
    /*
     * check that row status is a valid value 
     */
    else if (((entry->rowStatus = (int) strtol(cptr, (char **) NULL, 0))
              != SNMP_ROW_ACTIVE) &&
             (entry->rowStatus != SNMP_ROW_NOTINSERVICE) &&
             (entry->rowStatus != SNMP_ROW_NOTREADY)) {
        DEBUGMSGTL(("snmpTargetParamsEntry",
                    "ERROR snmpTargetParamsEntry: Row Status is not a valid value of "));
        DEBUGMSG(("snmpTargetParamsEntry",
                  "active(%d), notinservice(%d), or notready(%d) in config string.\n",
                  SNMP_ROW_ACTIVE, SNMP_ROW_NOTINSERVICE,
                  SNMP_ROW_NOTREADY));

        return (0);
    }
    return (1);
}                               /* snmpTargetParams_addRowStatus  */

/*
 * timestamp the current entry's modification time 
 */
void
update_timestamp(struct targetParamTable_struct *temp_struct)
{
    temp_struct->updateTime = time(NULL);
}

void
snmpd_parse_config_targetParams(const char *token, char *char_ptr)
{
    char           *cptr = char_ptr, buff[1024];
    struct targetParamTable_struct *newEntry;

    newEntry = snmpTargetParamTable_create();

    cptr = copy_nword(cptr, buff, sizeof(buff));
    if (snmpTargetParams_addParamName(newEntry, buff) == 0) {
        snmpTargetParamTable_dispose(newEntry);
        return;
    }
    cptr = copy_nword(cptr, buff, sizeof(buff));
    if (snmpTargetParams_addMPModel(newEntry, buff) == 0) {
        snmpTargetParamTable_dispose(newEntry);
        return;
    }
    cptr = copy_nword(cptr, buff, sizeof(buff));
    if (snmpTargetParams_addSecModel(newEntry, buff) == 0) {
        snmpTargetParamTable_dispose(newEntry);
        return;
    }
    cptr = copy_nword(cptr, buff, sizeof(buff));
    if (snmpTargetParams_addSecName(newEntry, buff) == 0) {
        snmpTargetParamTable_dispose(newEntry);
        return;
    }
    cptr = copy_nword(cptr, buff, sizeof(buff));
    if (snmpTargetParams_addSecLevel(newEntry, buff) == 0) {
        snmpTargetParamTable_dispose(newEntry);
        return;
    }
    cptr = copy_nword(cptr, buff, sizeof(buff));
    if (snmpTargetParams_addStorageType(newEntry, buff) == 0) {
        snmpTargetParamTable_dispose(newEntry);
        return;
    }
    cptr = copy_nword(cptr, buff, sizeof(buff));
    if (snmpTargetParams_addRowStatus(newEntry, buff) == 0) {
        snmpTargetParamTable_dispose(newEntry);
        return;
    }
    DEBUGMSGTL(("snmpTargetParamsEntry",
                "snmp_parse_config_targetParams, read: %s %d %d %s %d %d %d\n",
                newEntry->paramNameData, newEntry->mpModel, newEntry->secModel,
                newEntry->secNameData, newEntry->secLevel,
                newEntry->storageType, newEntry->rowStatus));

    update_timestamp(newEntry);
    snmpTargetParamTable_add(newEntry);
}                               /* snmpd_parse_config_target */


/*
 * shutdown routines 
 */


/*
 * MIB table access routines 
 */


u_char         *
var_snmpTargetParamsEntry(struct variable * vp,
                          oid * name,
                          size_t * length,
                          int exact,
                          size_t * var_len, WriteMethod ** write_method)
{
    /*
     * variables we may use later 
     */
    static long     long_ret;
    static unsigned char string[1500];
    struct targetParamTable_struct *temp_struct;

    switch (vp->magic) {
#ifndef NETSNMP_NO_WRITE_SUPPORT
    case SNMPTARGETPARAMSMPMODEL:
        *write_method = write_snmpTargetParamsMPModel;
        break;
    case SNMPTARGETPARAMSSECURITYMODEL:
        *write_method = write_snmpTargetParamsSecModel;
        break;
    case SNMPTARGETPARAMSSECURITYNAME:
        *write_method = write_snmpTargetParamsSecName;
        break;
    case SNMPTARGETPARAMSSECURITYLEVEL:
        *write_method = write_snmpTargetParamsSecLevel;
        break;
    case SNMPTARGETPARAMSSTORAGETYPE:
        *write_method = write_snmpTargetParamsStorageType;
        break;
    case SNMPTARGETPARAMSROWSTATUS:
        *write_method = write_snmpTargetParamsRowStatus;
        break;
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
    default:
        *write_method = NULL;
    }

    /* assume an integer and change later if not */
    *var_len = sizeof(long_ret);

    /*
     * look for OID in current table 
     */
    if ((temp_struct = search_snmpTargetParamsTable(vp->name, vp->namelen,
                                                    name, length,
                                                    exact)) == NULL) {
        return NULL;
    }

    /*
     * We found what we were looking for, either the next OID or the exact OID 
     */
    /*
     * this is where we do the value assignments for the mib results. 
     */
    switch (vp->magic) {

    case SNMPTARGETPARAMSMPMODEL:
        /*
         * if unset value, (i.e. new row) 
         */
        if (temp_struct->mpModel == -1)
            return NULL;
        long_ret = temp_struct->mpModel;
        return (unsigned char *) &long_ret;

    case SNMPTARGETPARAMSSECURITYMODEL:
        /*
         * if unset value, (i.e. new row) 
         */
        if (temp_struct->secModel == -1)
            return NULL;
        long_ret = temp_struct->secModel;
        return (unsigned char *) &long_ret;

    case SNMPTARGETPARAMSSECURITYNAME:
        /*
         * if unset value, (i.e. new row) 
         */
        if (temp_struct->secNameData == NULL)
            return NULL;
        /*
         * including null character. 
         */
        strlcpy((char *)string, temp_struct->secNameData, sizeof(string));
        *var_len = strlen(temp_struct->secNameData);
        return (unsigned char *) string;

    case SNMPTARGETPARAMSSECURITYLEVEL:
        /*
         * if unset value, (i.e. new row) 
         */
        if (temp_struct->secLevel == -1)
            return NULL;
        long_ret = temp_struct->secLevel;
        return (unsigned char *) &long_ret;

    case SNMPTARGETPARAMSSTORAGETYPE:
        long_ret = temp_struct->storageType;
        return (unsigned char *) &long_ret;

    case SNMPTARGETPARAMSROWSTATUS:
        long_ret = temp_struct->rowStatus;
        return (unsigned char *) &long_ret;

    default:
        DEBUGMSGTL(("snmpd",
                    "unknown sub-id %d in var_snmpTargetParamsEntry\n",
                    vp->magic));
    }

    return NULL;
}                               /* var_snmpTargetParamsEntry */


#ifndef NETSNMP_NO_WRITE_SUPPORT
/*
 * Assign a value to the mpModel variable.  
 */
int
write_snmpTargetParamsMPModel(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)
{
    long            long_ret = *((long *) var_val);
    static long     old_mp;
    struct targetParamTable_struct *params = NULL;

    if (action == RESERVE1) {
        if (var_val_type != ASN_INTEGER) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsMPModel: not ASN_INTEGER\n"));
            return SNMP_ERR_WRONGTYPE;
        }
        if (var_val_len != sizeof(long)) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsMPModel: bad length\n"));
            return SNMP_ERR_WRONGLENGTH;
        }
        if (long_ret < 0) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsMPModel: MP Model out of range\n"));
            return SNMP_ERR_INCONSISTENTVALUE;
        }
    } else if (action == RESERVE2) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSMPMODELCOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (params == NULL) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsMPModel: BAD OID\n"));
            return SNMP_ERR_INCONSISTENTNAME;
        } else {
            /*
             * Row exists, check if it is changeable.  
             */
            if (params->storageType == SNMP_STORAGE_READONLY) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamMPModel: row is read only\n"));
                return SNMP_ERR_NOTWRITABLE;
            }
            /*
             * Check if row is active.  
             */
            if (params->rowStatus == SNMP_ROW_ACTIVE) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamsMPModel: this change not allowed in active row.\n"));
                return SNMP_ERR_INCONSISTENTVALUE;
            }

            old_mp = params->mpModel;
            params->mpModel = long_ret;

            if (params->rowStatus == SNMP_ROW_NOTREADY &&
                snmpTargetParams_rowStatusCheck(params)) {
                params->rowStatus = SNMP_ROW_NOTINSERVICE;
            }
        }
    } else if (action == COMMIT) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSMPMODELCOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            update_timestamp(params);
        }
    } else if (action == FREE || action == UNDO) {
        /*
         * Try to undo the SET here (abnormal usage of FREE clause)  
         */
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSMPMODELCOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            if (params->storageType != SNMP_STORAGE_READONLY
                && params->rowStatus != SNMP_ROW_ACTIVE) {
                params->mpModel = old_mp;
                if (params->rowStatus == SNMP_ROW_NOTINSERVICE &&
                    !snmpTargetParams_rowStatusCheck(params)) {
                    params->rowStatus = SNMP_ROW_NOTREADY;
                }
            }
        }
    }

    return SNMP_ERR_NOERROR;
}                               /* write_snmpTargetParamsMPModel */

/*
 * Assign a value to the secModel variable.  
 */
int
write_snmpTargetParamsSecModel(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)
{
    long            long_ret = *((long *) var_val);
    static long     old_sec;
    struct targetParamTable_struct *params = NULL;

    if (action == RESERVE1) {
        if (var_val_type != ASN_INTEGER) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecModel: not ASN_INTEGER\n"));
            return SNMP_ERR_WRONGTYPE;
        }
        if (var_val_len != sizeof(long)) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecModel: bad length\n"));
            return SNMP_ERR_WRONGLENGTH;
        }
        if (long_ret <= 0) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecModel: secModel out of range\n"));
            return SNMP_ERR_WRONGVALUE;
        }
        if (find_sec_mod(long_ret) == NULL && long_ret >= 3) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecModel: secModel %ld unsupported\n",
                        long_ret));
            return SNMP_ERR_INCONSISTENTVALUE;
        }

    } else if (action == RESERVE2) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYMODELCOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (params == NULL) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecModel: BAD OID\n"));
            return SNMP_ERR_INCONSISTENTNAME;
        } else {
            /*
             * Row exists, check if it is changeable.  
             */
            if (params->storageType == SNMP_STORAGE_READONLY) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamSecModel: row is read only\n"));
                return SNMP_ERR_NOTWRITABLE;
            }
            /*
             * Check if row is active.  
             */
            if (params->rowStatus == SNMP_ROW_ACTIVE) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamsSecModel: this change not allowed in active row.\n"));
                return SNMP_ERR_INCONSISTENTVALUE;
            }

            old_sec = params->secModel;
            params->secModel = long_ret;

            if (params->rowStatus == SNMP_ROW_NOTREADY &&
                snmpTargetParams_rowStatusCheck(params)) {
                params->rowStatus = SNMP_ROW_NOTINSERVICE;
            }
        }
    } else if (action == COMMIT) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYMODELCOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            update_timestamp(params);
        }
    } else if (action == FREE || action == UNDO) {
        /*
         * Try to undo the SET here (abnormal usage of FREE clause)  
         */
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYMODELCOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            if (params->storageType != SNMP_STORAGE_READONLY
                && params->rowStatus != SNMP_ROW_ACTIVE) {
                params->secModel = old_sec;
                if (params->rowStatus == SNMP_ROW_NOTINSERVICE &&
                    !snmpTargetParams_rowStatusCheck(params)) {
                    params->rowStatus = SNMP_ROW_NOTREADY;
                }
            }
        }
    }

    return SNMP_ERR_NOERROR;
}                               /* write_snmpTargetParamsSecModel */

/*
 * Assign a value to the SecLevel variable.  
 */
int
write_snmpTargetParamsSecLevel(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)
{
    long            long_ret = *((long *) var_val);
    static long     old_level;
    struct targetParamTable_struct *params = NULL;

    if (action == RESERVE1) {
        if (var_val_type != ASN_INTEGER) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecLevel: not ASN_INTEGER\n"));
            return SNMP_ERR_WRONGTYPE;
        }
        if (var_val_len != sizeof(long)) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecLevel: bad length\n"));
            return SNMP_ERR_WRONGLENGTH;
        }
        if (long_ret <= 0 || long_ret > 3) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecLevel: security level is not noAuthNoPriv(1), authNopriv(2) or authPriv(3)\n"));
            return SNMP_ERR_WRONGVALUE;
        }
    } else if (action == RESERVE2) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYLEVELCOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (params == NULL) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecLevel: BAD OID\n"));
            return SNMP_ERR_INCONSISTENTNAME;
        } else {
            /*
             * Row exists, check if it is changeable.  
             */
            if (params->storageType == SNMP_STORAGE_READONLY) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamSecLevel: row is read only\n"));
                return SNMP_ERR_NOTWRITABLE;
            }
            /*
             * Check if row is active.  
             */
            if (params->rowStatus == SNMP_ROW_ACTIVE) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamsSecLevel: this change not allowed in active row.\n"));
                return SNMP_ERR_INCONSISTENTVALUE;
            }

            old_level = params->secLevel;
            params->secLevel = long_ret;

            if (params->rowStatus == SNMP_ROW_NOTREADY &&
                snmpTargetParams_rowStatusCheck(params)) {
                params->rowStatus = SNMP_ROW_NOTINSERVICE;
            }
        }
    } else if (action == COMMIT) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYLEVELCOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            update_timestamp(params);
        }
    } else if (action == FREE || action == UNDO) {
        /*
         * Try to undo the SET here (abnormal usage of FREE clause)  
         */
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYLEVELCOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            if (params->storageType != SNMP_STORAGE_READONLY
                && params->rowStatus != SNMP_ROW_ACTIVE) {
                params->secLevel = old_level;
                if (params->rowStatus == SNMP_ROW_NOTINSERVICE &&
                    !snmpTargetParams_rowStatusCheck(params)) {
                    params->rowStatus = SNMP_ROW_NOTREADY;
                }
            }
        }
    }

    return SNMP_ERR_NOERROR;
}                               /* write_snmpTargetParamsSecLevel */

/*
 * Assign a value to the storageType variable.  
 */
int
write_snmpTargetParamsStorageType(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)
{
    long            long_ret = *((long *) var_val);
    static long     old_st;
    struct targetParamTable_struct *params = NULL;

    if (action == RESERVE1) {
        if (var_val_type != ASN_INTEGER) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsStorageType: not ASN_INTEGER\n"));
            return SNMP_ERR_WRONGTYPE;
        }
        if (var_val_len != sizeof(long)) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsStorageType: bad length\n"));
            return SNMP_ERR_WRONGLENGTH;
        }
        if (long_ret != SNMP_STORAGE_OTHER &&
            long_ret != SNMP_STORAGE_VOLATILE &&
            long_ret != SNMP_STORAGE_NONVOLATILE) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsStorageType: attempted storage type not a valid"));
            DEBUGMSG(("snmpTargetParamsEntry",
                      " value of other(%d), volatile(%d), or nonvolatile(%d)\n",
                      SNMP_STORAGE_OTHER, SNMP_STORAGE_VOLATILE,
                      SNMP_STORAGE_NONVOLATILE));
            return SNMP_ERR_WRONGVALUE;
        }
    } else if (action == RESERVE2) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSTORAGETYPECOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (params == NULL) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsStorageType: BAD OID\n"));
            return SNMP_ERR_INCONSISTENTNAME;
        } else {
            /*
             * Row exists, check if it is changeable.  
             */
            if (params->storageType == SNMP_STORAGE_READONLY ||
                params->storageType == SNMP_STORAGE_PERMANENT) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamsStorageType: row has unchangeable storage status: %d\n",
                            params->storageType));
                return SNMP_ERR_INCONSISTENTVALUE;
            }

            old_st = params->storageType;
            params->storageType = long_ret;
        }
    } else if (action == FREE || action == UNDO) {
        /*
         * Try to undo the SET here (abnormal usage of FREE clause)  
         */
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSTORAGETYPECOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            if (params->storageType != SNMP_STORAGE_READONLY
                && params->storageType != SNMP_STORAGE_PERMANENT) {
                params->storageType = old_st;
            }
        }
    }

    return SNMP_ERR_NOERROR;
}                               /* write_snmpTargetParamsStorageType */

/*
 * Assign a value to the secName variable.  
 */
int
write_snmpTargetParamsSecName(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    *old_name = NULL;
    static size_t   old_name_len;
    struct targetParamTable_struct *params = NULL;

    if (action == RESERVE1) {
        if (var_val_type != ASN_OCTET_STR) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecName: not ASN_OCTET_STR\n"));
            return SNMP_ERR_WRONGTYPE;
        }
        if (var_val_len > 255) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecName: bad length\n"));
            return SNMP_ERR_WRONGLENGTH;
        }
    } else if (action == RESERVE2) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYNAMECOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (params == NULL) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsSecName: BAD OID\n"));
            return SNMP_ERR_INCONSISTENTNAME;
        } else {
            /*
             * Row exists, check if it is changeable.  
             */
            if (params->storageType == SNMP_STORAGE_READONLY) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamSecName: row is read only\n"));
                return SNMP_ERR_NOTWRITABLE;
            }
            /*
             * Check if row is active.  
             */
            if (params->rowStatus == SNMP_ROW_ACTIVE) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "write to snmpTargetParamsSecName: this change not allowed in active row.\n"));
                return SNMP_ERR_INCONSISTENTVALUE;
            }
            if (old_name != NULL) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "multiple rows/sets no supported.\n"));
                return SNMP_ERR_GENERR;
            }

            old_name = params->secNameData;
            old_name_len = params->secNameLen;
            params->secNameData = netsnmp_memdup_nt(var_val, var_val_len,
                                                    &params->secNameLen);
            if (params->secNameData == NULL) {
                return SNMP_ERR_RESOURCEUNAVAILABLE;
            }

            if (params->rowStatus == SNMP_ROW_NOTREADY &&
                snmpTargetParams_rowStatusCheck(params)) {
                params->rowStatus = SNMP_ROW_NOTINSERVICE;
            }
        }
    } else if (action == COMMIT) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYNAMECOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            update_timestamp(params);
            SNMP_FREE(old_name);
            old_name = NULL;
        }
    } else if (action == FREE || action == UNDO) {
        /*
         * Try to undo the SET here (abnormal usage of FREE clause)  
         */
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSSECURITYNAMECOLUMN;
        if ((params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                                   snmpTargetParamsOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
            if (params->storageType != SNMP_STORAGE_READONLY
                && params->rowStatus != SNMP_ROW_ACTIVE) {
                SNMP_FREE(params->secNameData);
                params->secNameData = old_name;
                params->secNameLen = old_name_len;
                if (params->rowStatus == SNMP_ROW_NOTINSERVICE &&
                    !snmpTargetParams_rowStatusCheck(params)) {
                    params->rowStatus = SNMP_ROW_NOTREADY;
                }
            }
        }
        old_name = NULL;
    }

    return SNMP_ERR_NOERROR;
}                               /* write_snmpTargetParamsSecName */

/*
 * snmpTargeParams_createNewRow is called from write_snmpTargetParamsRowStatus
 * when a new row is required. It creates a new row with 
 * the index of the passed in 'name' (i.e. full index OID) and
 * adds it to the linked list. 'name' should be the full OID of the new index. 
 * It passes back 0 if unsuccessfull.
 */
int
snmpTargetParams_createNewRow(oid * name, size_t name_len)
{
    int             pNameLen, i;
    struct targetParamTable_struct *temp_struct;

    /*
     * setup a new snmpTargetParamTable structure and add it to the list 
     */
    pNameLen = name_len - snmpTargetParamsOIDLen;
    if (pNameLen > 0) {
        temp_struct = snmpTargetParamTable_create();
        if (NULL == temp_struct)
            return 0;
        temp_struct->paramNameData = (char *) malloc(pNameLen + 1);

        for (i = 0; i < pNameLen; i++) {
            temp_struct->paramNameData[i] =
                (char) name[i + snmpTargetParamsOIDLen];
        }

        temp_struct->paramNameData[pNameLen] = '\0';
        temp_struct->paramNameLen = pNameLen;
        temp_struct->rowStatus = SNMP_ROW_NOTREADY;

        update_timestamp(temp_struct);
        snmpTargetParamTable_add(temp_struct);

        return 1;
    }

    return 0;
}                               /* snmpTargetParams_createNewRow */

/*
 * Assign a value to the Row Status variable 
 */
int
write_snmpTargetParamsRowStatus(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 long     value;
    struct targetParamTable_struct *params = NULL;

    if (action == RESERVE1) {
        if (var_val_type != ASN_INTEGER) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsRowStatus not ASN_INTEGER\n"));
            return SNMP_ERR_WRONGTYPE;
        }
        if (var_val_len != sizeof(long)) {
            DEBUGMSGTL(("snmpTargetParamsEntry",
                        "write to snmpTargetParamsRowStatus: bad length\n"));
            return SNMP_ERR_WRONGLENGTH;
        }
        value = *((long *) var_val);
        if (value == SNMP_ROW_NOTREADY || value < 1 || value > 6) {
            return SNMP_ERR_WRONGVALUE;
        }

        /*
         * Check index value is reasonable.  
         */

        if (name_len < snmpTargetParamsOIDLen + 1 ||
            name_len > snmpTargetParamsOIDLen + 32) {
            DEBUGMSGTL(("snmpTargetParamsEntry", "bad index length %d\n",
                        (int)(name_len - snmpTargetParamsOIDLen)));
            return SNMP_ERR_NOCREATION;
        }

        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSROWSTATUSCOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (params != NULL) {
            if (value == SNMP_ROW_CREATEANDGO
                || value == SNMP_ROW_CREATEANDWAIT) {
                value = SNMP_ROW_NOTREADY;
                return SNMP_ERR_INCONSISTENTVALUE;
            }
            if (params->storageType == SNMP_STORAGE_READONLY) {
                DEBUGMSGTL(("snmpTargetParamsEntry",
                            "row is read only\n"));
                return SNMP_ERR_NOTWRITABLE;
            }
            if (params->storageType == SNMP_STORAGE_PERMANENT) {
                if (value == SNMP_ROW_DESTROY) {
                    DEBUGMSGTL(("snmpTargetParamsEntry",
                                "unable to destroy permanent row\n"));
                    return SNMP_ERR_INCONSISTENTVALUE;
                }
            }
        } else {
            if (value == SNMP_ROW_ACTIVE || value == SNMP_ROW_NOTINSERVICE) {
                return SNMP_ERR_INCONSISTENTVALUE;
            }
            if (value == SNMP_ROW_CREATEANDGO
                || value == SNMP_ROW_CREATEANDWAIT) {
                if (snmpTargetParams_createNewRow(name, name_len) == 0) {
                    DEBUGMSGTL(("snmpTargetParamsEntry",
                                "couldn't malloc() new row\n"));
                    return SNMP_ERR_RESOURCEUNAVAILABLE;
                }
            }
        }
    } else if (action == ACTION) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSROWSTATUSCOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (params != NULL) {
            if (value == SNMP_ROW_CREATEANDGO) {
                /*
                 * Check whether all the required objects have been set.  
                 */
                if (snmpTargetParams_rowStatusCheck(params)) {
                    params->rowStatus = SNMP_ROW_ACTIVE;
                } else {
                    params->rowStatus = SNMP_ROW_NOTREADY;
                }
            } else if (value == SNMP_ROW_CREATEANDWAIT) {
                /*
                 * Check whether all the required objects have been set.  
                 */
                if (snmpTargetParams_rowStatusCheck(params)) {
                    params->rowStatus = SNMP_ROW_NOTINSERVICE;
                } else {
                    params->rowStatus = SNMP_ROW_NOTREADY;
                }
            } else if (value == SNMP_ROW_ACTIVE) {
                if (params->rowStatus == SNMP_ROW_NOTINSERVICE) {
                    params->rowStatus = SNMP_ROW_ACTIVE;
                } else if (params->rowStatus == SNMP_ROW_NOTREADY) {
                    return SNMP_ERR_INCONSISTENTVALUE;
                }
            } else if (value == SNMP_ROW_NOTINSERVICE) {
                if (params->rowStatus == SNMP_ROW_ACTIVE) {
                    params->rowStatus = SNMP_ROW_NOTINSERVICE;
                } else if (params->rowStatus == SNMP_ROW_NOTREADY) {
                    return SNMP_ERR_INCONSISTENTVALUE;
                }
            }
        }
    } else if (action == COMMIT) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSROWSTATUSCOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (params != NULL) {
            if (value == SNMP_ROW_DESTROY) {
                snmpTargetParamTable_remove(params);
            }
            if (value == SNMP_ROW_ACTIVE || value == SNMP_ROW_NOTINSERVICE) {
                update_timestamp(params);
            }
        }
    } else if (action == UNDO || action == FREE) {
        snmpTargetParamsOID[snmpTargetParamsOIDLen - 1] =
            SNMPTARGETPARAMSROWSTATUSCOLUMN;
        params = search_snmpTargetParamsTable(snmpTargetParamsOID,
                                              snmpTargetParamsOIDLen,
                                              name, &name_len, 1);
        if (value == SNMP_ROW_CREATEANDGO
            || value == SNMP_ROW_CREATEANDWAIT) {
            if (params != NULL) {
                snmpTargetParamTable_remove(params);
            }
        }
    }
    return SNMP_ERR_NOERROR;
}

#endif /* !NETSNMP_NO_WRITE_SUPPORT */
