You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3882 lines
94 KiB
3882 lines
94 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|