#include <winclude.h>


BOOL OpenMib(char *Name,LOCAL_MIB_ACCESS *Mib)
{
  Mib->m_hInst = LoadLibrary( Name );
  if(Mib->m_hInst < (HINSTANCE) HINSTANCE_ERROR){
    return FALSE;
  }

  Mib->m_Init=(pSnmpExtensionInit)GetProcAddress(Mib->m_hInst ,"SnmpExtensionInit");
  if(Mib->m_Init==NULL){
    CloseMib( Mib );
    return FALSE;
  }

  Mib->m_InitEx=(pSnmpExtensionInitEx)GetProcAddress(Mib->m_hInst ,"SnmpExtensionInitEx");
  if(Mib->m_InitEx==NULL){
    CloseMib( Mib );
    return FALSE;
  }

  Mib->m_Query=(pSnmpExtensionQuery)GetProcAddress(Mib->m_hInst ,"SnmpExtensionQuery");
  if(Mib->m_Query==NULL){
    CloseMib( Mib );
    return FALSE;
  }

  Mib->m_Trap=(pSnmpExtensionTrap)GetProcAddress(Mib->m_hInst ,"SnmpExtensionTrap");
  if(Mib->m_Trap==NULL){
    CloseMib( Mib );
    return FALSE;
  }

  return TRUE;
}

void CloseMib(LOCAL_MIB_ACCESS *Mib)
{
  FreeLibrary( Mib->m_hInst );
}


SNMPAPI
SNMP_FUNC_TYPE
SnmpUtilOidCpy(
    OUT AsnObjectIdentifier *DstObjId,
    IN  AsnObjectIdentifier *SrcObjId
    )
{
  DstObjId->ids = (UINT *)GlobalAlloc(GMEM_ZEROINIT,SrcObjId->idLength*sizeof(UINT));
  if(!DstObjId->ids){
    SetLastError(1);
    return 0;
  }

  memcpy(DstObjId->ids,SrcObjId->ids,SrcObjId->idLength*sizeof(UINT));
  DstObjId->idLength = SrcObjId->idLength;

  return 1;
}

VOID
SNMP_FUNC_TYPE
SnmpUtilOidFree(
    IN OUT AsnObjectIdentifier *ObjId
    )
{
  GlobalFree(ObjId->ids);
  ObjId->ids = 0;
  ObjId->idLength = 0;
}

SNMPAPI
SNMP_FUNC_TYPE
SnmpUtilOidNCmp(
    IN AsnObjectIdentifier *ObjIdA,
    IN AsnObjectIdentifier *ObjIdB,
    IN UINT                 Len
    )
{
  UINT CmpLen;
  UINT i;
  int  res;

  CmpLen = Len;
  if(ObjIdA->idLength < CmpLen)
    CmpLen = ObjIdA->idLength;
  if(ObjIdB->idLength < CmpLen)
    CmpLen = ObjIdB->idLength;

  for(i=0;i<CmpLen;i++){
    res = ObjIdA->ids[i] - ObjIdB->ids[i];
    if(res!=0)
      return res;
  }
  return 0;
}

VOID
SNMP_FUNC_TYPE
SnmpUtilVarBindFree(
    IN OUT RFC1157VarBind *VarBind
    )
{
  BYTE asnType;
  // free object name
  SnmpUtilOidFree(&VarBind->name);

  asnType = VarBind->value.asnType;

  if(asnType==ASN_OBJECTIDENTIFIER){
    SnmpUtilOidFree(&VarBind->value.asnValue.object);
  }
  else if(
        (asnType==ASN_OCTETSTRING) ||
        (asnType==ASN_RFC1155_IPADDRESS) ||
        (asnType==ASN_RFC1155_OPAQUE) ||
        (asnType==ASN_SEQUENCE)){
    if(VarBind->value.asnValue.string.dynamic){
      GlobalFree(VarBind->value.asnValue.string.stream);
    }
  }

  VarBind->value.asnType = ASN_NULL;

}

int FillIfList(struct _IFlist *iflist, int *icount)
{
  LOCAL_MIB_ACCESS Mib;
  BOOL ret;
  DWORD dwTimeZeroReference;
  HANDLE PollForTrapEvent;
  AsnObjectIdentifier SupportedView[32];
  int                 SupportedViewCount;
  RFC1157VarBindList  *varBindList;
  RFC1157VarBind      varBind[4];
  AsnInteger          errorStatus;
  AsnInteger          errorIndex;
  RFC1157VarBindList  BindList;

  AsnObjectIdentifier MIB_NULL = {0,0};
  int	i;	
  BOOL Exit;

	/*interface count*/  
  UINT OID_icount[] = {1,3,6,1,2,1,2,1};
  AsnObjectIdentifier MIB_icount= { OID_SIZEOF(OID_icount), OID_icount};


	/*interface info*/
  UINT OID_interfaceid[] = {1,3,6,1,2,1,2,2,1,1};
  AsnObjectIdentifier MIB_interfaceid= { OID_SIZEOF(OID_interfaceid), OID_interfaceid};

  UINT OID_interfacedesc[] = {1,3,6,1,2,1,2,2,1,2};
  AsnObjectIdentifier MIB_interfacedesc= { OID_SIZEOF(OID_interfacedesc), OID_interfacedesc};

  UINT OID_interfacetype[] = {1,3,6,1,2,1,2,2,1,3};
  AsnObjectIdentifier MIB_interfacetype= { OID_SIZEOF(OID_interfacetype), OID_interfacetype};

  UINT OID_interfaceaddr[] = {1,3,6,1,2,1,2,2,1,6};
  AsnObjectIdentifier MIB_interfaceaddr= { OID_SIZEOF(OID_interfaceaddr), OID_interfaceaddr};


  varBindList = &BindList;

  ret = OpenMib("inetmib1.dll",&Mib);
  if(!ret){
    printf("\nCan't find INETMIB1.DLL");
    return -1;
  }

   dwTimeZeroReference = GetTickCount();
  SupportedView[0] = MIB_NULL;

  SupportedViewCount = 0;

  dwTimeZeroReference = 0;
  ret = Mib.m_Init(dwTimeZeroReference,&PollForTrapEvent,&SupportedView[0]);
  SupportedViewCount = 1;

  if(!ret){
    printf("\nInit Fail");
    return -1;
  }

   varBindList->list = varBind;
  varBindList->len  = 1;
  varBind[0].name  = MIB_NULL;
	SNMP_oidcpy(&varBind[0].name,&MIB_icount);
 
    ret = Mib.m_Query(ASN_RFC1157_GETNEXTREQUEST,varBindList,&errorStatus,&errorIndex);
    if(ret)
	{
      ret = SNMP_oidncmp(&varBind[0].name,&MIB_icount,MIB_icount.idLength);
     if(!ret)
	 {  
		 *icount = varBind[0].value.asnValue.number;
	  }

	}

  SNMP_FreeVarBind(&varBind[0]);

  
  
  varBindList->list = varBind;
  varBindList->len  = 4;
  varBind[0].name  = MIB_NULL;
  varBind[1].name  = MIB_NULL;
  varBind[2].name  = MIB_NULL;
  varBind[3].name  = MIB_NULL;

  SNMP_oidcpy(&varBind[0].name,&MIB_interfaceid);
  SNMP_oidcpy(&varBind[1].name,&MIB_interfacedesc);
  SNMP_oidcpy(&varBind[2].name,&MIB_interfacetype);
  SNMP_oidcpy(&varBind[3].name,&MIB_interfaceaddr);
	
  Exit = FALSE;
  i = 0;
  while(!Exit)
  {
	memset(&iflist[i],0,sizeof(struct _IFlist));
    ret = Mib.m_Query(ASN_RFC1157_GETNEXTREQUEST,varBindList,&errorStatus,&errorIndex);
    if(!ret) Exit=TRUE;
    else
	{
      ret = SNMP_oidncmp(&varBind[0].name,&MIB_interfaceid,MIB_interfaceid.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		
        iflist[i].id = varBind[0].value.asnValue.number;
	  }
	  ret = SNMP_oidncmp(&varBind[1].name,&MIB_interfacedesc,MIB_interfacedesc.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		strncpy(iflist[i].desc,varBind[1].value.asnValue.address.stream,512);
	  }
	  ret = SNMP_oidncmp(&varBind[2].name,&MIB_interfacetype,MIB_interfacetype.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		iflist[i].type = varBind[2].value.asnValue.number;
	  }
	  ret = SNMP_oidncmp(&varBind[3].name,&MIB_interfaceaddr,MIB_interfaceaddr.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		if (varBind[3].value.asnValue.address.stream != NULL)
		{
			if ((varBind[3].value.asnValue.address.stream[0] == 0x44)
				&& (varBind[3].value.asnValue.address.stream[1] == 0x45)
				&& (varBind[3].value.asnValue.address.stream[2] == 0x53)
				&& (varBind[3].value.asnValue.address.stream[3] == 0x54)
				&& (varBind[3].value.asnValue.address.stream[4] == 0x00)) 
			{
				
				iflist[i].MAC[0] = 0x44;
				iflist[i].MAC[1] = 0x55;
				iflist[i].MAC[2] = 0x4E;
				//strcpy(iflist[i].MAC,"DUN");
				//printf("Interface #%i is a DUN adapter\n", j);
				continue;
			}
			if ((varBind[3].value.asnValue.address.stream[0] == 0x00)
				&& (varBind[3].value.asnValue.address.stream[1] == 0x00)
				&& (varBind[3].value.asnValue.address.stream[2] == 0x00)
				&& (varBind[3].value.asnValue.address.stream[3] == 0x00)
				&& (varBind[3].value.asnValue.address.stream[4] == 0x00)
				&& (varBind[3].value.asnValue.address.stream[5] == 0x00)) 
			{
				memset(iflist[i].MAC,0,6);
				//printf("Interface #%i is a NULL address\n", j);
				continue;
			}
	
			iflist[i].MAC[0] = varBind[3].value.asnValue.address.stream[0];
			iflist[i].MAC[1] = varBind[3].value.asnValue.address.stream[1];
			iflist[i].MAC[2] = varBind[3].value.asnValue.address.stream[2];
			iflist[i].MAC[3] = varBind[3].value.asnValue.address.stream[3];
			iflist[i].MAC[4] = varBind[3].value.asnValue.address.stream[4];
			iflist[i].MAC[5] = varBind[3].value.asnValue.address.stream[5];
			//memcpy(iflist[i].MAC,varBind[3].value.asnValue.address.stream,6);
		  }
	  }
		i++;
      //}
    }
  }

  SNMP_FreeVarBind(&varBind[0]);
  SNMP_FreeVarBind(&varBind[1]);
  SNMP_FreeVarBind(&varBind[2]);
  SNMP_FreeVarBind(&varBind[3]);

  

	return 0;
}


int FillIpList(struct _IPlist *iplist)
{
  LOCAL_MIB_ACCESS Mib;
  BOOL ret;
  DWORD dwTimeZeroReference;
  HANDLE PollForTrapEvent;
  AsnObjectIdentifier SupportedView[32];
  int                 SupportedViewCount;
  RFC1157VarBindList  *varBindList;
  RFC1157VarBind      varBind[2];
  AsnInteger          errorStatus;
  AsnInteger          errorIndex;
  RFC1157VarBindList  BindList;
  BOOL Exit;
  AsnObjectIdentifier MIB_NULL = {0,0};
  int i;
  
  /*ip address information*/

  UINT OID_ipaddr[] = {1,3,6,1,2,1,4,20,1,1 };
  AsnObjectIdentifier MIB_ipaddr= { OID_SIZEOF(OID_ipaddr), OID_ipaddr};

  UINT OID_ipid[] = {1,3,6,1,2,1,4,20,1,2};
  AsnObjectIdentifier MIB_ipid= { OID_SIZEOF(OID_ipid), OID_ipid};


  varBindList = &BindList;

  ret = OpenMib("inetmib1.dll",&Mib);
  if(!ret){
    printf("\nCan't find INETMIB1.DLL");
    return -1;
  }

   dwTimeZeroReference = GetTickCount();
  SupportedView[0] = MIB_NULL;

  SupportedViewCount = 0;

  dwTimeZeroReference = 0;
  ret = Mib.m_Init(dwTimeZeroReference,&PollForTrapEvent,&SupportedView[0]);
  SupportedViewCount = 1;

  if(!ret){
    printf("\nInit Fail");
    return -1;
  }
  varBindList->list = varBind;
  varBindList->len  = 2;
  varBind[0].name  = MIB_NULL;
  varBind[1].name  = MIB_NULL;

  SNMP_oidcpy(&varBind[0].name,&MIB_ipid);
  SNMP_oidcpy(&varBind[1].name,&MIB_ipaddr);
	
  Exit = FALSE;
  i = 0;
  while(!Exit)
  {
	memset(&iplist[i],0,sizeof(struct _IPlist));
    ret = Mib.m_Query(ASN_RFC1157_GETNEXTREQUEST,varBindList,&errorStatus,&errorIndex);
    if(!ret) Exit=TRUE;
    else
	{
      ret = SNMP_oidncmp(&varBind[0].name,&MIB_ipid,MIB_ipid.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		
        iplist[i].id = varBind[0].value.asnValue.number;
	  }
	  ret = SNMP_oidncmp(&varBind[1].name,&MIB_ipaddr,MIB_ipaddr.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		memcpy(&iplist[i].ip,varBind[1].value.asnValue.address.stream,4);
	  }
		i++;
      //}
    }
  }

  SNMP_FreeVarBind(&varBind[0]);
  SNMP_FreeVarBind(&varBind[1]);

  
	return 0;
}



int FillRouteList(struct myroute *routelist)
{
  LOCAL_MIB_ACCESS Mib;
  BOOL ret;
  DWORD dwTimeZeroReference;
  HANDLE PollForTrapEvent;
  AsnObjectIdentifier SupportedView[32];
  int                 SupportedViewCount;
  RFC1157VarBindList  *varBindList;
  RFC1157VarBind      varBind[4];
  AsnInteger          errorStatus;
  AsnInteger          errorIndex;
  RFC1157VarBindList  BindList;

  AsnObjectIdentifier MIB_NULL = {0,0};
  int	i;	
  BOOL Exit;


	/*interface info*/
  UINT OID_routeid[] = {1,3,6,1,2,1,4,21,1,2 };
  AsnObjectIdentifier MIB_routeid= { OID_SIZEOF(OID_routeid), OID_routeid};

  UINT OID_routedest[] = {1,3,6,1,2,1,4,21,1,1};
  AsnObjectIdentifier MIB_routedest= { OID_SIZEOF(OID_routedest), OID_routedest};

  UINT OID_routemask[] = {1,3,6,1,2,1,4,21,1,11};
  AsnObjectIdentifier MIB_routemask= { OID_SIZEOF(OID_routemask), OID_routemask};
   UINT OID_routenexthop[] = {1,3,6,1,2,1,4,21,1,7};
  AsnObjectIdentifier MIB_routenexthop= { OID_SIZEOF(OID_routenexthop), OID_routenexthop};




  varBindList = &BindList;

  ret = OpenMib("inetmib1.dll",&Mib);
  if(!ret){
    printf("\nCan't find INETMIB1.DLL");
    return -1;
  }

   dwTimeZeroReference = GetTickCount();
  SupportedView[0] = MIB_NULL;

  SupportedViewCount = 0;

  dwTimeZeroReference = 0;
  ret = Mib.m_Init(dwTimeZeroReference,&PollForTrapEvent,&SupportedView[0]);
  SupportedViewCount = 1;

  if(!ret){
    printf("\nInit Fail");
    return -1;
  }
  varBindList->list = varBind;
  varBindList->len  = 4;
  varBind[0].name  = MIB_NULL;
  varBind[1].name  = MIB_NULL;
  varBind[2].name  = MIB_NULL;
  varBind[3].name  = MIB_NULL;
  

  SNMP_oidcpy(&varBind[0].name,&MIB_routeid);
  SNMP_oidcpy(&varBind[1].name,&MIB_routedest);
  SNMP_oidcpy(&varBind[2].name,&MIB_routemask);
  SNMP_oidcpy(&varBind[3].name,&MIB_routenexthop);

	
  Exit = FALSE;
  i = 0;
  while(!Exit)
  {
	memset(&routelist[i],0,sizeof(struct myroute));
    ret = Mib.m_Query(ASN_RFC1157_GETNEXTREQUEST,varBindList,&errorStatus,&errorIndex);
    if(!ret) Exit=TRUE;
    else
	{
      ret = SNMP_oidncmp(&varBind[0].name,&MIB_routeid,MIB_routeid.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		
        routelist[i].ifid = varBind[0].value.asnValue.number;
	  }
	  ret = SNMP_oidncmp(&varBind[1].name,&MIB_routedest,MIB_routedest.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		  memcpy(&routelist[i].dest,varBind[1].value.asnValue.address.stream,4);
		//strncpy(arlist[i].desc,varBind[1].value.asnValue.address.stream,512);
	  }
	  ret = SNMP_oidncmp(&varBind[2].name,&MIB_routemask,MIB_routemask.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		memcpy(&routelist[i].mask,varBind[2].value.asnValue.address.stream,4);
	  }
	  ret = SNMP_oidncmp(&varBind[3].name,&MIB_routenexthop,MIB_routenexthop.idLength);    
	  if(ret!=0)
	  {
        Exit=TRUE;
      }
      else
	  {
		memcpy(&routelist[i].nexthop,varBind[3].value.asnValue.address.stream,4);
	  }
	 i++;
     }
  }
  SNMP_FreeVarBind(&varBind[0]);
  SNMP_FreeVarBind(&varBind[1]);
  SNMP_FreeVarBind(&varBind[2]);
  SNMP_FreeVarBind(&varBind[3]);
  return i-1;
}
