/*
 * mib.c - MIB Primitives
 *
 * Written by Scott W. Shumate
 * 
 * Copyright (c) 1995-97 All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this
 * software and its documentation is hereby granted,
 * provided that both the copyright notice and this
 * permission notice appear in all copies of the software,
 * derivative works or modified versions, and any portions
 * thereof, that both notices appear in supporting
 * documentation, and that the use of this software is
 * acknowledged in any publications resulting from using
 * the software.
 * 
 * I ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION AND DISCLAIM ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
 * SOFTWARE.
 */

#include "mib.h"
#include "sysgroup.h"
#include "atmf_uni.h"
#include "util.h"
#include "atmd.h"

#define COMPONENT "MIB"

static Variable variables[] =
{
  { &sysDescr, getString, NULL, NULL, &sysDescrValue },
  { &sysObjectID, getOid, NULL, NULL, &sysObjectIDValue },
  { &sysUpTime, getUpTime, NULL, NULL, NULL },
  { &sysContact, getString, NULL, NULL, &sysContactValue },
  { &sysName, getString, NULL, NULL, &sysNameValue },
  { &sysLocation, getString, NULL, NULL, &sysLocationValue },
  { &sysServices, getInteger, NULL, NULL, &sysServicesValue },
  { &atmfPortIndex, getInteger, NULL, NULL, &atmfPortIndexValue },
  { &atmfMyIpNmAddress, getOid, NULL, NULL, &atmfMyIpNmAddressValue },
  { &atmfNetPrefixStatus, getNetPrefix, getnextNetPrefix, setNetPrefix, NULL },
  { NULL }
};

void MIBget(VarBindList *list, PDUInt *status, AsnInt *index)
{
  VarBind *varbind;
  Variable *var;
  AsnOidResult result;
  
  *index = 1;
  FOR_EACH_LIST_ELMT(varbind, list)
  {
    /* Find the first MIB object not lexigraphically less than the *
     * requested OID                                               */
    var = variables;
    while(var->name != NULL)
    {
      result = AsnOidCompare(var->name, &varbind->name);
      if(result != AsnOidLess)
	break;
      var++;
    }

    /* Call get if the requested OID is equal to a simple MIB object */    
    /* OR if the requested OID is a leaf of a complex MIB object */
    if((result == AsnOidEqual && var->getnext == NULL) ||
       (result == AsnOidRoot && var->getnext != NULL))
      *status = var->get(varbind, var);
    /* else the object was not found */
    else
      *status = NOSUCHNAME;
    
    /* Check if the get failed */
    if(*status != NOERROR)
      return;
    
    (*index)++;
  }
  *index = 0;
  return;
}
  

void MIBgetnext(VarBindList *list, PDUInt *status, AsnInt *index)
{
  VarBind *varbind;
  Variable *var;
  AsnOidResult result;

  *index = 1;
  FOR_EACH_LIST_ELMT(varbind, list)
  {
    /* Find the first complex MIB object not lexigraphically less than *
     * or simple MIB object greater than the requested OID            */
    var = variables;
    while(var->name != NULL)
    {
      result = AsnOidCompare(var->name, &varbind->name);
      if(var->getnext == NULL)
      {
	if(result == AsnOidGreater)
	  break;
      } else if(result != AsnOidLess)
	break;
      var++;
    }

    /* Find the next valid MIB object */
    for(*status = NOSUCHNAME;
	var->name != NULL && *status == NOSUCHNAME;
	var++)
      if(var->getnext == NULL)
      {
	varbind->name.octs = Asn1Alloc(var->name->octetLen);
	AsnOidCopy(&varbind->name, var->name);
	*status = var->get(varbind, var);
      }
      else
	*status = var->getnext(varbind, var);

    /* Check if no valid MIB object found */
    if(*status != NOERROR)
      return;
      
    (*index)++;
  }
  *index = 0;
  return;
}

void MIBset(VarBindList *list, PDUInt *status, AsnInt *index)
{
  VarBind *varbind;
  Variable *var;
  AsnOidResult result;

  *index = 1;
  FOR_EACH_LIST_ELMT(varbind, list)
  {
    /* Find the first MIB object not lexigraphically less than the *
     * requested OID                                               */
    var = variables;
    while(var->name != NULL)
    {
      result = AsnOidCompare(var->name, &varbind->name);
      if(result != AsnOidLess)
	break;
      var++;
    }

    /* Call set if the requested variable is equal to a simple MIB object */    
    if((result == AsnOidEqual && var->getnext == NULL) ||
    /* OR if the request variable is a leaf of a complex MIB object */
      (result == AsnOidRoot && var->getnext != NULL))
      /* Return read only if no set function exists */
      if(var->set == NULL)
	*status = READONLY;
      else
	*status = var->set(varbind, var);
    else
    /* else the MIB object was not found */
      *status = NOSUCHNAME;

    /* Check if the set failed */
    if(*status != NOERROR)
      return;
      
    (*index)++;
  }
  *index = 0;
  return;
}

void *MIBdelete(AsnOid *oid)
{
  Variable *var;
  void *value;
  AsnOidResult result;

  /* Find the first MIB object not lexigraphically less than the *
   * requested variable                                          */
    var = variables;
    while(var->name != NULL)
    {
      result = AsnOidCompare(var->name, oid);
      if(result != AsnOidLess)
	break;
      var++;
    }

  /* Return NULL if the MIB object is not found */
  if(result != AsnOidEqual)
    return NULL;

  value = var->value;
  var->value = NULL;

  return value;
}

AsnInt getString(VarBind *varbind, Variable *var)
{
  varbind->value = Asn1Alloc(sizeof(struct ObjectSyntax));
  varbind->value->choiceId = OBJECTSYNTAX_SIMPLE;
  varbind->value->a.simple = Asn1Alloc(sizeof(struct SimpleSyntax));
  varbind->value->a.simple->choiceId = SIMPLESYNTAX_STRING;
  varbind->value->a.simple->a.string = (AsnOcts*) var->value;
  return NOERROR;
}

AsnInt getOid(VarBind *varbind, Variable *var)
{
  varbind->value = Asn1Alloc(sizeof(struct ObjectSyntax));
  varbind->value->choiceId = OBJECTSYNTAX_SIMPLE;
  varbind->value->a.simple = Asn1Alloc(sizeof(struct SimpleSyntax));
  varbind->value->a.simple->choiceId = SIMPLESYNTAX_OBJECT;
  varbind->value->a.simple->a.object = (AsnOid*) var->value;
  return NOERROR;
}

AsnInt getInteger(VarBind *varbind, Variable *var)
{
  varbind->value = Asn1Alloc(sizeof(struct ObjectSyntax));
  varbind->value->choiceId = OBJECTSYNTAX_SIMPLE;
  varbind->value->a.simple = Asn1Alloc(sizeof(struct SimpleSyntax));
  varbind->value->a.simple->choiceId = SIMPLESYNTAX_NUMBER;
  varbind->value->a.simple->a.number = *((AsnInt *) var->value);
  return NOERROR;
}





