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;
|
||
}
|