/*++ 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; }