windows-nt/Source/XPSP1/NT/net/snmp/newagent/exe/startup.c

400 lines
9.8 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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,
&regThreadId)) != 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;
}