text: /*
   * snmpTargetAddrEntry 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>
  #if 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 "snmpTargetAddrEntry.h"
  #include "snmpTargetAddrEntry_data.h"
  #include "util_funcs/header_generic.h"
  
  #define snmpTargetAddrOIDLen 11 /*This is base+column, 
                                   * i.e. everything but index */
  
  static oid      snmpTargetAddrOID[snmpTargetAddrOIDLen] =
      { 1, 3, 6, 1, 6, 3, 12, 1, 2, 1, 0 };
  
  static unsigned long snmpTargetSpinLock = 0;
  
  
  /*
   * snmpTargetAddr_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.
   */
  static int
  snmpTargetAddr_rowStatusCheck(const struct targetAddrTable_struct *entry)
  {
      return entry->tDomainLen && entry->tAddress && entry->paramsData;
  }                               /* snmtpTargetAddrTable_rowStatusCheck */
  
  
  /*
   * Init routines 
   */
  
  /*
   * this variable defines function callbacks and type return information 
   * for the snmpTargetAddrEntry mib 
   */
  
  static const struct variable2 snmpTargetAddrEntry_variables[] = {
      {SNMPTARGETADDRTDOMAIN, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
       var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRTDOMAINCOLUMN}},
      {SNMPTARGETADDRTADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
       var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRTADDRESSCOLUMN}},
      {SNMPTARGETADDRTIMEOUT, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
       var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRTIMEOUTCOLUMN}},
      {SNMPTARGETADDRRETRYCOUNT, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
       var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRRETRYCOUNTCOLUMN}},
      {SNMPTARGETADDRTAGLIST, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
       var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRTAGLISTCOLUMN}},
      {SNMPTARGETADDRPARAMS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
       var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRPARAMSCOLUMN}},
      {SNMPTARGETADDRSTORAGETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
       var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRSTORAGETYPECOLUMN}},
      {SNMPTARGETADDRROWSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
       var_snmpTargetAddrEntry, 1, {SNMPTARGETADDRROWSTATUSCOLUMN}},
  
  };
  
  static const struct variable2 snmpTargetSpinLock_var[] = {
      {SNMPTARGETSPINLOCK, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
       var_targetSpinLock, 1, {1}}
  };
  
  static const oid snmpTargetSpinLock_oid[] = { 1, 3, 6, 1, 6, 3, 12, 1 };
  
  /*
   * now load this mib into the agents mib table 
   */
  static const oid snmpTargetAddrEntry_variables_oid[] =
      { 1, 3, 6, 1, 6, 3, 12, 1, 2, 1 };
  
  
  void
  init_snmpTargetAddrEntry(void)
  {
      init_snmpTargetAddrEntry_data();
  
      DEBUGMSGTL(("snmpTargetAddrEntry", "init\n"));
      REGISTER_MIB("target/snmpTargetAddrEntry",
                   snmpTargetAddrEntry_variables, variable2,
                   snmpTargetAddrEntry_variables_oid);
      REGISTER_MIB("target/snmpTargetSpinLock", snmpTargetSpinLock_var,
                   variable2, snmpTargetSpinLock_oid);
  
  }                               /* init_snmpTargetAddrEntry */
  
  void
  shutdown_snmpTargetAddrEntry(void)
  {
      shutdown_snmpTargetAddrEntry_data();
  }
  
  /*
   * Shutdown routines 
   */
  
  
  /*
   * MIB table access routines 
   */
  
  
  u_char         *
  var_snmpTargetAddrEntry(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 char     string[1500];
      static oid      objid[128];
      struct targetAddrTable_struct *temp_struct;
      int             i = 0;
  
      /*
       * Set up write_method first, in case we return NULL before getting to the
       * switch (vp->magic) below.  In some of these cases, we still want to call
       * the appropriate write_method, if only to have it return the appropriate
       * error.  
       */
  
      switch (vp->magic) {
  #ifndef NETSNMP_NO_WRITE_SUPPORT
      case SNMPTARGETADDRTDOMAIN:
          *write_method = write_snmpTargetAddrTDomain;
          break;
      case SNMPTARGETADDRTADDRESS:
          *write_method = write_snmpTargetAddrTAddress;
          break;
      case SNMPTARGETADDRRETRYCOUNT:
          *write_method = write_snmpTargetAddrRetryCount;
          break;
      case SNMPTARGETADDRTIMEOUT:
          *write_method = write_snmpTargetAddrTimeout;
          break;
      case SNMPTARGETADDRTAGLIST:
          *write_method = write_snmpTargetAddrTagList;
          break;
      case SNMPTARGETADDRPARAMS:
          *write_method = write_snmpTargetAddrParams;
          break;
      case SNMPTARGETADDRSTORAGETYPE:
          *write_method = write_snmpTargetAddrStorageType;
          break;
      case SNMPTARGETADDRROWSTATUS:
          *write_method = write_snmpTargetAddrRowStatus;
          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_snmpTargetAddrTable(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 SNMPTARGETADDRTDOMAIN:
          if (temp_struct->tDomainLen <= 0) {
              return NULL;
          } else {
              for (i = 0; i < temp_struct->tDomainLen; i++) {
                  objid[i] = temp_struct->tDomain[i];
              }
              *var_len = temp_struct->tDomainLen * sizeof(oid);
          }
          return (unsigned char *) objid;
  
      case SNMPTARGETADDRTADDRESS:
          if (temp_struct->tAddress == NULL)
              return NULL;
          *var_len = temp_struct->tAddressLen;
          return (unsigned char *) temp_struct->tAddress;
  
      case SNMPTARGETADDRTIMEOUT:
          long_ret = temp_struct->timeout;
          return (unsigned char *) &long_ret;
  
      case SNMPTARGETADDRRETRYCOUNT:
          long_ret = temp_struct->retryCount;
          return (unsigned char *) &long_ret;
  
      case SNMPTARGETADDRTAGLIST:
          if (temp_struct->tagListData == NULL)
              return NULL;
          memcpy(string, temp_struct->tagListData, temp_struct->tagListLen);
          *var_len = temp_struct->tagListLen;
          return (unsigned char *) string;
  
      case SNMPTARGETADDRPARAMS:
          if (temp_struct->paramsData == NULL)
              return NULL;
          memcpy(string, temp_struct->paramsData, temp_struct->paramsLen);
          *var_len = temp_struct->paramsLen;
          return (unsigned char *) string;
  
      case SNMPTARGETADDRSTORAGETYPE:
          long_ret = temp_struct->storageType;
          return (unsigned char *) &long_ret;
  
      case SNMPTARGETADDRROWSTATUS:
          long_ret = temp_struct->rowStatus;
          return (unsigned char *) &long_ret;
  
      default:
          DEBUGMSGTL(("snmpd",
                      "unknown sub-id %d in var_snmpTargetAddrEntry\n",
                      vp->magic));
      }
  
      return NULL;
  }                               /* var_snmpTargetAddrEntry */
  
  
  #ifndef NETSNMP_NO_WRITE_SUPPORT
  int
  write_snmpTargetAddrTDomain(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 targetAddrTable_struct *target = NULL;
      static oid      old_oid[MAX_OID_LEN];
      static size_t   old_oid_len;
  
      if (action == RESERVE1) {
          if (var_val_type != ASN_OBJECT_ID) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTDomain not ASN_OBJECT_ID\n"));
              return SNMP_ERR_WRONGTYPE;
          }
          if ((var_val_len > (MAX_OID_LEN * sizeof(oid))) ||
              (var_val_len % sizeof(oid) != 0)) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTDomain: bad length\n"));
              return SNMP_ERR_WRONGLENGTH;
          }
      } else if (action == RESERVE2) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRTDOMAINCOLUMN;
          if ((target =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name,
                                          &name_len, 1)) == NULL) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTDomain: BAD OID!\n"));
              return SNMP_ERR_INCONSISTENTNAME;
          } else {
              if (target->storageType == SNMP_STORAGE_READONLY) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrTDomain: row is read only\n"));
                  return SNMP_ERR_NOTWRITABLE;
              }
              if (target->rowStatus == SNMP_ROW_ACTIVE) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrTDomain: not allowed in active row.\n"));
                  return SNMP_ERR_INCONSISTENTVALUE;
              }
  
              /*
               * Finally, we're golden, save current value.  
               */
  
              memcpy(old_oid, target->tDomain,
                     target->tDomainLen * sizeof(oid));
              old_oid_len = target->tDomainLen;
  
              memcpy((u_char *) target->tDomain, var_val, var_val_len);
              target->tDomainLen = var_val_len / sizeof(oid);
  
              /*
               * If row is new, check if its status can be updated.  
               */
              if ((target->rowStatus == SNMP_ROW_NOTREADY) &&
                  (snmpTargetAddr_rowStatusCheck(target) != 0)) {
                  target->rowStatus = SNMP_ROW_NOTINSERVICE;
              }
          }
      } else if (action == COMMIT) {
          snmp_store_needed(NULL);
      } else if (action == FREE || action == UNDO) {
          /*
           * Try to undo the SET here (abnormal usage of FREE clause)  
           */
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRTDOMAINCOLUMN;
          if ((target =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name,
                                          &name_len, 1)) != NULL) {
              if (target->storageType != SNMP_STORAGE_READONLY
                  && target->rowStatus != SNMP_ROW_ACTIVE) {
                  memcpy((u_char *) target->tDomain, (u_char *) old_oid,
                         (old_oid_len * sizeof(oid)));
                  target->tDomainLen = old_oid_len;
                  if (target->rowStatus == SNMP_ROW_NOTINSERVICE &&
                      snmpTargetAddr_rowStatusCheck(target) == 0) {
                      target->rowStatus = SNMP_ROW_NOTREADY;
                  }
              }
          }
      }
      return SNMP_ERR_NOERROR;
  }                               /* write_snmpTargetAddrTDomain */
  
  
  int
  write_snmpTargetAddrTAddress(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 targetAddrTable_struct *target = NULL;
      static char    *old_addr = NULL;
      static size_t   old_len = 0;
  
      if (action == RESERVE1) {
          if (var_val_type != ASN_OCTET_STR) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTAddress not ASN_OCTET_STR\n"));
              return SNMP_ERR_WRONGTYPE;
          } else if (var_val_len < 1 || var_val_len > 255) {
              return SNMP_ERR_WRONGLENGTH;
          }
      } else if (action == RESERVE2) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRTADDRESSCOLUMN;
          if ((target =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name,
                                          &name_len, 1)) == NULL) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTAddress: BAD OID!\n"));
              return SNMP_ERR_INCONSISTENTNAME;
          } else {
              if (target->storageType == SNMP_STORAGE_READONLY) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrTAddress: row is read only\n"));
                  return SNMP_ERR_NOTWRITABLE;
              }
              if (target->rowStatus == SNMP_ROW_ACTIVE) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrTAddress: not allowed in active row.\n"));
                  return SNMP_ERR_INCONSISTENTVALUE;
              }
  
              old_addr = (char *) target->tAddress;
              old_len = target->tAddressLen;
              target->tAddress = (u_char *) malloc(var_val_len);
              if (target->tAddress == NULL) {
                  return SNMP_ERR_RESOURCEUNAVAILABLE;
              }
              memcpy(target->tAddress, var_val, var_val_len);
              target->tAddressLen = var_val_len;
  
              /*
               * If row is new, check if its status can be updated.  
               */
              if ((target->rowStatus == SNMP_ROW_NOTREADY) &&
                  (snmpTargetAddr_rowStatusCheck(target) != 0)) {
                  target->rowStatus = SNMP_ROW_NOTINSERVICE;
              }
          }
      } else if (action == COMMIT) {
          SNMP_FREE(old_addr);
          old_addr = NULL;
          snmp_store_needed(NULL);
      } else if (action == FREE || action == UNDO) {
          /*
           * Try to undo the SET here (abnormal usage of FREE clause)  
           */
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRTADDRESSCOLUMN;
          if ((target =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name,
                                          &name_len, 1)) != NULL) {
              if (target->storageType != SNMP_STORAGE_READONLY
                  && target->rowStatus != SNMP_ROW_ACTIVE) {
                  SNMP_FREE(target->tAddress);
                  target->tAddress = (u_char *) old_addr;
                  target->tAddressLen = old_len;
                  if (target->rowStatus == SNMP_ROW_NOTINSERVICE &&
                      snmpTargetAddr_rowStatusCheck(target) == 0) {
                      target->rowStatus = SNMP_ROW_NOTREADY;
                  }
              }
          }
      }
  
      return SNMP_ERR_NOERROR;
  }                               /* write_snmpTargetAddrTAddress */
  
  
  int
  write_snmpTargetAddrTimeout(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)
  {
      /*
       * variables we may use later 
       */
      static long     long_ret;
      size_t          size;
      struct targetAddrTable_struct *temp_struct;
  
      if (action == RESERVE1) {
          if (var_val_type != ASN_INTEGER) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTimeout not ASN_INTEGER\n"));
              return SNMP_ERR_WRONGTYPE;
          }
          if (var_val_len > (size = sizeof(long_ret))) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTimeout: bad length\n"));
              return SNMP_ERR_WRONGLENGTH;
          }
          long_ret = *((long *) var_val);
          if (long_ret < 0 || long_ret > 2147483647) {
              return SNMP_ERR_WRONGVALUE;
          }
      } else if (action == RESERVE2) {
  
          /*
           * spec check range, no spec check 
           */
  
          /*
           * Find row in linked list and check pertinent status... 
           */
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRTIMEOUTCOLUMN;
          if ((temp_struct =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name, &name_len,
                                          1)) == NULL) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTimeout : BAD OID\n"));
              return SNMP_ERR_NOSUCHNAME;
          }
          /*
           * row exists, check if it is changeable 
           */
          if (temp_struct->storageType == SNMP_STORAGE_READONLY) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTimeout : row is read only\n"));
              return SNMP_ERR_NOTWRITABLE;
          }
      } else if  (action == COMMIT) {
          /*
           * Finally, we're golden, should we save value? 
           */
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRTIMEOUTCOLUMN;
          if ((temp_struct =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name, &name_len,
                                          1)) != NULL) {
              temp_struct->timeout = long_ret;
          }
          snmp_store_needed(NULL);
      }
  
      return SNMP_ERR_NOERROR;
  }                               /* write_snmpTargetAddrTimeout */
  
  
  int
  write_snmpTargetAddrRetryCount(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     long_ret;
      struct targetAddrTable_struct *target;
  
      if (action == RESERVE1) {
          if (var_val_type != ASN_INTEGER) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrRetryCount not ASN_INTEGER\n"));
              return SNMP_ERR_WRONGTYPE;
          }
          if (var_val_len != sizeof(long)) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrRetryCount: bad length\n"));
              return SNMP_ERR_WRONGLENGTH;
          }
          long_ret = *((long *) var_val);
          if (long_ret < 0 || long_ret > 255) {
              return SNMP_ERR_WRONGVALUE;
          }
      } else if (action == RESERVE2) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRRETRYCOUNTCOLUMN;
          if ((target = search_snmpTargetAddrTable(snmpTargetAddrOID,
                                                   snmpTargetAddrOIDLen,
                                                   name, &name_len,
                                                   1)) == NULL) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTimeout: BAD OID\n"));
              return SNMP_ERR_INCONSISTENTNAME;
          } else {
              if (target->storageType == SNMP_STORAGE_READONLY) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrRetryCount: row is read only\n"));
                  return SNMP_ERR_NOTWRITABLE;
              }
          }
      } else if (action == COMMIT) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRRETRYCOUNTCOLUMN;
          if ((target = search_snmpTargetAddrTable(snmpTargetAddrOID,
                                                   snmpTargetAddrOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
              target->retryCount = long_ret;
          }
          snmp_store_needed(NULL);
      }
  
      return SNMP_ERR_NOERROR;
  }                               /* write_snmpTargetAddrRetryCount */
  
  static int
  is_delim(const char c)
  {
      return (c == 0x020 || c == 0x09 || c == 0x0d || c == 0x0b);
  }
  
  int
  snmpTagListValid(const char *tagList, const size_t tagListLen)
  {
      size_t          i = 0;
      int             inTag = 0;
  
  
      for (i = 0; i < tagListLen; i++) {
          if (is_delim(tagList[i]) && !inTag) {
              /*
               * Either a leading delimiter or two consecutive delimiters.  
               */
              return 0;
          } else if (is_delim(tagList[i]) && inTag) {
              inTag = 0;
          } else if (!is_delim(tagList[i]) && !inTag) {
              inTag = 1;
          }
      }
      if (!inTag) {
          /*
           * Trailing delimiter.  
           */
          return 0;
      }
      return 1;
  }
  
  int
  write_snmpTargetAddrTagList(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 targetAddrTable_struct *target = NULL;
      static char    *old_tlist = NULL;
      static int      old_tlist_len;
  
      if (action == RESERVE1) {
          if (var_val_type != ASN_OCTET_STR) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTagList not ASN_OCTET_STR\n"));
              return SNMP_ERR_WRONGTYPE;
          }
          if (var_val_len > 255) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTagList: bad length\n"));
              return SNMP_ERR_WRONGLENGTH;
          }
          if (!snmpTagListValid((char *) var_val, var_val_len)) {
              return SNMP_ERR_WRONGVALUE;
          }
      } else if (action == RESERVE2) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRTAGLISTCOLUMN;
          if ((target =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name,
                                          &name_len, 1)) == NULL) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrTagList: BAD OID!\n"));
              return SNMP_ERR_INCONSISTENTNAME;
          } else {
              if (target->storageType == SNMP_STORAGE_READONLY) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrTagList: row is read only\n"));
                  return SNMP_ERR_NOTWRITABLE;
              }
              if (old_tlist != NULL) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "writing multiple rows/values not supported\n"));
                  return SNMP_ERR_GENERR;
              }
              old_tlist = target->tagListData;
              old_tlist_len = target->tagListLen;
              target->tagListData = netsnmp_memdup_nt(var_val, var_val_len,
                                                      &target->tagListLen);
              if (target->tagListData == NULL) {
                  return SNMP_ERR_RESOURCEUNAVAILABLE;
              }
          }
      } else if (action == COMMIT) {
          SNMP_FREE(old_tlist);
          old_tlist = NULL;
          snmp_store_needed(NULL);
      } else if (action == FREE || action == UNDO) {
          old_tlist = NULL;
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRTAGLISTCOLUMN;
          if ((target =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name,
                                          &name_len, 1)) != NULL) {
              if (target->storageType != SNMP_STORAGE_READONLY) {
                  SNMP_FREE(target->tagListData);
                  target->tagListData = old_tlist;
                  target->tagListLen = old_tlist_len;
              }
          }
      }
  
      return SNMP_ERR_NOERROR;
  }                               /* write_snmpTargetAddrTagList */
  
  
  int
  write_snmpTargetAddrParams(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 targetAddrTable_struct *target = NULL;
      static char    *old_params = NULL;
      static size_t   old_params_len;
  
      if (action == RESERVE1) {
          if (var_val_type != ASN_OCTET_STR) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrParams not ASN_OCTET_STR\n"));
              return SNMP_ERR_WRONGTYPE;
          } else if (var_val_len < 1 || var_val_len > 32) {
              return SNMP_ERR_WRONGLENGTH;
          }
      } else if (action == RESERVE2) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRPARAMSCOLUMN;
          if ((target =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name,
                                          &name_len, 1)) == NULL) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrParams: BAD OID!\n"));
              return SNMP_ERR_INCONSISTENTNAME;
          } else {
              if (target->storageType == SNMP_STORAGE_READONLY) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrParams: row is read only\n"));
                  return SNMP_ERR_NOTWRITABLE;
              }
              if (target->rowStatus == SNMP_ROW_ACTIVE) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrParams: not allowed in active row.\n"));
                  return SNMP_ERR_INCONSISTENTVALUE;
              }
              if (old_params != NULL) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "writing multiple rows/values not supported\n"));
                  return SNMP_ERR_GENERR;
              }
  
              old_params = target->paramsData;
              old_params_len = target->paramsLen;
              target->paramsData = netsnmp_memdup_nt(var_val, var_val_len,
                                                     &target->paramsLen);
              if (target->paramsData == NULL) {
                  return SNMP_ERR_RESOURCEUNAVAILABLE;
              }
  
              /*
               * If row is new, check if its status can be updated.  
               */
              if ((target->rowStatus == SNMP_ROW_NOTREADY) &&
                  (snmpTargetAddr_rowStatusCheck(target) != 0)) {
                  target->rowStatus = SNMP_ROW_NOTINSERVICE;
              }
          }
      } else if (action == COMMIT) {
          SNMP_FREE(old_params);
          old_params = NULL;
          snmp_store_needed(NULL);
      } else if (action == FREE || action == UNDO) {
          /*
           * Try to undo the SET here (abnormal usage of FREE clause)  
           */
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRPARAMSCOLUMN;
          if ((target =
               search_snmpTargetAddrTable(snmpTargetAddrOID,
                                          snmpTargetAddrOIDLen, name,
                                          &name_len, 1)) != NULL) {
              if (target->storageType != SNMP_STORAGE_READONLY
                  && target->rowStatus != SNMP_ROW_ACTIVE) {
                  SNMP_FREE(target->paramsData);
                  target->paramsData = old_params;
                  target->paramsLen = old_params_len;
                  old_params = NULL;
                  if (target->rowStatus == SNMP_ROW_NOTINSERVICE &&
                      snmpTargetAddr_rowStatusCheck(target) == 0) {
                      target->rowStatus = SNMP_ROW_NOTREADY;
                  }
              }
          }
      }
  
      return SNMP_ERR_NOERROR;
  }                               /* write_snmpTargetAddrParams */
  
  int
  write_snmpTargetAddrStorageType(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);
      struct targetAddrTable_struct *target;
  
      if (action == RESERVE1) {
          if (var_val_type != ASN_INTEGER) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrStorageType not ASN_INTEGER\n"));
              return SNMP_ERR_WRONGTYPE;
          }
          if (var_val_len != sizeof(long)) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrStorageType: bad length\n"));
              return SNMP_ERR_WRONGLENGTH;
          }
          if (long_ret != SNMP_STORAGE_OTHER &&
              long_ret != SNMP_STORAGE_VOLATILE &&
              long_ret != SNMP_STORAGE_NONVOLATILE) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrStorageType: attempted storage type not a valid"));
              DEBUGMSG(("snmpTargetAddrEntry",
                        " 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) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRSTORAGETYPECOLUMN;
          if ((target = search_snmpTargetAddrTable(snmpTargetAddrOID,
                                                   snmpTargetAddrOIDLen,
                                                   name, &name_len,
                                                   1)) == NULL) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrStorageType: BAD OID\n"));
              return SNMP_ERR_INCONSISTENTNAME;
          } else {
              if (target->storageType == SNMP_STORAGE_PERMANENT ||
                  target->storageType == SNMP_STORAGE_READONLY) {
                  DEBUGMSGTL(("snmpTargetAddrEntry",
                              "write to snmpTargetAddrStorageType: row has unchangeable storage status: %d\n",
                              target->storageType));
                  return SNMP_ERR_WRONGVALUE;
              }
          }
      } else if (action == COMMIT) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRSTORAGETYPECOLUMN;
          if ((target = search_snmpTargetAddrTable(snmpTargetAddrOID,
                                                   snmpTargetAddrOIDLen,
                                                   name, &name_len,
                                                   1)) != NULL) {
              target->storageType = long_ret;
          }
          snmp_store_needed(NULL);
      }
  
      return SNMP_ERR_NOERROR;
  }                               /* write_snmpTargetAddrStorageType */
  
  
  /*
   * snmpTargeAddr_createNewRow is called from write_snmpTargetAddrRowStatus
   * 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
  snmpTargetAddr_createNewRow(oid * name, size_t name_len)
  {
      size_t          newNameLen;
      int             i;
      struct targetAddrTable_struct *temp_struct;
  
      /*
       * setup a new snmpTargetAddrTable structure and add it to the list 
       */
      newNameLen = name_len - snmpTargetAddrOIDLen;
      if (newNameLen > 0) {
          temp_struct = snmpTargetAddrTable_create();
          if (!temp_struct)
              return SNMP_ERR_GENERR;
          temp_struct->nameData = (char *) malloc(newNameLen+1);
          if (temp_struct->nameData == NULL) {
              snmpTargetAddrTable_dispose(temp_struct);
              return 0;
          }
  
          temp_struct->nameLen = newNameLen;
          for (i = 0; i < (int) newNameLen; i++) {
              temp_struct->nameData[i] = (char) name[i + snmpTargetAddrOIDLen];
          }
          temp_struct->nameData[i] = 0; /* just-in-case null term */
  
          temp_struct->rowStatus = SNMP_ROW_NOTREADY;
  
          snmpTargetAddrTable_add(temp_struct);
  
          return 1;
      }
  
      return 0;
  }                               /* snmpTargetAddr_createNewRow */
  
  
  /*
   * Assign a value to the Row Status variable 
   */
  int
  write_snmpTargetAddrRowStatus(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 targetAddrTable_struct *target = NULL;
  
      if (action == RESERVE1) {
          value = *((long *) var_val);
          if (var_val_type != ASN_INTEGER) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrRowStatus not ASN_INTEGER\n"));
              return SNMP_ERR_WRONGTYPE;
          }
          if (var_val_len != sizeof(long)) {
              DEBUGMSGTL(("snmpTargetAddrEntry",
                          "write to snmpTargetAddrRowStatus: bad length\n"));
              return SNMP_ERR_WRONGLENGTH;
          }
          if (value == RS_NOTREADY || value < 1 || value > 6) {
              return SNMP_ERR_WRONGVALUE;
          }
  
          /*
           * Check index value is reasonable.  
           */
  
          if (name_len < snmpTargetAddrOIDLen + 1 ||
              name_len > snmpTargetAddrOIDLen + 32) {
              DEBUGMSGTL(("snmpTargetAddrEntry", "bad index length %d\n",
                          (int)(name_len - snmpTargetAddrOIDLen)));
              return SNMP_ERR_NOCREATION;
          }
  
          /*
           * Search for struct in linked list.  
           */
  
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRROWSTATUSCOLUMN;
          target =
              search_snmpTargetAddrTable(snmpTargetAddrOID,
                                         snmpTargetAddrOIDLen, name,
                                         &name_len, 1);
  
          if (target != NULL) {
              if (value == RS_CREATEANDGO || value == RS_CREATEANDWAIT) {
                  value = RS_NOTREADY;
                  return SNMP_ERR_INCONSISTENTVALUE;
              }
              if (target->storageType == SNMP_STORAGE_READONLY) {
                  DEBUGMSGTL(("snmpTargetAddrEntry", "row is read only\n"));
                  return SNMP_ERR_NOTWRITABLE;
              }
              if (target->storageType == SNMP_STORAGE_PERMANENT) {
                  if (value == RS_DESTROY) {
                      DEBUGMSGTL(("snmpTargetAddrEntry",
                                  "unable to destroy permanent row\n"));
                      return SNMP_ERR_INCONSISTENTVALUE;
                  }
              }
          } else {
              if (value == RS_ACTIVE || value == RS_NOTINSERVICE) {
                  return SNMP_ERR_INCONSISTENTVALUE;
              }
              if (value == RS_CREATEANDGO || value == RS_CREATEANDWAIT) {
                  if (snmpTargetAddr_createNewRow(name, name_len) == 0) {
                      DEBUGMSGTL(("snmpTargetAddrEntry",
                                  "couldn't malloc() new row\n"));
                      return SNMP_ERR_RESOURCEUNAVAILABLE;
                  }
              }
          }
      } else if (action == ACTION) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRROWSTATUSCOLUMN;
          target =
              search_snmpTargetAddrTable(snmpTargetAddrOID,
                                         snmpTargetAddrOIDLen, name,
                                         &name_len, 1);
  
          if (target != NULL) {
              if (value == RS_CREATEANDGO) {
                  /*
                   * Check whether all the required objects have been set.  
                   */
                  if (snmpTargetAddr_rowStatusCheck(target)) {
                      target->rowStatus = RS_ACTIVE;
                  } else {
                      target->rowStatus = RS_NOTREADY;
                  }
              } else if (value == RS_CREATEANDWAIT) {
                  /*
                   * Check whether all the required objects have been set.  
                   */
                  if (snmpTargetAddr_rowStatusCheck(target)) {
                      target->rowStatus = RS_NOTINSERVICE;
                  } else {
                      target->rowStatus = RS_NOTREADY;
                  }
              } else if (value == RS_ACTIVE) {
                  if (target->rowStatus == RS_NOTINSERVICE) {
                      target->rowStatus = RS_ACTIVE;
                  } else if (target->rowStatus == RS_NOTREADY) {
                      return SNMP_ERR_INCONSISTENTVALUE;
                  }
              } else if (value == RS_NOTINSERVICE) {
                  if (target->rowStatus == RS_ACTIVE) {
                      target->rowStatus = RS_NOTINSERVICE;
                  } else if (target->rowStatus == RS_NOTREADY) {
                      return SNMP_ERR_INCONSISTENTVALUE;
                  }
              }
          }
      } else if (action == COMMIT) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRROWSTATUSCOLUMN;
          target =
              search_snmpTargetAddrTable(snmpTargetAddrOID,
                                         snmpTargetAddrOIDLen, name,
                                         &name_len, 1);
          if (target != NULL) {
              if (value == RS_DESTROY) {
                  snmpTargetAddrTable_remove(target);
              }
              if (value == RS_NOTINSERVICE) {
                  if (target->sess != NULL) {
                      snmp_close(target->sess);
                      target->sess = NULL;
                  }
              }
          }
          snmp_store_needed(NULL);
      } else if (action == UNDO || action == FREE) {
          snmpTargetAddrOID[snmpTargetAddrOIDLen - 1] =
              SNMPTARGETADDRROWSTATUSCOLUMN;
          target =
              search_snmpTargetAddrTable(snmpTargetAddrOID,
                                         snmpTargetAddrOIDLen, name,
                                         &name_len, 1);
          if (value == RS_CREATEANDGO || value == RS_CREATEANDWAIT) {
              if (target != NULL) {
                  snmpTargetAddrTable_remove(target);
              }
          }
      }
      return SNMP_ERR_NOERROR;
  }                               /* write_snmpTargetAddrRowStatus */
  
  
  
  int
  write_targetSpinLock(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)
  {
      if (action == RESERVE1) {
          if (var_val_type != ASN_INTEGER) {
              return SNMP_ERR_WRONGTYPE;
          }
          if (var_val_len != sizeof(unsigned long)) {
              return SNMP_ERR_WRONGLENGTH;
          }
          if (*((unsigned long *) var_val) != snmpTargetSpinLock) {
              return SNMP_ERR_INCONSISTENTVALUE;
          }
      } else if (action == COMMIT) {
          if (snmpTargetSpinLock == 2147483647) {
              snmpTargetSpinLock = 0;
          } else {
              snmpTargetSpinLock++;
          }
      }
      return SNMP_ERR_NOERROR;
  }
  
  #endif /* !NETSNMP_NO_WRITE_SUPPORT */
  
  
  u_char         *
  var_targetSpinLock(struct variable * vp,
                     oid * name,
                     size_t * length,
                     int exact,
                     size_t * var_len, WriteMethod ** write_method)
  {
      if (header_generic(vp, name, length, exact, var_len, write_method) ==
          MATCH_FAILED) {
  #ifndef NETSNMP_NO_WRITE_SUPPORT
          *write_method = write_targetSpinLock;
  #else
  		*write_method = NULL;
  #endif /* !NETSNMP_NO_WRITE_SUPPORT */
          return NULL;
      }
      if (vp->magic == SNMPTARGETSPINLOCK) {
          *var_len = sizeof(unsigned long);
  #ifndef NETSNMP_NO_WRITE_SUPPORT
          *write_method = write_targetSpinLock;
  #else
  		*write_method = NULL;
  #endif /* !NETSNMP_NO_WRITE_SUPPORT */
          return (u_char *) & (snmpTargetSpinLock);
      }
      return NULL;
  }
  