|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
loopmgr.c
Abstract:
This module contains all of the code to drive the Loop Manager of IPSecSPD Service.
Author:
abhisheV 30-September-1999
Environment
User Level: Win32
Revision History:
--*/
#include "precomp.h"
enum { SERVICE_STOP_EVENT = 0, INTERFACE_CHANGE_EVENT, NEW_LOCAL_POLICY_EVENT, NEW_DS_POLICY_EVENT, FORCED_POLICY_RELOAD_EVENT, WAIT_EVENT_COUNT, };
DWORD ServiceWait( ) { DWORD dwError = 0; HANDLE hWaitForEvents[WAIT_EVENT_COUNT]; BOOL bDoneWaiting = FALSE; DWORD dwWaitMilliseconds = 0; DWORD dwStatus = 0; time_t LastTimeOutTime = 0;
AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, IPSECSVC_SUCCESSFUL_START, NULL, TRUE, TRUE );
hWaitForEvents[SERVICE_STOP_EVENT] = ghServiceStopEvent; hWaitForEvents[INTERFACE_CHANGE_EVENT] = GetInterfaceChangeEvent(); hWaitForEvents[NEW_LOCAL_POLICY_EVENT] = ghNewLocalPolicyEvent; hWaitForEvents[NEW_DS_POLICY_EVENT] = ghNewDSPolicyEvent; hWaitForEvents[FORCED_POLICY_RELOAD_EVENT] = ghForcedPolicyReloadEvent;
//
// First load the default main mode policy.
//
(VOID) LoadDefaultISAKMPInformation( gpszDefaultISAKMPPolicyDN );
//
// Initialize Policy State Block.
//
InitializePolicyStateBlock( gpIpsecPolicyState );
//
// Call the Polling Manager for the first time.
//
(VOID) StartStatePollingManager( gpIpsecPolicyState );
NotifyIpsecPolicyChange();
ComputeRelativePollingTime( LastTimeOutTime, TRUE, &dwWaitMilliseconds );
time(&LastTimeOutTime);
while (!bDoneWaiting) {
dwStatus = WaitForMultipleObjects( WAIT_EVENT_COUNT, hWaitForEvents, FALSE, dwWaitMilliseconds );
PADeleteInUsePolicies();
switch (dwStatus) {
case SERVICE_STOP_EVENT:
dwError = ERROR_SUCCESS; bDoneWaiting = TRUE; break;
case INTERFACE_CHANGE_EVENT:
(VOID) OnInterfaceChangeEvent( ); (VOID) IKEInterfaceChange(); break;
case NEW_LOCAL_POLICY_EVENT:
ResetEvent(ghNewLocalPolicyEvent); if ((gpIpsecPolicyState->dwCurrentState != POLL_STATE_DS_DOWNLOADED) && (gpIpsecPolicyState->dwCurrentState != POLL_STATE_CACHE_DOWNLOADED)) { (VOID) ProcessLocalPolicyPollState( gpIpsecPolicyState ); NotifyIpsecPolicyChange(); } break;
case NEW_DS_POLICY_EVENT:
ResetEvent(ghNewDSPolicyEvent); (VOID) OnPolicyChanged( gpIpsecPolicyState ); NotifyIpsecPolicyChange(); break;
case FORCED_POLICY_RELOAD_EVENT:
ResetEvent(ghForcedPolicyReloadEvent); (VOID) OnPolicyChanged( gpIpsecPolicyState ); NotifyIpsecPolicyChange(); AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FORCED_POLICY_RELOAD, NULL, TRUE, TRUE ); break;
case WAIT_TIMEOUT:
time(&LastTimeOutTime); (VOID) OnPolicyPoll( gpIpsecPolicyState ); break;
case WAIT_FAILED:
dwError = GetLastError(); bDoneWaiting = TRUE; break;
default:
dwError = ERROR_INVALID_EVENT_COUNT; bDoneWaiting = TRUE; break;
}
ComputeRelativePollingTime( LastTimeOutTime, FALSE, &dwWaitMilliseconds );
}
if (!dwError) { AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, IPSECSVC_SUCCESSFUL_SHUTDOWN, NULL, TRUE, TRUE ); } else { AuditOneArgErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, IPSECSVC_ERROR_SHUTDOWN, dwError, FALSE, TRUE ); }
return (dwError); }
VOID ComputeRelativePollingTime( time_t LastTimeOutTime, BOOL bInitialLoad, PDWORD pWaitMilliseconds ) { DWORD WaitMilliseconds = 0; DWORD DSReconnectMilliseconds = 0; time_t NextTimeOutTime = 0; time_t PresentTime = 0; long WaitSeconds = gDefaultPollingInterval;
WaitMilliseconds = gCurrentPollingInterval * 1000;
if (!WaitMilliseconds) { WaitMilliseconds = INFINITE; }
DSReconnectMilliseconds = gdwDSConnectivityCheck*60*1000;
if ((gpIpsecPolicyState->dwCurrentState != POLL_STATE_DS_DOWNLOADED) && (gpIpsecPolicyState->dwCurrentState != POLL_STATE_LOCAL_DOWNLOADED)) { if (WaitMilliseconds > DSReconnectMilliseconds) { WaitMilliseconds = DSReconnectMilliseconds; } }
if (!bInitialLoad && WaitMilliseconds != INFINITE) {
//
// LastTimeOutTime is the snapshot time value in the past when
// we timed out waiting for multiple events.
// Ideally, the time for the next time out, NextTimeOutTime, is
// the time value in future which is sum of the last time when
// we timed out + the current waiting time value.
//
NextTimeOutTime = LastTimeOutTime + (WaitMilliseconds/1000);
//
// However, the last time we may not have timed out waiting
// for multiple events but rather came out because one of the
// events other than WAIT_TIMEOUT happened.
// However, on that event we may not have done a policy
// poll to figure out whether there was a policy change or
// not. If we again wait for WaitMilliseconds, then we are
// un-knowingly making our net time for policy poll greater
// than the alloted time interval value = WaitMilliseconds.
// So, we need to adjust the WaitMilliseconds to such a value
// that no matter what happens, we always do a policy poll
// atmost every WaitMilliseconds time interval value.
// The current time is PresentTime.
//
time(&PresentTime);
WaitSeconds = (long) (NextTimeOutTime - PresentTime);
if (WaitSeconds < 0) { WaitMilliseconds = 0; } else { WaitMilliseconds = WaitSeconds * 1000; }
}
*pWaitMilliseconds = WaitMilliseconds; }
VOID NotifyIpsecPolicyChange( ) { PulseEvent(ghPolicyChangeNotifyEvent);
SendPschedIoctl();
ResetEvent(ghPolicyChangeNotifyEvent);
return; }
VOID SendPschedIoctl( ) { HANDLE hPschedDriverHandle = NULL; ULONG uBytesReturned = 0; BOOL bIOStatus = FALSE;
#define DriverName TEXT("\\\\.\\PSCHED")
#define IOCTL_PSCHED_ZAW_EVENT CTL_CODE( \
FILE_DEVICE_NETWORK, \ 20, \ METHOD_BUFFERED, \ FILE_ANY_ACCESS \ )
hPschedDriverHandle = CreateFile( DriverName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if (hPschedDriverHandle != INVALID_HANDLE_VALUE) {
bIOStatus = DeviceIoControl( hPschedDriverHandle, IOCTL_PSCHED_ZAW_EVENT, NULL, 0, NULL, 0, &uBytesReturned, NULL );
CloseHandle(hPschedDriverHandle);
} }
VOID PADeleteInUsePolicies( ) { DWORD dwError = 0;
dwError = PADeleteInUseMMPolicies();
dwError = PADeleteInUseMMAuthMethods();
dwError = PADeleteInUseQMPolicies();
return; }
|