📄 snmptrap.c
字号:
// snmptrap.c
//
// Original Microsoft code modified by ACE*COMM
// for use with WSNMP32.DLL and other trap receiving
// clients, per contract.
//
// Bob Natale, ACE*COMM (bnatale@acecomm.com)
// For NT v5 Beta, v970228
// Additional enhancements planned.
//
// This version of SNMPTRAP has no dependencies
// on either MGMTAPI.DLL or WSNMP32.DLL.
//
// WinSNMP clients use the SnmpRegister() function.
//
// Other clients will need to match the following
// values and structures:
//
// SNMP_TRAP structure
// SNMPTRAPPIPE name
// TRAPBUFSIZE value
//
// Change log:
// ------------------------------------------------
// 4.0.1381.3 Apr 8, 1998 Bob Natale
//
// 1. Re-worked the trap port monitoring thread into
// two threads...one for IP and one for IPX, to
// comply with WinSock v2's restrictions against
// multi-protocol select().
//
// 2. General clean-up/streamlining wrt "legacy" code
// from original MS version...more to do here, esp.
// wrt error handling code that does not do anything.
// ------------------------------------------------
// 4.0.1381.4 Apr. 10, 1998 Bob Natale
//
// 1. Replaced mutex calls with critical_sectin calls.
//
// 2. Cleaned out some dead code (removed commented out code)
// ------------------------------------------------
#include <windows.h>
#include <winsock.h>
#include <wsipx.h>
#include <process.h>
//--------------------------- PRIVATE VARIABLES -----------------------------
#define SNMPMGRTRAPPIPE "\\\\.\\PIPE\\MGMTAPI"
#define MAX_OUT_BUFS 16
#define TRAPBUFSIZE 4096
#define IP_TRAP_PORT 162
#define IPX_TRAP_PORT 36880
// ******** INITIALIZE A LIST HEAD ********
#define ll_init(head) (head)->next = (head)->prev = (head);
// ******** TEST A LIST FOR EMPTY ********
#define ll_empt(head) ( ((head)->next) == (head) )
// ******** Get ptr to next entry ********
#define ll_next(item,head)\
( (ll_node *)(item)->next == (head) ? 0 : \
(ll_node *)(item)->next )
// ******** 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));\
}
// ******** 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;\
}
// ******** 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
typedef struct
{// shared by server trap thread and pipe thread
ll_node links;
HANDLE hPipe;
} svrPipeListEntry;
typedef struct
{
SOCKADDR Addr;
int AddrLen;
UINT TrapBufSz;
char TrapBuf[TRAPBUFSIZE]; // the size of this array should match the size of the structure
// defined in wsnmp_no.c!!!
} SNMP_TRAP, *PSNMP_TRAP;
HANDLE hExitEvent = NULL;
LPCTSTR svcName = "SNMPTRAP";
SERVICE_STATUS_HANDLE hService = 0;
SERVICE_STATUS status =
{SERVICE_WIN32, SERVICE_STOPPED, SERVICE_ACCEPT_STOP, NO_ERROR, 0, 0, 0};
SOCKET ipSock = INVALID_SOCKET;
SOCKET ipxSock = INVALID_SOCKET;
HANDLE ipThread = NULL;
HANDLE ipxThread = NULL;
CRITICAL_SECTION cs_PIPELIST;
ll_node *pSvrPipeListHead = NULL;
//--------------------------- PRIVATE PROTOTYPES ----------------------------
DWORD WINAPI svrTrapThread (IN OUT LPVOID threadParam);
DWORD WINAPI svrPipeThread (IN LPVOID threadParam);
VOID WINAPI svcHandlerFunction (IN DWORD dwControl);
VOID WINAPI svcMainFunction (IN DWORD dwNumServicesArgs,
IN LPSTR *lpServiceArgVectors);
//--------------------------- PRIVATE PROCEDURES ----------------------------
VOID WINAPI svcHandlerFunction (IN DWORD dwControl)
{
if (dwControl == SERVICE_CONTROL_STOP)
{
status.dwCurrentState = SERVICE_STOP_PENDING;
status.dwCheckPoint++;
status.dwWaitHint = 45000;
if (!SetServiceStatus(hService, &status))
exit(1);
// set event causing trap thread to terminate
if (!SetEvent(hExitEvent))
{
status.dwCurrentState = SERVICE_STOPPED;
status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
status.dwServiceSpecificExitCode = 1; // OPENISSUE - svc err code
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
// We are exiting in any case, so ignore any error...
SetServiceStatus (hService, &status);
exit(1);
}
}
else
// dwControl == SERVICE_CONTROL_INTERROGATE
// dwControl == SERVICE_CONTROL_PAUSE
// dwControl == SERVICE_CONTROL_CONTINUE
// dwControl == <anything else>
{
if (status.dwCurrentState == SERVICE_STOP_PENDING ||
status.dwCurrentState == SERVICE_START_PENDING)
status.dwCheckPoint++;
if (!SetServiceStatus (hService, &status))
exit(1);
}
} // end_svcHandlerFunction()
VOID WINAPI svcMainFunction (IN DWORD dwNumServicesArgs,
IN LPSTR *lpServiceArgVectors)
{
WSADATA WinSockData;
HANDLE hPipeThread = NULL;
DWORD dwThreadId;
//---------------------------------------------------------------------
hService = RegisterServiceCtrlHandler (svcName, svcHandlerFunction);
if (hService == 0)
{
status.dwCurrentState = SERVICE_STOPPED;
status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
status.dwServiceSpecificExitCode = 2; // OPENISSUE - svc err code
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
// We are exiting in any case, so ignore any error...
SetServiceStatus (hService, &status);
exit(1);
}
status.dwCurrentState = SERVICE_START_PENDING;
status.dwWaitHint = 20000;
if (!SetServiceStatus(hService, &status))
exit(1);
__try
{
InitializeCriticalSection (&cs_PIPELIST);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
exit(1);
}
if (WSAStartup ((WORD)0x0101, &WinSockData))
goto CLOSE_OUT; // WinSock startup failure
// allocate linked-list header for client received traps
if ((pSvrPipeListHead = (ll_node *)GlobalAlloc (GHND, sizeof(ll_node))) == NULL)
goto CLOSE_OUT;
ll_init(pSvrPipeListHead);
if ((hPipeThread = (HANDLE)_beginthreadex
(NULL, 0, svrPipeThread, NULL, 0, &dwThreadId)) == 0)
goto CLOSE_OUT;
//-----------------------------------------------------------------------------------
//CHECK_IP:
ipSock = socket (AF_INET, SOCK_DGRAM, 0);
if (ipSock != INVALID_SOCKET)
{
struct sockaddr_in localAddress_in;
struct servent *serv;
ZeroMemory (&localAddress_in, sizeof(localAddress_in));
localAddress_in.sin_family = AF_INET;
if ((serv = getservbyname ("snmp-trap", "udp")) == NULL)
localAddress_in.sin_port = htons (IP_TRAP_PORT);
else
localAddress_in.sin_port = (SHORT)serv->s_port;
localAddress_in.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (ipSock, (LPSOCKADDR)&localAddress_in, sizeof(localAddress_in)) != SOCKET_ERROR)
ipThread = (HANDLE)_beginthreadex
(NULL, 0, svrTrapThread, (LPVOID)ipSock, 0, &dwThreadId);
}
//-----------------------------------------------------------------------------------
//CHECK_IPX:
ipxSock = socket (AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
if (ipxSock != INVALID_SOCKET)
{
struct sockaddr_ipx localAddress_ipx;
ZeroMemory (&localAddress_ipx, sizeof(localAddress_ipx));
localAddress_ipx.sa_family = AF_IPX;
localAddress_ipx.sa_socket = htons (IPX_TRAP_PORT);
if (bind (ipxSock, (LPSOCKADDR)&localAddress_ipx, sizeof(localAddress_ipx)) != SOCKET_ERROR)
ipxThread = (HANDLE)_beginthreadex
(NULL, 0, svrTrapThread, (LPVOID)ipxSock, 0, &dwThreadId);
}
//-----------------------------------------------------------------------------------
// We are ready to listen for traps...
status.dwCurrentState = SERVICE_RUNNING;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
if (!SetServiceStatus(hService, &status))
goto CLOSE_OUT;
WaitForSingleObject (hExitEvent, INFINITE);
//-----------------------------------------------------------------------------------
CLOSE_OUT:
EnterCriticalSection (&cs_PIPELIST);
if (hPipeThread != NULL)
{
TerminateThread (hPipeThread, 0);
CloseHandle (hPipeThread);
}
if (ipSock != INVALID_SOCKET)
closesocket (ipSock);
if (ipThread != NULL)
{
WaitForSingleObject (ipThread, INFINITE);
CloseHandle (ipThread);
}
if (ipxSock != INVALID_SOCKET)
closesocket (ipxSock);
if (ipxThread != NULL)
{
WaitForSingleObject (ipxThread, INFINITE);
CloseHandle (ipxThread);
}
if (pSvrPipeListHead != NULL)
GlobalFree (pSvrPipeListHead);
LeaveCriticalSection (&cs_PIPELIST);
DeleteCriticalSection (&cs_PIPELIST);
WSACleanup();
status.dwCurrentState = SERVICE_STOPPED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -