Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. loopmgr.c
  5. Abstract:
  6. This module contains all of the code to drive the
  7. Loop Manager of IPSecSPD Service.
  8. Author:
  9. abhisheV 30-September-1999
  10. Environment
  11. User Level: Win32
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. enum {
  16. SERVICE_STOP_EVENT = 0,
  17. INTERFACE_CHANGE_EVENT,
  18. NEW_LOCAL_POLICY_EVENT,
  19. NEW_DS_POLICY_EVENT,
  20. FORCED_POLICY_RELOAD_EVENT,
  21. WAIT_EVENT_COUNT,
  22. };
  23. DWORD
  24. ServiceWait(
  25. )
  26. {
  27. DWORD dwError = 0;
  28. HANDLE hWaitForEvents[WAIT_EVENT_COUNT];
  29. BOOL bDoneWaiting = FALSE;
  30. DWORD dwWaitMilliseconds = 0;
  31. DWORD dwStatus = 0;
  32. time_t LastTimeOutTime = 0;
  33. AuditEvent(
  34. SE_CATEGID_POLICY_CHANGE,
  35. SE_AUDITID_IPSEC_POLICY_CHANGED,
  36. IPSECSVC_SUCCESSFUL_START,
  37. NULL,
  38. TRUE,
  39. TRUE
  40. );
  41. hWaitForEvents[SERVICE_STOP_EVENT] = ghServiceStopEvent;
  42. hWaitForEvents[INTERFACE_CHANGE_EVENT] = GetInterfaceChangeEvent();
  43. hWaitForEvents[NEW_LOCAL_POLICY_EVENT] = ghNewLocalPolicyEvent;
  44. hWaitForEvents[NEW_DS_POLICY_EVENT] = ghNewDSPolicyEvent;
  45. hWaitForEvents[FORCED_POLICY_RELOAD_EVENT] = ghForcedPolicyReloadEvent;
  46. //
  47. // First load the default main mode policy.
  48. //
  49. (VOID) LoadDefaultISAKMPInformation(
  50. gpszDefaultISAKMPPolicyDN
  51. );
  52. //
  53. // Initialize Policy State Block.
  54. //
  55. InitializePolicyStateBlock(
  56. gpIpsecPolicyState
  57. );
  58. //
  59. // Call the Polling Manager for the first time.
  60. //
  61. (VOID) StartStatePollingManager(
  62. gpIpsecPolicyState
  63. );
  64. NotifyIpsecPolicyChange();
  65. ComputeRelativePollingTime(
  66. LastTimeOutTime,
  67. TRUE,
  68. &dwWaitMilliseconds
  69. );
  70. time(&LastTimeOutTime);
  71. while (!bDoneWaiting) {
  72. dwStatus = WaitForMultipleObjects(
  73. WAIT_EVENT_COUNT,
  74. hWaitForEvents,
  75. FALSE,
  76. dwWaitMilliseconds
  77. );
  78. PADeleteInUsePolicies();
  79. switch (dwStatus) {
  80. case SERVICE_STOP_EVENT:
  81. dwError = ERROR_SUCCESS;
  82. bDoneWaiting = TRUE;
  83. break;
  84. case INTERFACE_CHANGE_EVENT:
  85. (VOID) OnInterfaceChangeEvent(
  86. );
  87. (VOID) IKEInterfaceChange();
  88. break;
  89. case NEW_LOCAL_POLICY_EVENT:
  90. ResetEvent(ghNewLocalPolicyEvent);
  91. if ((gpIpsecPolicyState->dwCurrentState != POLL_STATE_DS_DOWNLOADED) &&
  92. (gpIpsecPolicyState->dwCurrentState != POLL_STATE_CACHE_DOWNLOADED)) {
  93. (VOID) ProcessLocalPolicyPollState(
  94. gpIpsecPolicyState
  95. );
  96. NotifyIpsecPolicyChange();
  97. }
  98. break;
  99. case NEW_DS_POLICY_EVENT:
  100. ResetEvent(ghNewDSPolicyEvent);
  101. (VOID) OnPolicyChanged(
  102. gpIpsecPolicyState
  103. );
  104. NotifyIpsecPolicyChange();
  105. break;
  106. case FORCED_POLICY_RELOAD_EVENT:
  107. ResetEvent(ghForcedPolicyReloadEvent);
  108. (VOID) OnPolicyChanged(
  109. gpIpsecPolicyState
  110. );
  111. NotifyIpsecPolicyChange();
  112. AuditEvent(
  113. SE_CATEGID_POLICY_CHANGE,
  114. SE_AUDITID_IPSEC_POLICY_CHANGED,
  115. PASTORE_FORCED_POLICY_RELOAD,
  116. NULL,
  117. TRUE,
  118. TRUE
  119. );
  120. break;
  121. case WAIT_TIMEOUT:
  122. time(&LastTimeOutTime);
  123. (VOID) OnPolicyPoll(
  124. gpIpsecPolicyState
  125. );
  126. break;
  127. case WAIT_FAILED:
  128. dwError = GetLastError();
  129. bDoneWaiting = TRUE;
  130. break;
  131. default:
  132. dwError = ERROR_INVALID_EVENT_COUNT;
  133. bDoneWaiting = TRUE;
  134. break;
  135. }
  136. ComputeRelativePollingTime(
  137. LastTimeOutTime,
  138. FALSE,
  139. &dwWaitMilliseconds
  140. );
  141. }
  142. if (!dwError) {
  143. AuditEvent(
  144. SE_CATEGID_POLICY_CHANGE,
  145. SE_AUDITID_IPSEC_POLICY_CHANGED,
  146. IPSECSVC_SUCCESSFUL_SHUTDOWN,
  147. NULL,
  148. TRUE,
  149. TRUE
  150. );
  151. }
  152. else {
  153. AuditOneArgErrorEvent(
  154. SE_CATEGID_POLICY_CHANGE,
  155. SE_AUDITID_IPSEC_POLICY_CHANGED,
  156. IPSECSVC_ERROR_SHUTDOWN,
  157. dwError,
  158. FALSE,
  159. TRUE
  160. );
  161. }
  162. return (dwError);
  163. }
  164. VOID
  165. ComputeRelativePollingTime(
  166. time_t LastTimeOutTime,
  167. BOOL bInitialLoad,
  168. PDWORD pWaitMilliseconds
  169. )
  170. {
  171. DWORD WaitMilliseconds = 0;
  172. DWORD DSReconnectMilliseconds = 0;
  173. time_t NextTimeOutTime = 0;
  174. time_t PresentTime = 0;
  175. long WaitSeconds = gDefaultPollingInterval;
  176. WaitMilliseconds = gCurrentPollingInterval * 1000;
  177. if (!WaitMilliseconds) {
  178. WaitMilliseconds = INFINITE;
  179. }
  180. DSReconnectMilliseconds = gdwDSConnectivityCheck*60*1000;
  181. if ((gpIpsecPolicyState->dwCurrentState != POLL_STATE_DS_DOWNLOADED) &&
  182. (gpIpsecPolicyState->dwCurrentState != POLL_STATE_LOCAL_DOWNLOADED)) {
  183. if (WaitMilliseconds > DSReconnectMilliseconds) {
  184. WaitMilliseconds = DSReconnectMilliseconds;
  185. }
  186. }
  187. if (!bInitialLoad && WaitMilliseconds != INFINITE) {
  188. //
  189. // LastTimeOutTime is the snapshot time value in the past when
  190. // we timed out waiting for multiple events.
  191. // Ideally, the time for the next time out, NextTimeOutTime, is
  192. // the time value in future which is sum of the last time when
  193. // we timed out + the current waiting time value.
  194. //
  195. NextTimeOutTime = LastTimeOutTime + (WaitMilliseconds/1000);
  196. //
  197. // However, the last time we may not have timed out waiting
  198. // for multiple events but rather came out because one of the
  199. // events other than WAIT_TIMEOUT happened.
  200. // However, on that event we may not have done a policy
  201. // poll to figure out whether there was a policy change or
  202. // not. If we again wait for WaitMilliseconds, then we are
  203. // un-knowingly making our net time for policy poll greater
  204. // than the alloted time interval value = WaitMilliseconds.
  205. // So, we need to adjust the WaitMilliseconds to such a value
  206. // that no matter what happens, we always do a policy poll
  207. // atmost every WaitMilliseconds time interval value.
  208. // The current time is PresentTime.
  209. //
  210. time(&PresentTime);
  211. WaitSeconds = (long) (NextTimeOutTime - PresentTime);
  212. if (WaitSeconds < 0) {
  213. WaitMilliseconds = 0;
  214. }
  215. else {
  216. WaitMilliseconds = WaitSeconds * 1000;
  217. }
  218. }
  219. *pWaitMilliseconds = WaitMilliseconds;
  220. }
  221. VOID
  222. NotifyIpsecPolicyChange(
  223. )
  224. {
  225. PulseEvent(ghPolicyChangeNotifyEvent);
  226. SendPschedIoctl();
  227. ResetEvent(ghPolicyChangeNotifyEvent);
  228. return;
  229. }
  230. VOID
  231. SendPschedIoctl(
  232. )
  233. {
  234. HANDLE hPschedDriverHandle = NULL;
  235. ULONG uBytesReturned = 0;
  236. BOOL bIOStatus = FALSE;
  237. #define DriverName TEXT("\\\\.\\PSCHED")
  238. #define IOCTL_PSCHED_ZAW_EVENT CTL_CODE( \
  239. FILE_DEVICE_NETWORK, \
  240. 20, \
  241. METHOD_BUFFERED, \
  242. FILE_ANY_ACCESS \
  243. )
  244. hPschedDriverHandle = CreateFile(
  245. DriverName,
  246. GENERIC_READ | GENERIC_WRITE,
  247. FILE_SHARE_READ | FILE_SHARE_WRITE,
  248. NULL,
  249. OPEN_EXISTING,
  250. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  251. NULL
  252. );
  253. if (hPschedDriverHandle != INVALID_HANDLE_VALUE) {
  254. bIOStatus = DeviceIoControl(
  255. hPschedDriverHandle,
  256. IOCTL_PSCHED_ZAW_EVENT,
  257. NULL,
  258. 0,
  259. NULL,
  260. 0,
  261. &uBytesReturned,
  262. NULL
  263. );
  264. CloseHandle(hPschedDriverHandle);
  265. }
  266. }
  267. VOID
  268. PADeleteInUsePolicies(
  269. )
  270. {
  271. DWORD dwError = 0;
  272. dwError = PADeleteInUseMMPolicies();
  273. dwError = PADeleteInUseMMAuthMethods();
  274. dwError = PADeleteInUseQMPolicies();
  275. return;
  276. }