none
如何使用snmp api实现 SNMP table RRS feed

  • 问题

  • 我参考文档How to develop a SNMP extension agent DLL[^]做了一个snmp扩展代理程序. 一些信息必须组织成snmp table。我是这样做的:

    下面是代表每一个oid的类。   

    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的组织是这样的:

    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);
    }

    其中.1.3.6.1.4.1.31492.3.1.1.1.10表示一个表,.1.3.6.1.4.1.31492.3.1.1.1.10.1是表的入口。正确的实现是能够用命令snmputil walk localhost public .1.3.6.1.4.1.31492.3.1.1.1.10 或者使用 snmp4j -c -v 2c -Ot localhost .1.3.6.1.4.1.31492.3.1.1.1.10  获取整个表的内容,返回的状态是0。但是我的实现,却是使用命令snmp4j -c -v 2c -Ot localhost  .1.3.6.1.4.1.31492.3.1.1.1.10.1能够将整个表的内容获取,但是返回状态不是0。请问这是怎么回事,怎么组织这个表?

    SnmpExtensionQuery的实现如下。

    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;
    }

    出现上面的问题还与SnmpExtensionQuery的实现有关。请问应该如何才能正确实现snmp table,也就是能够使用snmputil walk localhost public .1.3.6.1.4.1.31492.3.1.1.1.10 将整个表的数据取出来。

    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.1
    Value    = String visione
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.2
    Value    = Integer32 1
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.3
    Value    = Integer32 0
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.4
    Value    = Integer32 0
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.5
    Value    = String visione
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.6
    Value    = String 00-30-67-EC-F4-DF
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.7
    Value    = String 255.255.255.0
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.8
    Value    = String 172.110.11.1
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.9
    Value    = Integer32 0
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.10
    Value    = Integer32 0
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.11
    Value    = Integer32 2
    Variable = .iso.org.dod.internet.private.enterprises.31492.3.1.1.1.10.1.12
    Value    = Integer32 70
    End of MIB subtree.


    2012年10月25日 5:16