mirror of https://github.com/lianthony/NT4.0
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.
1948 lines
62 KiB
1948 lines
62 KiB
/*++
|
|
|
|
Copyright (c) 1992-1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mgmtapi.c
|
|
|
|
Abstract:
|
|
|
|
SNMP Management API.
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
10-May-1996 DonRyan
|
|
Removed banner from Technology Dynamics, Inc.
|
|
|
|
--*/
|
|
|
|
//--------------------------- WINDOWS DEPENDENCIES --------------------------
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
//--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
|
|
|
|
#include <winsock.h>
|
|
#include <wsipx.h>
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
|
|
//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
|
|
|
|
#include <snmp.h>
|
|
#include <snmputil.h>
|
|
#include "..\common\wellknow.h"
|
|
|
|
#include <mgmtapi.h>
|
|
#include <oidconv.h>
|
|
|
|
//--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
|
|
|
|
//--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
|
|
|
|
//--------------------------- PRIVATE CONSTANTS -----------------------------
|
|
|
|
#define SNMPMGRTRAPPIPE "\\\\.\\PIPE\\MGMTAPI"
|
|
|
|
#define pipeThreadTO INFINITE
|
|
#define generalMutexTO INFINITE
|
|
#define trapServerConnectTO 30000 // 30 seconds
|
|
#define trapThreadTO 30 // 30 seconds
|
|
|
|
#define NPOLLFILE 2 // UDP and IPX
|
|
#define MAX_OUT_BUFS 16
|
|
#define MAX_SESSIONS 64
|
|
#define MAX_PENDING_WAIT 1000
|
|
#define RECVBUFSIZE 4096
|
|
|
|
#define IPX_PACKET_TYPE 4
|
|
#define IPX_PROTOCOL_TYPE (NSPROTO_IPX+IPX_PACKET_TYPE)
|
|
|
|
#define IP_ADDR_SIZE 4
|
|
#define IPX_ADDR_SIZE 10
|
|
|
|
//--------------------------- PRIVATE STRUCTS -------------------------------
|
|
|
|
typedef VOID (* TRAP_THREAD_CALLBACK)(HANDLE *hTrapThreadExitEvent);
|
|
|
|
typedef struct _SNMP_MGR_SESSION {
|
|
SOCKET fd; // socket
|
|
struct sockaddr destAddr; // destination agent address
|
|
LPSTR community; // community name
|
|
INT timeout; // comm time-out (milliseconds)
|
|
INT retries; // comm retry count
|
|
AsnInteger requestId; // RFC1157 requestId
|
|
CRITICAL_SECTION recvBufCritSec; // serialize access
|
|
char recvBuf[RECVBUFSIZE]; // receive buffer
|
|
} SNMP_MGR_SESSION, *PSNMP_MGR_SESSION;
|
|
|
|
typedef struct _SNMP_MGR_TRAP {
|
|
struct sockaddr Addr;
|
|
int AddrLen;
|
|
char TrapBuf[RECVBUFSIZE];
|
|
} SNMP_MGR_TRAP, *PSNMP_MGR_TRAP;
|
|
|
|
#define AGENT_ADDR_LEN ((LONG)&(((PSNMP_MGR_TRAP)0)->TrapBuf))
|
|
|
|
//--------------------------- PRIVATE VARIABLES -----------------------------
|
|
|
|
OSVERSIONINFO OSVersionInfo;
|
|
|
|
SECURITY_ATTRIBUTES S_Attrib;
|
|
SECURITY_DESCRIPTOR S_Desc;
|
|
|
|
static INT fdarrayLen;
|
|
static SOCKET fdarray[NPOLLFILE];
|
|
|
|
static struct fd_set readfds;
|
|
static struct fd_set exceptfds;
|
|
|
|
static INT g_RequestId = 0;
|
|
static CRITICAL_SECTION g_RequestIdCritSec;
|
|
|
|
static INT g_IpxProtocolType = IPX_PROTOCOL_TYPE;
|
|
|
|
static SNMP_MGR_SESSION * g_SessionTable[MAX_SESSIONS];
|
|
static CRITICAL_SECTION g_SessionTableCritSec;
|
|
|
|
static DWORD g_ClientTrapStatus = ERROR_NOT_READY;
|
|
static CRITICAL_SECTION g_ClientTrapStatusCritSec;
|
|
|
|
//--------------------------- PRIVATE PROTOTYPES ----------------------------
|
|
|
|
BOOL StartServiceIfNecessary();
|
|
|
|
//--------------------------- PRIVATE PROCEDURES ----------------------------
|
|
|
|
#define bcopy(slp, dlp, size) (void)memcpy(dlp, slp, size)
|
|
#define bzero(lp, size) (void)memset(lp, 0, size)
|
|
typedef struct { unsigned char addr[6]; } IPX_NODENUM;
|
|
|
|
#if 1 /* ll utilities */
|
|
|
|
/* ******** List head/node ******** */
|
|
|
|
typedef struct ll_s { /* linked list structure */
|
|
struct ll_s *next; /* next node */
|
|
struct ll_s *prev; /* prev. node */
|
|
}ll_node; /* linked list node */
|
|
|
|
/* ******** INITIALIZE A LIST HEAD ******** */
|
|
|
|
#define ll_init(head) (head)->next = (head)->prev = (head);
|
|
|
|
/* ******** ADD AN ITEM TO THE END OF A LIST ******** */
|
|
|
|
#define ll_adde(item,head)\
|
|
{\
|
|
ll_node *pred = (head)->prev;\
|
|
((ll_node *)(item))->next = (head);\
|
|
((ll_node *)(item))->prev = pred;\
|
|
(pred)->next = ((ll_node *)(item));\
|
|
(head)->prev = ((ll_node *)(item));\
|
|
}
|
|
|
|
/* ******** TEST A LIST FOR EMPTY ******** */
|
|
|
|
#define ll_empt(head) ( ((head)->next) == (head) )
|
|
|
|
/* ******** INTERNAL REMOVE CODE ******** */
|
|
|
|
#define ll_rmvi(item,pred,succ)\
|
|
(pred)->next = (succ);\
|
|
(succ)->prev = (pred);
|
|
|
|
/* ******** REMOVE AN ITEM FROM A LIST ******** */
|
|
|
|
#define ll_rmv(item)\
|
|
{\
|
|
ll_node *pred = ((ll_node *)(item))->prev;\
|
|
ll_node *succ = ((ll_node *)(item))->next;\
|
|
pred->next = succ;\
|
|
succ->prev = pred;\
|
|
}
|
|
|
|
/* ******** REMOVE ITEM FROM BEGINNING OF LIST ******** */
|
|
|
|
#define ll_rmvb(item,head)\
|
|
if ( (((ll_node *)(item)) = (head)->next) == (head)){\
|
|
item = 0;\
|
|
} else {\
|
|
{\
|
|
ll_node *succ = ((ll_node *)(item))->next;\
|
|
(head)->next = succ;\
|
|
succ->prev = (head);\
|
|
}\
|
|
}
|
|
|
|
/* ******** Get ptr to first member of linked list (null if none) ******** */
|
|
|
|
#define ll_first(head)\
|
|
((head)->next == (head) ? 0 : (head)->next)
|
|
|
|
/* ******** Get ptr to next entry ******** */
|
|
|
|
#define ll_next(item,head)\
|
|
( (ll_node *)(item)->next == (head) ? 0 : \
|
|
(ll_node *)(item)->next )
|
|
|
|
#endif
|
|
|
|
BOOL StartServiceIfNecessary()
|
|
{
|
|
SC_HANDLE scmHandle = NULL;
|
|
SC_HANDLE svcHandle = NULL;
|
|
SERVICE_STATUS svcStatusInfo;
|
|
BOOL fOk = FALSE;
|
|
|
|
scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
|
|
if (scmHandle == NULL)
|
|
goto cleanup;
|
|
|
|
svcHandle = OpenService(
|
|
scmHandle,
|
|
TEXT("SNMPTRAP"),
|
|
SERVICE_START |
|
|
SERVICE_QUERY_STATUS
|
|
);
|
|
|
|
if (svcHandle == NULL)
|
|
goto cleanup;
|
|
|
|
fOk = QueryServiceStatus(svcHandle, &svcStatusInfo);
|
|
|
|
while (fOk)
|
|
{
|
|
|
|
switch (svcStatusInfo.dwCurrentState)
|
|
{
|
|
case SERVICE_RUNNING:
|
|
goto cleanup;
|
|
|
|
case SERVICE_STOPPED:
|
|
// manually change the status to pending
|
|
svcStatusInfo.dwCurrentState = SERVICE_START_PENDING;
|
|
|
|
fOk = StartService(svcHandle, 0, NULL);
|
|
break;
|
|
|
|
case SERVICE_STOP_PENDING:
|
|
case SERVICE_START_PENDING:
|
|
// wait before querying
|
|
Sleep(MAX_PENDING_WAIT);
|
|
|
|
fOk = QueryServiceStatus(svcHandle, &svcStatusInfo);
|
|
break;
|
|
|
|
case SERVICE_PAUSED:
|
|
case SERVICE_CONTINUE_PENDING:
|
|
case SERVICE_PAUSE_PENDING:
|
|
default:
|
|
fOk = FALSE; // only start if stopped...
|
|
break;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (scmHandle)
|
|
CloseServiceHandle(scmHandle);
|
|
|
|
if (svcHandle)
|
|
CloseServiceHandle(svcHandle);
|
|
|
|
return fOk;
|
|
}
|
|
|
|
|
|
PSNMP_MGR_SESSION
|
|
AllocateSession(
|
|
)
|
|
{
|
|
INT i;
|
|
PSNMP_MGR_SESSION SessionInfo = NULL;
|
|
|
|
// gain exclusive access to session table
|
|
EnterCriticalSection(&g_SessionTableCritSec);
|
|
|
|
// process each entry in table
|
|
for (i = 0; i < MAX_SESSIONS; i++)
|
|
{
|
|
// look for available session
|
|
if (g_SessionTable[i] != NULL)
|
|
{
|
|
// reuse session object
|
|
SessionInfo = g_SessionTable[i];
|
|
// reset session pointer
|
|
g_SessionTable[i] = NULL;
|
|
// done...
|
|
break;
|
|
}
|
|
}
|
|
|
|
// release lock on session table
|
|
LeaveCriticalSection(&g_SessionTableCritSec);
|
|
|
|
// is table empty?
|
|
if (SessionInfo == NULL)
|
|
{
|
|
// allocate new session table entry
|
|
if ((SessionInfo = SnmpUtilMemAlloc(sizeof(SNMP_MGR_SESSION))) == NULL)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: out of memory"));
|
|
|
|
SetLastError(SNMP_MEM_ALLOC_ERROR);
|
|
}
|
|
}
|
|
|
|
return SessionInfo;
|
|
}
|
|
|
|
|
|
VOID
|
|
ReleaseSession(
|
|
PSNMP_MGR_SESSION SessionInfo
|
|
)
|
|
{
|
|
INT i;
|
|
|
|
// is session valid?
|
|
if (SessionInfo != NULL)
|
|
{
|
|
// gain exclusive access to session table
|
|
EnterCriticalSection(&g_SessionTableCritSec);
|
|
|
|
// process each entry in table
|
|
for (i = 0; i < MAX_SESSIONS; i++)
|
|
{
|
|
// look for an empty entry
|
|
if (g_SessionTable[i] == NULL)
|
|
{
|
|
// zero out session object for next time...
|
|
memset(SessionInfo, 0, sizeof(SNMP_MGR_SESSION));
|
|
// save session object
|
|
g_SessionTable[i] = SessionInfo;
|
|
// reset session pointer
|
|
SessionInfo = NULL;
|
|
// done...
|
|
break;
|
|
}
|
|
}
|
|
|
|
// release lock on session table
|
|
LeaveCriticalSection(&g_SessionTableCritSec);
|
|
}
|
|
|
|
// is table full?
|
|
if (SessionInfo != NULL)
|
|
{
|
|
// free session object
|
|
SnmpUtilMemFree(SessionInfo);
|
|
}
|
|
}
|
|
|
|
|
|
INT
|
|
GetRequestId(
|
|
)
|
|
{
|
|
INT RequestId;
|
|
|
|
// gain exclusive access to request id
|
|
EnterCriticalSection(&g_RequestIdCritSec);
|
|
// write value to stack
|
|
RequestId = g_RequestId++;
|
|
// release lock on request id
|
|
LeaveCriticalSection(&g_RequestIdCritSec);
|
|
|
|
return RequestId;
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetClientTrapStatus(
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
// gain exclusive access to client trap status
|
|
EnterCriticalSection(&g_ClientTrapStatusCritSec);
|
|
// write value to stack
|
|
Status = g_ClientTrapStatus;
|
|
// release lock on status
|
|
LeaveCriticalSection(&g_ClientTrapStatusCritSec);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
SetClientTrapStatus(
|
|
DWORD Status
|
|
)
|
|
{
|
|
// gain exclusive access to client trap status
|
|
EnterCriticalSection(&g_ClientTrapStatusCritSec);
|
|
// write value to stack
|
|
g_ClientTrapStatus = Status;
|
|
// release lock on status
|
|
LeaveCriticalSection(&g_ClientTrapStatusCritSec);
|
|
}
|
|
|
|
//--------------------------- PUBLIC PROCEDURES -----------------------------
|
|
|
|
// dll initialization processing
|
|
|
|
BOOL DllEntryPoint(
|
|
HANDLE hDll,
|
|
DWORD dwReason,
|
|
LPVOID lpReserved)
|
|
{
|
|
static WORD NumUses = 0;
|
|
|
|
DWORD dwError;
|
|
DWORD dwResult;
|
|
|
|
|
|
|
|
|
|
// Handle any required attach/detach actions.
|
|
|
|
switch(dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
// record operating system version
|
|
OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
if (!GetVersionEx(&OSVersionInfo)) {
|
|
SNMPDBG((SNMP_LOG_ERROR,"MGMTAPI: INIT: error %d determining platform.\n",GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
// verify correct operating system
|
|
if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
|
SNMPDBG((SNMP_LOG_TRACE,"MGMTAPI: INIT: platform is Windows NT.\n"));
|
|
} else if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
|
SNMPDBG((SNMP_LOG_TRACE,"MGMTAPI: INIT: platform is Windows 95.\n"));
|
|
} else {
|
|
SNMPDBG((SNMP_LOG_ERROR,"MGMTAPI: INIT: platform 0x%08lx is not supported.\n",OSVersionInfo.dwPlatformId));
|
|
return FALSE;
|
|
}
|
|
|
|
// construct security decsriptor
|
|
InitializeSecurityDescriptor(
|
|
&S_Desc, SECURITY_DESCRIPTOR_REVISION);
|
|
|
|
(VOID) SetSecurityDescriptorDacl(
|
|
&S_Desc, TRUE, NULL, FALSE);
|
|
|
|
S_Attrib.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
S_Attrib.lpSecurityDescriptor = &S_Desc;
|
|
S_Attrib.bInheritHandle = TRUE;
|
|
|
|
InitializeCriticalSection(&g_RequestIdCritSec);
|
|
InitializeCriticalSection(&g_SessionTableCritSec);
|
|
InitializeCriticalSection(&g_ClientTrapStatusCritSec);
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
DeleteCriticalSection(&g_RequestIdCritSec);
|
|
DeleteCriticalSection(&g_SessionTableCritSec);
|
|
DeleteCriticalSection(&g_ClientTrapStatusCritSec);
|
|
break;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
|
|
default:
|
|
|
|
// Nothing to do.
|
|
|
|
|
|
break;
|
|
|
|
|
|
} // end switch()
|
|
|
|
return TRUE;
|
|
|
|
} // end DllEntryPoint()
|
|
|
|
|
|
// request/response processing
|
|
|
|
LPSNMP_MGR_SESSION
|
|
SNMP_FUNC_TYPE SnmpMgrOpen(
|
|
IN LPSTR lpAgentAddress, // Name/address of target SNMP agent
|
|
IN LPSTR lpAgentCommunity, // Community for target SNMP agent
|
|
IN INT nTimeOut, // Communication time-out in milliseconds
|
|
IN INT nRetries) // Communication time-out/retry count
|
|
{
|
|
SOCKET fd;
|
|
struct sockaddr localAddress;
|
|
struct sockaddr destAddress;
|
|
struct sockaddr_in Address_in;
|
|
PSNMP_MGR_SESSION SessionInfo;
|
|
LPSTR addrText;
|
|
DWORD size = 0;
|
|
WSADATA WinSockData;
|
|
|
|
// Establish a socket for this session.
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: SnmpMgrOpen entered.\n"));
|
|
if (WSAStartup((WORD)0x0101, &WinSockData)) {
|
|
SNMPDBG((SNMP_LOG_ERROR,"MGMTAPI: MGMT: error %d initializing WinSock.\n",GetLastError()));
|
|
return (LPSNMP_MGR_SESSION)0;
|
|
}
|
|
|
|
if (!SnmpSvcAddrToSocket(lpAgentAddress, &destAddress)) {
|
|
SNMPDBG((SNMP_LOG_ERROR,"MGMTAPI: MGMT: error %d resolving target agent's address.\n",GetLastError()));
|
|
return (LPSNMP_MGR_SESSION)0;
|
|
}
|
|
|
|
|
|
switch (destAddress.sa_family) {
|
|
|
|
case AF_INET:
|
|
{
|
|
struct sockaddr_in localAddress_in;
|
|
|
|
bcopy(&destAddress, &Address_in, sizeof(destAddress));
|
|
Address_in.sin_port = htons(WKSN_UDP_GETSET);
|
|
bcopy(&Address_in, &destAddress, sizeof(destAddress));
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: SnmpMgrOpen AF_INET.\n"));
|
|
localAddress_in.sin_family = AF_INET;
|
|
localAddress_in.sin_port = htons(0);
|
|
localAddress_in.sin_addr.s_addr = ntohl(INADDR_ANY);
|
|
bcopy(&localAddress_in, &localAddress, sizeof(localAddress_in));
|
|
} // end block.
|
|
|
|
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == (SOCKET)-1) {
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error %d creating udp snmp socket.\n", GetLastError()));
|
|
//SetLastError(<let the winsock error be the error>);
|
|
return (LPSNMP_MGR_SESSION)0;
|
|
}
|
|
break;
|
|
|
|
case AF_IPX:
|
|
{
|
|
struct sockaddr_ipx localAddress_ipx;
|
|
|
|
bcopy(&destAddress, &localAddress_ipx, sizeof(localAddress_ipx));
|
|
localAddress_ipx.sa_socket = htons(WKSN_IPX_GETSET);
|
|
bcopy(&localAddress_ipx, &destAddress, sizeof(localAddress_ipx));
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: SnmpMgrOpen AF_IPX.\n"));
|
|
bzero(&localAddress_ipx, sizeof(localAddress_ipx));
|
|
localAddress_ipx.sa_family = AF_IPX;
|
|
bcopy(&localAddress_ipx, &localAddress, sizeof(localAddress_ipx));
|
|
}
|
|
|
|
if ( ((fd = socket(AF_IPX, SOCK_DGRAM, g_IpxProtocolType )) == (SOCKET)-1 )
|
|
&& ((fd = socket(AF_IPX, SOCK_DGRAM, (g_IpxProtocolType=NSPROTO_IPX) )) == (SOCKET)-1) ) {
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error %d creating ipx snmp socket.\n", GetLastError()));
|
|
//SetLastError(<let the winsock error be the error>);
|
|
return (LPSNMP_MGR_SESSION)0;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return (LPSNMP_MGR_SESSION)0;
|
|
|
|
}
|
|
|
|
if (bind(fd, &localAddress, sizeof(localAddress)) != 0) {
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error %d binding snmp socket.\n", GetLastError()));
|
|
//SetLastError(<let the winsock error be the error>);
|
|
return (LPSNMP_MGR_SESSION)0;
|
|
}
|
|
|
|
if ((SessionInfo = AllocateSession()) == NULL) {
|
|
return (LPSNMP_MGR_SESSION)0;
|
|
}
|
|
|
|
InitializeCriticalSection(&SessionInfo->recvBufCritSec);
|
|
|
|
bcopy(&destAddress, &Address_in, sizeof(destAddress));
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: destAddress = %s.\n", inet_ntoa(Address_in.sin_addr)));
|
|
SessionInfo->fd = fd;
|
|
bcopy(&destAddress, &(SessionInfo->destAddr), sizeof(destAddress));
|
|
if ((SessionInfo->community = (LPSTR)SnmpUtilMemAlloc(strlen(lpAgentCommunity) + 1)) ==
|
|
NULL)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: out of memory.\n"));
|
|
|
|
ReleaseSession(SessionInfo);
|
|
|
|
SetLastError(SNMP_MEM_ALLOC_ERROR);
|
|
return (LPSNMP_MGR_SESSION)0;
|
|
}
|
|
strcpy(SessionInfo->community, lpAgentCommunity);
|
|
SessionInfo->timeout = nTimeOut;
|
|
SessionInfo->retries = nRetries;
|
|
SessionInfo->requestId = 0;
|
|
|
|
// Return session pointer.
|
|
|
|
return (LPSNMP_MGR_SESSION)SessionInfo;
|
|
|
|
} // end SnmpMgrOpen()
|
|
|
|
|
|
BOOL
|
|
SNMP_FUNC_TYPE SnmpMgrClose(
|
|
IN LPSNMP_MGR_SESSION session) // SNMP session pointer
|
|
{
|
|
PSNMP_MGR_SESSION SessionInfo = (PSNMP_MGR_SESSION)session;
|
|
|
|
// Close the socket.
|
|
|
|
if (closesocket(SessionInfo->fd) == SOCKET_ERROR)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error %d closing snmp socket.\n", GetLastError()));
|
|
|
|
//SetLastError(<let the winsock error be the error>);
|
|
return FALSE;
|
|
}
|
|
|
|
DeleteCriticalSection(&SessionInfo->recvBufCritSec);
|
|
|
|
SnmpUtilMemFree(SessionInfo->community);
|
|
|
|
ReleaseSession(SessionInfo);
|
|
|
|
return TRUE;
|
|
|
|
} // end SnmpMgrClose()
|
|
|
|
|
|
SNMPAPI
|
|
SNMP_FUNC_TYPE SnmpMgrRequest(
|
|
IN LPSNMP_MGR_SESSION session, // SNMP session pointer
|
|
IN BYTE requestType, // Get, GetNext, or Set
|
|
IN OUT RFC1157VarBindList *variableBindings, // Varible bindings
|
|
OUT AsnInteger *errorStatus, // Result error status
|
|
OUT AsnInteger *errorIndex) // Result error index
|
|
{
|
|
SnmpMgmtCom request;
|
|
SnmpMgmtCom response;
|
|
BYTE *pBuf;
|
|
UINT pBufLen;
|
|
UINT packetType;
|
|
int recvLength;
|
|
struct sockaddr_in Address_in;
|
|
DWORD dwResult;
|
|
PSNMP_MGR_SESSION SessionInfo = (PSNMP_MGR_SESSION)session;
|
|
|
|
// Setup the request.
|
|
|
|
request.dstParty.idLength = 0; // Secure SNMP not implemented.
|
|
request.dstParty.ids = NULL; // Secure SNMP not implemented.
|
|
request.srcParty.idLength = 0; // Secure SNMP not implemented.
|
|
request.srcParty.ids = NULL; // Secure SNMP not implemented.
|
|
|
|
request.pdu.pduType = requestType;
|
|
request.pdu.pduValue.pdu.errorStatus = 0;
|
|
request.pdu.pduValue.pdu.errorIndex = 0;
|
|
request.pdu.pduValue.pdu.varBinds = *variableBindings; // NOTE! struct copy
|
|
|
|
request.community.length = strlen(SessionInfo->community);
|
|
request.community.stream = (BYTE *)SnmpUtilMemAlloc(request.community.length);
|
|
memcpy(request.community.stream, SessionInfo->community,
|
|
request.community.length);
|
|
|
|
// Send/Receive request to/from destination agent.
|
|
// Appropriately handle time-out/retry for send/recv processing.
|
|
|
|
// Acquire exclusive access to session buffer
|
|
EnterCriticalSection(&SessionInfo->recvBufCritSec);
|
|
|
|
//block...
|
|
{
|
|
INT retries = SessionInfo->retries;
|
|
INT timeout = SessionInfo->timeout;
|
|
SOCKET fdarray[1];
|
|
struct fd_set readfds;
|
|
struct fd_set exceptfds;
|
|
struct timeval timeval;
|
|
INT fdarrayLen = 1;
|
|
int numReady;
|
|
struct sockaddr source;
|
|
int sourceLen;
|
|
LONG expireTime;
|
|
LONG remainingTime;
|
|
|
|
|
|
fdarray[0] = SessionInfo->fd;
|
|
|
|
|
|
timeval.tv_sec = timeout / 1000;
|
|
timeval.tv_usec = ((timeout % 1000) * 1000);
|
|
expireTime = (LONG)GetCurrentTime() + timeout;
|
|
|
|
|
|
do
|
|
{
|
|
// Encode the request.
|
|
|
|
SessionInfo->requestId = GetRequestId();
|
|
request.pdu.pduValue.pdu.requestId = SessionInfo->requestId;
|
|
pBuf = NULL;
|
|
pBufLen = 0;
|
|
if (!SnmpSvcEncodeMessage(ASN_SEQUENCE, &request, &pBuf, &pBufLen))
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: error on SnmpSvcEncodeMessage %d.\n",
|
|
GetLastError()));
|
|
|
|
//SetLastError(<let the snmpauthencodemessage error be the
|
|
// error>);
|
|
SnmpUtilMemFree(request.community.stream);
|
|
LeaveCriticalSection(&SessionInfo->recvBufCritSec);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Send request to targeted agent.
|
|
|
|
bcopy(&(SessionInfo->destAddr), &Address_in, sizeof(SessionInfo->destAddr));
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: sending request to %s.\n", inet_ntoa(Address_in.sin_addr)));
|
|
if ((recvLength = sendto(SessionInfo->fd, pBuf, pBufLen, 0,
|
|
&(SessionInfo->destAddr), sizeof((SessionInfo->destAddr)))) == -1)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error %d sending request.\n", GetLastError()));
|
|
|
|
//SetLastError(<let the winsock error be the error>);
|
|
SnmpUtilMemFree(request.community.stream);
|
|
LeaveCriticalSection(&SessionInfo->recvBufCritSec);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Free the communications packet.
|
|
|
|
SnmpUtilMemFree(pBuf);
|
|
|
|
|
|
badReqidRetry:
|
|
|
|
FD_ZERO(&readfds);
|
|
FD_ZERO(&exceptfds);
|
|
|
|
FD_SET(SessionInfo->fd, &readfds);
|
|
FD_SET(SessionInfo->fd, &exceptfds);
|
|
|
|
|
|
// Poll for response from targeted agent.
|
|
if ((numReady = select(0, &readfds, NULL, &exceptfds,
|
|
&timeval)) == -1)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error %d waiting to process snmp socket.\n", GetLastError()));
|
|
|
|
//SetLastError(<let the winsock error be the error>);
|
|
SnmpUtilMemFree(request.community.stream);
|
|
LeaveCriticalSection(&SessionInfo->recvBufCritSec);
|
|
return FALSE;
|
|
}
|
|
else if (numReady == 0)
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: timeout waiting to process snmp socket.\n"));
|
|
|
|
|
|
// Adjust time-out for retry.
|
|
|
|
// timeout *= 2; // CODEWORK... make type of backoff optional
|
|
|
|
timeval.tv_sec = timeout / 1000;
|
|
timeval.tv_usec = ((timeout % 1000) * 1000);
|
|
expireTime = (LONG)GetCurrentTime() + timeout;
|
|
|
|
continue;
|
|
}
|
|
else if (numReady == 1 && FD_ISSET(SessionInfo->fd, &readfds))
|
|
{
|
|
if (FD_ISSET(SessionInfo->fd, &exceptfds))
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: %d=select(), readfds & exceptfds = 0x%x.\n",
|
|
numReady, FD_ISSET(SessionInfo->fd, &exceptfds)));
|
|
}
|
|
|
|
sourceLen = sizeof(source);
|
|
if ((recvLength = recvfrom(SessionInfo->fd, SessionInfo->recvBuf,
|
|
RECVBUFSIZE, 0, &source, &sourceLen)) == -1)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error on recvfrom %d.\n", GetLastError()));
|
|
|
|
}
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: received %d octet response.\n", recvLength));
|
|
|
|
// Decode the response request.
|
|
|
|
if (!SnmpSvcDecodeMessage(&packetType, &response,
|
|
SessionInfo->recvBuf, recvLength, FALSE))
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: error on SnmpSvcDecodeMessage %d.\n",
|
|
GetLastError()));
|
|
|
|
//SetLastError(<let the snmpauthdecodemessage error be the
|
|
// error>);
|
|
SnmpUtilMemFree(request.community.stream);
|
|
LeaveCriticalSection(&SessionInfo->recvBufCritSec);
|
|
return FALSE;
|
|
}
|
|
else if (response.pdu.pduValue.pdu.requestId !=
|
|
SessionInfo->requestId)
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE,
|
|
"MGMTAPI: MGMT: requestId mismatch, expected %d, received %d.\n",
|
|
SessionInfo->requestId,
|
|
response.pdu.pduValue.pdu.requestId));
|
|
|
|
if ((remainingTime = expireTime - (LONG)GetCurrentTime())
|
|
> 0)
|
|
{
|
|
// if timeout not exhaused...
|
|
|
|
timeval.tv_sec = remainingTime / 1000;
|
|
timeval.tv_usec = ((remainingTime % 1000) * 1000);
|
|
|
|
goto badReqidRetry;
|
|
}
|
|
else
|
|
{
|
|
// else treat like a timeout...
|
|
|
|
// timeout *= 2; // CODEWORK... make type of backoff optional
|
|
|
|
timeval.tv_sec = timeout / 1000;
|
|
timeval.tv_usec = ((timeout % 1000) * 1000);
|
|
expireTime = (LONG)GetCurrentTime() + timeout;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else // other unexpected/error conditions
|
|
{
|
|
if (FD_ISSET(SessionInfo->fd, &exceptfds))
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: %d=select(), exceptfds = 0x%x.\n",
|
|
numReady, FD_ISSET(SessionInfo->fd, &exceptfds)));
|
|
}
|
|
else
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: unknown error on select.\n"));
|
|
}
|
|
|
|
SetLastError(SNMP_MGMTAPI_SELECT_FDERRORS);
|
|
SnmpUtilMemFree(request.community.stream);
|
|
LeaveCriticalSection(&SessionInfo->recvBufCritSec);
|
|
return FALSE;
|
|
} // end if (poll)
|
|
|
|
}
|
|
while(--retries);
|
|
|
|
SnmpUtilMemFree(request.community.stream);
|
|
if (retries == 0)
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: timeout waiting for response.\n"));
|
|
|
|
SetLastError(SNMP_MGMTAPI_TIMEOUT);
|
|
LeaveCriticalSection(&SessionInfo->recvBufCritSec);
|
|
return FALSE;
|
|
}
|
|
|
|
} // end block
|
|
|
|
|
|
// Indicate status of request to caller.
|
|
|
|
*errorStatus = response.pdu.pduValue.pdu.errorStatus;
|
|
*errorIndex = response.pdu.pduValue.pdu.errorIndex;
|
|
|
|
// The user has passed in a list of variables to be processed.
|
|
// These are copied to an outgoing pdu and sent to the target
|
|
// machine. The response is parsed for the list of variables
|
|
// returned by the target machine. Unfortunately, the decode
|
|
// routine simply aims any pointers in the VarBindList to the
|
|
// return buffer which is unique only per session handle. If
|
|
// multiple threads want to use the same snmp session handle
|
|
// then the list of variables must be copied into new buffers
|
|
// or else they cannot be guaranteed to be valid.
|
|
|
|
// Free user supplied varbinds...
|
|
SnmpUtilVarBindListFree(variableBindings);
|
|
|
|
// Copy varbinds returned from target in session buffer to new buffer...
|
|
SnmpUtilVarBindListCpy(variableBindings, &response.pdu.pduValue.pdu.varBinds);
|
|
|
|
// Free varbinds returned from target in session buffer...
|
|
SnmpUtilVarBindListFree(&response.pdu.pduValue.pdu.varBinds);
|
|
|
|
// Release lock on session buffer
|
|
LeaveCriticalSection(&SessionInfo->recvBufCritSec);
|
|
return TRUE;
|
|
|
|
} // end SnmpMgrRequest()
|
|
|
|
|
|
|
|
// oid conversion processing
|
|
|
|
BOOL
|
|
SNMP_FUNC_TYPE SnmpMgrStrToOid(
|
|
IN LPSTR string, // OID string to be converted
|
|
OUT AsnObjectIdentifier *oid) // OID internal representation
|
|
{
|
|
return SnmpMgrText2Oid(string, oid);
|
|
} // end SnmpMgrStrToOid()
|
|
|
|
|
|
BOOL
|
|
SNMP_FUNC_TYPE SnmpMgrOidToStr(
|
|
IN AsnObjectIdentifier *oid, // OID internal rep to be converted
|
|
OUT LPSTR *string) // OID string representation
|
|
{
|
|
return SnmpMgrOid2Text(oid, string);
|
|
} // end SnmpMgrOidToStr()
|
|
|
|
|
|
// server side trap processing
|
|
|
|
// data structure on list shared by server trap thread and pipe thread
|
|
typedef struct {
|
|
ll_node links;
|
|
HANDLE hPipe;
|
|
} ServerPipeListEntry;
|
|
|
|
// list shared by server trap thread and pipe thread
|
|
ll_node *pServerPipeListHead = NULL;
|
|
|
|
HANDLE hServerPipeListMutex = NULL;
|
|
|
|
|
|
/* static */ VOID serverPipeThread(VOID *threadParam)
|
|
{
|
|
// This thread creates a named pipe instance and blocks waiting for a
|
|
// client connection. When client connects, the pipe handle is added
|
|
// to the list of trap notification pipes. It then waits for another
|
|
// connection.
|
|
|
|
DWORD nInBufLen = sizeof(SNMP_MGR_TRAP);
|
|
DWORD nOutBufLen = sizeof(SNMP_MGR_TRAP) * MAX_OUT_BUFS;
|
|
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: serverPipeThread entered.\n"));
|
|
|
|
|
|
|
|
while(1)
|
|
{
|
|
HANDLE hPipe;
|
|
ServerPipeListEntry *item;
|
|
DWORD dwResult;
|
|
|
|
if ((hPipe = CreateNamedPipe(SNMPMGRTRAPPIPE, PIPE_ACCESS_DUPLEX,
|
|
(PIPE_WAIT | PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE),
|
|
PIPE_UNLIMITED_INSTANCES, nOutBufLen, nInBufLen, 0, &S_Attrib))
|
|
== (HANDLE)0xffffffff)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d opening trap distribution pipe.\n", GetLastError()));
|
|
|
|
return;
|
|
}
|
|
|
|
else if (!ConnectNamedPipe(hPipe, NULL) &&
|
|
(GetLastError() != ERROR_PIPE_CONNECTED))
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d connecting trap distribution pipe.\n", GetLastError()));
|
|
|
|
return;
|
|
}
|
|
|
|
else if ((item = (ServerPipeListEntry *)
|
|
SnmpUtilMemAlloc(sizeof(ServerPipeListEntry))) == NULL)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: out of memory.\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
else
|
|
{
|
|
item->hPipe = hPipe;
|
|
|
|
if ((dwResult = WaitForSingleObject(hServerPipeListMutex,
|
|
generalMutexTO)) == 0xffffffff)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d waiting for server pipe list mutex.\n",
|
|
GetLastError()));
|
|
|
|
return;
|
|
}
|
|
|
|
ll_adde(item, pServerPipeListHead);
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: pipe 0x%x added to server pipe list.\n", hPipe));
|
|
|
|
if (!ReleaseMutex(hServerPipeListMutex))
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d releasing server pipe list mutex.\n", GetLastError()));
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
} // end while()
|
|
|
|
} // end serverPipeThread()
|
|
|
|
|
|
VOID serverTrapThread(VOID *threadParam)
|
|
{
|
|
// This thread setsup a trap listen socket, creates the serverPipeThread,
|
|
// and when receives a trap from the socket sends its data to all pipes
|
|
// currently on the list of trap notification pipes.
|
|
|
|
struct sockaddr localAddress;
|
|
SOCKET fd;
|
|
HANDLE hPipeThread;
|
|
DWORD dwThreadId;
|
|
BOOL fSuccess;
|
|
WSADATA WinSockData;
|
|
HANDLE hTrapThreadExitEvent = NULL;
|
|
TRAP_THREAD_CALLBACK trapThreadCB = (TRAP_THREAD_CALLBACK)threadParam;
|
|
PSNMP_MGR_TRAP recvTrap = NULL;
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: serverTrapThread entered.\n"));
|
|
fdarrayLen = 0;
|
|
|
|
if (!trapThreadCB)
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: old version of snmptrap.exe.\n"));
|
|
return; // this indicates an old version of snmptrap.exe...
|
|
}
|
|
|
|
if (WSAStartup((WORD)0x0101, &WinSockData)) {
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d initializing WinSock.\n", GetLastError()));
|
|
return;
|
|
}
|
|
|
|
fSuccess = FALSE;
|
|
|
|
// block...
|
|
{
|
|
struct sockaddr_in localAddress_in;
|
|
struct servent *serv;
|
|
|
|
localAddress_in.sin_family = AF_INET;
|
|
if ((serv = getservbyname( "snmp-trap", "udp" )) == NULL) {
|
|
localAddress_in.sin_port = htons(162);
|
|
} else {
|
|
localAddress_in.sin_port = (SHORT)serv->s_port;
|
|
}
|
|
localAddress_in.sin_addr.s_addr = ntohl(INADDR_ANY);
|
|
bcopy(&localAddress_in, &localAddress, sizeof(localAddress_in));
|
|
} // end block.
|
|
|
|
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == (SOCKET)-1) {
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: error %d creating udp trap socket.\n", GetLastError()));
|
|
} else if (bind(fd, &localAddress, sizeof(localAddress)) != 0) {
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: error %d binding on udp trap socket.\n", GetLastError()));
|
|
} else {
|
|
fdarray[fdarrayLen] = fd;
|
|
fdarrayLen += 1;
|
|
fSuccess = TRUE;
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: setup udp trap listen port.\n"));
|
|
}
|
|
|
|
|
|
{
|
|
struct sockaddr_ipx localAddress_ipx;
|
|
|
|
bzero(&localAddress_ipx, sizeof(localAddress_ipx));
|
|
localAddress_ipx.sa_family = AF_IPX;
|
|
localAddress_ipx.sa_socket = htons(WKSN_IPX_TRAP);
|
|
bcopy(&localAddress_ipx, &localAddress, sizeof(localAddress_ipx));
|
|
} // end block.
|
|
|
|
if ((fd = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == (SOCKET)-1) {
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: error %d creating ipx trap socket.\n", GetLastError()));
|
|
} else if (bind(fd, &localAddress, sizeof(localAddress)) != 0) {
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: error %d binding ipx trap socket.\n", GetLastError()));
|
|
} else {
|
|
fdarray[fdarrayLen] = fd;
|
|
fdarrayLen += 1;
|
|
fSuccess = TRUE;
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: setup ipx trap listen port.\n"));
|
|
}
|
|
|
|
if (!fSuccess) {
|
|
return; // can't open either socket
|
|
}
|
|
|
|
if ((recvTrap = SnmpUtilMemAlloc(sizeof(SNMP_MGR_TRAP))) == NULL)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: out of memory.\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
if ((hServerPipeListMutex = CreateMutex(NULL, FALSE, NULL))
|
|
== NULL)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %s creating server pipe list mutex.\n", GetLastError()));
|
|
|
|
return;
|
|
}
|
|
|
|
// allocate linked-list header for client received traps
|
|
if ((pServerPipeListHead = (ll_node *)SnmpUtilMemAlloc(sizeof(ll_node)))
|
|
== NULL)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: out of memory.\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
ll_init(pServerPipeListHead);
|
|
|
|
if ((hPipeThread = CreateThread(NULL, 0,
|
|
(LPTHREAD_START_ROUTINE)serverPipeThread, NULL, 0, &dwThreadId)) == 0)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d creating serverPipeThread.\n", GetLastError()));
|
|
|
|
return;
|
|
}
|
|
|
|
else
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: serverTrapThread tid=0x%lx.\n", dwThreadId));
|
|
}
|
|
|
|
// announce server is up and running.
|
|
(*trapThreadCB)(&hTrapThreadExitEvent);
|
|
|
|
while(1)
|
|
{
|
|
DWORD dwResult;
|
|
INT numReady;
|
|
struct timeval trapThreadTimeout = { trapThreadTO, 0 };
|
|
|
|
|
|
FD_ZERO(&readfds);
|
|
FD_ZERO(&exceptfds);
|
|
{
|
|
int i, sd;
|
|
|
|
// construct readfds and exceptfds which gets destroyed by select()
|
|
|
|
for (i=0; i < fdarrayLen; i++) {
|
|
sd = fdarray[i];
|
|
FD_SET(sd, &readfds);
|
|
FD_SET(sd, &exceptfds);
|
|
}
|
|
}
|
|
numReady = select(0, &readfds, NULL, &exceptfds, &trapThreadTimeout);
|
|
if (numReady == -1)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d waiting to process trap socket.\n", GetLastError()));
|
|
|
|
//not serious error.
|
|
}
|
|
else if (numReady == 0)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: timeout waiting to process trap socket.\n"));
|
|
|
|
//not serious error.
|
|
}
|
|
else
|
|
{
|
|
INT i;
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE,"MGMTAPI: TRAP: processing trap socket...\n"));
|
|
|
|
for (i=0; i<fdarrayLen; i++)
|
|
{
|
|
int length;
|
|
struct sockaddr_in *saddr;
|
|
|
|
if (FD_ISSET(fdarray[i], &readfds))
|
|
{
|
|
if (FD_ISSET(fdarray[i], &exceptfds))
|
|
{
|
|
// SNMPDBG((SNMP_LOG_TRACE,
|
|
// "MGMTAPI: MGMT: %d=select(), readfds & exceptfds = 0x%x.\n",
|
|
// numReady, FD_ISSET(fdarray[i], &exceptfds)));
|
|
|
|
//not serious error.
|
|
}
|
|
else
|
|
{
|
|
// SNMPDBG((SNMP_LOG_TRACE,
|
|
// "MGMTAPI: TRAP: %d=poll(), POLLIN on fdarray[%d].\n",
|
|
// numReady, i));
|
|
}
|
|
|
|
recvTrap->AddrLen = sizeof(recvTrap->Addr);
|
|
if ((length = recvfrom(fdarray[i],
|
|
recvTrap->TrapBuf,
|
|
sizeof(recvTrap->TrapBuf),
|
|
0,
|
|
&recvTrap->Addr,
|
|
&recvTrap->AddrLen)) == -1)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d reading trap pdu.\n", GetLastError()));
|
|
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// add header to length
|
|
length += AGENT_ADDR_LEN;
|
|
|
|
if ((dwResult = WaitForSingleObject(hServerPipeListMutex,
|
|
generalMutexTO)) == 0xffffffff)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d waiting for server pipe list mutex.\n",
|
|
GetLastError()));
|
|
continue;
|
|
}
|
|
|
|
if (!ll_empt(pServerPipeListHead)) {
|
|
DWORD written;
|
|
ll_node *item = pServerPipeListHead;
|
|
|
|
while(item = ll_next(item, pServerPipeListHead))
|
|
{
|
|
if (!WriteFile(((ServerPipeListEntry *)item)->hPipe,
|
|
(LPBYTE)recvTrap,
|
|
length,
|
|
&written,
|
|
NULL))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
|
|
// OPENISSUE - what errors could result from pipe break
|
|
if (dwError != ERROR_NO_DATA) {
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d writing to trap distribution pipe.\n", dwError));
|
|
}
|
|
|
|
if (!DisconnectNamedPipe(
|
|
((ServerPipeListEntry *)item)->hPipe))
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: error %d disconnecting trap distribution pipe.\n",
|
|
GetLastError()));
|
|
}
|
|
else if (!CloseHandle(
|
|
((ServerPipeListEntry *)item)->hPipe))
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d closing trap distribution pipe.\n",
|
|
GetLastError()));
|
|
}
|
|
|
|
ll_rmv(item);
|
|
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE,"MGMTAPI: TRAP: pipe 0x%x removed from server pipe list.\n",
|
|
((ServerPipeListEntry *)item)->hPipe));
|
|
|
|
SnmpUtilMemFree(item); // check for errors?
|
|
|
|
item = pServerPipeListHead;
|
|
|
|
}
|
|
else if (written != (DWORD)length) {
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: trap request only partially written to pipe.\n"));
|
|
|
|
if (!ReleaseMutex(hServerPipeListMutex))
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d releasing server pipe list mutex.\n",
|
|
GetLastError()));
|
|
|
|
continue;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE,
|
|
"MGMTAPI: TRAP: trap pdu successfully written to pipe 0x%x.\n",
|
|
((ServerPipeListEntry *)item)->hPipe));
|
|
}
|
|
|
|
|
|
} // end while()
|
|
}
|
|
|
|
if (!ReleaseMutex(hServerPipeListMutex))
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: TRAP: error %d releasing server pipe list mutex.\n", GetLastError()));
|
|
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// make sure that the snmp trap server has not been stopped
|
|
if (WaitForSingleObject(hTrapThreadExitEvent, 0) == WAIT_OBJECT_0)
|
|
return;
|
|
|
|
} // end while()
|
|
|
|
} // end serverTrapThread()
|
|
|
|
|
|
// client side trap processing
|
|
|
|
// data structure communicated between client trap thread and SnmpMgrGetTrap
|
|
typedef struct {
|
|
ll_node links;
|
|
PSNMP_MGR_TRAP recvTrap;
|
|
DWORD recvTrapBufLen;
|
|
} ClientTrapListEntry;
|
|
|
|
// queue between client trap thread and SnmpMgrGetTrap
|
|
ll_node *pClientTrapListHead = NULL;
|
|
|
|
HANDLE hClientTrapListMutex = NULL;
|
|
|
|
/* static */ VOID clientTrapThread(VOID *threadParam)
|
|
{
|
|
DWORD modePipe = PIPE_WAIT | PIPE_READMODE_MESSAGE;
|
|
HANDLE notifyEvent = *((HANDLE *)threadParam);
|
|
HANDLE hPipe = NULL;
|
|
|
|
DWORD sizeread;
|
|
ClientTrapListEntry *item;
|
|
DWORD dwResult = NO_ERROR;
|
|
PSNMP_MGR_TRAP recvTrap = NULL;
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: clientTrapThread entered.\n"));
|
|
|
|
while (1)
|
|
{
|
|
//
|
|
// loop here in case the trap pipe server goes down so
|
|
// we first check whether there is an open pipe handle.
|
|
//
|
|
if (hPipe != NULL)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"MGMTAPI: TRAP: closing pipe 0x%08lx.\n",
|
|
hPipe
|
|
));
|
|
// close broken pipe
|
|
CloseHandle(hPipe);
|
|
// reset...
|
|
hPipe = NULL;
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"MGMTAPI: TRAP: clientTrapThread connecting...\n"
|
|
));
|
|
|
|
// block on instance of server pipe becoming available
|
|
if (!WaitNamedPipe(SNMPMGRTRAPPIPE, NMPWAIT_WAIT_FOREVER))
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: error %d waiting for trap distribution pipe.\n",
|
|
dwResult
|
|
));
|
|
// check if the trap server is down
|
|
if (dwResult == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
//
|
|
// no instance of the pipe was available. since we
|
|
// checked that the server was running when the user
|
|
// called SnmpMgrTrapListen it must have gone down
|
|
// since then. unfortunately, there is not a clean
|
|
// way to reconnect (or disconnect) so we end up
|
|
// simply polling for the server to come back up.
|
|
//
|
|
|
|
// report error status
|
|
SetClientTrapStatus(ERROR_SERVICE_NOT_ACTIVE);
|
|
// alert user process
|
|
SetEvent(notifyEvent);
|
|
// dream server comes back
|
|
Sleep(trapServerConnectTO);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// connect to pipe
|
|
hPipe = CreateFile(
|
|
SNMPMGRTRAPPIPE,
|
|
(GENERIC_READ | GENERIC_WRITE),
|
|
(FILE_SHARE_READ | FILE_SHARE_WRITE),
|
|
&S_Attrib,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
if (hPipe == INVALID_HANDLE_VALUE)
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: error %d connecting to trap distribution pipe.\n",
|
|
dwResult
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!SetNamedPipeHandleState(hPipe, &modePipe, NULL, NULL))
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: error %d setting pipe handle to message mode.\n",
|
|
dwResult
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"MGMTAPI: TRAP: listening on pipe 0x%08lx.\n",
|
|
hPipe
|
|
));
|
|
|
|
// report thread initialized
|
|
SetClientTrapStatus(NO_ERROR);
|
|
// notify user process
|
|
SetEvent(notifyEvent);
|
|
|
|
while(1)
|
|
{
|
|
if ((recvTrap = SnmpUtilMemAlloc(sizeof(SNMP_MGR_TRAP))) == NULL)
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: out of memory.\n"
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
else if (!ReadFile(hPipe,
|
|
(LPBYTE)recvTrap,
|
|
sizeof(SNMP_MGR_TRAP),
|
|
&sizeread,
|
|
NULL))
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: error %d reading trap pdu from trap distribution pipe.\n",
|
|
dwResult
|
|
));
|
|
// check to see if disconnected
|
|
if (dwResult == ERROR_BROKEN_PIPE)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"MGMTAPI: TRAP: attempting to reconnect to service.\n"
|
|
));
|
|
// report error status
|
|
SetClientTrapStatus(ERROR_SERVICE_NOT_ACTIVE);
|
|
// alert user process
|
|
SetEvent(notifyEvent);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
else if ((recvTrap = SnmpUtilMemReAlloc(recvTrap, sizeread)) == NULL)
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: error %d shrinking trap pdu to actual size.\n",
|
|
dwResult
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
else if ((item = (ClientTrapListEntry *)
|
|
SnmpUtilMemAlloc(sizeof(ClientTrapListEntry))) == NULL)
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: out of memory.\n"
|
|
));
|
|
SnmpUtilMemFree(recvTrap);
|
|
goto cleanup;
|
|
}
|
|
|
|
else if ((dwResult = WaitForSingleObject(hClientTrapListMutex,
|
|
generalMutexTO)) == 0xffffffff)
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: error %d waiting for client trap list mutex.\n",
|
|
dwResult
|
|
));
|
|
SnmpUtilMemFree(recvTrap);
|
|
SnmpUtilMemFree(item);
|
|
goto cleanup;
|
|
}
|
|
|
|
// check for unfinished writes
|
|
if (sizeread > AGENT_ADDR_LEN)
|
|
{
|
|
// save trap and adjust length
|
|
item->recvTrap = recvTrap;
|
|
item->recvTrapBufLen = sizeread - AGENT_ADDR_LEN;
|
|
|
|
ll_adde(item, pClientTrapListHead);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"MGMTAPI: TRAP: added 0x%x to end of client trap list.\n",
|
|
item
|
|
));
|
|
}
|
|
else
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"MGMTAPI: TRAP: ignoring stub trap data.\n"
|
|
));
|
|
SnmpUtilMemFree(recvTrap);
|
|
SnmpUtilMemFree(item);
|
|
}
|
|
|
|
if (!ReleaseMutex(hClientTrapListMutex))
|
|
{
|
|
dwResult = GetLastError();
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: TRAP: error %d releasing client trap list mutex.\n",
|
|
dwResult
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
// alert user process
|
|
SetEvent(notifyEvent);
|
|
|
|
} // end while()
|
|
|
|
} // end while()
|
|
|
|
cleanup:
|
|
|
|
if (hPipe)
|
|
CloseHandle(hPipe);
|
|
|
|
// report client thread is dead
|
|
SetClientTrapStatus(ERROR_NOT_READY);
|
|
|
|
// alert user process
|
|
SetEvent(notifyEvent);
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: TRAP: clientTrapThread exited.\n"));
|
|
|
|
} // end clientTrapThread()
|
|
|
|
|
|
BOOL
|
|
SNMP_FUNC_TYPE SnmpMgrTrapListen(
|
|
OUT HANDLE *phTrapAvailable) // Event handle indicating trap(s) available
|
|
{
|
|
static BOOL fFirstTime = TRUE;
|
|
HANDLE hTrapRecvThread;
|
|
DWORD threadId;
|
|
DWORD dwResult;
|
|
|
|
if (fFirstTime)
|
|
{
|
|
// make sure service started
|
|
if (!StartServiceIfNecessary())
|
|
{
|
|
SetLastError(ERROR_SERVICE_NOT_ACTIVE);
|
|
return FALSE;
|
|
}
|
|
|
|
// create mutual exclusion object for queue of traps
|
|
hClientTrapListMutex = CreateMutex(NULL, FALSE, NULL);
|
|
|
|
// validate mutex handle
|
|
if (hClientTrapListMutex == NULL)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: MGMT: error %d creating client trap list mutex.\n",
|
|
GetLastError()
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
// allocate linked-list header for client received traps
|
|
pClientTrapListHead = (ll_node *)SnmpUtilMemAlloc(sizeof(ll_node));
|
|
|
|
// validate linked-list header
|
|
if (pClientTrapListHead == NULL)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: MGMT: out of memory.\n"
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
// initialize list header
|
|
ll_init(pClientTrapListHead);
|
|
|
|
// create event
|
|
if (phTrapAvailable)
|
|
{
|
|
// create event to indicate trap queue should be read
|
|
*phTrapAvailable = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
|
|
// validate event handle
|
|
if (*phTrapAvailable == NULL)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: MGMT: error %d creating trap notification event.\n",
|
|
GetLastError()
|
|
));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
else if (GetClientTrapStatus() != ERROR_NOT_READY)
|
|
{
|
|
SetLastError(SNMP_MGMTAPI_TRAP_DUPINIT);
|
|
return FALSE;
|
|
}
|
|
|
|
// create thread to receive traps
|
|
if ((hTrapRecvThread = CreateThread(
|
|
NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE)clientTrapThread,
|
|
phTrapAvailable,
|
|
0,
|
|
&threadId)) == 0)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: MGMT: error %d creating clientTrapThread.\n",
|
|
GetLastError()
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"MGMTAPI: MGMT: clientTrapThread tid=0x%lx.\n",
|
|
threadId
|
|
));
|
|
|
|
// client trap thread will send out status during
|
|
// startup so we wait for that here before returning
|
|
if ((dwResult = WaitForSingleObject(*phTrapAvailable,
|
|
pipeThreadTO)) == 0xffffffff)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"MGMTAPI: MGMT: error %d waiting for clientPipeThread event.\n",
|
|
GetLastError()
|
|
));
|
|
goto cleanup;
|
|
}
|
|
|
|
// return success if thread running
|
|
if (GetClientTrapStatus() == NO_ERROR)
|
|
{
|
|
SetLastError(NO_ERROR);
|
|
fFirstTime = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
// report error based on thread failing
|
|
SetLastError(SNMP_MGMTAPI_TRAP_ERRORS);
|
|
|
|
// fall through...
|
|
|
|
cleanup:
|
|
|
|
if (fFirstTime)
|
|
{
|
|
if (hClientTrapListMutex)
|
|
{
|
|
CloseHandle(hClientTrapListMutex);
|
|
hClientTrapListMutex = NULL;
|
|
}
|
|
|
|
if (pClientTrapListHead)
|
|
{
|
|
SnmpUtilMemFree(pClientTrapListHead);
|
|
pClientTrapListHead = NULL;
|
|
}
|
|
|
|
if (phTrapAvailable && *phTrapAvailable)
|
|
{
|
|
CloseHandle(*phTrapAvailable);
|
|
*phTrapAvailable = NULL;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
} // end SnmpMgrTrapListen()
|
|
|
|
|
|
BOOL
|
|
SNMP_FUNC_TYPE SnmpMgrGetTrap(
|
|
OUT AsnObjectIdentifier *enterprise, // Generating enterprise
|
|
OUT AsnNetworkAddress *IPAddress, // Generating IP Address
|
|
OUT AsnInteger *genericTrap, // Generic trap type
|
|
OUT AsnInteger *specificTrap, // Enterprise specific type
|
|
OUT AsnTimeticks *timeStamp, // Time stamp
|
|
OUT RFC1157VarBindList *variableBindings) // Variable bindings
|
|
{
|
|
|
|
return SnmpMgrGetTrapEx(
|
|
enterprise,
|
|
IPAddress,
|
|
NULL,
|
|
genericTrap,
|
|
specificTrap,
|
|
NULL,
|
|
timeStamp,
|
|
variableBindings
|
|
);
|
|
|
|
} // end SnmpMgrGetTrap()
|
|
|
|
|
|
BOOL
|
|
SNMP_FUNC_TYPE
|
|
SnmpMgrGetTrapEx(
|
|
OUT AsnObjectIdentifier *enterprise, // Generating enterprise
|
|
OUT AsnNetworkAddress *agentAddress, // Generating agent addr
|
|
OUT AsnNetworkAddress *sourceAddress, // Generating network addr
|
|
OUT AsnInteger *genericTrap, // Generic trap type
|
|
OUT AsnInteger *specificTrap, // Enterprise specific type
|
|
OUT AsnOctetString *community, // Generating community
|
|
OUT AsnTimeticks *timeStamp, // Time stamp
|
|
OUT RFC1157VarBindList *variableBindings // Variable bindings
|
|
)
|
|
{
|
|
DWORD dwResult;
|
|
ClientTrapListEntry *item = NULL;
|
|
DWORD dwSnmpMgrError = SNMP_MGMTAPI_TRAP_ERRORS;
|
|
BOOL fResult = FALSE;
|
|
UINT packetType;
|
|
SnmpMgmtCom decoded;
|
|
|
|
if ((dwResult = WaitForSingleObject(hClientTrapListMutex,
|
|
generalMutexTO)) == 0xffffffff)
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error %d waiting for client trap list mutex.\n", GetLastError()));
|
|
goto cleanup;
|
|
}
|
|
|
|
// is anything in the list?
|
|
else if (ll_empt(pClientTrapListHead))
|
|
{
|
|
if (GetClientTrapStatus() == NO_ERROR)
|
|
{
|
|
dwSnmpMgrError = SNMP_MGMTAPI_NOTRAPS;
|
|
}
|
|
else
|
|
{
|
|
dwSnmpMgrError = SNMP_MGMTAPI_TRAP_ERRORS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ll_rmvb(item, pClientTrapListHead);
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: remove 0x%x from head of trap queue.\n", item));
|
|
}
|
|
|
|
if (!ReleaseMutex(hClientTrapListMutex))
|
|
{
|
|
SNMPDBG((SNMP_LOG_ERROR, "MGMTAPI: MGMT: error %d releasing client trap list mutex.\n", GetLastError()));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (item)
|
|
{
|
|
if (!SnmpSvcDecodeMessage(&packetType, &decoded,
|
|
item->recvTrap->TrapBuf, item->recvTrapBufLen, FALSE))
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: error on SnmpSvcDecodeMessage %d.\n",
|
|
GetLastError()));
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
if (enterprise != NULL)
|
|
{
|
|
SnmpUtilOidCpy(
|
|
enterprise,
|
|
&decoded.pdu.pduValue.trap.enterprise
|
|
);
|
|
}
|
|
|
|
if (agentAddress != NULL)
|
|
{
|
|
agentAddress->length = 0;
|
|
agentAddress->stream = SnmpUtilMemAlloc(
|
|
decoded.pdu.pduValue.trap.agentAddr.length * sizeof(BYTE));
|
|
if (agentAddress->stream != NULL)
|
|
{
|
|
agentAddress->length = decoded.pdu.pduValue.trap.agentAddr.length;
|
|
memcpy(
|
|
agentAddress->stream,
|
|
decoded.pdu.pduValue.trap.agentAddr.stream,
|
|
agentAddress->length
|
|
);
|
|
agentAddress->dynamic = TRUE;
|
|
}
|
|
}
|
|
|
|
if (sourceAddress != NULL)
|
|
{
|
|
LPBYTE Addr;
|
|
DWORD AddrLen;
|
|
|
|
// initialize...
|
|
sourceAddress->length = 0;
|
|
sourceAddress->stream = NULL;
|
|
|
|
// determine length of address information
|
|
AddrLen = (item->recvTrap->Addr.sa_family == AF_INET)
|
|
? IP_ADDR_SIZE
|
|
: (item->recvTrap->Addr.sa_family == AF_IPX)
|
|
? IPX_ADDR_SIZE
|
|
: 0
|
|
;
|
|
|
|
// determine start of address information
|
|
Addr = (item->recvTrap->Addr.sa_family == AF_INET)
|
|
? (LPBYTE)&(((struct sockaddr_in*)(&item->recvTrap->Addr))->sin_addr)
|
|
: (item->recvTrap->Addr.sa_family == AF_IPX)
|
|
? (LPBYTE)&(((struct sockaddr_ipx*)(&item->recvTrap->Addr))->sa_netnum)
|
|
: NULL
|
|
;
|
|
|
|
if (Addr && AddrLen)
|
|
{
|
|
sourceAddress->stream = SnmpUtilMemAlloc(AddrLen);
|
|
if (sourceAddress->stream != NULL)
|
|
{
|
|
sourceAddress->length = AddrLen;
|
|
memcpy(sourceAddress->stream, Addr, AddrLen);
|
|
sourceAddress->dynamic = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (community != NULL)
|
|
{
|
|
community->length = 0;
|
|
community->stream = SnmpUtilMemAlloc(
|
|
decoded.community.length * sizeof(BYTE));
|
|
if (community->stream != NULL)
|
|
{
|
|
community->length = decoded.community.length;
|
|
memcpy(
|
|
community->stream,
|
|
decoded.community.stream,
|
|
community->length
|
|
);
|
|
community->dynamic = TRUE;
|
|
}
|
|
}
|
|
|
|
if (genericTrap != NULL)
|
|
{
|
|
*genericTrap = decoded.pdu.pduValue.trap.genericTrap;
|
|
}
|
|
if (specificTrap != NULL)
|
|
{
|
|
*specificTrap = decoded.pdu.pduValue.trap.specificTrap;
|
|
}
|
|
if (timeStamp != NULL)
|
|
{
|
|
*timeStamp = decoded.pdu.pduValue.trap.timeStamp;
|
|
}
|
|
if (variableBindings != NULL)
|
|
{
|
|
SnmpUtilVarBindListCpy(
|
|
variableBindings,
|
|
&decoded.pdu.pduValue.trap.varBinds
|
|
);
|
|
}
|
|
|
|
if (!SnmpSvcReleaseMessage(&decoded))
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "MGMTAPI: MGMT: error on SnmpSvcReleaseMessage %d.\n",
|
|
GetLastError()));
|
|
goto cleanup;
|
|
}
|
|
|
|
fResult = TRUE; // indicate success...
|
|
dwSnmpMgrError = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (item)
|
|
{
|
|
SnmpUtilMemFree(item->recvTrap);
|
|
SnmpUtilMemFree(item);
|
|
}
|
|
|
|
SetLastError(dwSnmpMgrError);
|
|
|
|
return fResult;
|
|
|
|
} // end SnmpMgrGetTrapEx()
|
|
|
|
//-------------------------------- END --------------------------------------
|
|
|