400 lines
9.8 KiB
C
400 lines
9.8 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992-1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
startup.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Contains routines for starting SNMP master agent.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode - Win32
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
10-Feb-1997 DonRyan
|
|||
|
Rewrote to implement SNMPv2 support.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Include files //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#include "globals.h"
|
|||
|
#include "startup.h"
|
|||
|
#include "network.h"
|
|||
|
#include "registry.h"
|
|||
|
#include "snmpthrd.h"
|
|||
|
#include "regthrd.h"
|
|||
|
#include "trapthrd.h"
|
|||
|
#include "args.h"
|
|||
|
#include "mem.h"
|
|||
|
#include "snmpmgmt.h"
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Global variables //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
HANDLE g_hAgentThread = NULL;
|
|||
|
HANDLE g_hRegistryThread = NULL; // Used to track registry changes
|
|||
|
CRITICAL_SECTION g_RegCriticalSectionA;
|
|||
|
CRITICAL_SECTION g_RegCriticalSectionB;
|
|||
|
CRITICAL_SECTION g_RegCriticalSectionC; // protect the generation of trap from
|
|||
|
// registry changes
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Private procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
BOOL
|
|||
|
LoadWinsock(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Startup winsock.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
WSADATA WsaData;
|
|||
|
WORD wVersionRequested = MAKEWORD(2,0);
|
|||
|
INT nStatus;
|
|||
|
|
|||
|
// attempt to startup winsock
|
|||
|
nStatus = WSAStartup(wVersionRequested, &WsaData);
|
|||
|
|
|||
|
// validate return code
|
|||
|
if (nStatus == SOCKET_ERROR) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: error %d starting winsock.\n",
|
|||
|
WSAGetLastError()
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
UnloadWinsock(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Shutdown winsock.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
INT nStatus;
|
|||
|
|
|||
|
// cleanup
|
|||
|
nStatus = WSACleanup();
|
|||
|
|
|||
|
// validate return code
|
|||
|
if (nStatus == SOCKET_ERROR) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: error %d stopping winsock.\n",
|
|||
|
WSAGetLastError()
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Public procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
BOOL
|
|||
|
StartupAgent(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Performs essential initialization of master agent.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL fOk = TRUE;
|
|||
|
DWORD dwThreadId = 0;
|
|||
|
DWORD regThreadId = 0;
|
|||
|
INT nCSOk = 0; // counts the number of CS that were successfully initialized
|
|||
|
|
|||
|
// initialize management variables
|
|||
|
mgmtInit();
|
|||
|
|
|||
|
// initialize list heads
|
|||
|
InitializeListHead(&g_Subagents);
|
|||
|
InitializeListHead(&g_SupportedRegions);
|
|||
|
InitializeListHead(&g_ValidCommunities);
|
|||
|
InitializeListHead(&g_TrapDestinations);
|
|||
|
InitializeListHead(&g_PermittedManagers);
|
|||
|
InitializeListHead(&g_IncomingTransports);
|
|||
|
InitializeListHead(&g_OutgoingTransports);
|
|||
|
|
|||
|
__try
|
|||
|
{
|
|||
|
InitializeCriticalSection(&g_RegCriticalSectionA); nCSOk++;
|
|||
|
InitializeCriticalSection(&g_RegCriticalSectionB); nCSOk++;
|
|||
|
InitializeCriticalSection(&g_RegCriticalSectionC); nCSOk++;
|
|||
|
}
|
|||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|||
|
{
|
|||
|
if (nCSOk == 1)
|
|||
|
DeleteCriticalSection(&g_RegCriticalSectionA);
|
|||
|
if (nCSOk == 2)
|
|||
|
{
|
|||
|
DeleteCriticalSection(&g_RegCriticalSectionA);
|
|||
|
DeleteCriticalSection(&g_RegCriticalSectionB);
|
|||
|
}
|
|||
|
// nCSOk can't be 3 as far as we are here
|
|||
|
|
|||
|
fOk = FALSE;
|
|||
|
}
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: Initialize critical sections...%s\n", fOk? "Ok" : "Failed"));
|
|||
|
|
|||
|
|
|||
|
fOk = fOk &&
|
|||
|
(g_hRegistryEvent = CreateEvent(NULL, FALSE, TRUE, NULL)) != NULL;
|
|||
|
|
|||
|
|
|||
|
g_dwUpTimeReference = SnmpSvcInitUptime();
|
|||
|
// retreive system uptime reference
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: Getting system uptime...%d\n", g_dwUpTimeReference));
|
|||
|
|
|||
|
// allocate essentials
|
|||
|
fOk = fOk && AgentHeapCreate();
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: Creating agent heap...%s\n", fOk? "Ok" : "Failed"));
|
|||
|
|
|||
|
fOk = fOk && LoadWinsock();
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: Loading Winsock stack...%s\n", fOk? "Ok" : "Failed"));
|
|||
|
|
|||
|
fOk = fOk && LoadIncomingTransports();
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: Loading Incoming transports...%s\n", fOk? "Ok" : "Failed"));
|
|||
|
|
|||
|
fOk = fOk && LoadOutgoingTransports();
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: Loading Outgoing transports...%s\n", fOk? "Ok" : "Failed"));
|
|||
|
|
|||
|
fOk = fOk &&
|
|||
|
// attempt to start main thread
|
|||
|
(g_hAgentThread = CreateThread(
|
|||
|
NULL, // lpThreadAttributes
|
|||
|
0, // dwStackSize
|
|||
|
ProcessSnmpMessages,
|
|||
|
NULL, // lpParameter
|
|||
|
CREATE_SUSPENDED, // dwCreationFlags
|
|||
|
&dwThreadId
|
|||
|
)) != NULL;
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: Starting ProcessSnmpMessages thread...%s\n", fOk? "Ok" : "Failed"));
|
|||
|
|
|||
|
fOk = fOk &&
|
|||
|
// attempt to start registry listener thread
|
|||
|
(g_hRegistryThread = CreateThread(
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
ProcessRegistryMessage,
|
|||
|
NULL,
|
|||
|
CREATE_SUSPENDED,
|
|||
|
®ThreadId)) != NULL;
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: Starting ProcessRegistryMessages thread...%s\n", fOk? "Ok" : "Failed"));
|
|||
|
|
|||
|
return fOk;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ShutdownAgent(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Performs final cleanup of master agent.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL fOk;
|
|||
|
DWORD dwStatus;
|
|||
|
|
|||
|
// make sure shutdown signalled
|
|||
|
fOk = SetEvent(g_hTerminationEvent);
|
|||
|
|
|||
|
if (!fOk) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: error %d signalling termination.\n",
|
|||
|
GetLastError()
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
// check if thread created
|
|||
|
if ((g_hAgentThread != NULL) && (g_hRegistryThread != NULL)) {
|
|||
|
HANDLE hEvntArray[2];
|
|||
|
|
|||
|
hEvntArray[0] = g_hAgentThread;
|
|||
|
hEvntArray[1] = g_hRegistryThread;
|
|||
|
|
|||
|
dwStatus = WaitForMultipleObjects(2, hEvntArray, TRUE, SHUTDOWN_WAIT_HINT);
|
|||
|
|
|||
|
// validate return status
|
|||
|
if ((dwStatus != WAIT_OBJECT_0) &&
|
|||
|
(dwStatus != WAIT_OBJECT_0 + 1) &&
|
|||
|
(dwStatus != WAIT_TIMEOUT)) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: error %d waiting for thread(s) termination.\n",
|
|||
|
GetLastError()
|
|||
|
));
|
|||
|
}
|
|||
|
} else if (g_hAgentThread != NULL) {
|
|||
|
|
|||
|
// wait for pdu processing thread to terminate
|
|||
|
dwStatus = WaitForSingleObject(g_hAgentThread, SHUTDOWN_WAIT_HINT);
|
|||
|
|
|||
|
// validate return status
|
|||
|
if ((dwStatus != WAIT_OBJECT_0) &&
|
|||
|
(dwStatus != WAIT_TIMEOUT)) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: error %d waiting for main thread termination.\n",
|
|||
|
GetLastError()
|
|||
|
));
|
|||
|
}
|
|||
|
} else if (g_hRegistryThread != NULL) {
|
|||
|
|
|||
|
// wait for registry processing thread to terminate
|
|||
|
dwStatus = WaitForSingleObject(g_hRegistryThread, SHUTDOWN_WAIT_HINT);
|
|||
|
|
|||
|
// validate return status
|
|||
|
if ((dwStatus != WAIT_OBJECT_0) &&
|
|||
|
(dwStatus != WAIT_TIMEOUT)) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: error %d waiting for registry thread termination.\n",
|
|||
|
GetLastError()
|
|||
|
));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// unload incoming transports
|
|||
|
UnloadIncomingTransports();
|
|||
|
|
|||
|
// unload outgoing transports
|
|||
|
UnloadOutgoingTransports();
|
|||
|
|
|||
|
// unload registry info
|
|||
|
UnloadRegistryParameters();
|
|||
|
|
|||
|
// unload the winsock stack
|
|||
|
UnloadWinsock();
|
|||
|
|
|||
|
// cleanup the internal management buffers
|
|||
|
mgmtCleanup();
|
|||
|
|
|||
|
// nuke private heap
|
|||
|
AgentHeapDestroy();
|
|||
|
|
|||
|
// clean up critical section resources
|
|||
|
DeleteCriticalSection(&g_RegCriticalSectionA);
|
|||
|
DeleteCriticalSection(&g_RegCriticalSectionB);
|
|||
|
DeleteCriticalSection(&g_RegCriticalSectionC);
|
|||
|
|
|||
|
ReportSnmpEvent(
|
|||
|
SNMP_EVENT_SERVICE_STOPPED,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|