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;i len;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;i name) ==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;i name); 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;i name) ==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; }