www.pudn.com > SNMP范例源代码.zip > Mib.c


/* mib.c - Processes SNMP messages and communicates with IDB */
/*
modification history
--------------------
*/

/*
* DESCRIPTION
* mib contains various routines used internally by the SNMP agent.
* These routines include routines to process SNMP messages by 
* walking the internal MIB tree to routines that communicate 
* with IDB. Helper routines for RMON are also included in here.
*/
#include 

/* globals */
extern snmp_stat_t SnmpStat;
#define XSNMP_TOTAL_OBJECTS 100
xdata i32 Table[XSNMP_TOTAL_OBJECTS];
static idata i32 Mib_Count;
static 
xdata mib_object_t MibRoot[] = 
{
		{{1,3,6,1,2,1,1,1},8, LEAF_sysDescr,SNMP_OCTETSTR,MIB_READ|MIB_WRITE},/*sysDescr*/

		{{1,3,6,1,2,1,1,2},8, LEAF_sysObjectID,SNMP_OBJECTID,MIB_READ},/*sysObjectID*/

		{{1,3,6,1,2,1,1,3},8, LEAF_sysUpTime,SNMP_TIMETICKS,MIB_READ},/*sysUpTime*/

		{{1,3,6,1,2,1,1,4},8, LEAF_sysContact,SNMP_OCTETSTR,MIB_READ|MIB_WRITE},/*sysContact*/

		{{1,3,6,1,2,1,1,5},8, LEAF_sysName,SNMP_OCTETSTR,MIB_READ|MIB_WRITE},/*sysName*/

		{{1,3,6,1,2,1,1,6},8, LEAF_sysLocation,SNMP_OCTETSTR,MIB_READ|MIB_WRITE},/*sysLocation*/

		{{1,3,6,1,2,1,1,7},8, LEAF_sysServices,SNMP_INTEGER,MIB_READ},/*sysServices*/

		{{1,3,6,1,2,1,1,8},8, LEAF_sysORLastChange,SNMP_TIMETICKS,MIB_READ},/*sysORLastChange*/

/* Following belongs to snmp group*/

		{{1,3,6,1,2,1,11,1},8, LEAF_snmpInPkts,SNMP_OCTETSTR,MIB_READ},/*snmpInPkts*/

		{{1,3,6,1,2,1,11,3},8, LEAF_snmpInBadVersions,SNMP_COUNTER,MIB_READ},/*snmpInBadVersions*/

		{{1,3,6,1,2,1,11,4},8, LEAF_snmpInBadCommunityNames,SNMP_COUNTER,MIB_READ},/*snmpInBadCommunityNames*/

		{{1,3,6,1,2,1,11,5},8, LEAF_snmpInBadCommunityUses,SNMP_COUNTER,MIB_READ},/*snmpInBadCommunityUses*/

		{{1,3,6,1,2,1,11,6},8, LEAF_snmpInASNParseErrs,SNMP_COUNTER,MIB_READ},/*snmpInASNParseErrs*/

		{{1,3,6,1,2,1,11,6},8, LEAF_snmpEnableAuthenTraps,SNMP_INTEGER,MIB_READ},/*snmpEnableAuthenTraps*/

/* Following from Trap group*/

		{{1,3,6,1,6,3,1,1,4,1},10, LEAF_snmpTrapOID,SNMP_OBJECTID,MIB_READ},/*snmpTrapOID*/


		{{1,3,6,1,6,3,1,1,4,3},10, LEAF_snmpTrapEnterprise,SNMP_OBJECTID,MIB_READ},/*snmpTrapEnterprise*/

/* Following from Traps group*/

		{{1,3,6,1,6,3,1,1,5,1},10, 0,SNMP_NULL,MIB_READ},/*coldStart*/

		{{1,3,6,1,6,3,1,1,5,2},10, 0,SNMP_NULL,MIB_READ},/*warmStart*/

		{{1,3,6,1,6,3,1,1,5,3},10, 0,SNMP_NULL,MIB_READ},/*linkDown*/

		{{1,3,6,1,6,3,1,1,5,4},10, 0,SNMP_NULL,MIB_READ},/*linkUp*/

		{{1,3,6,1,6,3,1,1,5,5},10, 0,SNMP_NULL,MIB_READ},/*authenticationFailure*/

		{{1,3,6,1,6,3,1,1,5,6},10, 0,SNMP_NULL,MIB_READ},/*egpNeighorLoss*/

/* Following from privite tree*/

		{{1,3,6,1,2,4,1,5326,5,1,1},11, LEAF_txfxDevSoftwareVersion,SNMP_INTEGER,MIB_READ},/*txfxDevSoftwareVersion*/
	
		{{1,3,6,1,2,4,1,5326,5,1,2},11, LEAF_txfxDeviceType,SNMP_INTEGER,MIB_READ},/*txfxDeviceType*/

		{{1,3,6,1,2,4,1,5326,5,1,3},11, LEAF_txfxDeviceHardwareVersion,SNMP_INTEGER,MIB_READ},/*txfxDeviceHardwareVersion*/

		{{1,3,6,1,2,4,1,5326,5,1,4},11, LEAF_txfxDeviceModuleNum,SNMP_INTEGER,MIB_READ},/*txfxDeviceModuleNum*/

/* the following is a tablur vars*/
		{{1,3,6,1,2,4,1,5326,5,1,5,1},13, LEAF_txfxModuleType,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleType*/

		{{1,3,6,1,2,4,1,5326,5,1,5,2,0},13, LEAF_txfxModuleTimeElapsed,SNMP_TIMETICKS,MIB_READ},/*LEAF_txfxModuleTimeElapsed*/

		{{1,3,6,1,2,4,1,5326,5,1,5,3,0},13, LEAF_txfxModuleAdminStatus,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleAdminStatus*/

		{{1,3,6,1,2,4,1,5326,5,1,5,4,0},13, LEAF_txfxModuleHardwareVer,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleHardwareVer*/

		{{1,3,6,1,2,4,1,5326,5,1,5,5,0},13, LEAF_txfxModuleSlot,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleSlot*/

		{{1,3,6,1,2,4,1,5326,5,1,5,6,0},13, LEAF_txfxModuleOpertionalStatus,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleOpertionalStatus*/

		{{1,3,6,1,2,4,1,5326,5,1,5,7,0},13, LEAF_txfxModuleOnOff,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleOnOff*/

		{{1,3,6,1,2,4,1,5326,5,1,5,8,0},13, LEAF_txfxModuleCapacity,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleCapacity*/

		{{1,3,6,1,2,4,1,5326,5,1,5,9,0},13, LEAF_txfxModuleLinkAlt,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleLinkAlt*/

		{{1,3,6,1,2,4,1,5326,5,1,5,10,0},13, LEAF_txfxModuleTxMode,SNMP_INTEGER,MIB_READ},/*LEAF_txfxModuleTxMode*/

		{{1,3,6,1,2,4,1,5326,5,1,5,11,0},13, LEAF_txfxModuleState,SNMP_INTEGER,MIB_READ}/*LEAF_txfxModuleState*/
};

extern xdata system_t system;
extern xdata txfxDevice_t txfxDevice;
extern xdata txfxModule_t modules[16];

xdata u8 oldSysDescr[SNMP_SIZE_BUFCHR];
xdata u8 oldSysContact[SNMP_SIZE_BUFCHR];
xdata u8 oldSysName[SNMP_SIZE_BUFCHR];
xdata u8 oldSysLocation[SNMP_SIZE_BUFCHR];

/* forward declarations */

LOCAL i32  MibCmpObjId(ul32 * ObjId, u16 ObjIdLen1, ul32 * ObjId2, u16 ObjIdLen2);
LOCAL i32  MibObjectFind(ul32 * Id, i32 IdLen, i32 * cmp);
LOCAL u16  setupIdbCall(u32 object, snmp_object_t * Obj, u16 IdLen, u32 type);
LOCAL u16  Request(snmp_object_t * Obj, i32 * lastindex);
LOCAL u16 idbDispatch(idb_t* idbBuf);

/*******************************************************************************
*
* MibRequest - Calls Request(arg1, arg2) to process SNMP request 
*
* DESCRIPTION
* MibRequest is called by Request(5 args) in agent.c and other trap
* routines to process an SNMP request.
* 
* This routine calls SET/COMMIT/UNDO in that order depending on
* the success/failure of the SET/COMMIT.
*
* MibRequest allows for different requests per varbind list 
*
* RETURNS
*  
* NOMANUAL
*/

u16 MibRequest
    (
    u32             listLen, 
    snmp_object_t * list, 
    u16 *           errindex
    )
{
	u16 status, mindex, errstatus;
	LOCAL snmp_object_t MibRequestbackup[AGENT_LIST_SIZE];
	LOCAL i32 MibRequestlastindex[AGENT_LIST_SIZE];

	for (mindex = 0; mindex < AGENT_LIST_SIZE; mindex++)
		MibRequestlastindex[mindex] = 0;

	for (mindex = 0, status = SNMP_NOERROR;
		 mindex < listLen && status == SNMP_NOERROR;
		 mindex++)
	{
		if (list[mindex].Request != SNMP_PDU_SET)
		{
			MibRequestbackup[mindex] = list[mindex];
		}
		else
		{						/* prevent backup later on */
			MibRequestbackup[mindex].Request = SNMP_PDU_SET;
		}
		status = Request(list + mindex, MibRequestlastindex+mindex);
	}
	errstatus = status;
	*errindex = mindex;

	/*
	 * if it's a set, then go through list a second time and actually
	 * do the set, if there were no errors the first time
	 */
	if (errstatus == SNMP_NOERROR)
	{
		for (mindex = 0, status = SNMP_NOERROR;
			 mindex < listLen && status == SNMP_NOERROR;
			 mindex++)
		{
			if (list[mindex].Request == SNMP_PDU_SET)
			{
				list[mindex].Request = SNMP_PDU_COMMIT;
				status = Request(list + mindex, MibRequestlastindex + mindex);
			}
		}
		errstatus = status;
		*errindex = mindex;
	}

	if (errstatus != SNMP_NOERROR)
	{
		/*
		 * count the errors by types for reporting snmp group errors
		 */
		switch (errstatus)
		{
		case SNMP_NOSUCHNAME:
			SnmpStat.OutNoSuchNames++;
			break;
		case SNMP_BADVALUE:
			SnmpStat.OutBadValues++;
			break;
		case SNMP_READONLY:
			break;
		case SNMP_GENERROR:
			SnmpStat.OutGenErrs++;
			break;
		default:
			break;
		}
		for (mindex = 0, status = SNMP_NOERROR;
			 mindex < *errindex && status == SNMP_NOERROR;
			 mindex++)
		{
			/*
			 * if a set was attempted, this can undo those sets when a set
			 * fails
			 */
			if (list[mindex].Request == SNMP_PDU_SET ||
				list[mindex].Request == SNMP_PDU_COMMIT)
			{
				list[mindex].Request = SNMP_PDU_UNDO;
				status = Request(list + mindex, MibRequestlastindex + mindex);
			}
			else
			{
				list[mindex] = MibRequestbackup[mindex];
			}
		}
	}

	return errstatus;
}

/*******************************************************************************
*
* Request - Calls setupIdbCall() if it finds MIB object in local MIB tree
*
* DESCRIPTION
* Request calls setupIdbCall() to communicate with IDB to process the
* SNMP request for a particualr MIB object. This routine maps the SNMP
* request into an IDB request.
*
* Request is called by MibRequest in mib.c
*
* RETURNS
*  
* NOMANUAL
*/

LOCAL u16 Request
    (
    snmp_object_t * Obj, 
    i32 *           lastindex
    )
{
	i32 mindex, cmp;
	u16 error;

	if (MibRoot == NULL)
	{
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 1");
#endif

		return SNMP_GENERROR;
	}

	error = SNMP_NOSUCHNAME;
	
	cmp = MibCmpObjId(MibRoot[Table[*lastindex]].Id,
					  MibRoot[Table[*lastindex]].IdLen,
					  Obj->Id,
					  (u16) Obj->IdLen);
	if (cmp == -2
		&& Obj->Request == SNMP_PDU_NEXT
		&& ++(*lastindex) < Mib_Count)
	{
		cmp = MibCmpObjId(MibRoot[Table[*lastindex]].Id,
						  MibRoot[Table[*lastindex]].IdLen,
						  Obj->Id,
						  (u16) Obj->IdLen);
	}

	if (cmp == -1)
	{
		mindex = *lastindex;
	}
	else
	{
		mindex = *lastindex = MibObjectFind(Obj->Id,
											(i32) Obj->IdLen,
											&cmp);
	}
	
	switch (Obj->Request)
	{

	case SNMP_PDU_GET:

		if (cmp!=-1|| MibRoot[Table[mindex]].Rqs == 0)
		{
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 2");
#endif

			return error;
			
		}

		if (!(MibRoot[Table[mindex]].Support & MIB_READ))
		{
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 3");
#endif

			return error;
		}

		error = setupIdbCall(MibRoot[Table[mindex]].Rqs,
							 Obj,
							 MibRoot[Table[mindex]].IdLen,
							 MibRoot[Table[mindex]].Type);

		if (error == SNMP_NOERROR)
		{
			Obj->Type = MibRoot[Table[mindex]].Type;
		}

#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 4");
#endif

		return error;

	case SNMP_PDU_SET:

		if (cmp != -1 || MibRoot[Table[mindex]].Rqs == 0)
		{
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 5");
#endif

			return error;
		}

		if (!(MibRoot[Table[mindex]].Support & MIB_WRITE))
		{
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 6");
#endif

			return SNMP_READONLY;
		}

		if (Obj->Type == SNMP_OBJECTID
			&& Obj->SyntaxLen > SNMP_SIZE_BUFINT)
		{
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 7");
#endif

			return SNMP_BADVALUE;
		}

		if ((Obj->Type == SNMP_OCTETSTR
			 || Obj->Type == SNMP_DISPLAYSTR
			 || Obj->Type == SNMP_OPAQUE)
			&& (Obj->SyntaxLen > SNMP_SIZE_BUFCHR))
		{
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 8");
#endif

			return SNMP_BADVALUE;
		}


		error = setupIdbCall(MibRoot[Table[mindex]].Rqs,
							 Obj,
							 MibRoot[Table[mindex]].IdLen,
							 MibRoot[Table[mindex]].Type);
		return error;

	case SNMP_PDU_NEXT:

		switch (cmp)
		{

		case -2:
			return error;

		case -1:
		case 0:
			if (MibRoot[Table[mindex]].Support & MIB_READ &&
				MibRoot[Table[mindex]].Rqs != 0)
			{


				error = setupIdbCall(MibRoot[Table[mindex]].Rqs,
									 Obj,
									 MibRoot[Table[mindex]].IdLen,
									 MibRoot[Table[mindex]].Type);
				if (error == SNMP_NOERROR)
				{
					Obj->Type = MibRoot[Table[mindex]].Type;
					break;
				}
			}

			mindex++;
			break;

		default:
			break;
		}

		while (error == SNMP_NOSUCHNAME && mindex < (sizeof(MibRoot)/sizeof(mib_object_t)))
		{
			memcpy(Obj->Id,
				   MibRoot[Table[mindex]].Id,
				   MibRoot[Table[mindex]].IdLen * sizeof(l32));

			Obj->IdLen = MibRoot[Table[mindex]].IdLen;

			if (MibRoot[Table[mindex]].Support & MIB_READ
				&& MibRoot[Table[mindex]].Rqs != 0)
			{
	
				error = setupIdbCall(MibRoot[Table[mindex]].Rqs,
									 Obj,
									 MibRoot[Table[mindex]].IdLen,
									 MibRoot[Table[mindex]].Type);
				if (error == SNMP_NOERROR)
				{
					Obj->Type = MibRoot[Table[mindex]].Type;
					break;
				}
			}

			mindex++;
		}

		return error;

	case SNMP_PDU_COMMIT:
	case SNMP_PDU_UNDO:

		if (cmp != -1 || MibRoot[Table[mindex]].Rqs == 0)
		{
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 9");
#endif
			return error;
		}


		error = setupIdbCall(MibRoot[Table[mindex]].Rqs,
							 Obj,
							 MibRoot[Table[mindex]].IdLen,
							 MibRoot[Table[mindex]].Type);
#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 10");
#endif
	
		return error;

	default:
		break;

	}

#ifdef SNMP_DEBUG
		PrintStr("\r\n leaving mib request module 11");
#endif

	return SNMP_GENERROR;
}


/*******************************************************************************
*
* MibCmpObjId - Used to compare if 2 OIDs match
*
* DESCRIPTION
*
* RETURNS
*  
* NOMANUAL
*/

i32 MibCmpObjId
    (
    ul32 * ObjId1, 
    u16    ObjIdLen1, 
    ul32 * ObjId2, 
    u16    ObjIdLen2
    )
{
	while (ObjIdLen1 > 0 && ObjIdLen2 > 0 && *ObjId1 == *ObjId2)
	{
		ObjIdLen1--;
		ObjIdLen2--;
		ObjId1++;
		ObjId2++;
	}
	if (!ObjIdLen1 && !ObjIdLen2)
	{
		return 0;
	}
	if (!ObjIdLen1)
	{
		return -1;
	}
	if (!ObjIdLen2)
	{
		return 1;
	}
	if (*ObjId1 < *ObjId2)
	{
		return -2;
	}
	else
	{
		return 2;
	}
}

/*******************************************************************************
*
* MibObjectFind - Used to find OIDs in internal MIB tree
*
* DESCRIPTION
*
* RETURNS
*  
* NOMANUAL
*/

i32 MibObjectFind
    (
    ul32 * Id, 
    i32    IdLen, 
    i32 *  cmp
    )
{
	i32 first, last, mindex;

	first = 0;
	last = Mib_Count - 1;
	*cmp = 2;

	if (last < 0)
	{
		return 0;
	}

	while (first < last)
	{
		mindex = (first + last) / 2;
		*cmp = MibCmpObjId(MibRoot[Table[mindex]].Id,
						   MibRoot[Table[mindex]].IdLen, Id, (u16) IdLen);
		switch (*cmp)
		{
		case -2:
			first = mindex + 1;
			break;
		case -1:
		case 0:
			first = last = mindex;
			return mindex;
		case 1:
		case 2:
			last = mindex;
			break;
		default:
			break;
		}
	}

	mindex = first;

		*cmp = MibCmpObjId(MibRoot[Table[mindex]].Id,
						   MibRoot[Table[mindex]].IdLen, Id, (u16) IdLen);

	return mindex;
}

/*******************************************************************************
*
* MibObjectInit - Used to init MIB objects into agent's internal MIB tree
*
* DESCRIPTION
*
* RETURNS
*  
* NOMANUAL
*/

void MibObjectInit()
{
	i32 mindex, cmp, i,j;
	Mib_Count =0;

	if (Mib_Count >= XSNMP_TOTAL_OBJECTS)
	{
		return;	
	}
	for(i=0;i< sizeof(MibRoot)/sizeof(mib_object_t); i++)
	{
		Table[Mib_Count++]=i;
		mindex = MibObjectFind(MibRoot[i].Id, MibRoot[i].IdLen,&cmp);
		if (cmp == -1 && mindex != Mib_Count - 1)
		{
			Mib_Count--;
			continue;
		}

		for (j = Mib_Count - 1; j > mindex; j--)
		Table[j] = Table[j - 1];
		Table[mindex] = i;
	}
		return;
}


/*******************************************************************************
*
* setupIdbCall - Interface routine to communicate with IDB
*
* DESCRIPTION
* This routine is the interface routine between SNMP and IDB. This routine sets
* up the idb_t structure and calls idbDispatch() to get to the relevant module.
* Upon return from IDB, this routine gets the needed information from the 
* idb_t structure and uses it for responding back to the SNMP request.
*
* RETURNS
*  
* NOMANUAL
*/

u16 setupIdbCall
    (
    u32             object, 	
    snmp_object_t * Obj, 
    u16             IdLen, 
    u32             type
    )
{
	idb_t idbBuf;
	u32 i;
	u32 indexBuf[32];
	u16 retval;


	if ((Obj->Type != SNMP_NULL) && (Obj->Type != type) && (Obj->Request == SNMP_PDU_SET))
		return SNMP_BADVALUE;

	idbBuf.object = object;	      //指向内部定义的对象类型。
	idbBuf.request = Obj->Request;
	idbBuf.indexLength = Obj->IdLen - IdLen;

    if ((idbBuf.request == SNMP_PDU_GET) || (idbBuf.request == SNMP_PDU_NEXT))
        Obj->SyntaxLen = 0;

	for (i = 0; i < idbBuf.indexLength; i++)
	{
		indexBuf[i] = Obj->Id[IdLen + i];
	}

	idbBuf.index = &(indexBuf[0]);	  //保存表结构中的子项。

	switch (type)
	{

	case SNMP_NULL:
	case SNMP_COUNTER:
	case SNMP_GAUGE:
	case SNMP_TIMETICKS:
		idbBuf.value.LngUns = Obj->Syntax.LngUns;
		idbBuf.valueLength = 4;
		break;

	case SNMP_INTEGER:
		idbBuf.value.LngInt = Obj->Syntax.LngInt;
		idbBuf.valueLength = 4;
		break;

	case SNMP_OBJECTID:
		memcpy(idbBuf.value.BufChr, Obj->Syntax.BufChr,sizeof(Obj->Syntax.BufChr));
		//idbBuf.value.BufChr = &(Obj->Syntax.BufChr[0]);
		idbBuf.valueLength = 128;

		break;
	case SNMP_IPADDR:
		memcpy(idbBuf.value.BufChr, Obj->Syntax.BufChr,sizeof(Obj->Syntax.BufChr));
	//	idbBuf.value.BufChr = &(Obj->Syntax.BufChr[0]);
		idbBuf.valueLength = 256;

		break;

	case SNMP_OPAQUE:
	case SNMP_OCTETSTR:
		memcpy(idbBuf.value.BufChr, Obj->Syntax.BufChr,sizeof(Obj->Syntax.BufChr));	
	//idbBuf.value.BufChr = &(Obj->Syntax.BufChr[0]);
		if (((idbBuf.request == SNMP_PDU_SET) ||
			 (idbBuf.request == SNMP_PDU_UNDO) ||
			 (idbBuf.request == SNMP_PDU_COMMIT)) &&
			(Obj->SyntaxLen >= 0))
			idbBuf.valueLength = Obj->SyntaxLen;
		else
			idbBuf.valueLength = 256;

		break;

	default:
		return SNMP_GENERROR;
	}

	if (Obj->SyntaxLen > 0)
		idbBuf.valueLength = Obj->SyntaxLen;

	retval = idbDispatch(&idbBuf);			     //  调用接口。

	Obj->SyntaxLen = idbBuf.valueLength;
	Obj->IdLen += (idbBuf.indexLength - (Obj->IdLen - IdLen));

	for (i = 0; i < idbBuf.indexLength; i++)
	{
		Obj->Id[IdLen + i] = indexBuf[i];
	}

	switch (type)
	{

	case SNMP_NULL:

	case SNMP_COUNTER:
	case SNMP_GAUGE:
	case SNMP_TIMETICKS:
		Obj->Syntax.LngUns = idbBuf.value.LngUns;
		break;

	case SNMP_INTEGER:
		Obj->Syntax.LngInt = idbBuf.value.LngInt;
		break;


	case SNMP_IPADDR:
	case SNMP_OCTETSTR:
	case SNMP_OBJECTID:
	case SNMP_OPAQUE:
		break;

	default:
		return SNMP_GENERROR;
	}

	if ((Obj->Type != type) && (Obj->Request == SNMP_PDU_GET))
        Obj->Type = type;
	return (idbBuf.snmpReturnCode);
}

u16 idbDispatch(idb_t* idbBuf)
{
	u16 error;
	u32 object;
	u16 index;
	object = idbBuf->object;

	if(idbBuf->indexLength>1)
	{
		if(idbBuf->indexLength!=3)
			return SNMP_NOSUCHNAME;
		index = idbBuf->index[0];
		//在MibRoot中查找该数据的子项。获得新的object参数。
	}

	if(idbBuf->request == SNMP_PDU_GET||SNMP_PDU_NEXT)
	{
		switch(object)
		{
			// system group member.
			case LEAF_sysDescr:
				memcpy(idbBuf->value.BufChr, system.sysDescr, sizeof(system.sysDescr));
				idbBuf->valueLength = sizeof(system.sysDescr);	
				idbBuf->snmpReturnCode = SNMP_NOERROR;
#ifdef SNMP_DEBUG
				PrintStr("\r\nrun in sysDescr section");
#endif
				return SNMP_NOERROR;
			case LEAF_sysObjectID:
				memcpy(idbBuf->value.BufChr, system.sysObjectID, sizeof(system.sysObjectID));
				idbBuf->valueLength= sizeof(system.sysDescr);	
				idbBuf->snmpReturnCode = SNMP_NOERROR;
#ifdef SNMP_DEBUG
				PrintStr("\r\nrun in sysObjectId section");
#endif				
				return SNMP_NOERROR;
			case LEAF_sysUpTime:
				idbBuf->value.LngUns = system.sysUpTime;
				idbBuf->snmpReturnCode = SNMP_NOERROR;
				return SNMP_NOERROR; 
			case LEAF_sysContact:
				memcpy(idbBuf->value.BufChr,system.sysContact, sizeof(system.sysContact));
				idbBuf->valueLength = sizeof(system.sysContact);	
				idbBuf->snmpReturnCode = SNMP_NOERROR;
				return SNMP_NOERROR; 
			case LEAF_sysName:
				memcpy(idbBuf->value.BufChr,system.sysContact, sizeof(system.sysContact));
				idbBuf->valueLength = sizeof(system.sysContact);	
				idbBuf->snmpReturnCode = SNMP_NOERROR;
				return SNMP_NOERROR; 
			case LEAF_sysLocation:
				memcpy(idbBuf->value.BufChr,system.sysLocation, sizeof(system.sysLocation));
				idbBuf->valueLength = sizeof(system.sysContact);	
				idbBuf->snmpReturnCode = SNMP_NOERROR;
				return SNMP_NOERROR; 

			case LEAF_sysServices:
				memcpy(idbBuf->value.BufChr,system.sysContact, sizeof(system.sysContact));
				idbBuf->valueLength = sizeof(system.sysContact);	
				idbBuf->snmpReturnCode = SNMP_NOERROR;
				return SNMP_NOERROR; 

			case LEAF_sysORLastChange:
				memcpy(idbBuf->value.BufChr,system.sysContact, sizeof(system.sysContact));
				idbBuf->valueLength = sizeof(system.sysContact);	
				idbBuf->snmpReturnCode = SNMP_NOERROR;
				return SNMP_NOERROR; 

// snmp group member.

			case LEAF_snmpInPkts:
			idbBuf->value.LngInt = SnmpStat.InPkts; 
			break;
			case LEAF_snmpOutPkts:
			idbBuf->value.LngInt = SnmpStat.OutPkts;
			break;
			case LEAF_snmpInBadVersions:
			idbBuf->value.LngInt = SnmpStat.InBadVersions;
			break;

			case LEAF_snmpInBadCommunityNames:
			idbBuf->value.LngInt = 0;
			break;

			case LEAF_snmpInBadCommunityUses:
			idbBuf->value.LngInt = SnmpStat.snmpInBadCommunityUses;
			break;
			case LEAF_snmpInASNParseErrs:
			idbBuf->value.LngInt = SnmpStat.InASNParseErrs;
			break;
			case LEAF_snmpInTooBigs:
			idbBuf->value.LngInt = SnmpStat.InTooBigs;
			break;

			
			case LEAF_snmpInNoSuchNames:
			idbBuf->value.LngInt = SnmpStat.InNoSuchNames;
			break;

			case LEAF_snmpInBadValues:
			idbBuf->value.LngInt = SnmpStat.InBadValues;
			break;

			case LEAF_snmpInReadOnlys:

			idbBuf->value.LngInt = SnmpStat.InReadOnlys;
			break;
			case LEAF_snmpInGenErrs:
			idbBuf->value.LngInt = SnmpStat.InGenErrs;
			break;

			case LEAF_snmpInTotalReqVars:
			idbBuf->value.LngInt = 0;
			break;
			case LEAF_snmpInTotalSetVars:
			idbBuf->value.LngInt = 0;
			break;
			case LEAF_snmpInGetRequests:
			idbBuf->value.LngInt = SnmpStat.InGetRequests;
			break;
			case LEAF_snmpInGetNexts:
			idbBuf->value.LngInt = SnmpStat.InGetNexts;
			break;
			case LEAF_snmpInSetRequests:
			idbBuf->value.LngInt = SnmpStat.InSetRequests;
			break;
			case LEAF_snmpInGetResponses:
			idbBuf->value.LngInt = SnmpStat.InGetResponses;
			break;
			case LEAF_snmpInTraps:
			idbBuf->value.LngInt = SnmpStat.InTraps;
			break;
			case LEAF_snmpOutTooBigs:
			idbBuf->value.LngInt = SnmpStat.OutTooBigs;
			break;
			case LEAF_snmpOutNoSuchNames:
			idbBuf->value.LngInt = SnmpStat.OutNoSuchNames;
			break;
			case LEAF_snmpOutBadValues:
			idbBuf->value.LngInt = SnmpStat.OutBadValues;
			break;
			case LEAF_snmpOutGenErrs:
			idbBuf->value.LngInt = SnmpStat.OutGenErrs;
			break;
			case LEAF_snmpOutGetRequests:
			idbBuf->value.LngInt = SnmpStat.OutGetRequests;
			break;
			case LEAF_snmpOutGetNexts:
			idbBuf->value.LngInt = SnmpStat.OutGetNexts;
			break;
			case LEAF_snmpOutSetRequests:
			idbBuf->value.LngInt = SnmpStat.OutSetRequests;
			break;
			case LEAF_snmpOutGetResponses:
			idbBuf->value.LngInt = SnmpStat.OutGetResponses;
			break;
			case LEAF_snmpOutTraps:
			idbBuf->value.LngInt = SnmpStat.OutTraps;
			break;
			case LEAF_snmpEnableAuthenTraps:
			idbBuf->value.LngInt = SnmpStat.snmpEnableAuthenTraps;
			break;
			case LEAF_snmpSilentDrops:
			idbBuf->value.LngInt = SnmpStat.snmpSilentDrops;
			break;
			case LEAF_snmpProxyDrops:
			idbBuf->value.LngInt = SnmpStat.snmpProxyDrops;
			break;

		// txfxMib Memembers
			case LEAF_txfxDevSoftwareVersion:
			idbBuf->value.LngUns = txfxDevice.txfxDevSoftwareVersion;
			break;
			case LEAF_txfxDeviceType:
			idbBuf-> value.LngUns = txfxDevice.txfxDeviceType;
			break;
			case LEAF_txfxDeviceHardwareVersion:
			idbBuf-> value.LngUns = txfxDevice.txfxDeviceHardwareVersion;
			break;
			case LEAF_txfxDeviceModuleNum:
			idbBuf-> value.LngUns = txfxDevice.txfxDeviceModuleNum;
			break;

// entry to the txfxModuleTable	      
			case LEAF_txfxModuleType:
				idbBuf->value.LngUns = (l32)modules[index].txfxModuleType;
				idbBuf->valueLength = 4;
				idbBuf->snmpReturnCode = SNMP_NOERROR;
				break;
			case LEAF_txfxModuleTimeElapsed:
			case LEAF_txfxModuleAdminStatus:
			case LEAF_txfxModuleHardwareVer:
			case LEAF_txfxModuleSlot:
			case LEAF_txfxModuleOpertionalStatus:
			case LEAF_txfxModuleOnOff:
			case LEAF_txfxModuleCapacity:
			case LEAF_txfxModuleLinkAlt:
			case LEAF_txfxModuleTxMode:
			case LEAF_txfxModuleState:
			default:
				return SNMP_NOSUCHNAME;
		}
		idbBuf->snmpReturnCode = SNMP_NOERROR;
		return SNMP_NOERROR; 

	}

	else if(idbBuf->request == SNMP_PDU_SET)
	{
		switch(object)
		{
			// system group member.
			case LEAF_sysDescr:
				strcpy(oldSysDescr, system.sysDescr);
				memcpy(system.sysDescr, idbBuf->value.BufChr, idbBuf->valueLength);
				return SNMP_NOERROR;
			case LEAF_sysContact:
				strcpy(oldSysContact, system.sysContact);
				memcpy(system.sysContact, idbBuf->value.BufChr,idbBuf->valueLength);
				return SNMP_NOERROR;
			case LEAF_sysName:
				strcpy(oldSysName, system.sysName);
				memcpy(system.sysName, idbBuf->value.BufChr,idbBuf->valueLength);
				return SNMP_NOERROR;
			case LEAF_sysLocation:
				strcpy(oldSysLocation, system.sysLocation);
				memcpy(system.sysLocation, idbBuf->value.BufChr,idbBuf->valueLength);
				return SNMP_NOERROR;
				break;
			default:
				return SNMP_READONLY;
		}
	}
	else if(idbBuf->request==SNMP_PDU_COMMIT||SNMP_PDU_COMMIT)	
	{
		switch(object)
		{
			// system group member.
			case LEAF_sysDescr:
				if(idbBuf->request==SNMP_PDU_UNDO)
				{
					strcpy(system.sysDescr,oldSysDescr);
					memcpy(idbBuf->value.BufChr, system.sysDescr, sizeof(system.sysLocation));
					idbBuf->valueLength = sizeof(system.sysDescr);
				}
				break;
			case LEAF_sysContact:
				if(idbBuf->request==SNMP_PDU_UNDO)
				{
					strcpy(system.sysContact,oldSysContact);
					memcpy(idbBuf->value.BufChr, system.sysContact, sizeof(system.sysLocation));
					idbBuf->valueLength = sizeof(system.sysContact);
				}
				break;
			case LEAF_sysName:
				if(idbBuf->request==SNMP_PDU_UNDO)
				{
					strcpy(system.sysName,oldSysName);
					memcpy(idbBuf->value.BufChr, system.sysName, sizeof(system.sysName));
					idbBuf->valueLength = sizeof(system.sysName);
				}
				break;
			case LEAF_sysLocation:
				if(idbBuf->request==SNMP_PDU_UNDO)
				{
					strcpy(system.sysLocation,oldSysLocation);
					memcpy(idbBuf->value.BufChr, system.sysLocation, sizeof(system.sysLocation));
					idbBuf->valueLength = sizeof(system.sysLocation);
				}
				break;

			default:
				return SNMP_READONLY;
		}

	}

	return error;
}