|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
mgmtapi.c
Abstract:
SNMP Management API (wrapped around WinSNMP API).
Environment:
User Mode - Win32
Revision History:
05-Feb-1997 DonRyan Rewrote functions to be wrappers around WinSNMP.
--*/
///////////////////////////////////////////////////////////////////////////////
// //
// Include Files //
// //
///////////////////////////////////////////////////////////////////////////////
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <wsipx.h>
#include <winsnmp.h>
#include <mgmtapi.h>
#include <oidconv.h>
#include <snmputil.h>
///////////////////////////////////////////////////////////////////////////////
// //
// Private Definitions //
// //
///////////////////////////////////////////////////////////////////////////////
typedef struct _SNMP_MGR_SESSION {
SOCKET UnusedSocket; // WARNING: Previous versions of the
struct sockaddr UnusedDestAddr; // MGMTAPI.H header file exposed the
LPSTR UnusedCommunity; // SNMP_MGR_SESSION structure which
INT UnusedTimeout; // unfortunately encouraged people to
INT UnusedNumRetries; // muck with it. Since this structure
AsnInteger UnusedRequestId; // has now changed we must protect it.
CRITICAL_SECTION SessionLock; // multiple threads may share session
HSNMP_SESSION hSnmpSession; // handle to winsnmp session
HSNMP_ENTITY hAgentEntity; // handle to agent entity
HSNMP_ENTITY hManagerEntity; // handle to manager entity
HSNMP_CONTEXT hViewContext; // handle to view context
HSNMP_PDU hPdu; // handle to snmp pdu
HSNMP_VBL hVbl; // handle to snmp pdu
HWND hWnd; // handle to window
smiINT32 nPduType; // current pdu type
smiINT32 nRequestId; // current request id
smiINT32 nErrorIndex; // error index from pdu
smiINT32 nErrorStatus; // error status from pdu
smiINT32 nLastError; // last system error
SnmpVarBindList * pVarBindList; // pointer to varbind list
} SNMP_MGR_SESSION, *PSNMP_MGR_SESSION;
typedef struct _TRAP_LIST_ENTRY {
LIST_ENTRY Link; // linked-list link
AsnObjectIdentifier EnterpriseOID; // generating enterprise
AsnNetworkAddress AgentAddress; // generating agent addr
AsnNetworkAddress SourceAddress; // generating network addr
AsnInteger nGenericTrap; // generic trap type
AsnInteger nSpecificTrap; // enterprise specific type
AsnOctetString Community; // generating community
AsnTimeticks TimeStamp; // time stamp
SnmpVarBindList VarBindList; // variable bindings
} TRAP_LIST_ENTRY, * PTRAP_LIST_ENTRY;
#define IPADDRLEN 4
#define IPXADDRLEN 10
#define MAXENTITYSTRLEN 128
#define MINVARBINDLEN 2
#define SYSUPTIMEINDEX 0
#define SNMPTRAPOIDINDEX 1
#define DEFAULT_ADDRESS_IP "127.0.0.1"
#define DEFAULT_ADDRESS_IPX "00000000.000000000000"
#define NOTIFICATION_CLASS "MGMTAPI Notification Class"
#define WM_WSNMP_INCOMING (WM_USER + 1)
#define WM_WSNMP_DONE (WM_USER + 2)
#define WSNMP_FAILED(s) ((s) == SNMPAPI_FAILURE)
#define WSNMP_SUCCEEDED(s) ((s) != SNMPAPI_FAILURE)
#define WSNMP_ASSERT(s) ASSERT((s))
///////////////////////////////////////////////////////////////////////////////
// //
// Global Variables //
// //
///////////////////////////////////////////////////////////////////////////////
HINSTANCE g_hDll; // module handle
HANDLE g_hTrapEvent = NULL; // trap event handle
HANDLE g_hTrapThread = NULL; // trap thread handle
HANDLE g_hTrapRegisterdEvent = NULL; // event to sync. SnmpMgrTrapListen
BOOL g_fIsSnmpStarted = FALSE; // indicates winsnmp inited
BOOL g_fIsSnmpListening = FALSE; // indicates trap thread on
BOOL g_fIsTrapRegistered = FALSE; // indicates trap registered
DWORD g_dwRequestId = 1; // unique pdu request id
LIST_ENTRY g_IncomingTraps; // incoming trap queue
CRITICAL_SECTION g_GlobalLock; // process resource lock
SNMP_MGR_SESSION g_TrapSMS; // process trap session
DWORD g_cSnmpMgmtRef = 0; // ref. count on using mgmtapi
///////////////////////////////////////////////////////////////////////////////
// //
// Private Procedures //
// //
///////////////////////////////////////////////////////////////////////////////
DWORD GetRequestId( )
/*++
Routine Description:
Retrieve next global request id.
Arguments:
None.
Return Values:
Returns request id.
--*/
{ DWORD dwRequestId;
// obtain exclusive access to request id
EnterCriticalSection(&g_GlobalLock);
// obtain copy of request id
dwRequestId = g_dwRequestId++;
// obtain exclusive access to request id
LeaveCriticalSection(&g_GlobalLock);
return dwRequestId; }
BOOL TransferVb( PSNMP_MGR_SESSION pSMS, SnmpVarBind * pVarBind )
/*++
Routine Description:
Transfer VarBind structure to WinSNMP structure.
Arguments:
pSMS - pointer to mgmtapi session structure.
pVarBind - pointer to varbind to transfer.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = FALSE; SNMPAPI_STATUS status; smiVALUE tmpValue; smiOID tmpOID;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// validate pointers
if ((pVarBind != NULL) && (pVarBind->name.ids != NULL) && (pVarBind->name.idLength != 0)) {
// re-init
fOk = TRUE;
// transfer oid information
tmpOID.len = pVarBind->name.idLength; tmpOID.ptr = pVarBind->name.ids;
// only initialize value if set
if (pSMS->nPduType == SNMP_PDU_SET) {
// syntax values are equivalent
tmpValue.syntax = (smiINT32)(BYTE)pVarBind->value.asnType;
// determine type
switch (pVarBind->value.asnType) {
case ASN_INTEGER32:
// transfer signed int
tmpValue.value.sNumber = pVarBind->value.asnValue.number; break;
case ASN_UNSIGNED32: case ASN_COUNTER32: case ASN_GAUGE32: case ASN_TIMETICKS:
// transfer unsigned int
tmpValue.value.uNumber = pVarBind->value.asnValue.unsigned32; break;
case ASN_COUNTER64:
// transfer 64-bit counter
tmpValue.value.hNumber.lopart = pVarBind->value.asnValue.counter64.LowPart; tmpValue.value.hNumber.hipart = pVarBind->value.asnValue.counter64.HighPart; break;
case ASN_OPAQUE: case ASN_IPADDRESS: case ASN_OCTETSTRING: case ASN_BITS:
// transfer octet string
tmpValue.value.string.len = pVarBind->value.asnValue.string.length; tmpValue.value.string.ptr = pVarBind->value.asnValue.string.stream; break;
case ASN_OBJECTIDENTIFIER:
// transfer object id
tmpValue.value.oid.len = pVarBind->value.asnValue.object.idLength; tmpValue.value.oid.ptr = pVarBind->value.asnValue.object.ids; break;
case ASN_NULL: case SNMP_EXCEPTION_NOSUCHOBJECT: case SNMP_EXCEPTION_NOSUCHINSTANCE: case SNMP_EXCEPTION_ENDOFMIBVIEW:
// initialize empty byte
tmpValue.value.empty = 0; break;
default:
// failure
fOk = FALSE; break; } }
if (fOk) {
// register varbind
status = SnmpSetVb( pSMS->hVbl, 0, // index
&tmpOID, (pSMS->nPduType == SNMP_PDU_SET) ? &tmpValue : NULL );
// validate return code
if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpSetVb returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// failure
fOk = FALSE; } } }
return fOk; }
BOOL AllocateVbl( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Transfer VarBindList structure to WinSNMP structure.
Arguments:
pSMS - pointer to mgmtapi session structure.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = FALSE; SNMPAPI_STATUS status; SnmpVarBind * pVarBind; DWORD cVarBind;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// validate parameters
WSNMP_ASSERT(pSMS->pVarBindList != NULL); WSNMP_ASSERT(pSMS->pVarBindList->len != 0); WSNMP_ASSERT(pSMS->pVarBindList->list != NULL);
// allocate resources for variable bindings list
pSMS->hVbl = SnmpCreateVbl(pSMS->hSnmpSession, NULL, NULL);
// validate varbind handle
if (WSNMP_SUCCEEDED(pSMS->hVbl)) {
// re-init
fOk = TRUE;
// initialize varbind pointer
pVarBind = pSMS->pVarBindList->list;
// initialize varbind count
cVarBind = pSMS->pVarBindList->len;
// process each varbind
while (fOk && cVarBind--) {
// transfer variable binding
fOk = TransferVb(pSMS, pVarBind++); }
if (!fOk) {
// release varbind list handle
status = SnmpFreeVbl(pSMS->hVbl);
// validate return code
if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpFreeVbl returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) )); }
// re-initialize
pSMS->hVbl = (HSNMP_VBL)NULL; }
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpCreateVbl returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) )); }
return fOk; }
BOOL FreeVbl( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Cleanup VarBind resources from WinSNMP structure.
Arguments:
pSMS - pointer to mgmtapi session structure.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = TRUE; SNMPAPI_STATUS status;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// validate handle
if (pSMS->hVbl != (HSNMP_VBL)NULL) {
// actually release vbl handle
status = SnmpFreeVbl(pSMS->hVbl);
// validate return code
if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpFreeVbl returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// failure
fOk = FALSE; }
// re-initialize handle
pSMS->hVbl = (HSNMP_VBL)NULL; }
return fOk; }
BOOL AllocatePdu( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Initialize session structure for sending request.
Arguments:
pSMS - pointer to mgmtapi session structure.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = FALSE;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// transfer varbinds
if (AllocateVbl(pSMS)) {
// grab next shared request id
pSMS->nRequestId = GetRequestId();
// create request pdu
pSMS->hPdu = SnmpCreatePdu( pSMS->hSnmpSession, pSMS->nPduType, pSMS->nRequestId, 0, // errorStatus
0, // errorIndex
pSMS->hVbl );
// validate return status
if (WSNMP_SUCCEEDED(pSMS->hPdu)) {
// success
fOk = TRUE;
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpCreatePdu returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// free resources
FreeVbl(pSMS); } }
return fOk; }
BOOL FreePdu( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Cleanup session structure after processing response.
Arguments:
pSMS - pointer to mgmtapi session structure.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = TRUE; SNMPAPI_STATUS status;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// validate handle
if (pSMS->hPdu != (HSNMP_PDU)NULL) {
// free vbl
FreeVbl(pSMS);
// actually release pdu handle
status = SnmpFreePdu(pSMS->hPdu);
// validate return code
if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpFreePdu returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// failure
fOk = FALSE; }
// re-initialize handle
pSMS->hPdu = (HSNMP_PDU)NULL; }
return fOk; }
BOOL CopyOid( AsnObjectIdentifier * pDstOID, smiLPOID pSrcOID )
/*++
Routine Description:
Copies object identifier from WinSNMP format to MGMTAPI format.
Arguments:
pDstOID - points to MGMTAPI structure to receive OID.
pSrcOID - points to WinSNMP structure to copy.
Return Values:
Returns true if successful.
Note: if pSrcOID is valid, its contents will be freed regardless of return value
--*/
{ BOOL fOk = FALSE;
// validate pointers
WSNMP_ASSERT(pDstOID != NULL); WSNMP_ASSERT(pSrcOID != NULL); WSNMP_ASSERT(pSrcOID->len != 0); WSNMP_ASSERT(pSrcOID->ptr != NULL);
// store the number of subids
pDstOID->idLength = pSrcOID->len;
// allocate memory for subidentifiers
pDstOID->ids = SnmpUtilMemAlloc(pDstOID->idLength * sizeof(DWORD));
// validate pointer
if (pDstOID->ids != NULL) {
// transfer memory
memcpy(pDstOID->ids, pSrcOID->ptr, pDstOID->idLength * sizeof(DWORD) );
// success
fOk = TRUE; }
// now release memory for original oid
SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE)pSrcOID);
return fOk; }
BOOL CopyOctets( AsnOctetString * pDstOctets, smiLPOCTETS pSrcOctets )
/*++
Routine Description:
Copies octet string from WinSNMP format to MGMTAPI format.
Arguments:
pDstOctets - points to MGMTAPI structure to receive octets.
pSrcOctets - points to WinSNMP structure to copy.
Return Values:
Returns true if successful.
Note: if pSrcOctets is valid, its contents will be freed regardless of return value
--*/
{ BOOL fOk = FALSE; SNMPAPI_STATUS status;
// validate pointers
WSNMP_ASSERT(pDstOctets != NULL); WSNMP_ASSERT(pSrcOctets != NULL);
// it is legitimate that
// 1. pSrcOctets->len == 0
// 2. pSrcOctets->ptr == NULL
if (pSrcOctets->len == 0 || pSrcOctets->ptr == NULL) { pDstOctets->dynamic = FALSE; pDstOctets->length = 0; pDstOctets->stream = NULL; fOk = TRUE; } else { // allocate memory for octet string
pDstOctets->stream = SnmpUtilMemAlloc(pSrcOctets->len);
// validate pointer
if (pDstOctets->stream != NULL) {
// octet string allocated
pDstOctets->dynamic = TRUE;
// store the number of bytes
pDstOctets->length = pSrcOctets->len; // transfer memory
memcpy(pDstOctets->stream, pSrcOctets->ptr, pDstOctets->length );
// success
fOk = TRUE; } }
// now release memory for original string
SnmpFreeDescriptor(SNMP_SYNTAX_OCTETS, (smiLPOPAQUE)pSrcOctets);
return fOk; }
CopyVb( PSNMP_MGR_SESSION pSMS, DWORD iVarBind, SnmpVarBind * pVarBind )
/*++
Routine Description:
Copy variable binding from WinSNMP structure to MGMTAPI structure.
Arguments:
pSMS - pointer to mgmtapi session structure.
iVarBind - index of varbind structure to copy.
pVarBind - pointer to varbind structure.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = FALSE; SNMPAPI_STATUS status; smiOID tmpOID; smiVALUE tmpValue;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL); WSNMP_ASSERT(pVarBind != NULL);
// attempt to retrieve varbind data from winsnmp structure
status = SnmpGetVb(pSMS->hVbl, iVarBind, &tmpOID, &tmpValue);
// validate return code
if (WSNMP_SUCCEEDED(status)) {
// transfer object identifier value
fOk = CopyOid(&pVarBind->name, &tmpOID);
// syntax values are equivalent
pVarBind->value.asnType = (BYTE)(smiINT32)tmpValue.syntax;
// determine syntax
switch (tmpValue.syntax) {
case SNMP_SYNTAX_INT32:
// transfer signed int
pVarBind->value.asnValue.number = tmpValue.value.sNumber; break;
case SNMP_SYNTAX_UINT32: case SNMP_SYNTAX_CNTR32: case SNMP_SYNTAX_GAUGE32: case SNMP_SYNTAX_TIMETICKS:
// transfer unsigned int
pVarBind->value.asnValue.unsigned32 = tmpValue.value.uNumber; break;
case SNMP_SYNTAX_CNTR64:
// transfer 64-bit counter
pVarBind->value.asnValue.counter64.LowPart = tmpValue.value.hNumber.lopart; pVarBind->value.asnValue.counter64.HighPart = tmpValue.value.hNumber.hipart; break;
case SNMP_SYNTAX_OPAQUE: case SNMP_SYNTAX_IPADDR: case SNMP_SYNTAX_OCTETS: case SNMP_SYNTAX_BITS:
// transfer octet string
if (!CopyOctets(&pVarBind->value.asnValue.string, &tmpValue.value.string)) { // re-initialize
pVarBind->value.asnType = ASN_NULL;
// failure
fOk = FALSE; }
break;
case SNMP_SYNTAX_OID:
// transfer object identifier
if (!CopyOid(&pVarBind->value.asnValue.object, &tmpValue.value.oid)) {
// re-initialize
pVarBind->value.asnType = ASN_NULL;
// failure
fOk = FALSE; }
break;
case SNMP_SYNTAX_NULL: case SNMP_SYNTAX_NOSUCHOBJECT: case SNMP_SYNTAX_NOSUCHINSTANCE: case SNMP_SYNTAX_ENDOFMIBVIEW:
break; // do nothing...
default:
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpGetVb returned invalid type.\n" ));
// re-initialize
pVarBind->value.asnType = ASN_NULL;
// failure
fOk = FALSE;
break; }
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpGetVb returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) )); }
return fOk; }
BOOL CopyVbl( PSNMP_MGR_SESSION pSMS, SnmpVarBindList * pVarBindList )
/*++
Routine Description:
Copy variable bindings from WinSNMP structure to MGMTAPI structure.
Arguments:
pSMS - pointer to mgmtapi session structure.
pVarBindList - pointer to varbind list structure.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = TRUE;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL); WSNMP_ASSERT(pVarBindList != NULL);
// initialize
pVarBindList->len = 0; pVarBindList->list = NULL;
// validate varbind list handle
if (pSMS->hVbl != (HSNMP_VBL)NULL) {
// determine number of varbinds
pVarBindList->len = SnmpCountVbl(pSMS->hVbl);
// validate number of varbinds
if (WSNMP_SUCCEEDED(pVarBindList->len)) {
// allocate memory for varbinds
pVarBindList->list = SnmpUtilMemAlloc( pVarBindList->len * sizeof(SnmpVarBind) );
// validate pointer
if (pVarBindList->list != NULL) {
DWORD cVarBind = 1; SnmpVarBind * pVarBind;
// save pointer to varbinds
pVarBind = pVarBindList->list;
// process varbinds in the list
while (fOk && (cVarBind <= pVarBindList->len)) {
// copy varbind from winsnmp to mgmtapi
fOk = CopyVb(pSMS, cVarBind++, pVarBind++); }
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Could not allocate VBL.\n" ));
// re-initialize
pVarBindList->len = 0;
// failure
fOk = FALSE; }
} else if (SnmpGetLastError(pSMS->hSnmpSession) != SNMPAPI_NOOP) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpCountVbl returned %s.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// re-initialize
pVarBindList->len = 0;
// failure
fOk = FALSE; } }
if (!fOk) {
// cleanup any varbinds allocated
SnmpUtilVarBindListFree(pVarBindList); }
return fOk; }
BOOL ParseVbl( PSNMP_MGR_SESSION pSMS, PTRAP_LIST_ENTRY pTLE )
/*++
Routine Description:
Parse varbind list for trap-related varbinds.
Arguments:
pSMS - pointer to MGMTAPI session structure.
pTLE - pointer to trap list entry.
Return Values:
Returns true if successful.
--*/
{ SnmpVarBind * pVarBind; AsnObjectIdentifier * pOID; AsnNetworkAddress * pAgentAddress = NULL; AsnObjectIdentifier * pEnterpriseOID = NULL;
// object identifiers to convert snmpv2 trap format
static UINT _sysUpTime[] = { 1, 3, 6, 1, 2, 1, 1, 3 }; static UINT _snmpTrapOID[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1 }; static UINT _snmpAddress[] = { 1, 3, 6, 1, 3, 1057, 1 }; static UINT _snmpTrapEnterprise[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 3 }; static UINT _snmpTraps[] = { 1, 3, 6, 1, 6, 3, 1, 1, 5 };
static AsnObjectIdentifier sysUpTime = DEFINE_OID(_sysUpTime); static AsnObjectIdentifier snmpTrapOID = DEFINE_OID(_snmpTrapOID); static AsnObjectIdentifier snmpAddress = DEFINE_OID(_snmpAddress); static AsnObjectIdentifier snmpTrapEnterprise = DEFINE_OID(_snmpTrapEnterprise); static AsnObjectIdentifier snmpTraps = DEFINE_OID(_snmpTraps);
// validate pointers
WSNMP_ASSERT(pSMS != NULL); WSNMP_ASSERT(pTLE != NULL);
// validate vbl have minimum entries
if (pTLE->VarBindList.len >= MINVARBINDLEN) {
// point to sysUpTime varbind structure
pVarBind = &pTLE->VarBindList.list[SYSUPTIMEINDEX];
// verify variable is sysUpTime
if ((pVarBind->value.asnType == ASN_TIMETICKS) && !SnmpUtilOidNCmp(&pVarBind->name, &sysUpTime, sysUpTime.idLength)) {
// transfer sysUpTime value to trap entry
pTLE->TimeStamp = pVarBind->value.asnValue.ticks;
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Could not find sysUpTime.\n" ));
goto cleanup; // bail...
}
// see if any additional varbinds present
if (pTLE->VarBindList.len > MINVARBINDLEN) {
// point to snmpTrapEnterprise varbind structure (maybe)
pVarBind = &pTLE->VarBindList.list[pTLE->VarBindList.len - 1];
// verify variable is snmpTrapEnterprise
if ((pVarBind->value.asnType == ASN_OBJECTIDENTIFIER) && !SnmpUtilOidNCmp(&pVarBind->name, &snmpTrapEnterprise, snmpTrapEnterprise.idLength)) {
// transfer enterprise oid to list entry
pTLE->EnterpriseOID = pVarBind->value.asnValue.object;
// store enterprise oid for later
pEnterpriseOID = &pTLE->EnterpriseOID;
// modify type to avoid deallocation
pVarBind->value.asnType = ASN_NULL;
} else {
SNMPDBG(( SNMP_LOG_TRACE, "MGMTAPI: Could not find snmpTrapEnterprise.\n" )); } }
// see if the agent address is present
if (pTLE->VarBindList.len > MINVARBINDLEN+1) { // point to snmpAddress varbind structure (maybe)
pVarBind = &pTLE->VarBindList.list[pTLE->VarBindList.len - 2];
// verify variable is snmpAddress
if ((pVarBind->value.asnType == SNMP_SYNTAX_IPADDR) && !SnmpUtilOidNCmp(&pVarBind->name, &snmpAddress, snmpAddress.idLength)) {
// transfer agent address oid to list entry
pTLE->AgentAddress = pVarBind->value.asnValue.address;
// store agent address for later
pAgentAddress = &pTLE->AgentAddress;
// modify type to avoid deallocation
pVarBind->value.asnType = ASN_NULL;
} else {
SNMPDBG(( SNMP_LOG_TRACE, "MGMTAPI: Could not find snmpAddress.\n" )); } }
// point to snmpTrapOID varbind structure
pVarBind = &pTLE->VarBindList.list[SNMPTRAPOIDINDEX];
// verify variable is snmpTrapOID
if ((pVarBind->value.asnType == ASN_OBJECTIDENTIFIER) && !SnmpUtilOidNCmp(&pVarBind->name, &snmpTrapOID, snmpTrapOID.idLength)) {
// retrieve pointer to oid
pOID = &pVarBind->value.asnValue.object;
// check for generic trap
if (!SnmpUtilOidNCmp(pOID, &snmpTraps, snmpTraps.idLength)) {
// validate size is one greater than root
if (pOID->idLength == (snmpTraps.idLength + 1)) {
// retrieve trap id
// --ft:10/01/98 (bug #231344): WINSNMP gives up the V2 syntax => pOID->ids[snmpTraps.idLength] = [1..6]
// --ft:10/01/98 (bug #231344): as MGMTAPI turns back to V1, we need to decrement this value.
pTLE->nGenericTrap = (pOID->ids[snmpTraps.idLength])-1;
// re-initialize
pTLE->nSpecificTrap = 0;
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Invalid snmpTrapOID.\n" ));
goto cleanup; // bail...
}
// check for specific trap
} else if ((pEnterpriseOID != NULL) && !SnmpUtilOidNCmp(pOID, pEnterpriseOID, pEnterpriseOID->idLength)) {
// validate size is two greater than root
if (pOID->idLength == (pEnterpriseOID->idLength + 2)) {
// validate separator sub-identifier
WSNMP_ASSERT(pOID->ids[pEnterpriseOID->idLength] == 0);
// retrieve trap id
pTLE->nSpecificTrap = pOID->ids[pEnterpriseOID->idLength + 1];
// re-initialize
pTLE->nGenericTrap = SNMP_GENERICTRAP_ENTERSPECIFIC;
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Invalid snmpTrapOID.\n" ));
goto cleanup; // bail...
}
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Could not identify snmpTrapOID.\n" ));
goto cleanup; // bail...
}
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Could not find snmpTrapOID.\n" ));
goto cleanup; // bail...
}
// check for enterprise oid
if (pEnterpriseOID != NULL) {
// release snmpTrapEnterprise varbind structure
SnmpUtilVarBindFree(&pTLE->VarBindList.list[pTLE->VarBindList.len - 1]);
// decrement the list length as the last varbind was freed
pTLE->VarBindList.len--; }
// check for agent address
if (pAgentAddress != NULL) {
// release snmpAgentAddress varbind structure
SnmpUtilVarBindFree(&pTLE->VarBindList.list[pTLE->VarBindList.len - 1]);
// decrement the list length as the last varbind was again freed
pTLE->VarBindList.len--; }
// release sysUpTime varbind structure
SnmpUtilVarBindFree(&pTLE->VarBindList.list[SYSUPTIMEINDEX]);
// release snmpTrapOID varbind structure
SnmpUtilVarBindFree(&pTLE->VarBindList.list[SNMPTRAPOIDINDEX]);
// subtract released varbinds
pTLE->VarBindList.len -= MINVARBINDLEN;
// check if all varbinds freed
if (pTLE->VarBindList.len == 0) {
// release memory for list
SnmpUtilMemFree(pTLE->VarBindList.list);
// re-initialize
pTLE->VarBindList.list = NULL;
} else {
// shift varbind list up two spaces
memmove((LPBYTE)(pTLE->VarBindList.list), (LPBYTE)(pTLE->VarBindList.list + MINVARBINDLEN), (pTLE->VarBindList.len * sizeof(SnmpVarBind)) ); }
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Too few subidentifiers.\n" )); }
// success
return TRUE;
cleanup:
// failure
return FALSE; }
BOOL FreeTle( PTRAP_LIST_ENTRY pTLE )
/*++
Routine Description:
Release memory used for trap entry.
Arguments:
pTLE - pointer to trap list entry.
Return Values:
Returns true if successful.
--*/
{ // validate pointer
WSNMP_ASSERT(pTLE != NULL); // release memory for enterprise oid if necessary
SnmpUtilOidFree(&pTLE->EnterpriseOID); // release memory for AgentAddress if necessary
SnmpUtilOctetsFree(&pTLE->AgentAddress); // AgentAddress is a AsnOctetString type
// release memory for SourceAddress if necessary
SnmpUtilOctetsFree(&pTLE->SourceAddress); // SourceAddress is a AsnOctetString type
// release memory for community string if necessary
SnmpUtilMemFree(pTLE->Community.stream); // release memory used in varbind list if necessary
SnmpUtilVarBindListFree(&pTLE->VarBindList); // release list entry
SnmpUtilMemFree(pTLE); return TRUE; }
BOOL AllocateTle( PSNMP_MGR_SESSION pSMS, PTRAP_LIST_ENTRY * ppTLE, HSNMP_ENTITY hAgentEntity, HSNMP_CONTEXT hViewContext )
/*++
Routine Description:
Allocate memory for trap entry.
Arguments:
pSMS - pointer to MGMTAPI session structure.
ppTLE - pointer to pointer to trap list entry.
hAgentEntity - handle to agent sending trap.
hViewContext - handle to view context of trap.
Return Values:
Returns true if successful.
--*/
{ PTRAP_LIST_ENTRY pTLE; SNMPAPI_STATUS status; smiOCTETS CommunityStr; CHAR SourceStrAddr[MAXENTITYSTRLEN+1]; struct sockaddr SourceSockAddr;
// validate pointers
WSNMP_ASSERT(pSMS != NULL); WSNMP_ASSERT(ppTLE != NULL);
// allocate memory from list entry
pTLE = SnmpUtilMemAlloc(sizeof(TRAP_LIST_ENTRY));
// validate pointer
if (pTLE == NULL) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Could not allocate trap entry.\n" ));
return FALSE; // bail...
}
// initialize
*ppTLE = NULL;
// copy varbinds to trap list entry
if (!CopyVbl(pSMS, &pTLE->VarBindList)) { goto cleanup; // bail...
}
// parse trap-related varbinds
if (!ParseVbl(pSMS, pTLE)) { goto cleanup; // bail...
}
// check if source address is specified
if (hAgentEntity != (HSNMP_ENTITY)NULL) {
// convert addr to string
status = SnmpEntityToStr( hAgentEntity, sizeof(SourceStrAddr), SourceStrAddr );
// validate error code
if (WSNMP_SUCCEEDED(status)) {
DWORD AddrLen = 0; LPBYTE AddrPtr = NULL;
// convert string to socket address structure
if (! SnmpSvcAddrToSocket(SourceStrAddr, &SourceSockAddr)) { SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Ignoring invalid address.\n" ));
goto cleanup; // bail...
}
// validate address family
if (SourceSockAddr.sa_family == AF_INET) {
// assign ip values
AddrLen = IPADDRLEN; AddrPtr = (LPBYTE)&(((struct sockaddr_in *) (&SourceSockAddr))->sin_addr);
} else if (SourceSockAddr.sa_family == AF_IPX) {
// assign ipx values
AddrLen = IPXADDRLEN; AddrPtr = (LPBYTE)&(((struct sockaddr_ipx *) (&SourceSockAddr))->sa_netnum);
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Ignoring invalid address.\n" ));
goto cleanup; // bail...
}
// allocate address to return (if specified)
pTLE->SourceAddress.stream = SnmpUtilMemAlloc(AddrLen);
// validate pointer
if (pTLE->SourceAddress.stream != NULL) {
// initialize length values
pTLE->SourceAddress.length = AddrLen; pTLE->SourceAddress.dynamic = TRUE;
// transfer agent address information
memcpy(pTLE->SourceAddress.stream, AddrPtr, AddrLen); }
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpEntityToStr returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
goto cleanup; // bail...
} }
// check if community specified
if (hViewContext != (HSNMP_CONTEXT)NULL) {
// convert agent entity to string
status = SnmpContextToStr(hViewContext, &CommunityStr);
// validate error code
if (WSNMP_SUCCEEDED(status)) {
// copy octet string, memory allocated in CommunityStr is also freed
CopyOctets(&pTLE->Community, &CommunityStr);
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpContextToStr returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
goto cleanup; // bail...
} }
// transfer
*ppTLE = pTLE;
// success
return TRUE;
cleanup:
// release
FreeTle(pTLE);
// failure
return FALSE; }
BOOL NotificationCallback( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Callback for processing notification messages.
Arguments:
pSMS - pointer to mgmtapi session structure.
Return Values:
Returns true if processing finished.
--*/
{ BOOL fDone = TRUE; SNMPAPI_STATUS status; HSNMP_ENTITY hAgentEntity = (HSNMP_ENTITY)NULL; HSNMP_ENTITY hManagerEntity = (HSNMP_ENTITY)NULL; HSNMP_CONTEXT hViewContext = (HSNMP_CONTEXT)NULL; smiINT32 nPduType; smiINT32 nRequestId;
// validate pointer
WSNMP_ASSERT(pSMS != NULL);
// retrieve message
status = SnmpRecvMsg( pSMS->hSnmpSession, &hAgentEntity, &hManagerEntity, &hViewContext, &pSMS->hPdu );
// validate return code
if (WSNMP_SUCCEEDED(status)) {
// retrieve pdu data
status = SnmpGetPduData( pSMS->hPdu, &nPduType, &nRequestId, &pSMS->nErrorStatus, &pSMS->nErrorIndex, &pSMS->hVbl );
// validate return code
if (WSNMP_SUCCEEDED(status)) {
// process reponse to request
if (nPduType == SNMP_PDU_RESPONSE) {
// validate context information
if ((pSMS->nRequestId == nRequestId) && (pSMS->hViewContext == hViewContext) && (pSMS->hAgentEntity == hAgentEntity) && (pSMS->hManagerEntity == hManagerEntity)) {
// validate returned error status
if (pSMS->nErrorStatus == SNMP_ERROR_NOERROR) {
SnmpVarBindList VarBindList;
// copy variable binding list
if (CopyVbl(pSMS, &VarBindList)) {
// release existing varbind list
SnmpUtilVarBindListFree(pSMS->pVarBindList);
// manually copy new varbind list
*pSMS->pVarBindList = VarBindList;
} else {
// modify last error status
pSMS->nLastError = SNMPAPI_ALLOC_ERROR; } }
} else {
SNMPDBG(( SNMP_LOG_TRACE, "MGMTAPI: Ignoring invalid context.\n" ));
// continue
fDone = FALSE; }
} else if (nPduType == SNMP_PDU_TRAP) {
PTRAP_LIST_ENTRY pTLE;
// allocate trap list entry (transfers varbinds etc.)
if (AllocateTle(pSMS, &pTLE, hAgentEntity, hViewContext)) {
// obtain exclusive access
EnterCriticalSection(&g_GlobalLock);
// insert new trap into the incoming queue
InsertTailList(&g_IncomingTraps, &pTLE->Link);
// alert user
SetEvent(g_hTrapEvent);
// release exclusive access
LeaveCriticalSection(&g_GlobalLock); }
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Ignoring invalid pdu type %d.\n", nPduType ));
// continue
fDone = FALSE; }
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpGetPduData returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// retrieve last error status from winsnmp
pSMS->nLastError = SnmpGetLastError(pSMS->hSnmpSession); }
// release temporary entity
SnmpFreeEntity(hAgentEntity);
// release temporary entity
SnmpFreeEntity(hManagerEntity);
// release temporary context
SnmpFreeContext(hViewContext);
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpRecvMsg returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// retrieve last error status from winsnmp
pSMS->nLastError = SnmpGetLastError(pSMS->hSnmpSession);
}
// release pdu
FreePdu(pSMS);
return fDone; }
LRESULT CALLBACK NotificationWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
/*++
Routine Description:
Callback that processes WinSNMP notifications.
Arguments:
hWnd - window handle.
uMsg - message identifier.
wParam - first message parameter.
lParam - second message parameter.
Return Values:
The return value is the result of the message processing and depends on the message sent.
--*/
{ // check for winsnmp notification and transport timeout
if (uMsg == WM_WSNMP_INCOMING && wParam == SNMPAPI_TL_TIMEOUT) { PSNMP_MGR_SESSION pSMS;
// retrieve mgmtapi session pointer from window
pSMS = (PSNMP_MGR_SESSION)GetWindowLongPtr(hWnd, 0);
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// translate winsnmp error to mgmtapi error
pSMS->nLastError = SNMP_MGMTAPI_TIMEOUT;
// post message to break out of message pump
PostMessage(pSMS->hWnd, WM_WSNMP_DONE, (WPARAM)0, (LPARAM)0); return (LRESULT)0; } // check for winsnmp notification
else if (uMsg == WM_WSNMP_INCOMING) {
PSNMP_MGR_SESSION pSMS;
// retrieve mgmtapi session pointer from window
pSMS = (PSNMP_MGR_SESSION)GetWindowLongPtr(hWnd, 0);
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// process notification message
if (NotificationCallback(pSMS)) {
// post message to break out of message pump
PostMessage(pSMS->hWnd, WM_WSNMP_DONE, (WPARAM)0, (LPARAM)0); }
return (LRESULT)0;
} else {
// forward all other messages to windows
return DefWindowProc(hWnd, uMsg, wParam, lParam); } }
BOOL RegisterNotificationClass( )
/*++
Routine Description:
Register notification class for sessions.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk; WNDCLASS wc;
// initialize notification window class
wc.lpfnWndProc = NotificationWndProc; wc.lpszClassName = NOTIFICATION_CLASS; wc.lpszMenuName = NULL; wc.hInstance = g_hDll; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = NULL; wc.cbWndExtra = sizeof(PSNMP_MGR_SESSION); wc.cbClsExtra = 0; wc.style = 0;
// register class
fOk = RegisterClass(&wc);
if (!fOk) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: RegisterClass returned %d.\n", GetLastError() )); }
return fOk; }
BOOL UnregisterNotificationClass( )
/*++
Routine Description:
Unregister notification class.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk;
// unergister notification window class
fOk = UnregisterClass(NOTIFICATION_CLASS, g_hDll);
if (!fOk) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: UnregisterClass returned %d.\n", GetLastError() )); }
return fOk; }
BOOL StartSnmpIfNecessary( )
/*++
Routine Description:
Initialize WinSNMP DLL if necessary.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk;
// serialize access to startup code
EnterCriticalSection(&g_GlobalLock);
// see if already started
if (g_fIsSnmpStarted != TRUE) {
SNMPAPI_STATUS status;
// initialize start params
smiUINT32 nMajorVersion = 0; smiUINT32 nMinorVersion = 0; smiUINT32 nLevel = 0; smiUINT32 nTranslateMode = 0; smiUINT32 nRetransmitMode = 0;
// start winsnmp
status = SnmpStartup( &nMajorVersion, &nMinorVersion, &nLevel, &nTranslateMode, &nRetransmitMode );
// validate return code
if (WSNMP_SUCCEEDED(status)) {
SNMPDBG(( SNMP_LOG_TRACE, "MGMTAPI: SnmpStartup succeeded:\n" "MGMTAPI:\tnMajorVersion = %d\n" "MGMTAPI:\tnMinorVersion = %d\n" "MGMTAPI:\tnLevel = %d\n" "MGMTAPI:\tnTranslateMode = %d\n" "MGMTAPI:\tnRetransmitMode = %d\n", nMajorVersion, nMinorVersion, nLevel, nTranslateMode, nRetransmitMode ));
// allocate global trap available event
if ((g_hTrapEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) { SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: CreateEvent returned %d.\n", GetLastError() ));
// failure
goto cleanup; }
// allocate global event to sync. SnmpMgrTrapListen
if ((g_hTrapRegisterdEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) ==NULL) { SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: CreateEvent returned %d.\n", GetLastError() ));
// failure
goto cleanup; }
// make sure translate mode is snmp v1
status = SnmpSetTranslateMode(SNMPAPI_UNTRANSLATED_V1); if (WSNMP_FAILED(status)) { SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpSetTranslateMode returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
// failure
goto cleanup; }
// make sure retransmit mode is on
status = SnmpSetRetransmitMode(SNMPAPI_ON); if (WSNMP_FAILED(status)) { SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpSetRetransmitMode returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
// failure
goto cleanup; }
// register notification class
if (!RegisterNotificationClass()) { SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: RegisterNotificationClass returned %d.\n", GetLastError() ));
// failure
goto cleanup; }
// save new status
g_fIsSnmpStarted = TRUE;
// success
fOk = TRUE;
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpStartup returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
// failure, but no need to cleanup
fOk = FALSE; }
} else {
fOk = TRUE;
}
// serialize access to startup code
LeaveCriticalSection(&g_GlobalLock);
return fOk;
cleanup:
// cleanup if necessary
SnmpCleanup(); // ignore any return status at this stage
if (g_hTrapEvent) { CloseHandle(g_hTrapEvent); g_hTrapEvent = NULL; } if (g_hTrapRegisterdEvent) { CloseHandle(g_hTrapRegisterdEvent); g_hTrapRegisterdEvent = NULL; }
LeaveCriticalSection(&g_GlobalLock); return FALSE; }
BOOL CleanupIfNecessary( )
/*++
Routine Description:
Cleanup WinSNMP DLL if necessary.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = TRUE;
// serialize access to startup code
EnterCriticalSection(&g_GlobalLock);
// see if already started
if (g_fIsSnmpStarted == TRUE) {
SNMPAPI_STATUS status;
// shutdown winsnmp
status = SnmpCleanup();
// validate return code
if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpCleanup returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
// failure
fOk = FALSE; }
// unregister notification class
UnregisterNotificationClass();
// save new status
g_fIsSnmpStarted = FALSE; }
// check trap handle
if (g_hTrapEvent != NULL) {
// close trap handle
CloseHandle(g_hTrapEvent);
// re-initialize
g_hTrapEvent = NULL; } // check event that syncs SnmpMgrTrapListen
if (g_hTrapRegisterdEvent != NULL) { // close trap handle
CloseHandle(g_hTrapRegisterdEvent);
// re-initialize
g_hTrapRegisterdEvent = NULL; }
// serialize access to startup code
LeaveCriticalSection(&g_GlobalLock);
return fOk; }
DWORD AddMgmtRef() /*++
Routine Description:
Increment the reference count on using the mgmtapi.dll module.
Arguments:
none
Return Values:
Returns the reference count value after the increment is done.
--*/ { EnterCriticalSection(&g_GlobalLock);
++g_cSnmpMgmtRef; LeaveCriticalSection(&g_GlobalLock); return g_cSnmpMgmtRef; }
DWORD ReleaseMgmtRef() /*++
Routine Description:
Decrement the reference count if it is greater than zero. Call CleanupIfNecessary if the reference count on using mgmtapi.dll becomes zero after the decrement.
Arguments:
none
Return Values:
Returns the final reference count value.
--*/ { EnterCriticalSection(&g_GlobalLock);
if (g_cSnmpMgmtRef) { --g_cSnmpMgmtRef; if (g_cSnmpMgmtRef == 0) { CleanupIfNecessary(); } } LeaveCriticalSection(&g_GlobalLock); return g_cSnmpMgmtRef; }
BOOL CreateNotificationWindow( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Create notification window for session.
Arguments:
pSMS - pointer to MGMTAPI session structure.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// create notification window
pSMS->hWnd = CreateWindow( NOTIFICATION_CLASS, NULL, // pointer to window name
0, // window style
0, // horizontal position of window
0, // vertical position of window
0, // window width
0, // window height
NULL, // handle to parent or owner window
NULL, // handle to menu or child-window identifier
g_hDll, // handle to application instance
NULL // pointer to window-creation data
);
// validate window handle
if (pSMS->hWnd != NULL) {
// store pointer to session in window
SetWindowLongPtr(pSMS->hWnd, 0, (LONG_PTR)pSMS);
// success
fOk = TRUE;
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: CreateWindow returned %d.\n", GetLastError() ));
// failure
fOk = FALSE; }
return fOk; }
BOOL DestroyNotificationWindow( HWND hWnd )
/*++
Routine Description:
Destroy notification window for session.
Arguments:
hWnd - window handle for session.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk;
// destroy notification window
fOk = DestroyWindow(hWnd);
if (!fOk) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: DestroyWindow returned %d.\n", GetLastError() )); }
return fOk; }
BOOL CloseSession( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Close WinSNMP session associated with MGMTAPI session.
Arguments:
pSMS - pointer to MGMTAPI session structure.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = TRUE; SNMPAPI_STATUS status;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// check if window opened
if (pSMS->hWnd != (HWND)NULL) {
// destroy notification window
fOk = DestroyNotificationWindow(pSMS->hWnd); }
// check if agent entity allocated
if (pSMS->hAgentEntity != (HSNMP_ENTITY)NULL) {
// close the entity handle
status = SnmpFreeEntity(pSMS->hAgentEntity);
// validate status
if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpFreeEntity returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
// failure
fOk = FALSE; }
// re-initialize
pSMS->hAgentEntity = (HSNMP_ENTITY)NULL; }
// check if manager entity allocated
if (pSMS->hManagerEntity != (HSNMP_ENTITY)NULL) {
// close the entity handle
status = SnmpFreeEntity(pSMS->hManagerEntity);
// validate status
if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpFreeEntity returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
// failure
fOk = FALSE; }
// re-initialize
pSMS->hManagerEntity = (HSNMP_ENTITY)NULL; }
// check if session allocated
if (pSMS->hSnmpSession != (HSNMP_SESSION)NULL) {
// close the winsnmp session
status = SnmpClose(pSMS->hSnmpSession);
// validate status
if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpClose returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
// failure
fOk = FALSE; }
// re-initialize
pSMS->hSnmpSession = (HSNMP_SESSION)NULL; }
return fOk; }
//SNMPAPI_STATUS SNMPAPI_CALL
// SnmpConveyAgentAddress (SNMPAPI_STATUS mode);
BOOL OpenSession( PSNMP_MGR_SESSION pSMS, LPSTR pAgentAddress, LPSTR pAgentCommunity, INT nTimeOut, INT nRetries )
/*++
Routine Description:
Open WinSNMP session and associate with MGMTAPI session.
Arguments:
pSMS - pointer to MGMTAPI session structure.
pAgentAddress - points to a null-terminated string specifying either a dotted-decimal IP address or a host name that can be resolved to an IP address, an IPX address (in 8.12 notation), or an ethernet address.
pAgentCommunity - points to a null-terminated string specifying the SNMP community name used when communicating with the agent specified in the lpAgentAddress parameter
nTimeOut - specifies the communications time-out in milliseconds.
nRetries - specifies the communications retry count.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk; struct sockaddr AgentSockAddr; CHAR AgentStrAddr[MAXENTITYSTRLEN+1]; smiOCTETS smiCommunity; SNMPAPI_STATUS status;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// initialize notification window
if (!CreateNotificationWindow(pSMS)) { return FALSE; // bail...
}
// open a winsnmp session which corresponds to mgmtapi session
pSMS->hSnmpSession = SnmpOpen(pSMS->hWnd, WM_WSNMP_INCOMING);
// --ft
// we need to turn this on in order to have WINSNMP to pass back not
// only the entity standing for the source Ip address but also the
// agent address as it was sent into the V1 Trap Pdu. Without it,
// SnmpMgrGetTrapEx() will return a NULL address for the pSourceAddress
// paramter. However, SnmpMgrGetTrapEx() is not documented!!!
//SnmpConveyAgentAddress(SNMPAPI_ON); // Move this into wsnmp_cf.c:SnmpStartup
// to avoid missing entry point problem when wsnmp32.dll is from other vendors
// validate session handle returned
if (WSNMP_FAILED(pSMS->hSnmpSession)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpOpen returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
// re-initialize
pSMS->hSnmpSession = (HSNMP_SESSION)NULL;
goto cleanup; // bail...
}
// validate pointer
if (pAgentAddress != NULL) {
AgentStrAddr[MAXENTITYSTRLEN] = '\0';
// use snmpapi.dll to do convert to sockets structure
if (!SnmpSvcAddrToSocket(pAgentAddress, &AgentSockAddr)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Ignoring invalid address.\n" ));
goto cleanup; // bail...
}
// check address family of agent
if (AgentSockAddr.sa_family == AF_INET) {
LPSTR pAgentStrAddr; struct sockaddr_in * pAgentSockAddr;
// cast generic socket address structure to inet
pAgentSockAddr = (struct sockaddr_in *)&AgentSockAddr;
// obtain exclusive access to api
EnterCriticalSection(&g_GlobalLock);
// attempt to convert address into string
pAgentStrAddr = inet_ntoa(pAgentSockAddr->sin_addr);
// copy to stack variable
strncpy(AgentStrAddr, pAgentStrAddr, MAXENTITYSTRLEN);
// release exclusive access to api
LeaveCriticalSection(&g_GlobalLock);
} else if (AgentSockAddr.sa_family == AF_IPX) {
// simply copy original string
strncpy(AgentStrAddr, pAgentAddress, MAXENTITYSTRLEN);
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Incorrect address family.\n" ));
goto cleanup; // bail...
}
// create remote agent entity
pSMS->hAgentEntity = SnmpStrToEntity( pSMS->hSnmpSession, AgentStrAddr );
// validate agent entity returned
if (WSNMP_FAILED(pSMS->hAgentEntity)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpStrToEntity returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// re-initialize
pSMS->hAgentEntity = (HSNMP_ENTITY)NULL;
goto cleanup; // bail...
}
// attach timeout specified with agent
status = SnmpSetTimeout(pSMS->hAgentEntity, nTimeOut / 10); if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpSetTimeout returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
goto cleanup; // bail...
}
// attach retries specified with agent
status = SnmpSetRetry(pSMS->hAgentEntity, nRetries); if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpSetRetry returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
goto cleanup; // bail...
}
// create local manager entity
pSMS->hManagerEntity = SnmpStrToEntity( pSMS->hSnmpSession, (AgentSockAddr.sa_family == AF_INET) ? DEFAULT_ADDRESS_IP : DEFAULT_ADDRESS_IPX );
// validate manager entity returned
if (WSNMP_FAILED(pSMS->hManagerEntity)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpStrToEntity returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// re-initialize
pSMS->hManagerEntity = (HSNMP_ENTITY)NULL;
goto cleanup; // bail...
}
// attach timeout specified with manager
status = SnmpSetTimeout(pSMS->hManagerEntity, nTimeOut / 10); if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpSetTimeout returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
goto cleanup; // bail...
}
// attach retries specified with manager
status = SnmpSetRetry(pSMS->hManagerEntity, nRetries); if (WSNMP_FAILED(status)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpSetRetry returned %d.\n", SnmpGetLastError((HSNMP_SESSION)NULL) ));
goto cleanup; // bail...
} }
// validate pointer
if (pAgentCommunity != NULL) {
// transfer community string
smiCommunity.ptr = (smiLPBYTE)pAgentCommunity; smiCommunity.len = pAgentCommunity ? lstrlen(pAgentCommunity) : 0;
// obtain context from community string
pSMS->hViewContext = SnmpStrToContext( pSMS->hSnmpSession, &smiCommunity );
// validate context handle
if (WSNMP_FAILED(pSMS->hViewContext)) {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpStrToContext returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// re-initialize
pSMS->hViewContext = (HSNMP_CONTEXT)NULL;
goto cleanup; // bail...
} }
// success
return TRUE;
cleanup:
// cleanup resources
CloseSession(pSMS);
// failure
return FALSE; }
BOOL AllocateSession( PSNMP_MGR_SESSION * ppSMS )
/*++
Routine Description:
Allocate mgmtapi session structure.
Arguments:
ppSMS - pointer to session pointer to return.
Return Values:
Returns true if successful.
--*/
{ PSNMP_MGR_SESSION pSMS = NULL;
__try { // allocate new session table entry
pSMS = SnmpUtilMemAlloc(sizeof(SNMP_MGR_SESSION));
// validate pointer
if (pSMS != NULL) {
// initialize session level lock
InitializeCriticalSection(&pSMS->SessionLock);
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Could not allocate session.\n" ));
// notify application of error
SetLastError(SNMP_MEM_ALLOC_ERROR); }
// transfer
*ppSMS = pSMS; } __except(EXCEPTION_EXECUTE_HANDLER) { if (pSMS != NULL) { SnmpUtilMemFree(pSMS); pSMS = NULL; } }
// return status
return (pSMS != NULL); }
VOID FreeSession( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Frees mgmtapi session structure.
Arguments:
pSMS - pointer to mgmtapi session structure.
Return Values:
None.
--*/
{ // is session valid?
if (pSMS != NULL) {
// destroy the session level lock
DeleteCriticalSection(&pSMS->SessionLock);
// free session object
SnmpUtilMemFree(pSMS); } }
BOOL ProcessAgentResponse( PSNMP_MGR_SESSION pSMS )
/*++
Routine Description:
Message pump for notification window.
Arguments:
pSMS - pointer to MGMTAPI session structure.
Return Values:
Returns true if agent responded.
--*/
{ MSG msg; BOOL fOk = FALSE; BOOL fRet;
// validate session ptr
WSNMP_ASSERT(pSMS != NULL);
// get the next message for this session
while ((fRet = GetMessage(&msg, pSMS->hWnd, 0, 0))) { if (fRet == -1) { // If there is an error, GetMessage returns -1
pSMS->nLastError = SNMPAPI_OTHER_ERROR;
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: ProcessAgentResponse: GetMessage returns -1.\n" )); break; }
// check for private message
if (msg.message != WM_WSNMP_DONE) {
// translate message
TranslateMessage(&msg);
// dispatch message
DispatchMessage(&msg);
} else {
// success
fOk = TRUE;
break; } }
return fOk; }
DWORD WINAPI TrapThreadProc( LPVOID lpParam )
/*++
Routine Description:
Trap processing procedure.
Arguments:
lpParam - unused thread parameter.
Return Values:
Returns NOERROR if successful.
--*/
{ SNMPAPI_STATUS status; PSNMP_MGR_SESSION pSMS;
SNMPDBG(( SNMP_LOG_TRACE, "MGMTAPI: Trap thread starting...\n" ));
// obtain pointer
pSMS = &g_TrapSMS;
// re-initialize
ZeroMemory(&g_TrapSMS, sizeof(g_TrapSMS));
g_fIsTrapRegistered = FALSE; // init to failure. Note that there will
// be only 1 instance of this thread
// initialize winsnmp trap session
if (OpenSession(pSMS, NULL, NULL, 0, 0)) {
// register
status = SnmpRegister( pSMS->hSnmpSession, (HSNMP_ENTITY)NULL, // hAgentEntity
(HSNMP_ENTITY)NULL, // hManagerEntity
(HSNMP_CONTEXT)NULL, // hViewContext
(smiLPCOID)NULL, // notification
SNMPAPI_ON );
// validate return code
if (WSNMP_SUCCEEDED(status)) { // signal main thread that Trap has been registered with WinSNMP
g_fIsTrapRegistered = TRUE; SetEvent(g_hTrapRegisterdEvent);
// loop processing responses
while (ProcessAgentResponse(pSMS)) {
//
// processing done in window procedure...
//
}
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpRegister returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) ));
// transfer last error to global structure
pSMS->nLastError = SnmpGetLastError(pSMS->hSnmpSession);
// signal main thread that there is an error
// in registering Trap with WinSNMP
SetEvent(g_hTrapRegisterdEvent); }
} else {
// transfer last error to global structure
pSMS->nLastError = SnmpGetLastError((HSNMP_SESSION)NULL); // signal main thread that there is an error
// in registering Trap with WinSNMP
SetEvent(g_hTrapRegisterdEvent);
goto ERROR_OUT; }
if (g_fIsTrapRegistered) { // unregister WinSNMP notification reception
status = SnmpRegister( pSMS->hSnmpSession, (HSNMP_ENTITY)NULL, // hAgentEntity
(HSNMP_ENTITY)NULL, // hManagerEntity
(HSNMP_CONTEXT)NULL, // hViewContext
(smiLPCOID)NULL, // notification
SNMPAPI_OFF );
// validate return code
if (WSNMP_FAILED(status)) { SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpRegister SNMPAPI_OFF returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) )); } }
// free session
CloseSession(pSMS);
ERROR_OUT:
// obtain exclusive access
EnterCriticalSection(&g_GlobalLock);
// signal this thread has gone
g_fIsSnmpListening = FALSE;
// release exclusive access
LeaveCriticalSection(&g_GlobalLock);
SNMPDBG(( SNMP_LOG_TRACE, "MGMTAPI: Trap thread exiting...\n" ));
// success
return NOERROR; }
BOOL StartTrapsIfNecessary( HANDLE * phTrapAvailable )
/*++
Routine Description:
Initializes global structures for trap listening.
Arguments:
phTrapAvailable - pointer to event for signalling traps.
Return Values:
Returns true if successful (must be called only once).
--*/
{ BOOL fOk = FALSE; DWORD dwTrapThreadId; DWORD dwWaitTrapRegisterd;
// validate pointer
if (phTrapAvailable != NULL) {
// obtain exclusive access
EnterCriticalSection(&g_GlobalLock);
// transfer trap event to app
*phTrapAvailable = g_hTrapEvent;
// only start listening once
if (g_fIsSnmpListening == FALSE) {
// spawn client trap thread
g_hTrapThread = CreateThread( NULL, // lpThreadAttributes
0, // dwStackSize
TrapThreadProc, NULL, // lpParameter
0, // dwCreationFlags
&dwTrapThreadId );
if (g_hTrapThread != NULL) { // signal successful start
g_fIsSnmpListening = TRUE;
// release exclusive access
LeaveCriticalSection(&g_GlobalLock);
// WinSE bug 6182
// wait for TrapThreadProc to signal sucessful or failure
dwWaitTrapRegisterd = WaitForSingleObject(g_hTrapRegisterdEvent, INFINITE); if (dwWaitTrapRegisterd == WAIT_OBJECT_0) { if (g_fIsTrapRegistered == TRUE) fOk = TRUE; // success
else { CloseHandle(g_hTrapThread); g_hTrapThread = NULL; SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Traps are not accessible.\n" ));
} } else { CloseHandle(g_hTrapThread); g_hTrapThread = NULL; SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Traps are not accessible.\n" )); } // In case where fOk == TRUE, g_hTrapThread will be closed when
// - new app calls SnmpMgrClose(NULL)
// OR
// - DLL_PROCESS_DETACH in DllMain is called for legacy app.
} else { // release exclusive access
LeaveCriticalSection(&g_GlobalLock);
SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: CreateThread TrapThreadProc failed %d.\n", GetLastError() )); } } else {
// whine about having called this before
SetLastError(SNMP_MGMTAPI_TRAP_DUPINIT);
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: Duplicate registration detected.\n" )); // release exclusive access
LeaveCriticalSection(&g_GlobalLock); }
}
return fOk; }
///////////////////////////////////////////////////////////////////////////////
// //
// Dll Entry Point //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL DllMain( HANDLE hDll, DWORD dwReason, LPVOID lpReserved )
/*++
Routine Description:
Dll entry point.
Arguments:
hDll - module handle.
dwReason - reason DllMain is being called.
lpReserved - unused.
Return Values:
None.
--*/
{ BOOL bOk = TRUE;
__try { // determine reason for being called
if (dwReason == DLL_PROCESS_ATTACH) {
// initialize startup critical section
InitializeCriticalSection(&g_GlobalLock);
// initialize list of incoming traps
InitializeListHead(&g_IncomingTraps);
// optimize thread startup
DisableThreadLibraryCalls(hDll);
// save handle
g_hDll = hDll; } else if (dwReason == DLL_PROCESS_DETACH) { if (g_hTrapThread) { CloseHandle(g_hTrapThread); } // cleanup winsnmp
CleanupIfNecessary();
// nuke startup critical section
DeleteCriticalSection(&g_GlobalLock); }
} __except(EXCEPTION_EXECUTE_HANDLER) { bOk = FALSE; }
return bOk; }
///////////////////////////////////////////////////////////////////////////////
// //
// Public Procedures //
// //
///////////////////////////////////////////////////////////////////////////////
LPSNMP_MGR_SESSION SNMP_FUNC_TYPE SnmpMgrOpen( LPSTR pAgentAddress, LPSTR pAgentCommunity, INT nTimeOut, INT nRetries )
/*++
Routine Description:
Initializes resources necessary for communication with specified agent.
Arguments:
pAgentAddress - points to a null-terminated string specifying either a dotted-decimal IP address or a host name that can be resolved to an IP address, an IPX address (in 8.12 notation), or an ethernet address.
pAgentCommunity - points to a null-terminated string specifying the SNMP community name used when communicating with the agent specified in the lpAgentAddress parameter
nTimeOut - specifies the communications time-out in milliseconds.
nRetries - specifies the communications retry count.
Return Values:
Returns session handle if successful.
--*/
{ PSNMP_MGR_SESSION pSMS = NULL;
// initialize winsnmp
if (StartSnmpIfNecessary()) {
// allocate mgmtapi session
if (AllocateSession(&pSMS)) {
// open session
if (!OpenSession( pSMS, pAgentAddress, pAgentCommunity, nTimeOut, nRetries)) {
// free session
FreeSession(pSMS);
// reset
pSMS = NULL; } else { // add ref
AddMgmtRef(); } } }
// return opaque pointer
return (LPSNMP_MGR_SESSION)pSMS; }
BOOL SNMP_FUNC_TYPE SnmpMgrCtl( LPSNMP_MGR_SESSION session, // pointer to the MGMTAPI session
DWORD dwCtlCode, // control code for the command requested
LPVOID lpvInBuffer, // buffer with the input parameters for the operation
DWORD cbInBuffer, // size of lpvInBuffer in bytes
LPVOID lpvOUTBuffer, // buffer for all the output parameters of the command
DWORD cbOUTBuffer, // size of lpvOUTBuffer
LPDWORD lpcbBytesReturned // space used from lpvOutBuffer
) /*++
Routine Description:
Operates several control operations over the MGMTAPI session
Arguments:
pSession - pointer to the session to
Return Values:
--*/ { BOOL bOk = FALSE; PSNMP_MGR_SESSION pSMS = (PSNMP_MGR_SESSION)session;
switch(dwCtlCode) { case MGMCTL_SETAGENTPORT: if (pSMS == NULL) SetLastError(SNMP_MGMTAPI_INVALID_SESSION); else if (lpvInBuffer == NULL || cbInBuffer < sizeof(UINT)) SetLastError(SNMP_MGMTAPI_INVALID_BUFFER); else if (WSNMP_FAILED(SnmpSetPort(pSMS->hAgentEntity, *(UINT*)lpvInBuffer))) SetLastError(SnmpGetLastError(pSMS->hSnmpSession)); else bOk = TRUE; break;
default: SetLastError(SNMP_MGMTAPI_INVALID_CTL); break; }
return bOk; }
BOOL SNMP_FUNC_TYPE SnmpMgrClose( LPSNMP_MGR_SESSION session )
/*++
Routine Description:
Cleanups resources needed for communication with specified agent.
Arguments:
session - points to an internal structure that specifies which session to close.
Return Values:
Returns true if successful.
Notes: BUG: 585652 -Cleanup WinSNMP resources if reference count on using mgmtapi.dll reaches 0 -SnmpMgrClose(NULL) is used to cleanup resources created by SnmpMgrTrapListen
--*/
{ BOOL fOk = TRUE; DWORD dwWaitResult; PSNMP_MGR_SESSION pSMS = (PSNMP_MGR_SESSION)session;
// validate pointer
if (pSMS != NULL) {
// close session
CloseSession(pSMS);
// free session
FreeSession(pSMS);
// release ref
ReleaseMgmtRef(); } else if (g_fIsSnmpListening && g_TrapSMS.hWnd && g_hTrapThread) { if (PostMessage(g_TrapSMS.hWnd, WM_QUIT, (WPARAM)0, (LPARAM)0)) { // block until TrapThreadProc has gone
dwWaitResult = WaitForSingleObject(g_hTrapThread, INFINITE); switch (dwWaitResult) { case WAIT_OBJECT_0 : SNMPDBG(( SNMP_LOG_TRACE, "MGMTAPI: SnmpMgrClose: TrapThreadProc exited.\n" )); break;
case WAIT_FAILED: SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpMgrClose: WaitForSingleObject returned WAIT_FAILED %u.\n", GetLastError() )); break; default : SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpMgrClose: WaitForSingleObject returned %u.\n", dwWaitResult )); break; } } else { fOk = FALSE;
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpMgrClose: PostMessage returned %u.\n", GetLastError() )); }
if (! CloseHandle(g_hTrapThread)) { SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpMgrClose: CloseHandle on %u returned %u.\n", g_hTrapThread, GetLastError() )); } g_hTrapThread = NULL;
// release ref
ReleaseMgmtRef(); }
return fOk; }
SNMPAPI SNMP_FUNC_TYPE SnmpMgrRequest( LPSNMP_MGR_SESSION session, BYTE requestType, SnmpVarBindList * pVarBindList, AsnInteger * pErrorStatus, AsnInteger * pErrorIndex )
/*++
Routine Description:
Requests the specified operation be performed with the specified agent.
Arguments:
session - points to an internal structure that specifies the session that will perform the request.
requestType - specifies the SNMP request type.
pVarBindList - points to the variable bindings list
pErrorStatus - points to a variable in which the error status result will be returned.
pErrorIndex - points to a variable in which the error index result will be returned.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = FALSE; SNMPAPI_STATUS status; PSNMP_MGR_SESSION pSMS = (PSNMP_MGR_SESSION)session;
// validate pointers
if ((pSMS != NULL) && (pErrorIndex != NULL) && (pErrorStatus != NULL) && (pVarBindList != NULL) && (pVarBindList->len != 0) && (pVarBindList->list != NULL)) {
// obtain exclusive access to session
EnterCriticalSection(&pSMS->SessionLock);
// initialize session structure
pSMS->pVarBindList = pVarBindList; pSMS->nPduType = (smiINT32)(BYTE)requestType; pSMS->hVbl = (HSNMP_VBL)NULL; pSMS->hPdu = (HSNMP_PDU)NULL; pSMS->nErrorStatus = 0; pSMS->nErrorIndex = 0; pSMS->nLastError = 0;
// allocate resources
if (AllocatePdu(pSMS)) {
// actually send
status = SnmpSendMsg( pSMS->hSnmpSession, pSMS->hManagerEntity, pSMS->hAgentEntity, pSMS->hViewContext, pSMS->hPdu );
// release now
FreePdu(pSMS);
// validate return code
if (WSNMP_SUCCEEDED(status)) {
// process agent response
if (ProcessAgentResponse(pSMS) && (pSMS->nLastError == SNMP_ERROR_NOERROR)) {
// update error status and index
*pErrorStatus = pSMS->nErrorStatus; *pErrorIndex = pSMS->nErrorIndex;
// success
fOk = TRUE;
} else {
// set error to winsnmp error
SetLastError(pSMS->nLastError);
// failure
fOk = FALSE; }
} else {
SNMPDBG(( SNMP_LOG_ERROR, "MGMTAPI: SnmpSendMsg returned %d.\n", SnmpGetLastError(pSMS->hSnmpSession) )); } }
// release exclusive access to session
LeaveCriticalSection(&pSMS->SessionLock); }
return fOk; }
BOOL SNMP_FUNC_TYPE SnmpMgrStrToOid( LPSTR pString, AsnObjectIdentifier * pOID )
/*++
Routine Description:
Converts a string object identifier or object descriptor representation to an internal object identifier.
Arguments:
pString - points to a null-terminated string to be converted.
pOID - points to an object identifier variable that will receive the converted value.
Return Values:
Returns true if successful.
--*/
{ // validate pointer to oid and string
if ((pOID != NULL) && (pString != NULL)) {
// forward to mibcc code for now
return SnmpMgrText2Oid(pString, pOID); }
return FALSE; }
BOOL SNMP_FUNC_TYPE SnmpMgrOidToStr( AsnObjectIdentifier * pOID, LPSTR * ppString )
/*++
Routine Description:
Converts an internal object identifier to a string object identifier or object descriptor representation.
Arguments:
pOID - pointers to object identifier to be converted.
ppString - points to string pointer to receive converted value.
Return Values:
Returns true if successful.
--*/
{ // validate pointer to oid and string
if ((pOID != NULL) && (ppString != NULL)) {
// forward to mibcc code for now
return SnmpMgrOid2Text(pOID, ppString); }
return FALSE; }
BOOL SNMP_FUNC_TYPE SnmpMgrTrapListen( HANDLE * phTrapAvailable )
/*++
Routine Description:
Registers the ability of a manager application to receive SNMP traps.
Arguments:
phTrapAvailable - points to an event handle that will be used to indicate that there are traps available
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = FALSE;
// startup winsnmp
if (StartSnmpIfNecessary()) {
// spawn only one trap client thread
if (StartTrapsIfNecessary(phTrapAvailable)) {
// success
fOk = TRUE;
// add ref
AddMgmtRef(); } }
return fOk; }
BOOL SNMP_FUNC_TYPE SnmpMgrGetTrap( AsnObjectIdentifier * pEnterpriseOID, AsnNetworkAddress * pAgentAddress, AsnInteger * pGenericTrap, AsnInteger * pSpecificTrap, AsnTimeticks * pTimeStamp, SnmpVarBindList * pVarBindList )
/*++
Routine Description:
Returns outstanding trap data that the caller has not received if trap reception is enabled.
Arguments:
pEnterpriseOID - points to an object identifier that specifies the enterprise that generated the SNMP trap
pAgentAddress - points to the address of the agent that generated the SNMP trap (retrieved from PDU).
pGenericTrap - points to an indicator of the generic trap id.
pSpecificTrap - points to an indicator of the specific trap id.
pTimeStamp - points to a variable to receive the time stamp.
pVarBindList - points to the associated variable bindings.
Return Values:
Returns true if successful.
--*/
{ // forward to new api
return SnmpMgrGetTrapEx( pEnterpriseOID, pAgentAddress, NULL, pGenericTrap, pSpecificTrap, NULL, pTimeStamp, pVarBindList ); }
BOOL SNMP_FUNC_TYPE SnmpMgrGetTrapEx( AsnObjectIdentifier * pEnterpriseOID, AsnNetworkAddress * pAgentAddress, AsnNetworkAddress * pSourceAddress, AsnInteger * pGenericTrap, AsnInteger * pSpecificTrap, AsnOctetString * pCommunity, AsnTimeticks * pTimeStamp, SnmpVarBindList * pVarBindList )
/*++
Routine Description:
Returns outstanding trap data that the caller has not received if trap reception is enabled.
Arguments:
pEnterpriseOID - points to an object identifier that specifies the enterprise that generated the SNMP trap
pAgentAddress - points to the address of the agent that generated the SNMP trap (retrieved from PDU).
pSourceAddress - points to the address of the agent that generated the SNMP trap (retrieved from network transport).
pGenericTrap - points to an indicator of the generic trap id.
pSpecificTrap - points to an indicator of the specific trap id.
pCommunity - points to structure to receive community string.
pTimeStamp - points to a variable to receive the time stamp.
pVarBindList - points to the associated variable bindings.
Return Values:
Returns true if successful.
--*/
{ BOOL fOk = FALSE; PLIST_ENTRY pLE = NULL; PTRAP_LIST_ENTRY pTLE = NULL; smiINT32 nLastError;
// obtain exclusive access
EnterCriticalSection(&g_GlobalLock);
// make sure list has entries
if (!IsListEmpty(&g_IncomingTraps)) {
// remove first item from list
pLE = RemoveHeadList(&g_IncomingTraps);
} else {
// check for trap thread failure
nLastError = g_TrapSMS.nLastError; }
// release exclusive access
LeaveCriticalSection(&g_GlobalLock);
// validate pointer
if (pLE != NULL) {
// retrieve pointer to trap list entry
pTLE = CONTAINING_RECORD(pLE, TRAP_LIST_ENTRY, Link);
// validate pointer
if (pEnterpriseOID != NULL) {
// manually copy enterprise oid
*pEnterpriseOID = pTLE->EnterpriseOID;
// re-initialize list entry
pTLE->EnterpriseOID.ids = NULL; pTLE->EnterpriseOID.idLength = 0; }
// validate pointer
if (pCommunity != NULL) {
// transfer string info
*pCommunity = pTLE->Community;
// re-initialize list entry
pTLE->Community.length = 0; pTLE->Community.stream = NULL; pTLE->Community.dynamic = FALSE; }
// validate pointer
if (pVarBindList != NULL) {
// transfer varbindlist
*pVarBindList = pTLE->VarBindList;
// re-initialize list entry
pTLE->VarBindList.len = 0; pTLE->VarBindList.list = NULL; }
// validate pointer
if (pAgentAddress != NULL) {
// copy structure
*pAgentAddress = pTLE->AgentAddress; // remove our reference
pTLE->AgentAddress.length = 0; pTLE->AgentAddress.stream = NULL; pTLE->AgentAddress.dynamic = FALSE; }
// validate pointer
if (pSourceAddress != NULL) {
// copy structure
*pSourceAddress = pTLE->SourceAddress; // remove our reference
pTLE->SourceAddress.length = 0; pTLE->SourceAddress.stream = NULL; pTLE->SourceAddress.dynamic = FALSE; }
// validate pointer
if (pGenericTrap != NULL) {
// transfer generic trap info
*pGenericTrap = pTLE->nGenericTrap; }
// validate pointer
if (pSpecificTrap != NULL) {
// transfer generic trap info
*pSpecificTrap = pTLE->nSpecificTrap; }
// validate pointer
if (pTimeStamp != NULL) {
// transfer time info
*pTimeStamp = pTLE->TimeStamp; }
// release
FreeTle(pTLE);
// success
fOk = TRUE;
} else if (nLastError != NOERROR) {
// indicate there was an thread error
SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
} else {
// indicate there are no traps
SetLastError(SNMP_MGMTAPI_NOTRAPS); }
return fOk; }
|