Click here to Skip to main content
15,900,378 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have implemented a SNMP agent by windows snmp api with reference to an article How to develop a SNMP extension agent DLL[^]. Several oids must be organized to be a SNMP table. I did it like this:
This class represent a oid.
C++
class VeMIB_ENTRY
{
public:
	AsnObjectIdentifier m_asnOid;
	VeMIB_ENTRY*		m_pMibNext;

	VeMIB_ENTRY(VeMIB_ENTRY* pMibNext,UINT unLength,UINT asnOid,...)
	{
		m_asnOid.idLength = unLength;
		m_asnOid.ids = new UINT[unLength];
		memcpy(m_asnOid.ids,&asnOid,unLength*sizeof(UINT));
		m_pMibNext = pMibNext;
	}

	VeMIB_ENTRY(VeMIB_ENTRY* pMibNext,UINT unLength,UINT asnOid[])
	{
		m_asnOid.idLength = unLength;
		m_asnOid.ids = new UINT[unLength];
		memcpy(m_asnOid.ids,asnOid,unLength*sizeof(UINT));
		m_pMibNext = pMibNext;
	}

	virtual ~VeMIB_ENTRY() 
	{ 
		delete[] m_asnOid.ids; 
	}

	virtual int  GetStorageValue( AsnAny* pasnValue ) {return SNMP_ERRORSTATUS_NOERROR;}
	virtual int  SetStorageValue( const AsnAny* pasnValue ) {return SNMP_ERRORSTATUS_READONLY;}

private:
	VeMIB_ENTRY( const VeMIB_ENTRY& ) {};
	VeMIB_ENTRY& operator=( const VeMIB_ENTRY& ) {};
};

class VeNullValue:
	public VeMIB_ENTRY
{
public:
	VeNullValue(VeMIB_ENTRY *pMibNext,UINT unLength,UINT asnOid,...)
		:VeMIB_ENTRY(pMibNext,unLength,&asnOid)
	{
	}

	virtual int  GetStorageValue(AsnAny* pasnValue) 
	{
		pasnValue->asnType = ASN_NULL;

		return SNMP_ERRORSTATUS_NOERROR;
	}

	virtual int  SetStorageValue( const AsnAny* pasnValue ) {return SNMP_ERRORSTATUS_NOERROR;}
};

class VeEntryValue:
	public VeMIB_ENTRY
{
private:
	const TCHAR* m_szMsg;
public:
	VeEntryValue(VeMIB_ENTRY *pMibNext,UINT unLength,UINT asnOid,...)
		:VeMIB_ENTRY(pMibNext,unLength,&asnOid)
	{
		m_szMsg = _T("entry");
	}

	virtual int  GetStorageValue(AsnAny* pasnValue) 
	{
		pasnValue->asnType = ASN_SEQUENCE;
		pasnValue->asnValue.sequence.length = _tcslen(m_szMsg)*sizeof(TCHAR);
		pasnValue->asnValue.sequence.stream 
			= (unsigned char*)SnmpUtilMemAlloc(pasnValue->asnValue.sequence.length);

		memcpy(pasnValue->asnValue.string.stream,m_szMsg,pasnValue->asnValue.sequence.length);

		pasnValue->asnValue.sequence.dynamic = TRUE;
		return SNMP_ERRORSTATUS_NOERROR;
	}

	virtual int  SetStorageValue( const AsnAny* pasnValue ) {return SNMP_ERRORSTATUS_NOERROR;}
};


MIB is organised like this.
C++
UINT g_unMyOIDPrefix[] = {1, 3, 6, 1, 4, 1, 31492};
CMap<AsnObjectIdentifier*,AsnObjectIdentifier*,VeMIB_ENTRY*,VeMIB_ENTRY*> g_VeMIB;

void  InitialVeMIB()
{
	VeMIB_ENTRY *pMibEntry = NULL;
	VeMIB_ENTRY *pMibEntryNext = NULL;

	g_VeMIB.InitHashTable(100);

#define ADD_MIB_ITEM(type,length,...)            \
	pMibEntry = new type(pMibEntryNext,length,##__VA_ARGS__);\
	g_VeMIB.SetAt(&(pMibEntry->m_asnOid),pMibEntry);\
	pMibEntryNext = pMibEntry

	ADD_MIB_ITEM(VeMIB_ENTRY ,7,3,1,1,1,10,1,5);
	ADD_MIB_ITEM(VeMIB_ENTRY ,7,3,1,1,1,10,1,4);
	ADD_MIB_ITEM(VeMIB_ENTRY ,7,3,1,1,1,10,1,3);
	ADD_MIB_ITEM(VeMIB_ENTRY ,1,7,3,1,1,1,10,1,2);
	ADD_MIB_ITEM(VeMIB_ENTRY ,7,3,1,1,1,10,1,1);
	ADD_MIB_ITEM(VeEntryValue,6,3,1,1,1,10,1);
	ADD_MIB_ITEM(VeNullValue,5,3,1,1,1,10);
}


If it is correctly implemented,one can use command line like snmputil walk localhost public .1.3.6.1.4.1.31492.3.1.1.1.10 or snmp4j -c -v 2c -Ot localhost .1.3.6.1.4.1.31492.3.1.1.1.10 to query the table. But now i can use command line snmp4j -c -v 2c -Ot localhost .1.3.6.1.4.1.31492.3.1.1.1.10.1 query the table with an error number 2 returned.

It may also concerned with SnmpExtensionQuery. Its source code provide as follow.
C++
BOOL SNMP_FUNC_TYPE SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, AsnInteger32 *pErrorStatus, AsnInteger32 *pErrorIndex)
{
	int nRet = 0;

	*pErrorStatus = SNMP_ERRORSTATUS_NOERROR;
	*pErrorIndex = 0;

	for(UINT i=0;i<pVarBindList->len;i++)
	{
		*pErrorStatus = SNMP_ERRORSTATUS_NOERROR;

		VeMIB_ENTRY* pMIBItem = GetVeMIBItem(&pVarBindList->list[i]);
		if (pMIBItem != NULL)
		{
			// what type of request we are getting?
			switch(bPduType)
			{
			case SNMP_PDU_GET:// // gets the variable value passed variable in pVarBindList
				*pErrorStatus = pMIBItem->GetStorageValue(&(pVarBindList->list[i].value));
				if(*pErrorStatus != SNMP_ERRORSTATUS_NOERROR)
					*pErrorIndex++;
				break;
			case SNMP_PDU_GETNEXT: // gets the next variable related to the passed variable in pVarBindList
				*pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
				if(pMIBItem->m_pMibNext != NULL)
				{
					SnmpUtilOidFree(&pVarBindList->list[i].name);			
					SnmpUtilOidCpy(&pVarBindList->list[i].name, &MIB_OidPrefix);
					SnmpUtilOidAppend(&pVarBindList->list[i].name, &pMIBItem->m_pMibNext->m_asnOid);
					*pErrorStatus = pMIBItem->m_pMibNext->GetStorageValue(&(pVarBindList->list[i].value));
				}
				else

				if(*pErrorStatus != SNMP_ERRORSTATUS_NOERROR)
					*pErrorIndex++;
				break;
			case SNMP_PDU_SET: // sets a variable
				*pErrorStatus = pMIBItem->SetStorageValue(&(pVarBindList->list[i].value));
				if(*pErrorStatus != SNMP_ERRORSTATUS_NOERROR)
					*pErrorIndex++;
				break;
			default:
				*pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
				*pErrorIndex++;
			};
		}
		else
		{
			*pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
			*pErrorIndex++;
		}
	}	

	return SNMPAPI_NOERROR;
}


How it happens, How to implement an agent width Windows SNMP API for a MIB containing SNMP tables?
Posted
Updated 25-Oct-12 17:43pm
v6

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900