www.pudn.com > Snmp.Agent.win32.zip > SnmpAgent.cpp


// MyAgent.cpp : Defines the entry point for the DLL application. 
// 
 
#include "stdafx.h" 
#include  
#include  
 
#define OID_SIZEOF( Oid )      ( sizeof Oid / sizeof(UINT) ) 
 
// template MIB entry 
struct MIB_ENTRY 
{ 
	AsnObjectIdentifier asnOid; 
	void *              pStorageValue; 
	CHAR *              szStorageName; 
	BYTE                chType; 
	UINT                unAccess; 
	MIB_ENTRY*			pMibNext; 
}; 
 
// this is the our branch starting point (clled prefix) 
UINT g_unMyOIDPrefix[]	= {1, 3, 6, 1, 4, 1, 15}; 
 
// this is the trap OID to send to client 
UINT g_TrapOid[]		= {1, 3, 6, 1, 4, 1, 15, 0}; 
 
AsnObjectIdentifier MIB_OidPrefix = { OID_SIZEOF(g_unMyOIDPrefix), g_unMyOIDPrefix}; 
 
DWORD g_dwStartTime = 0; 
HANDLE g_hSimulateTrap = NULL; 
HANDLE g_hTrapGenThread = NULL; 
unsigned long __stdcall TrapGenThread(void *lpVoid); 
 
int GetRequest(SnmpVarBind *pVarBind); 
int GetNextRequest(SnmpVarBind *pVarBind); 
int SetRequest(SnmpVarBind *pVarBind); 
 
UINT GetStoreVar(MIB_ENTRY* pMIB, AsnAny *pasnValue); 
UINT SetStoreVar(MIB_ENTRY* pMIB, AsnAny asnValue); 
 
 
/////////MIB Table //////////////////////////////////////////////// 
UINT g_unAboutOid[] = {0,0,1}; 
UINT g_unNameOid[] = {0,0,2}; 
UINT g_unAgeOid[] = {0,0,3}; 
 
char *g_szAbout = NULL; 
char *g_szName = NULL; 
AsnInteger g_asnIntAge = 0; 
 
/// This is the MIB table and its related variable store 
//    here evry thing is hard-coded to demonstration perpose 
//    Actualy it should be loaded from the registry or from some file 
MIB_ENTRY g_MyMibTable[] = { 
	{	 
		{OID_SIZEOF(g_unAboutOid),g_unAboutOid}, 
		&g_szAbout, 
		"About", 
		ASN_OCTETSTRING, 
		SNMP_ACCESS_READ_ONLY, 
		&g_MyMibTable[1] 
	}, 
	{ 
		{OID_SIZEOF(g_unNameOid),g_unNameOid}, 
		&g_szName, 
		"Name", 
		ASN_OCTETSTRING, 
		SNMP_ACCESS_READ_WRITE, 
		&g_MyMibTable[2] 
	}, 
	{ 
		{OID_SIZEOF(g_unAgeOid),g_unAgeOid}, 
		&g_asnIntAge, 
		"Age", 
		ASN_INTEGER, 
		SNMP_ACCESS_READ_WRITE, 
		NULL 
	} 
}; 
 
UINT g_unMyMibCount = (sizeof(g_MyMibTable) / sizeof(MIB_ENTRY)); 
/////////////////////////////////////////////////////////////////// 
 
BOOL APIENTRY DllMain( HANDLE hModule,DWORD  ul_reason_for_call, LPVOID lpReserved) 
{ 
	switch (ul_reason_for_call) 
	{ 
		case DLL_PROCESS_ATTACH: 
			break; 
		case DLL_THREAD_ATTACH: 
			break; 
		case DLL_THREAD_DETACH: 
			break; 
		case DLL_PROCESS_DETACH: 
			TerminateThread(g_hTrapGenThread,0); 
			CloseHandle(g_hTrapGenThread); 
			CloseHandle(g_hSimulateTrap); 
			break; 
    } 
    return TRUE; 
} 
 
// When exported funtion will be called during DLL loading and initialization 
BOOL SNMP_FUNC_TYPE SnmpExtensionInit(DWORD dwUptimeReference,HANDLE *phSubagentTrapEvent, AsnObjectIdentifier *pFirstSupportedRegion) 
{ 
	g_hSimulateTrap = CreateEvent(NULL, FALSE, FALSE, NULL); // creaet this event for the trap 
 
	*pFirstSupportedRegion = MIB_OidPrefix; 
	*phSubagentTrapEvent = g_hSimulateTrap; // by assigning it pass it to the SNMP service 
											// So when ever you set this event service will call  
											// SnmpExtensionTrap exported function 
	 
	// on loading the our SNMP DLL create the thread 
	g_hTrapGenThread = CreateThread(NULL,0,TrapGenThread,NULL,0,NULL); 
 
	// hard coded initialization 
	g_szAbout = (char*)malloc(sizeof(char)*64); 
	strcpy(g_szAbout,"Author : Ramanan.T"); 
	g_szName = (char*)malloc(sizeof(char)*64); 
	strcpy(g_szName,"Your Name"); 
	g_asnIntAge = 0; 
 
	g_dwStartTime = GetTickCount(); 
 
	return SNMPAPI_NOERROR; 
} 
 
// this export is to query the MIB table and fields 
BOOL SNMP_FUNC_TYPE SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, AsnInteger32 *pErrorStatus, AsnInteger32 *pErrorIndex) 
{ 
	int nRet = 0; 
	AsnObjectName; 
	 
	*pErrorStatus = SNMP_ERRORSTATUS_NOERROR; 
	*pErrorIndex = 0; 
 
	for(UINT i=0;ilen;i++) 
	{ 
		*pErrorStatus = SNMP_ERRORSTATUS_NOERROR; 
 
		// what type of request we are getting? 
		switch(bPduType) 
		{ 
		case SNMP_PDU_GET:// // gets the variable value passed variable in pVarBindList 
			*pErrorStatus = GetRequest(&pVarBindList->list[i]); 
			if(*pErrorStatus != SNMP_ERRORSTATUS_NOERROR) 
				*pErrorIndex++; 
			break; 
		case SNMP_PDU_GETNEXT: // gets the next variable related to the passed variable in pVarBindList 
			*pErrorStatus = GetNextRequest(&pVarBindList->list[i]); 
			if(*pErrorStatus != SNMP_ERRORSTATUS_NOERROR) 
				*pErrorIndex++; 
			break; 
		case SNMP_PDU_SET: // sets a variable 
			*pErrorStatus = SetRequest(&pVarBindList->list[i]); 
			if(*pErrorStatus != SNMP_ERRORSTATUS_NOERROR) 
				*pErrorIndex++; 
			break; 
		default: 
			*pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 
			*pErrorIndex++; 
		}; 
	}	 
 
	return SNMPAPI_NOERROR; 
} 
 
// this function just simulate traps 
//   Traps just a 2 variables value from MIB 
//  Trap is kind of event from server to client 
///         When ever the event is set service will call this function and gets the parameters filled. 
//       After filling the parameters service willsend the trap to all the client connected 
BOOL SNMP_FUNC_TYPE SnmpExtensionTrap(AsnObjectIdentifier *pEnterpriseOid, AsnInteger32 *pGenericTrapId, AsnInteger32 *pSpecificTrapId, AsnTimeticks *pTimeStamp, SnmpVarBindList *pVarBindList) 
{ 
	static int nNoOfTraps = 1; // just ignore this, I introduced this to send meny traps at once 
								// any way below we are generating one trap with two values 
 
	if(nNoOfTraps) // if it is zero don't send traps 
	{ 
		pEnterpriseOid->idLength = sizeof(g_TrapOid); 
		pEnterpriseOid->ids = g_TrapOid; 
 
		*pGenericTrapId		= SNMP_GENERICTRAP_ENTERSPECIFIC; 
		*pSpecificTrapId	= 1;   // ToasterControl Up trap. 
		*pTimeStamp			= GetTickCount() - g_dwStartTime; 
 
		// Allocate space for the Variable Bindings. 
		pVarBindList->list = (SnmpVarBind*)SnmpUtilMemAlloc(2*sizeof(SnmpVarBind)); 
 
		SnmpUtilOidCpy(&pVarBindList->list[0].name,&MIB_OidPrefix); 
		SnmpUtilOidAppend(&pVarBindList->list[0].name,&g_MyMibTable[1].asnOid); 
		pVarBindList->list[0].value.asnType = ASN_OCTETSTRING; 
		pVarBindList->list[0].value.asnValue.string.dynamic = TRUE; 
		pVarBindList->list[0].value.asnValue.string.length = strlen(*(LPSTR*)g_MyMibTable[1].pStorageValue); 
		pVarBindList->list[0].value.asnValue.string.stream =(unsigned char*)SnmpUtilMemAlloc(pVarBindList->list[0].value.asnValue.string.length * sizeof(char)); 
		memcpy(pVarBindList->list[0].value.asnValue.string.stream,*(LPSTR*)g_MyMibTable[1].pStorageValue,pVarBindList->list[0].value.asnValue.string.length); 
				 
		SnmpUtilOidCpy(&pVarBindList->list[1].name,&MIB_OidPrefix); 
		SnmpUtilOidAppend(&pVarBindList->list[1].name,&g_MyMibTable[2].asnOid); 
		pVarBindList->list[1].value.asnType = ASN_INTEGER; 
		pVarBindList->list[1].value.asnValue.number = *((AsnInteger32*)g_MyMibTable[2].pStorageValue); 
 
		pVarBindList->len = 2; 
 
		nNoOfTraps--; 
		// Indicate that valid trap data exists in the parameters. 
		return TRUE; 
	} 
	nNoOfTraps = 1; 
	// Indicate that no more traps are available, and parameters do not refer to any valid data 
	return FALSE; 
} 
 
// get the value of the variable pased 
int GetRequest(SnmpVarBind *pVarBind) 
{ 
	int nRet = SNMP_ERRORSTATUS_NOSUCHNAME; 
	AsnObjectIdentifier  asnOidTemp; 
 
	for(UINT i=0;iname) ==0) 
		{ 
			SnmpUtilOidFree(&asnOidTemp); 
 
			nRet = GetStoreVar(&g_MyMibTable[i],&pVarBind->value); 
			break; 
		} 
		SnmpUtilOidFree(&asnOidTemp); 
	} 
	return nRet; 
} 
 
// get the next variable & value related to the passed variable 
int GetNextRequest(SnmpVarBind *pVarBind) 
{ 
	int nRet = SNMP_ERRORSTATUS_NOSUCHNAME; 
	int nResult = 0; 
	AsnObjectIdentifier  asnOidTemp; 
 
	for(UINT i=0;iname); 
		if(nResult >0) 
		{ 
			SnmpUtilOidFree(&pVarBind->name); 
 
			// kind of memcpy 
			SnmpUtilOidCpy(&pVarBind->name, &asnOidTemp); 
 
			nRet = GetStoreVar(&g_MyMibTable[i],&pVarBind->value); 
			SnmpUtilOidFree(&asnOidTemp); 
			nRet = SNMP_ERRORSTATUS_NOERROR; 
			break; 
		} 
		else if(nResult == 0) 
		{ 
			SnmpUtilOidFree(&asnOidTemp); 
			if(g_MyMibTable[i].pMibNext == NULL) 
				break; 
			// king of mem free 
			SnmpUtilOidFree(&pVarBind->name);			 
 
			// kind of memcpy :) 
			SnmpUtilOidCpy(&pVarBind->name, &MIB_OidPrefix); 
 
			// kind of strcat 
			SnmpUtilOidAppend(&pVarBind->name, &g_MyMibTable[i].pMibNext->asnOid); 
 
			nRet = GetStoreVar(g_MyMibTable[i].pMibNext,&pVarBind->value); 
			break; 
		} 
		SnmpUtilOidFree(&asnOidTemp); 
	} 
	return nRet; 
} 
 
// if it is a writable variable passed value will be copied to it 
int SetRequest(SnmpVarBind *pVarBind) 
{ 
	int nRet = SNMP_ERRORSTATUS_NOSUCHNAME; 
	AsnObjectIdentifier  asnOidTemp; 
 
	for(UINT i=0;iname) ==0) 
		{ 
			// kind of SNMP 'free' 
			SnmpUtilOidFree(&asnOidTemp); 
			nRet = SetStoreVar(&g_MyMibTable[i],pVarBind->value); 
			break; 
		} 
		SnmpUtilOidFree(&asnOidTemp); 
	} 
	return nRet; 
} 
 
// retrieves the value from the MIB table 
//  Imagine AsnAny is like VARIANT structure to populate that you need to go through the types 
UINT GetStoreVar(MIB_ENTRY* pMIB, AsnAny *pasnValue) 
{ 
	// check rights is there to access 
	if((pMIB->unAccess != SNMP_ACCESS_READ_ONLY)&&(pMIB->unAccess != SNMP_ACCESS_READ_WRITE)&&(pMIB->unAccess != SNMP_ACCESS_READ_CREATE)) 
		return SNMP_ERRORSTATUS_GENERR; 
 
	// set the type 
	pasnValue->asnType = pMIB->chType; 
	 
	switch(pasnValue->asnType) 
	{ 
	case ASN_INTEGER: 
		pasnValue->asnValue.number = *(AsnInteger32*)pMIB->pStorageValue; 
		break; 
	case ASN_COUNTER32: 
	case ASN_GAUGE32: 
	case ASN_TIMETICKS: 
	case ASN_UNSIGNED32: 
		pasnValue->asnValue.unsigned32 = *(AsnUnsigned32*)pMIB->pStorageValue; 
		break; 
	case ASN_OCTETSTRING: 
		pasnValue->asnValue.string.length = strlen(*(LPSTR*)pMIB->pStorageValue); 
		pasnValue->asnValue.string.stream =(unsigned char*)SnmpUtilMemAlloc(pasnValue->asnValue.string.length * sizeof(char)); 
 
		memcpy(pasnValue->asnValue.string.stream,*(LPSTR*)pMIB->pStorageValue,pasnValue->asnValue.string.length); 
		pasnValue->asnValue.string.dynamic = TRUE; 
		break; 
	case ASN_COUNTER64: 
		pasnValue->asnValue.counter64 = *(AsnCounter64*)pMIB->pStorageValue; 
		break; 
	case ASN_OBJECTIDENTIFIER: 
		SnmpUtilOidCpy(&pasnValue->asnValue.object,(AsnObjectIdentifier*)pMIB->pStorageValue); 
		break; 
	case ASN_IPADDRESS: 
		pasnValue->asnValue.address.length = 4; 
		pasnValue->asnValue.string.dynamic = TRUE; 
 
		pasnValue->asnValue.address.stream[0] = ((char*)pMIB->pStorageValue)[0]; 
		pasnValue->asnValue.address.stream[1] = ((char*)pMIB->pStorageValue)[1]; 
		pasnValue->asnValue.address.stream[2] = ((char*)pMIB->pStorageValue)[2]; 
		pasnValue->asnValue.address.stream[3] = ((char*)pMIB->pStorageValue)[3]; 
		break; 
	case ASN_OPAQUE: 
		AsnSequence; 
		break; 
	case ASN_BITS: 
		break;	 
	case ASN_SEQUENCE: 
		break;	 
	case ASN_NULL: 
	default: 
		return SNMP_ERRORSTATUS_GENERR;	 
	} 
	return SNMP_ERRORSTATUS_NOERROR; 
} 
 
// to store the value to the MIB table 
//  Imagine AsnAny is like VARIANT structure to populate that you need to go through the types 
UINT SetStoreVar(MIB_ENTRY* pMIB, AsnAny asnValue) 
{ 
	// check whether rights is there to access 
	if((pMIB->unAccess != SNMP_ACCESS_READ_WRITE)&&(pMIB->unAccess != SNMP_ACCESS_READ_CREATE)) 
		return SNMP_ERRORSTATUS_READONLY; 
 
	// check type matches with the table type 
	if(pMIB->chType != asnValue.asnType) 
		return SNMP_ERRORSTATUS_BADVALUE; 
 
	switch(asnValue.asnType) 
	{ 
	case ASN_INTEGER: 
		*(AsnInteger *)(pMIB->pStorageValue) = asnValue.asnValue.number; 
		break; 
	case ASN_COUNTER32: 
	case ASN_GAUGE32: 
	case ASN_TIMETICKS: 
	case ASN_UNSIGNED32: 
		*(AsnInteger *)(pMIB->pStorageValue) = asnValue.asnValue.unsigned32; 
		break; 
	case ASN_OCTETSTRING: 
		free(*(LPSTR*)(pMIB->pStorageValue)); 
		*(LPSTR*)(pMIB->pStorageValue) = (LPSTR)malloc((asnValue.asnValue.string.length+1) * sizeof(char)); 
		memcpy(*(LPSTR*)(pMIB->pStorageValue), asnValue.asnValue.string.stream,asnValue.asnValue.string.length); 
		(*(LPSTR*)pMIB->pStorageValue)[asnValue.asnValue.string.length] = '\0'; 
		break; 
	case ASN_COUNTER64: 
		*(AsnCounter64*)pMIB->pStorageValue = asnValue.asnValue.counter64; 
		break; 
	case ASN_OBJECTIDENTIFIER: 
		SnmpUtilOidCpy((AsnObjectIdentifier*)pMIB->pStorageValue,&asnValue.asnValue.object); 
		break; 
 
	case ASN_IPADDRESS: 
		((char*)pMIB->pStorageValue)[0] = asnValue.asnValue.address.stream[0]; 
		((char*)pMIB->pStorageValue)[1] = asnValue.asnValue.address.stream[1]; 
		((char*)pMIB->pStorageValue)[2] = asnValue.asnValue.address.stream[2]; 
		((char*)pMIB->pStorageValue)[3] = asnValue.asnValue.address.stream[3]; 
		break; 
	case ASN_OPAQUE: 
		AsnSequence; 
		break; 
	case ASN_BITS: 
		break;	 
	case ASN_SEQUENCE: 
		break;	 
	case ASN_NULL: 
		break; 
	default: 
		return SNMP_ERRORSTATUS_GENERR;	 
	} 
	return SNMP_ERRORSTATUS_NOERROR; 
} 
 
// simple trap generation thread 
//   I'm sending traps in a loops in 15 second intervals 
unsigned long __stdcall TrapGenThread(void *lpVoid) 
{ 
	for(;;) 
	{ 
		Sleep(15000); 
		SetEvent(g_hSimulateTrap); 
	} 
	return 0; 
}