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.

3210 lines
82 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. driver.c
  5. Abstract:
  6. This module contains the DriverEntry and other initialization
  7. code for the IPSEC module of the Tcpip transport.
  8. Author:
  9. Sanjay Anand (SanjayAn) 2-January-1997
  10. ChunYe
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(INIT, DriverEntry)
  19. #pragma alloc_text(INIT, IPSecGeneralInit)
  20. #pragma alloc_text(PAGE, IPSecDispatch)
  21. #pragma alloc_text(PAGE, IPSecBindToIP)
  22. #pragma alloc_text(PAGE, IPSecUnbindFromIP)
  23. #pragma alloc_text(PAGE, IPSecFreeConfig)
  24. #pragma alloc_text(PAGE, IPSecInitMdlPool)
  25. #pragma alloc_text(PAGE, AllocateCacheStructures)
  26. #pragma alloc_text(PAGE, FreeExistingCache)
  27. #pragma alloc_text(PAGE, FreePatternDbase)
  28. #pragma alloc_text(PAGE, OpenRegKey)
  29. #pragma alloc_text(PAGE, GetRegDWORDValue)
  30. #pragma alloc_text(PAGE, IPSecCryptoInitialize)
  31. #pragma alloc_text(PAGE, IPSecCryptoDeinitialize)
  32. #endif
  33. NTSTATUS
  34. DriverEntry(
  35. IN PDRIVER_OBJECT DriverObject,
  36. IN PUNICODE_STRING RegistryPath
  37. )
  38. /*++
  39. Routine Description:
  40. This routine performs initialization of the IPSEC module.
  41. It creates the device object for the transport
  42. provider and performs other driver initialization.
  43. Arguments:
  44. DriverObject - Pointer to driver object created by the system.
  45. RegistryPath - The name of IPSEC's node in the registry.
  46. Return Value:
  47. The function value is the final status from the initialization operation.
  48. --*/
  49. {
  50. PDEVICE_OBJECT deviceObject = NULL;
  51. WCHAR deviceNameBuffer[] = DD_IPSEC_DEVICE_NAME;
  52. WCHAR symbolicLinkBuffer[] = DD_IPSEC_SYM_NAME;
  53. UNICODE_STRING symbolicLinkName;
  54. UNICODE_STRING deviceNameUnicodeString;
  55. NTSTATUS status;
  56. NTSTATUS status1;
  57. //DbgBreakPoint();
  58. IPSEC_DEBUG(LOAD, ("Entering DriverEntry\n"));
  59. //
  60. // Init g_ipsec structure and read reg keys.
  61. //
  62. IPSecZeroMemory(&g_ipsec, sizeof(g_ipsec));
  63. IPSecReadRegistry();
  64. //
  65. // Create the device - do we need a device at all?
  66. //
  67. // Setup the handlers.
  68. //
  69. //
  70. // Initialize the driver object with this driver's entry points.
  71. //
  72. g_ipsec.IPSecDriverObject = DriverObject;
  73. DriverObject->MajorFunction [IRP_MJ_CREATE] =
  74. DriverObject->MajorFunction [IRP_MJ_CLOSE] =
  75. DriverObject->MajorFunction [IRP_MJ_CLEANUP] =
  76. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  77. DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = IPSecDispatch;
  78. DriverObject->DriverUnload = IPSecUnload;
  79. RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer);
  80. status = IoCreateDevice(
  81. DriverObject,
  82. 0, // DeviceExtensionSize
  83. &deviceNameUnicodeString, // DeviceName
  84. FILE_DEVICE_NETWORK, // DeviceType
  85. FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
  86. FALSE, // Exclusive
  87. &deviceObject); // *DeviceObject
  88. if (!NT_SUCCESS (status)) {
  89. IPSEC_DEBUG(LOAD, ("Failed to create device: %lx\n", status));
  90. LOG_EVENT(
  91. DriverObject,
  92. EVENT_IPSEC_CREATE_DEVICE_FAILED,
  93. 1,
  94. 1,
  95. &deviceNameUnicodeString.Buffer,
  96. 0,
  97. NULL);
  98. goto err;
  99. }
  100. deviceObject->Flags |= DO_BUFFERED_IO;
  101. IPSecDevice = deviceObject;
  102. RtlInitUnicodeString (&symbolicLinkName, symbolicLinkBuffer);
  103. status = IoCreateSymbolicLink(&symbolicLinkName, &deviceNameUnicodeString);
  104. if (!NT_SUCCESS (status)) {
  105. IPSEC_DEBUG(LOAD, ("Failed to create symbolic link: %lx\n", status));
  106. LOG_EVENT(
  107. DriverObject,
  108. EVENT_IPSEC_CREATE_DEVICE_FAILED,
  109. 2,
  110. 1,
  111. &deviceNameUnicodeString.Buffer,
  112. 0,
  113. NULL);
  114. IoDeleteDevice(DriverObject->DeviceObject);
  115. goto err;
  116. }
  117. //
  118. // General structs init here.
  119. // Allocates the SA Table etc.
  120. //
  121. status = IPSecGeneralInit();
  122. if (!NT_SUCCESS (status)) {
  123. IPSEC_DEBUG(LOAD, ("Failed to init general structs: %lx\n", status));
  124. //
  125. // Free the general structs and SA Table etc.
  126. //
  127. status1 = IPSecGeneralFree();
  128. if (!NT_SUCCESS (status1)) {
  129. IPSEC_DEBUG(LOAD, ("Failed to free config: %lx\n", status1));
  130. }
  131. LOG_EVENT(
  132. DriverObject,
  133. EVENT_IPSEC_NO_RESOURCES_FOR_INIT,
  134. 1,
  135. 0,
  136. NULL,
  137. 0,
  138. NULL);
  139. IoDeleteSymbolicLink(&symbolicLinkName);
  140. IoDeleteDevice(DriverObject->DeviceObject);
  141. goto err;
  142. }
  143. //
  144. // Wait for TCP/IP to load and call IOCTL_IPSEC_SET_TCPIP_STATUS where we
  145. // would finish the initialization.
  146. //
  147. status = STATUS_SUCCESS;
  148. IPSEC_DEBUG(LOAD, ("Exiting DriverEntry; SUCCESS\n"));
  149. err:
  150. return status;
  151. }
  152. VOID
  153. IPSecUnload(
  154. IN PDRIVER_OBJECT DriverObject
  155. )
  156. /*++
  157. Routine Description:
  158. Called when the driver is unloaded.
  159. Arguments:
  160. DriverObject
  161. Return Value:
  162. None
  163. --*/
  164. {
  165. UNICODE_STRING IPSecLinkName;
  166. KIRQL OldIrq;
  167. KIRQL kIrql;
  168. NTSTATUS status;
  169. INT class;
  170. IPSEC_DEBUG(LOAD, ("Entering IPSecUnload\n"));
  171. //
  172. // Set IPSEC_DRIVER_UNLOADING bit.
  173. //
  174. IPSEC_DRIVER_UNLOADING() = TRUE;
  175. //
  176. // Stop the reaper timer.
  177. //
  178. IPSecStopTimer(&g_ipsec.ReaperTimer);
  179. //
  180. // Stop the EventLog timer.
  181. //
  182. IPSecStopTimer(&g_ipsec.EventLogTimer);
  183. //
  184. // Complete the Acquire Irp with error status
  185. //
  186. if (g_ipsec.AcquireInfo.Irp) {
  187. IPSEC_DEBUG(ACQUIRE, ("Unload: Completing Irp..\n"));
  188. if (g_ipsec.AcquireInfo.InMe) {
  189. IoAcquireCancelSpinLock(&g_ipsec.AcquireInfo.Irp->CancelIrql);
  190. IPSecAcquireIrpCancel(NULL, g_ipsec.AcquireInfo.Irp);
  191. }
  192. }
  193. //
  194. // Stop timers for all SAs (of all states)
  195. //
  196. IPSecStopSATimers();
  197. //
  198. // Wait for all timers to clear before going further
  199. //
  200. while (IPSEC_GET_VALUE(g_ipsec.NumTimers) != 0) {
  201. IPSEC_DELAY_EXECUTION();
  202. }
  203. //
  204. // Cleanup any larval SAs
  205. //
  206. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  207. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &OldIrq);
  208. IPSecFlushLarvalSAList();
  209. IPSecFlushSAExpirations();
  210. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  211. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  212. //
  213. // Free the SA Table.
  214. //
  215. status = IPSecFreeConfig();
  216. if (!NT_SUCCESS (status)) {
  217. IPSEC_DEBUG(LOAD, ("Failed to free config: %lx\n", status));
  218. }
  219. //
  220. // Free the MDL pools and run down all buffered packets.
  221. //
  222. status = IPSecQuiesce();
  223. if (!NT_SUCCESS (status)) {
  224. IPSEC_DEBUG(LOAD, ("Failed to reach quiescent state: %lx\n", status));
  225. }
  226. //
  227. // Destroy timer structures
  228. //
  229. ACQUIRE_LOCK(&g_ipsec.TimerLock, &kIrql);
  230. for (class = 0; class < IPSEC_CLASS_MAX; class++) {
  231. ASSERT(g_ipsec.TimerList[class].TimerCount == 0);
  232. IPSecFreeMemory(g_ipsec.TimerList[class].pTimers);
  233. }
  234. RELEASE_LOCK(&g_ipsec.TimerLock, kIrql);
  235. IPSecCryptoDeinitialize();
  236. #if GPC
  237. IPSecGpcDeinitialize();
  238. #endif
  239. RtlInitUnicodeString(&IPSecLinkName, DD_IPSEC_SYM_NAME);
  240. IoDeleteSymbolicLink(&IPSecLinkName);
  241. IoDeleteDevice(DriverObject->DeviceObject);
  242. IPSEC_DEBUG(LOAD, ("Exiting IPSecUnload\n"));
  243. }
  244. NTSTATUS
  245. IPSecDispatch(
  246. IN PDEVICE_OBJECT DeviceObject,
  247. IN PIRP Irp
  248. )
  249. /*++
  250. Routine Description:
  251. Dispatch Routine for the driver. Gets the current irp stack location, validates
  252. the parameters and routes the calls
  253. Arguments:
  254. DeviceObject
  255. Irp
  256. Return Value:
  257. Status as returned by the worker functions
  258. --*/
  259. {
  260. PIO_STACK_LOCATION irpStack;
  261. PVOID pvIoBuffer;
  262. LONG inputBufferLength;
  263. LONG outputBufferLength;
  264. ULONG ioControlCode;
  265. NTSTATUS status = STATUS_SUCCESS;
  266. LONG dwSize = 0;
  267. PAGED_CODE();
  268. IPSEC_DEBUG(IOCTL, ("Entering IPSecDispath\n"));
  269. Irp->IoStatus.Status = status;
  270. Irp->IoStatus.Information = 0;
  271. //
  272. // Get a pointer to the current location in the Irp. This is where
  273. // the function codes and parameters are located.
  274. //
  275. irpStack = IoGetCurrentIrpStackLocation(Irp);
  276. //
  277. // Get the pointer to the input/output buffer and its length.
  278. //
  279. pvIoBuffer = Irp->AssociatedIrp.SystemBuffer;
  280. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  281. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  282. switch (irpStack->MajorFunction) {
  283. case IRP_MJ_CREATE: {
  284. IPSEC_DEBUG(IOCTL, ("IRP_MJ_CREATE\n"));
  285. break;
  286. }
  287. case IRP_MJ_CLOSE: {
  288. IPSEC_DEBUG(IOCTL, ("IRP_MJ_CLOSE\n"));
  289. break;
  290. }
  291. case IRP_MJ_DEVICE_CONTROL: {
  292. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  293. IPSEC_DEBUG(IOCTL, ("IRP_MJ_DEVICE_CONTROL: %lx\n", ioControlCode));
  294. if (ioControlCode != IOCTL_IPSEC_SET_TCPIP_STATUS) {
  295. if (IPSEC_DRIVER_IS_INACTIVE()) {
  296. status = STATUS_INVALID_DEVICE_STATE;
  297. break;
  298. }
  299. if (!IPSecCryptoInitialize()) {
  300. status = STATUS_CRYPTO_SYSTEM_INVALID;
  301. break;
  302. }
  303. }
  304. IPSEC_INCREMENT(g_ipsec.NumIoctls);
  305. switch (ioControlCode) {
  306. case IOCTL_IPSEC_ADD_FILTER: {
  307. PIPSEC_ADD_FILTER pAddFilter = (PIPSEC_ADD_FILTER)pvIoBuffer;
  308. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_ADD_FILTER\n"));
  309. dwSize = sizeof(IPSEC_ADD_FILTER);
  310. if (inputBufferLength < dwSize) {
  311. status = STATUS_BUFFER_TOO_SMALL;
  312. break;
  313. }
  314. //
  315. // Check the size of the entry
  316. //
  317. if (pAddFilter->NumEntries == 0) {
  318. status = STATUS_SUCCESS;
  319. } else {
  320. dwSize = FIELD_OFFSET(IPSEC_ADD_FILTER, pInfo[0]) +
  321. pAddFilter->NumEntries * sizeof(IPSEC_FILTER_INFO);
  322. if (dwSize < FIELD_OFFSET(IPSEC_ADD_FILTER, pInfo[0]) ||
  323. inputBufferLength < dwSize) {
  324. status = STATUS_BUFFER_TOO_SMALL;
  325. IPSEC_DEBUG(IOCTL, ("returning: %lx\n", status));
  326. break;
  327. }
  328. status = IPSecAddFilter(pAddFilter);
  329. }
  330. break;
  331. }
  332. case IOCTL_IPSEC_DELETE_FILTER: {
  333. PIPSEC_DELETE_FILTER pDelFilter = (PIPSEC_DELETE_FILTER)pvIoBuffer;
  334. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_DELETE_FILTER\n"));
  335. dwSize = sizeof(IPSEC_DELETE_FILTER);
  336. if (inputBufferLength < dwSize) {
  337. status = STATUS_BUFFER_TOO_SMALL;
  338. break;
  339. }
  340. //
  341. // Check the size of the entry
  342. //
  343. if (pDelFilter->NumEntries == 0) {
  344. status = STATUS_SUCCESS;
  345. } else {
  346. dwSize = FIELD_OFFSET(IPSEC_DELETE_FILTER, pInfo[0]) +
  347. pDelFilter->NumEntries * sizeof(IPSEC_FILTER_INFO);
  348. if (dwSize < FIELD_OFFSET(IPSEC_DELETE_FILTER, pInfo[0]) ||
  349. inputBufferLength < dwSize) {
  350. status = STATUS_BUFFER_TOO_SMALL;
  351. break;
  352. }
  353. status = IPSecDeleteFilter(pDelFilter);
  354. }
  355. break;
  356. }
  357. case IOCTL_IPSEC_ENUM_SAS: {
  358. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_ENUM_SAS\n"));
  359. dwSize = sizeof(IPSEC_ENUM_SAS);
  360. //
  361. // Output/Input in the same buffer at MdlAddress
  362. //
  363. status = IPSecEnumSAs(Irp, &dwSize);
  364. break;
  365. }
  366. case IOCTL_IPSEC_ENUM_FILTERS: {
  367. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_ENUM_FILTERS\n"));
  368. dwSize = sizeof(IPSEC_ENUM_FILTERS);
  369. //
  370. // Output/Input in the same buffer at MdlAddress
  371. //
  372. status = IPSecEnumFilters(Irp, &dwSize);
  373. break;
  374. }
  375. case IOCTL_IPSEC_QUERY_STATS: {
  376. //
  377. // The minimum size is without any Keys
  378. //
  379. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_QUERY_STATS\n"));
  380. dwSize = sizeof(IPSEC_QUERY_STATS);
  381. if (outputBufferLength < dwSize) {
  382. status = STATUS_BUFFER_TOO_SMALL;
  383. break;
  384. }
  385. *((PIPSEC_QUERY_STATS)pvIoBuffer) = g_ipsec.Statistics;
  386. status = STATUS_SUCCESS;
  387. break;
  388. }
  389. case IOCTL_IPSEC_ADD_SA: {
  390. //
  391. // Adds the SA to the relevant database.
  392. // Typically used to add outbound SAs to the DB.
  393. //
  394. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_ADD_SA\n"));
  395. //
  396. // The minimum size is without any Keys
  397. //
  398. dwSize = IPSEC_ADD_SA_NO_KEY_SIZE;
  399. if (inputBufferLength < dwSize) {
  400. status = STATUS_BUFFER_TOO_SMALL;
  401. break;
  402. }
  403. status = IPSecAddSA((PIPSEC_ADD_SA)pvIoBuffer, inputBufferLength);
  404. ASSERT(status != STATUS_PENDING);
  405. if (outputBufferLength >= sizeof(NTSTATUS)) {
  406. (*(NTSTATUS *)pvIoBuffer) = status;
  407. dwSize = sizeof(NTSTATUS);
  408. } else {
  409. dwSize = 0;
  410. }
  411. status = STATUS_SUCCESS;
  412. break;
  413. }
  414. case IOCTL_IPSEC_UPDATE_SA: {
  415. //
  416. // This completes the negotiation kicked off via the Acquire.
  417. //
  418. // Adds the SA to the relevant database.
  419. // Typically used to complete inbound SA acquisitions.
  420. //
  421. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_UPDATE_SA\n"));
  422. //
  423. // The minimum size is without any Keys
  424. //
  425. dwSize = IPSEC_UPDATE_SA_NO_KEY_SIZE;
  426. if (inputBufferLength < dwSize) {
  427. status = STATUS_BUFFER_TOO_SMALL;
  428. break;
  429. }
  430. status = IPSecUpdateSA((PIPSEC_UPDATE_SA)pvIoBuffer, inputBufferLength);
  431. ASSERT(status != STATUS_PENDING);
  432. if (outputBufferLength >= sizeof(NTSTATUS)) {
  433. (*(NTSTATUS *)pvIoBuffer)=status;
  434. dwSize = sizeof(NTSTATUS);
  435. } else {
  436. dwSize = 0;
  437. }
  438. status = STATUS_SUCCESS;
  439. break;
  440. }
  441. case IOCTL_IPSEC_EXPIRE_SA: {
  442. //
  443. // Deref the particular SA - delete when ref cnt drops to 0.
  444. //
  445. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_EXPIRE_SA\n"));
  446. dwSize = sizeof(IPSEC_EXPIRE_SA);
  447. if (inputBufferLength < dwSize) {
  448. status = STATUS_BUFFER_TOO_SMALL;
  449. break;
  450. }
  451. status = IPSecExpireSA((PIPSEC_EXPIRE_SA)pvIoBuffer);
  452. break;
  453. }
  454. case IOCTL_IPSEC_GET_SPI: {
  455. //
  456. // returns the SPI for an inbound SA
  457. //
  458. IPSEC_DEBUG(IOCTL, ("IOCTL_IPSEC_GET_SPI\n"));
  459. dwSize = sizeof(IPSEC_GET_SPI);
  460. if (outputBufferLength < dwSize) {
  461. status = STATUS_BUFFER_TOO_SMALL;
  462. break;
  463. }
  464. status = IPSecGetSPI((PIPSEC_GET_SPI)pvIoBuffer);
  465. break;
  466. }
  467. case IOCTL_IPSEC_POST_FOR_ACQUIRE_SA: {
  468. //
  469. // The SAAPI client posts a request that we complete when
  470. // an SA needs to be initialized or updated (due to
  471. // re-key).
  472. // We keep the Irp around until we need an SA to be
  473. // negotiated.
  474. //
  475. IPSEC_DEBUG(IOCTL, ("IPSEC_POST_FOR_ACQUIRE_SA\n"));
  476. dwSize = sizeof(IPSEC_POST_FOR_ACQUIRE_SA);
  477. if (outputBufferLength < dwSize) {
  478. IPSEC_DEBUG(IOCTL, ("IPSEC_POST_FOR_ACQUIRE_SA: bad size: dwSize: %lx, input: %lx\n",
  479. dwSize, inputBufferLength));
  480. status = STATUS_BUFFER_TOO_SMALL;
  481. break;
  482. }
  483. Irp->IoStatus.Status = STATUS_PENDING;
  484. status = IPSecHandleAcquireRequest( Irp,
  485. (PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer);
  486. if (status == STATUS_PENDING) {
  487. IPSEC_DECREMENT(g_ipsec.NumIoctls);
  488. return status;
  489. }
  490. break;
  491. }
  492. case IOCTL_IPSEC_QUERY_EXPORT: {
  493. //
  494. // Queries whether the driver is built for export. Used by the IPSEC components
  495. // to decide what key lengths to use for encryption.
  496. //
  497. IPSEC_DEBUG(IOCTL, ("IPSEC_QUERY_EXPORT\n"));
  498. dwSize = sizeof(IPSEC_QUERY_EXPORT);
  499. if (outputBufferLength < dwSize) {
  500. IPSEC_DEBUG(IOCTL, ("IPSEC_QUERY_EXPORT: bad size: dwSize: %lx, input: %lx\n",
  501. dwSize, inputBufferLength));
  502. status = STATUS_BUFFER_TOO_SMALL;
  503. break;
  504. }
  505. ((PIPSEC_QUERY_EXPORT)pvIoBuffer)->Export = FALSE;
  506. status = STATUS_SUCCESS;
  507. break;
  508. }
  509. case IOCTL_IPSEC_QUERY_SPI: {
  510. IPSEC_DEBUG(IOCTL, ("Entered Query SPI\n"));
  511. dwSize = sizeof(IPSEC_QUERY_SPI);
  512. if (inputBufferLength < dwSize) {
  513. IPSEC_DEBUG(IOCTL, ("IPSEC_QUERY_SPI: bad size: dwSize: %lx, input: %lx\n",
  514. dwSize, inputBufferLength));
  515. status = STATUS_BUFFER_TOO_SMALL;
  516. break;
  517. }
  518. status = IPSecQuerySpi((PIPSEC_QUERY_SPI)pvIoBuffer);
  519. break;
  520. }
  521. case IOCTL_IPSEC_DELETE_SA: {
  522. IPSEC_DEBUG(IOCTL, ("Entered Delete SA\n"));
  523. dwSize = sizeof(IPSEC_DELETE_SA);
  524. if (inputBufferLength < dwSize) {
  525. IPSEC_DEBUG(IOCTL, ("IPSEC_DELETE_SA: bad size: dwSize: %lx, input: %lx\n",
  526. dwSize, inputBufferLength));
  527. status = STATUS_BUFFER_TOO_SMALL;
  528. break;
  529. }
  530. status = IPSecDeleteSA((PIPSEC_DELETE_SA)pvIoBuffer);
  531. break;
  532. }
  533. case IOCTL_IPSEC_SET_OPERATION_MODE: {
  534. IPSEC_DEBUG(IOCTL, ("Entered Set Operation Mode\n"));
  535. dwSize = sizeof(IPSEC_SET_OPERATION_MODE);
  536. if (inputBufferLength < dwSize) {
  537. IPSEC_DEBUG(IOCTL, ("IPSEC_SET_OPERATION_MODE: bad size: dwSize: %lx, input: %lx\n",
  538. dwSize, inputBufferLength));
  539. status = STATUS_BUFFER_TOO_SMALL;
  540. break;
  541. }
  542. status = IPSecSetOperationMode((PIPSEC_SET_OPERATION_MODE)pvIoBuffer);
  543. break;
  544. }
  545. case IOCTL_IPSEC_SET_TCPIP_STATUS: {
  546. IPSEC_DEBUG(IOCTL, ("Entered Set Tcpip Status\n"));
  547. if (Irp->RequestorMode != KernelMode) {
  548. status = STATUS_ACCESS_DENIED;
  549. break;
  550. }
  551. dwSize = sizeof(IPSEC_SET_TCPIP_STATUS);
  552. if (inputBufferLength < dwSize) {
  553. IPSEC_DEBUG(IOCTL, ("IPSEC_SET_TCPIP_STATUS: bad size: dwSize: %lx, input: %lx\n",
  554. dwSize, inputBufferLength));
  555. status = STATUS_BUFFER_TOO_SMALL;
  556. break;
  557. }
  558. status = IPSecSetTcpipStatus((PIPSEC_SET_TCPIP_STATUS)pvIoBuffer);
  559. break;
  560. }
  561. case IOCTL_IPSEC_REGISTER_PROTOCOL: {
  562. dwSize = sizeof(IPSEC_REGISTER_PROTOCOL);
  563. if (inputBufferLength < dwSize) {
  564. status = STATUS_BUFFER_TOO_SMALL;
  565. break;
  566. }
  567. status = IPSecRegisterProtocols(
  568. (PIPSEC_REGISTER_PROTOCOL) pvIoBuffer
  569. );
  570. break;
  571. }
  572. default: {
  573. status = STATUS_INVALID_PARAMETER;
  574. break;
  575. }
  576. }
  577. IPSEC_DECREMENT(g_ipsec.NumIoctls);
  578. break ;
  579. }
  580. default: {
  581. IPSEC_DEBUG(IOCTL, ("IPSEC: unknown IRP_MJ_XXX: %lx\n", irpStack->MajorFunction));
  582. status = STATUS_INVALID_PARAMETER;
  583. break;
  584. }
  585. }
  586. ASSERT(status != STATUS_PENDING);
  587. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  588. Irp->IoStatus.Status = status;
  589. Irp->IoStatus.Information = MIN(dwSize, outputBufferLength);
  590. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  591. IPSEC_DEBUG(IOCTL, ("Exiting IPSecDispath\n"));
  592. return status;
  593. }
  594. NTSTATUS
  595. IPSecBindToIP()
  596. /*++
  597. Routine Description:
  598. This bind exchanges a number of entrypoints with IP so that
  599. - packets relevant to IPSEC can be handed over from the IP driver.
  600. - buffered packets can be flushed.
  601. - SA Table indices can be plumbed.
  602. - ....
  603. Arguments:
  604. NONE
  605. Return Value:
  606. The function value is the final status from the bind operation.
  607. --*/
  608. {
  609. NTSTATUS status;
  610. IPSEC_FUNCTIONS ipsecFns;
  611. PAGED_CODE();
  612. IPSEC_DEBUG(LOAD, ("Entering IPSecBindToIP\n"));
  613. ipsecFns.Version = IP_IPSEC_BIND_VERSION;
  614. ipsecFns.IPSecHandler = IPSecHandlePacket;
  615. ipsecFns.IPSecQStatus = IPSecQueryStatus;
  616. ipsecFns.IPSecSendCmplt = IPSecSendComplete;
  617. ipsecFns.IPSecNdisStatus = IPSecNdisStatus;
  618. ipsecFns.IPSecRcvFWPacket = IPSecRcvFWPacket;
  619. status = TCPIP_SET_IPSEC(&ipsecFns);
  620. if (status != IP_SUCCESS) {
  621. IPSEC_DEBUG(LOAD, ("Failed to bind to IP: %lx\n", status));
  622. } else {
  623. IPSEC_DRIVER_BOUND() = TRUE;
  624. IPSEC_DRIVER_SEND_BOUND() = TRUE;
  625. }
  626. IPSEC_DEBUG(LOAD, ("Exiting IPSecBindToIP\n"));
  627. return status;
  628. }
  629. NTSTATUS
  630. IPSecUnbindFromIP()
  631. /*++
  632. Routine Description:
  633. This unbinds from the Filter Driver
  634. Arguments:
  635. NONE
  636. Return Value:
  637. The function value is the final status from the bind operation.
  638. --*/
  639. {
  640. NTSTATUS status;
  641. IPSEC_FUNCTIONS ipsecFns={0};
  642. PAGED_CODE();
  643. IPSEC_DEBUG(LOAD, ("Entering IPSecUnbindFromIP\n"));
  644. ipsecFns.Version = IP_IPSEC_BIND_VERSION;
  645. status = TCPIP_UNSET_IPSEC(&ipsecFns);
  646. if (status != IP_SUCCESS) {
  647. IPSEC_DEBUG(LOAD, ("Failed to bind to IP: %lx\n", status));
  648. } else {
  649. IPSEC_DRIVER_BOUND() = FALSE;
  650. }
  651. IPSEC_DEBUG(LOAD, ("Exiting IPSecUnbindFromIP\n"));
  652. return status;
  653. }
  654. NTSTATUS
  655. IPSecUnbindSendFromIP()
  656. /*++
  657. Routine Description:
  658. Unbinds just the send handler from IP
  659. Arguments:
  660. NONE
  661. Return Value:
  662. The function value is the final status from the bind operation.
  663. --*/
  664. {
  665. NTSTATUS status;
  666. IPSEC_FUNCTIONS ipsecFns={0};
  667. PAGED_CODE();
  668. IPSEC_DEBUG(LOAD, ("Entering IPSecUnbindSendFromIP\n"));
  669. ipsecFns.Version = IP_IPSEC_BIND_VERSION;
  670. status = TCPIP_UNSET_IPSEC_SEND(&ipsecFns);
  671. if (status != IP_SUCCESS) {
  672. IPSEC_DEBUG(LOAD, ("Failed to bind to IP: %lx\n", status));
  673. } else {
  674. IPSEC_DRIVER_SEND_BOUND() = FALSE;
  675. }
  676. IPSEC_DEBUG(LOAD, ("Exiting IPSecUnbindSendFromIP\n"));
  677. return status;
  678. }
  679. NTSTATUS
  680. OpenRegKey(
  681. PHANDLE HandlePtr,
  682. PWCHAR KeyName
  683. )
  684. /*++
  685. Routine Description:
  686. Opens a Registry key and returns a handle to it.
  687. Arguments:
  688. HandlePtr - The varible into which to write the opened handle.
  689. KeyName - The name of the Registry key to open.
  690. Return Value:
  691. STATUS_SUCCESS or an appropriate failure code.
  692. --*/
  693. {
  694. NTSTATUS Status;
  695. OBJECT_ATTRIBUTES ObjectAttributes;
  696. UNICODE_STRING UKeyName;
  697. PAGED_CODE();
  698. RtlInitUnicodeString(&UKeyName, KeyName);
  699. memset(&ObjectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  700. InitializeObjectAttributes(&ObjectAttributes,
  701. &UKeyName,
  702. OBJ_CASE_INSENSITIVE,
  703. NULL,
  704. NULL);
  705. Status = ZwOpenKey(HandlePtr,
  706. KEY_READ,
  707. &ObjectAttributes);
  708. return Status;
  709. }
  710. NTSTATUS
  711. GetRegDWORDValue(
  712. HANDLE KeyHandle,
  713. PWCHAR ValueName,
  714. PULONG ValueData
  715. )
  716. /*++
  717. Routine Description:
  718. Reads a REG_DWORD value from the registry into the supplied variable.
  719. Arguments:
  720. KeyHandle - Open handle to the parent key of the value to read.
  721. ValueName - The name of the value to read.
  722. ValueData - The variable into which to read the data.
  723. Return Value:
  724. STATUS_SUCCESS or an appropriate failure code.
  725. --*/
  726. {
  727. NTSTATUS status;
  728. ULONG resultLength;
  729. PKEY_VALUE_FULL_INFORMATION keyValueFullInformation;
  730. UCHAR keybuf[WORK_BUFFER_SIZE];
  731. UNICODE_STRING UValueName;
  732. PAGED_CODE();
  733. RtlInitUnicodeString(&UValueName, ValueName);
  734. keyValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)keybuf;
  735. RtlZeroMemory(keyValueFullInformation, sizeof(keyValueFullInformation));
  736. status = ZwQueryValueKey(KeyHandle,
  737. &UValueName,
  738. KeyValueFullInformation,
  739. keyValueFullInformation,
  740. WORK_BUFFER_SIZE,
  741. &resultLength);
  742. if (NT_SUCCESS(status)) {
  743. if (keyValueFullInformation->Type != REG_DWORD) {
  744. status = STATUS_INVALID_PARAMETER_MIX;
  745. } else {
  746. *ValueData = *((ULONG UNALIGNED *)((PCHAR)keyValueFullInformation +
  747. keyValueFullInformation->DataOffset));
  748. }
  749. }
  750. return status;
  751. }
  752. NTSTATUS
  753. GetRegStringValue(
  754. HANDLE KeyHandle,
  755. PWCHAR ValueName,
  756. PKEY_VALUE_PARTIAL_INFORMATION *ValueData,
  757. PUSHORT ValueSize
  758. )
  759. /*++
  760. Routine Description:
  761. Reads a REG_*_SZ string value from the Registry into the supplied
  762. key value buffer. If the buffer string buffer is not large enough,
  763. it is reallocated.
  764. Arguments:
  765. KeyHandle - Open handle to the parent key of the value to read.
  766. ValueName - The name of the value to read.
  767. ValueData - Destination for the read data.
  768. ValueSize - Size of the ValueData buffer. Updated on output.
  769. Return Value:
  770. STATUS_SUCCESS or an appropriate failure code.
  771. --*/
  772. {
  773. NTSTATUS status;
  774. ULONG resultLength;
  775. UNICODE_STRING UValueName;
  776. PAGED_CODE();
  777. RtlInitUnicodeString(&UValueName, ValueName);
  778. status = ZwQueryValueKey(
  779. KeyHandle,
  780. &UValueName,
  781. KeyValuePartialInformation,
  782. *ValueData,
  783. (ULONG) *ValueSize,
  784. &resultLength
  785. );
  786. if ( (status == STATUS_BUFFER_OVERFLOW) ||
  787. (status == STATUS_BUFFER_TOO_SMALL)
  788. )
  789. {
  790. PVOID temp;
  791. //
  792. // Free the old buffer and allocate a new one of the
  793. // appropriate size.
  794. //
  795. ASSERT(resultLength > (ULONG) *ValueSize);
  796. if (resultLength <= 0xFFFF) {
  797. temp = IPSecAllocateMemory(resultLength, IPSEC_TAG_IOCTL);
  798. if (temp != NULL) {
  799. if (*ValueData != NULL) {
  800. IPSecFreeMemory(*ValueData);
  801. }
  802. *ValueData = temp;
  803. *ValueSize = (USHORT) resultLength;
  804. status = ZwQueryValueKey(KeyHandle,
  805. &UValueName,
  806. KeyValuePartialInformation,
  807. *ValueData,
  808. *ValueSize,
  809. &resultLength
  810. );
  811. ASSERT( (status != STATUS_BUFFER_OVERFLOW) &&
  812. (status != STATUS_BUFFER_TOO_SMALL)
  813. );
  814. }
  815. else {
  816. status = STATUS_INSUFFICIENT_RESOURCES;
  817. }
  818. }
  819. else {
  820. status = STATUS_BUFFER_TOO_SMALL;
  821. }
  822. }
  823. return status;
  824. }
  825. NTSTATUS
  826. GetRegMultiSZValue(
  827. HANDLE KeyHandle,
  828. PWCHAR ValueName,
  829. PUNICODE_STRING ValueData
  830. )
  831. /*++
  832. Routine Description:
  833. Reads a REG_MULTI_SZ string value from the Registry into the supplied
  834. Unicode string. If the Unicode string buffer is not large enough,
  835. it is reallocated.
  836. Arguments:
  837. KeyHandle - Open handle to the parent key of the value to read.
  838. ValueName - The name of the value to read.
  839. ValueData - Destination Unicode string for the value data.
  840. Return Value:
  841. STATUS_SUCCESS or an appropriate failure code.
  842. --*/
  843. {
  844. NTSTATUS status;
  845. ULONG resultLength;
  846. PKEY_VALUE_PARTIAL_INFORMATION keyValuePartialInformation;
  847. UNICODE_STRING UValueName;
  848. PAGED_CODE();
  849. ValueData->Length = 0;
  850. status = GetRegStringValue(
  851. KeyHandle,
  852. ValueName,
  853. (PKEY_VALUE_PARTIAL_INFORMATION *) &(ValueData->Buffer),
  854. &(ValueData->MaximumLength)
  855. );
  856. if (NT_SUCCESS(status)) {
  857. keyValuePartialInformation =
  858. (PKEY_VALUE_PARTIAL_INFORMATION) ValueData->Buffer;
  859. if (keyValuePartialInformation->Type == REG_MULTI_SZ) {
  860. ValueData->Length = (USHORT)
  861. keyValuePartialInformation->DataLength;
  862. RtlCopyMemory(
  863. ValueData->Buffer,
  864. &(keyValuePartialInformation->Data),
  865. ValueData->Length
  866. );
  867. }
  868. else {
  869. status = STATUS_INVALID_PARAMETER_MIX;
  870. }
  871. }
  872. return status;
  873. } // GetRegMultiSZValue
  874. VOID
  875. IPSecReadRegistry()
  876. /*++
  877. Routine Description:
  878. Reads config info from registry into g_ipsec
  879. Arguments:
  880. Return Value:
  881. status of the read.
  882. --*/
  883. {
  884. NTSTATUS status;
  885. HANDLE hRegKey;
  886. WCHAR IPSecParametersRegistryKey[] = IPSEC_REG_KEY;
  887. BOOLEAN isAs = MmIsThisAnNtAsSystem();
  888. g_ipsec.EnableOffload = IPSEC_DEFAULT_ENABLE_OFFLOAD;
  889. g_ipsec.DefaultSAIdleTime = IPSEC_DEFAULT_SA_IDLE_TIME;
  890. g_ipsec.LogInterval = IPSEC_DEFAULT_LOG_INTERVAL;
  891. g_ipsec.EventQueueSize = IPSEC_DEFAULT_EVENT_QUEUE_SIZE;
  892. g_ipsec.RekeyTime = IPSEC_DEFAULT_REKEY;
  893. g_ipsec.NoDefaultExempt = IPSEC_DEFAULT_NO_DEFAULT_EXEMPT;
  894. g_ipsec.NoDefaultExempt = DEFAULT_IPSEC_OPERATION_MODE;
  895. g_ipsec.DiagnosticMode = IPSEC_DEFAULT_ENABLE_DIAGNOSTICS;
  896. if (isAs) {
  897. g_ipsec.CacheSize = IPSEC_DEFAULT_AS_CACHE_SIZE;
  898. g_ipsec.SAHashSize = IPSEC_DEFAULT_AS_SA_HASH_SIZE;
  899. } else {
  900. g_ipsec.CacheSize = IPSEC_DEFAULT_CACHE_SIZE;
  901. g_ipsec.SAHashSize = IPSEC_DEFAULT_SA_HASH_SIZE;
  902. }
  903. status = OpenRegKey(&hRegKey,
  904. IPSecParametersRegistryKey);
  905. if (NT_SUCCESS(status)) {
  906. //
  907. // Expected configuration values. We use reasonable defaults if they
  908. // aren't available for some reason.
  909. //
  910. IPSEC_REG_READ_DWORD( hRegKey,
  911. IPSEC_REG_PARAM_ENABLE_OFFLOAD,
  912. &g_ipsec.EnableOffload,
  913. IPSEC_DEFAULT_ENABLE_OFFLOAD,
  914. IPSEC_MAX_ENABLE_OFFLOAD,
  915. IPSEC_MIN_ENABLE_OFFLOAD);
  916. IPSEC_REG_READ_DWORD( hRegKey,
  917. IPSEC_REG_PARAM_SA_IDLE_TIME,
  918. &g_ipsec.DefaultSAIdleTime,
  919. IPSEC_DEFAULT_SA_IDLE_TIME,
  920. IPSEC_MAX_SA_IDLE_TIME,
  921. IPSEC_MIN_SA_IDLE_TIME);
  922. IPSEC_REG_READ_DWORD( hRegKey,
  923. IPSEC_REG_PARAM_EVENT_QUEUE_SIZE,
  924. &g_ipsec.EventQueueSize,
  925. IPSEC_DEFAULT_EVENT_QUEUE_SIZE,
  926. IPSEC_MAX_EVENT_QUEUE_SIZE,
  927. IPSEC_MIN_EVENT_QUEUE_SIZE);
  928. IPSEC_REG_READ_DWORD( hRegKey,
  929. IPSEC_REG_PARAM_LOG_INTERVAL,
  930. &g_ipsec.LogInterval,
  931. IPSEC_DEFAULT_LOG_INTERVAL,
  932. IPSEC_MAX_LOG_INTERVAL,
  933. IPSEC_MIN_LOG_INTERVAL);
  934. IPSEC_REG_READ_DWORD( hRegKey,
  935. IPSEC_REG_PARAM_REKEY_TIME,
  936. &g_ipsec.RekeyTime,
  937. IPSEC_DEFAULT_REKEY,
  938. IPSEC_MAX_REKEY,
  939. IPSEC_MIN_REKEY);
  940. IPSEC_REG_READ_DWORD( hRegKey,
  941. IPSEC_REG_PARAM_CACHE_SIZE,
  942. &g_ipsec.CacheSize,
  943. isAs? IPSEC_DEFAULT_AS_CACHE_SIZE:
  944. IPSEC_DEFAULT_CACHE_SIZE,
  945. IPSEC_MAX_CACHE_SIZE,
  946. IPSEC_MIN_CACHE_SIZE);
  947. IPSEC_REG_READ_DWORD( hRegKey,
  948. IPSEC_REG_PARAM_SA_HASH_SIZE,
  949. &g_ipsec.SAHashSize,
  950. isAs? IPSEC_DEFAULT_AS_SA_HASH_SIZE:
  951. IPSEC_DEFAULT_SA_HASH_SIZE,
  952. IPSEC_MAX_SA_HASH_SIZE,
  953. IPSEC_MIN_SA_HASH_SIZE);
  954. IPSEC_REG_READ_DWORD( hRegKey,
  955. IPSEC_REG_PARAM_NO_DEFAULT_EXEMPT,
  956. &g_ipsec.NoDefaultExempt,
  957. IPSEC_DEFAULT_NO_DEFAULT_EXEMPT,
  958. IPSEC_MAX_NO_DEFAULT_EXEMPT,
  959. IPSEC_MIN_NO_DEFAULT_EXEMPT);
  960. IPSEC_REG_READ_DWORD( hRegKey,
  961. IPSEC_REG_PARAM_ENABLE_DIAGNOSTICS,
  962. &g_ipsec.DiagnosticMode,
  963. IPSEC_DEFAULT_ENABLE_DIAGNOSTICS,
  964. IPSEC_MAX_ENABLE_DIAGNOSTICS,
  965. IPSEC_MIN_ENABLE_DIAGNOSTICS);
  966. IPSEC_REG_READ_DWORD( hRegKey,
  967. IPSEC_REG_PARAM_OPERATION_MODE,
  968. &(ULONG)g_ipsec.OperationMode,
  969. DEFAULT_IPSEC_OPERATION_MODE,
  970. IPSEC_OPERATION_MODE_MAX-1,
  971. 0);
  972. ZwClose(hRegKey);
  973. }
  974. g_ipsec.CacheHalfSize = g_ipsec.CacheSize / 2;
  975. //
  976. // Init SAIdleTime for low memory reaper
  977. //
  978. IPSEC_CONVERT_SECS_TO_100NS(g_ipsec.SAIdleTime, g_ipsec.DefaultSAIdleTime);
  979. }
  980. NTSTATUS
  981. IPSecGeneralInit()
  982. /*++
  983. Routine Description:
  984. General structures are initialized here.
  985. Arguments:
  986. None
  987. Return Value:
  988. --*/
  989. {
  990. PSA_TABLE_ENTRY pSA;
  991. LONG i;
  992. NTSTATUS status = STATUS_SUCCESS;;
  993. PAGED_CODE();
  994. IPSEC_DEBUG(LOAD, ("Entering IPSecGeneralInit\n"));
  995. //
  996. // init the acquireinfo struct
  997. //
  998. InitializeListHead(&g_ipsec.AcquireInfo.PendingAcquires);
  999. InitializeListHead(&g_ipsec.AcquireInfo.PendingNotifies);
  1000. InitializeListHead(&g_ipsec.LarvalSAList);
  1001. INIT_LOCK(&g_ipsec.LarvalListLock);
  1002. INIT_LOCK(&g_ipsec.AcquireInfo.Lock);
  1003. //
  1004. // Set up the hashes/tables
  1005. //
  1006. InitializeMRSWLock(&g_ipsec.SADBLock);
  1007. InitializeMRSWLock(&g_ipsec.SPIListLock);
  1008. g_ipsec.IPProtInfo.pi_xmitdone = IPSecProtocolSendComplete;
  1009. g_ipsec.IPProtInfo.pi_protocol = PROTOCOL_ESP;
  1010. //
  1011. // init filter linked lists
  1012. //
  1013. for (i = MIN_FILTER; i <= MAX_FILTER; i++) {
  1014. InitializeListHead(&g_ipsec.FilterList[i]);
  1015. }
  1016. //
  1017. // SAs in a hash table, hashed by <SPI, Dest addr>
  1018. //
  1019. g_ipsec.pSADb = IPSecAllocateMemory(g_ipsec.SAHashSize * sizeof(SA_HASH), IPSEC_TAG_INIT);
  1020. if (!g_ipsec.pSADb) {
  1021. IPSEC_DEBUG(LOAD, ("Failed to alloc SADb hash\n"));
  1022. return STATUS_INSUFFICIENT_RESOURCES;
  1023. }
  1024. IPSecInitFlag |= INIT_SA_DATABASE;
  1025. IPSecZeroMemory(g_ipsec.pSADb, g_ipsec.SAHashSize * sizeof(SA_HASH));
  1026. for (i = 0; i < g_ipsec.SAHashSize; i++) {
  1027. PSA_HASH Entry = &g_ipsec.pSADb[i];
  1028. InitializeListHead(&Entry->SAList);
  1029. }
  1030. //
  1031. // Initialize the MDL pools.
  1032. //
  1033. status = IPSecInitMdlPool();
  1034. if (!NT_SUCCESS (status)) {
  1035. IPSEC_DEBUG(LOAD, ("Failed to alloc MDL pools\n"));
  1036. return STATUS_INSUFFICIENT_RESOURCES;
  1037. }
  1038. IPSecInitFlag |= INIT_MDL_POOLS;
  1039. //
  1040. // Initialize the cache structures.
  1041. //
  1042. if (!AllocateCacheStructures()) {
  1043. IPSEC_DEBUG(LOAD, ("Failed to alloc cache structs\n"));
  1044. return STATUS_INSUFFICIENT_RESOURCES;
  1045. }
  1046. IPSecInitFlag |= INIT_CACHE_STRUCT;
  1047. //
  1048. // Allocate EventQueue memory.
  1049. //
  1050. g_ipsec.IPSecLogMemory = IPSecAllocateMemory( g_ipsec.EventQueueSize * sizeof(IPSEC_EVENT_CTX),
  1051. IPSEC_TAG_EVT_QUEUE);
  1052. if (!g_ipsec.IPSecLogMemory) {
  1053. return STATUS_INSUFFICIENT_RESOURCES;
  1054. }
  1055. IPSecInitFlag |= INIT_DEBUG_MEMORY;
  1056. g_ipsec.IPSecLogMemoryLoc = &g_ipsec.IPSecLogMemory[0];
  1057. g_ipsec.IPSecLogMemoryEnd = &g_ipsec.IPSecLogMemory[g_ipsec.EventQueueSize * sizeof(IPSEC_EVENT_CTX)];
  1058. //
  1059. // Init the timer stuff.
  1060. //
  1061. if (!IPSecInitTimer()) {
  1062. IPSEC_DEBUG(LOAD, ("Failed to init timer\n"));
  1063. return STATUS_INSUFFICIENT_RESOURCES;
  1064. }
  1065. IPSecInitFlag |= INIT_TIMERS;
  1066. #if GPC
  1067. status = IPSecGpcInitialize();
  1068. if (status != STATUS_SUCCESS) {
  1069. IPSEC_DEBUG(LOAD, ("Failed to register GPC clients\n"));
  1070. }
  1071. #endif
  1072. //
  1073. // Arm the reaper timer
  1074. //
  1075. IPSEC_DEBUG(LOAD, ("Starting ReaperTimer\n"));
  1076. IPSecStartTimer(&g_ipsec.ReaperTimer,
  1077. IPSecReaper,
  1078. IPSEC_REAPER_TIME,
  1079. (PVOID)NULL);
  1080. //
  1081. // Start EventLog timer
  1082. //
  1083. IPSEC_DEBUG(LOAD, ("Starting EventLogTimer\n"));
  1084. IPSecStartTimer(&g_ipsec.EventLogTimer,
  1085. IPSecFlushEventLog,
  1086. g_ipsec.LogInterval,
  1087. (PVOID)NULL);
  1088. IPSEC_DEBUG(LOAD, ("Exiting IPSecGeneralInit\n"));
  1089. return STATUS_SUCCESS;
  1090. }
  1091. NTSTATUS
  1092. IPSecGeneralFree()
  1093. /*++
  1094. Routine Description:
  1095. Free general structures if IPSecGeneralInit fails.
  1096. Arguments:
  1097. None
  1098. Return Value:
  1099. --*/
  1100. {
  1101. INT index;
  1102. //
  1103. // Free SA database.
  1104. //
  1105. if (IPSecInitFlag & INIT_SA_DATABASE) {
  1106. if (g_ipsec.pSADb) {
  1107. IPSecFreeMemory(g_ipsec.pSADb);
  1108. }
  1109. }
  1110. //
  1111. // Free MDL pool.
  1112. //
  1113. if (IPSecInitFlag & INIT_MDL_POOLS) {
  1114. IPSecDeinitMdlPool();
  1115. }
  1116. //
  1117. // Free cache struct.
  1118. //
  1119. if (IPSecInitFlag & INIT_CACHE_STRUCT) {
  1120. FreeExistingCache();
  1121. }
  1122. //
  1123. // Free EventQueue memory.
  1124. //
  1125. if (IPSecInitFlag & INIT_DEBUG_MEMORY) {
  1126. if (g_ipsec.IPSecLogMemory) {
  1127. IPSecFreeMemory(g_ipsec.IPSecLogMemory);
  1128. }
  1129. }
  1130. //
  1131. // Free timers allocated.
  1132. //
  1133. if (IPSecInitFlag & INIT_TIMERS) {
  1134. for (index = 0; index < IPSEC_CLASS_MAX; index++) {
  1135. IPSecFreeMemory(g_ipsec.TimerList[index].pTimers);
  1136. }
  1137. }
  1138. return STATUS_SUCCESS;
  1139. }
  1140. NTSTATUS
  1141. IPSecFreeConfig()
  1142. /*++
  1143. Routine Description:
  1144. Free the SA table etc.
  1145. Arguments:
  1146. None
  1147. Return Value:
  1148. --*/
  1149. {
  1150. IPSEC_DEBUG(LOAD, ("Entering IPSecFreeConfig\n"));
  1151. PAGED_CODE();
  1152. FreeExistingCache();
  1153. FreePatternDbase();
  1154. if (g_ipsec.IPSecLogMemory) {
  1155. IPSecFreeMemory(g_ipsec.IPSecLogMemory);
  1156. }
  1157. IPSEC_DEBUG(LOAD, ("Exiting IPSecFreeConfig\n"));
  1158. return STATUS_SUCCESS;
  1159. }
  1160. NTSTATUS
  1161. IPSecInitMdlPool()
  1162. /*++
  1163. Routine Description:
  1164. Create the MDL pool for AH and ESP headers.
  1165. Arguments:
  1166. None
  1167. Return Value:
  1168. --*/
  1169. {
  1170. PAGED_CODE();
  1171. IPSEC_DEBUG(LOAD, ("Entering IPSecInitMdlPool\n"));
  1172. g_ipsec.IPSecSmallBufferSize = IPSEC_SMALL_BUFFER_SIZE;
  1173. g_ipsec.IPSecLargeBufferSize = IPSEC_LARGE_BUFFER_SIZE;
  1174. g_ipsec.IPSecSendCompleteCtxSize = sizeof(IPSEC_SEND_COMPLETE_CONTEXT);
  1175. g_ipsec.IPSecSmallBufferListDepth = IPSEC_LIST_DEPTH;
  1176. g_ipsec.IPSecLargeBufferListDepth = IPSEC_LIST_DEPTH;
  1177. g_ipsec.IPSecSendCompleteCtxDepth = IPSEC_LIST_DEPTH;
  1178. g_ipsec.IPSecCacheLineSize = IPSEC_CACHE_LINE_SIZE;
  1179. //
  1180. // Initialize the lookaside lists.
  1181. //
  1182. g_ipsec.IPSecLookasideLists = IPSecAllocateMemory(
  1183. sizeof(*g_ipsec.IPSecLookasideLists),
  1184. IPSEC_TAG_LOOKASIDE_LISTS);
  1185. if (g_ipsec.IPSecLookasideLists == NULL) {
  1186. return STATUS_INSUFFICIENT_RESOURCES;
  1187. }
  1188. //
  1189. // Initialize the IPSEC buffer lookaside lists.
  1190. //
  1191. ExInitializeNPagedLookasideList(&g_ipsec.IPSecLookasideLists->LargeBufferList,
  1192. IPSecAllocateBufferPool,
  1193. NULL,
  1194. 0,
  1195. g_ipsec.IPSecLargeBufferSize,
  1196. IPSEC_TAG_BUFFER_POOL,
  1197. (USHORT)g_ipsec.IPSecLargeBufferListDepth);
  1198. ExInitializeNPagedLookasideList(&g_ipsec.IPSecLookasideLists->SmallBufferList,
  1199. IPSecAllocateBufferPool,
  1200. NULL,
  1201. 0,
  1202. g_ipsec.IPSecSmallBufferSize,
  1203. IPSEC_TAG_BUFFER_POOL,
  1204. (USHORT)g_ipsec.IPSecSmallBufferListDepth);
  1205. ExInitializeNPagedLookasideList(&g_ipsec.IPSecLookasideLists->SendCompleteCtxList,
  1206. NULL,
  1207. NULL,
  1208. 0,
  1209. g_ipsec.IPSecSendCompleteCtxSize,
  1210. IPSEC_TAG_SEND_COMPLETE,
  1211. (USHORT)g_ipsec.IPSecSendCompleteCtxDepth);
  1212. IPSEC_DEBUG(LOAD, ("Exiting IPSecInitMdlPool\n"));
  1213. return STATUS_SUCCESS;
  1214. }
  1215. VOID
  1216. IPSecDeinitMdlPool()
  1217. /*++
  1218. Routine Description:
  1219. Free the MDL pool for AH and ESP headers.
  1220. Arguments:
  1221. None
  1222. Return Value:
  1223. --*/
  1224. {
  1225. PAGED_CODE();
  1226. IPSEC_DEBUG(LOAD, ("Entering IPSecDeinitMdlPool\n"));
  1227. //
  1228. // Destroy the lookaside lists.
  1229. //
  1230. if (g_ipsec.IPSecLookasideLists != NULL) {
  1231. ExDeleteNPagedLookasideList(&g_ipsec.IPSecLookasideLists->LargeBufferList);
  1232. ExDeleteNPagedLookasideList(&g_ipsec.IPSecLookasideLists->SmallBufferList);
  1233. ExDeleteNPagedLookasideList(&g_ipsec.IPSecLookasideLists->SendCompleteCtxList);
  1234. IPSecFreeMemory(g_ipsec.IPSecLookasideLists);
  1235. }
  1236. IPSEC_DEBUG(LOAD, ("Exiting IPSecDeinitMdlPool\n"));
  1237. }
  1238. NTSTATUS
  1239. IPSecQuiesce()
  1240. /*++
  1241. Routine Description:
  1242. Destroy MDL pools and run down all driver activity
  1243. Arguments:
  1244. None
  1245. Return Value:
  1246. --*/
  1247. {
  1248. IPSEC_DEBUG(LOAD, ("Entering IPSecQuiesce\n"));
  1249. IPSecDeinitMdlPool();
  1250. IPSEC_DEBUG(LOAD, ("Exiting IPSecQuiesce\n"));
  1251. return STATUS_SUCCESS;
  1252. }
  1253. BOOLEAN
  1254. AllocateCacheStructures()
  1255. /*++
  1256. Routine Description:
  1257. Allocates the necessary memory for cache (which is an array of pointers to
  1258. cache entries)
  1259. Allocates necessary number of cache entries (but doesnt initialize them)
  1260. Allocates a small number of entries and puts them on the free list (doesnt
  1261. initialize these either)
  1262. Arguments:
  1263. None
  1264. Return Value:
  1265. True if the function completely succeeds, else FALSE. If FALSE, it is upto
  1266. the CALLER to do a rollback and clear any allocated memory
  1267. --*/
  1268. {
  1269. ULONG i;
  1270. PAGED_CODE();
  1271. g_ipsec.ppCache = IPSecAllocateMemory(g_ipsec.CacheSize * sizeof(PFILTER_CACHE), IPSEC_TAG_INIT);
  1272. if (!g_ipsec.ppCache) {
  1273. IPSEC_DEBUG(LOAD, ("Couldnt allocate memory for Input Cache\n"));
  1274. return FALSE;
  1275. }
  1276. IPSecZeroMemory(g_ipsec.ppCache, g_ipsec.CacheSize * sizeof(PFILTER_CACHE));
  1277. for (i = 0; i < g_ipsec.CacheSize; i++) {
  1278. PFILTER_CACHE pTemp1;
  1279. pTemp1 = IPSecAllocateMemory(sizeof(FILTER_CACHE), IPSEC_TAG_INIT);
  1280. if (!pTemp1) {
  1281. FreeExistingCache();
  1282. return FALSE;
  1283. }
  1284. IPSecZeroMemory(pTemp1, sizeof(FILTER_CACHE));
  1285. g_ipsec.ppCache[i] = pTemp1;
  1286. }
  1287. return TRUE;
  1288. }
  1289. VOID
  1290. FreeExistingCache()
  1291. /*++
  1292. Routine Description
  1293. Frees all the cache entries, free entries and cache pointer array
  1294. Arguments
  1295. None
  1296. Return Value
  1297. None
  1298. --*/
  1299. {
  1300. ULONG i;
  1301. PAGED_CODE();
  1302. IPSEC_DEBUG(LOAD, ("Freeing existing cache...\n"));
  1303. IPSecResetCacheTable();
  1304. if (g_ipsec.ppCache) {
  1305. for (i = 0; i < g_ipsec.CacheSize; i++) {
  1306. if (g_ipsec.ppCache[i]) {
  1307. ExFreePool(g_ipsec.ppCache[i]);
  1308. }
  1309. }
  1310. ExFreePool(g_ipsec.ppCache);
  1311. g_ipsec.ppCache = NULL;
  1312. }
  1313. }
  1314. VOID
  1315. FreePatternDbase()
  1316. /*++
  1317. Routine Description
  1318. Frees all filters and SAs.
  1319. Arguments
  1320. None
  1321. Return Value
  1322. None
  1323. --*/
  1324. {
  1325. PLIST_ENTRY pEntry;
  1326. PFILTER pFilter;
  1327. PSA_TABLE_ENTRY pSA;
  1328. LONG i, j;
  1329. PAGED_CODE();
  1330. //
  1331. // Free all masked filters and associated (outbound) SAs
  1332. //
  1333. for (i = MIN_FILTER; i <= MAX_FILTER; i++) {
  1334. while (!IsListEmpty(&g_ipsec.FilterList[i])) {
  1335. pEntry = RemoveHeadList(&g_ipsec.FilterList[i]);
  1336. pFilter = CONTAINING_RECORD(pEntry,
  1337. FILTER,
  1338. MaskedLinkage);
  1339. IPSEC_DEBUG(LOAD, ("Freeing filter: %lx\n", pFilter));
  1340. //
  1341. // Free each SA under it.
  1342. //
  1343. for (j = 0; j < pFilter->SAChainSize; j++) {
  1344. while (!IsListEmpty(&pFilter->SAChain[j])) {
  1345. pEntry = RemoveHeadList(&pFilter->SAChain[j]);
  1346. pSA = CONTAINING_RECORD(pEntry,
  1347. SA_TABLE_ENTRY,
  1348. sa_FilterLinkage);
  1349. IPSEC_DEBUG(LOAD, ("Freeing SA: %lx\n", pSA));
  1350. //
  1351. // Remove SA from miniport if plumbed
  1352. //
  1353. if (pSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  1354. IPSecDelHWSA(pSA);
  1355. }
  1356. //
  1357. // Also remove the inbound SAs from their SPI list
  1358. // so we dont double free them below.
  1359. //
  1360. IPSecRemoveSPIEntry(pSA);
  1361. //
  1362. // Stop the timer if armed and deref SA.
  1363. //
  1364. IPSecStopTimerDerefSA(pSA);
  1365. }
  1366. }
  1367. #if GPC
  1368. IPSecUninstallGpcFilter(pFilter);
  1369. #endif
  1370. IPSecFreeFilter(pFilter);
  1371. }
  1372. }
  1373. //
  1374. // Free all SAs under the SPI hashes.
  1375. //
  1376. for (i = 0; i < g_ipsec.SAHashSize; i++) {
  1377. PSA_HASH pHash = &g_ipsec.pSADb[i];
  1378. while (!IsListEmpty(&pHash->SAList)) {
  1379. pEntry = RemoveHeadList(&pHash->SAList);
  1380. pSA = CONTAINING_RECORD(pEntry,
  1381. SA_TABLE_ENTRY,
  1382. sa_SPILinkage);
  1383. IPSEC_DEBUG(LOAD, ("Freeing SA: %lx\n", pSA));
  1384. if (pSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  1385. IPSecDelHWSA(pSA);
  1386. }
  1387. IPSecStopTimerDerefSA(pSA);
  1388. }
  1389. }
  1390. IPSecFreeMemory(g_ipsec.pSADb);
  1391. IPSEC_DEBUG(LOAD, ("Freed filters/SAs\n"));
  1392. }
  1393. SIZE_T
  1394. IPSecCalculateBufferSize(
  1395. IN SIZE_T BufferDataSize
  1396. )
  1397. /*++
  1398. Routine Description:
  1399. Determines the size of an AFD buffer structure given the amount of
  1400. data that the buffer contains.
  1401. Arguments:
  1402. BufferDataSize - data length of the buffer.
  1403. AddressSize - length of address structure for the buffer.
  1404. Return Value:
  1405. Number of bytes needed for an IPSEC_LA_BUFFER structure for data of
  1406. this size.
  1407. --*/
  1408. {
  1409. SIZE_T mdlSize;
  1410. SIZE_T bufferSize;
  1411. ASSERT(BufferDataSize != 0);
  1412. ASSERT(g_ipsec.IPSecCacheLineSize < 100);
  1413. //
  1414. // Determine the sizes of the various components of an IPSEC_LA_BUFFER
  1415. // structure. Note that these are all worst-case calculations--
  1416. // actual sizes of the MDL and the buffer may be smaller.
  1417. //
  1418. bufferSize = BufferDataSize + g_ipsec.IPSecCacheLineSize;
  1419. mdlSize = MmSizeOfMdl( (PVOID)(PAGE_SIZE-1), bufferSize );
  1420. return ((sizeof(IPSEC_LA_BUFFER) + mdlSize + bufferSize + 3) & ~3);
  1421. }
  1422. VOID
  1423. IPSecInitializeBuffer(
  1424. IN PIPSEC_LA_BUFFER IPSecBuffer,
  1425. IN SIZE_T BufferDataSize
  1426. )
  1427. /*++
  1428. Routine Description:
  1429. Initializes an IPSec buffer. Sets up fields in the actual IPSEC_LA_BUFFER
  1430. structure and initializes the MDL associated with the buffer. This routine
  1431. assumes that the caller has properly allocated sufficient space for all this.
  1432. Arguments:
  1433. IPSecBuffer - points to the IPSEC_LA_BUFFER structure to initialize.
  1434. BufferDataSize - the size of the data buffer that goes along with the
  1435. buffer structure.
  1436. Return Value:
  1437. None
  1438. --*/
  1439. {
  1440. SIZE_T mdlSize;
  1441. //
  1442. // Set up the MDL pointer but don't build it yet. We have to wait
  1443. // until after the data buffer is built to build the MDL.
  1444. //
  1445. mdlSize = MmSizeOfMdl( (PVOID)(PAGE_SIZE-1), BufferDataSize );
  1446. IPSecBuffer->Mdl = (PMDL)&IPSecBuffer->Data[0];
  1447. IPSEC_DEBUG(POOL, ("IPSecBuffer: %lx, MDL: %lx\n", IPSecBuffer, IPSecBuffer->Mdl));
  1448. //
  1449. // Set up the data buffer pointer and length. Note that the buffer
  1450. // MUST begin on a cache line boundary so that we can use the fast
  1451. // copy routines like RtlCopyMemory on the buffer.
  1452. //
  1453. IPSecBuffer->Buffer = (PVOID)
  1454. (((ULONG_PTR)((PCHAR)IPSecBuffer->Mdl + mdlSize) +
  1455. g_ipsec.IPSecCacheLineSize - 1 ) & ~((ULONG_PTR)(g_ipsec.IPSecCacheLineSize - 1)));
  1456. IPSecBuffer->BufferLength = (ULONG)BufferDataSize; // Sundown - FIX
  1457. //
  1458. // Now build the MDL and set up a pointer to the MDL in the IRP.
  1459. //
  1460. MmInitializeMdl( IPSecBuffer->Mdl, IPSecBuffer->Buffer, BufferDataSize );
  1461. MmBuildMdlForNonPagedPool( IPSecBuffer->Mdl );
  1462. }
  1463. PVOID
  1464. IPSecAllocateBufferPool(
  1465. IN POOL_TYPE PoolType,
  1466. IN SIZE_T NumberOfBytes,
  1467. IN ULONG Tag
  1468. )
  1469. /*++
  1470. Routine Description:
  1471. Used by the lookaside list allocation function to allocate a new
  1472. IPSec buffer structure. The returned structure will be fully
  1473. initialized.
  1474. Arguments:
  1475. PoolType - passed to ExAllocatePoolWithTag.
  1476. NumberOfBytes - the number of bytes required for the data buffer
  1477. portion of the IPSec buffer.
  1478. Tag - passed to ExAllocatePoolWithTag.
  1479. Return Value:
  1480. PVOID - a fully initialized PIPSEC_LA_BUFFER, or NULL if the allocation
  1481. attempt fails.
  1482. --*/
  1483. {
  1484. PIPSEC_LA_BUFFER IPSecBuffer;
  1485. SIZE_T bytesRequired;
  1486. //
  1487. // The requested length must be the same as one of the standard
  1488. // IPSec buffer sizes.
  1489. //
  1490. ASSERT( NumberOfBytes == g_ipsec.IPSecSmallBufferSize ||
  1491. NumberOfBytes == g_ipsec.IPSecLargeBufferSize );
  1492. //
  1493. // Determine how much data we'll actually need for the buffer.
  1494. //
  1495. bytesRequired = IPSecCalculateBufferSize(NumberOfBytes);
  1496. //
  1497. // Get nonpaged pool for the buffer.
  1498. //
  1499. IPSecBuffer = IPSecAllocateMemory( bytesRequired, Tag );
  1500. if ( IPSecBuffer == NULL ) {
  1501. return NULL;
  1502. }
  1503. //
  1504. // Initialize the buffer and return a pointer to it.
  1505. //
  1506. IPSecInitializeBuffer( IPSecBuffer, NumberOfBytes );
  1507. return IPSecBuffer;
  1508. }
  1509. PIPSEC_LA_BUFFER
  1510. IPSecGetBuffer(
  1511. IN CLONG BufferDataSize,
  1512. IN ULONG Tag
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. Obtains a buffer of the appropriate size for the caller. Uses
  1517. the preallocated buffers if possible, or else allocates a new buffer
  1518. structure if required.
  1519. Arguments:
  1520. BufferDataSize - the size of the data buffer that goes along with the
  1521. buffer structure.
  1522. Return Value:
  1523. PIPSEC_LA_BUFFER - a pointer to an IPSEC_LA_BUFFER structure, or NULL if one
  1524. was not available or could not be allocated.
  1525. --*/
  1526. {
  1527. PIPSEC_LA_BUFFER IPSecBuffer;
  1528. SIZE_T bufferSize;
  1529. PLIST_ENTRY listEntry;
  1530. PNPAGED_LOOKASIDE_LIST lookasideList;
  1531. //
  1532. // If possible, allocate the buffer from one of the lookaside lists.
  1533. //
  1534. if (BufferDataSize <= g_ipsec.IPSecLargeBufferSize) {
  1535. if ( BufferDataSize <= g_ipsec.IPSecSmallBufferSize ) {
  1536. lookasideList = &g_ipsec.IPSecLookasideLists->SmallBufferList;
  1537. BufferDataSize = g_ipsec.IPSecSmallBufferSize;
  1538. } else {
  1539. lookasideList = &g_ipsec.IPSecLookasideLists->LargeBufferList;
  1540. BufferDataSize = g_ipsec.IPSecLargeBufferSize;
  1541. }
  1542. IPSecBuffer = ExAllocateFromNPagedLookasideList( lookasideList );
  1543. if (!IPSecBuffer) {
  1544. return NULL;
  1545. }
  1546. IPSecBuffer->Tag = Tag;
  1547. return IPSecBuffer;
  1548. }
  1549. //
  1550. // Couldn't find an appropriate buffer that was preallocated.
  1551. // Allocate one manually. If the buffer size requested was
  1552. // zero bytes, give them four bytes. This is because some of
  1553. // the routines like MmSizeOfMdl() cannot handle getting passed
  1554. // in a length of zero.
  1555. //
  1556. // !!! It would be good to ROUND_TO_PAGES for this allocation
  1557. // if appropriate, then use entire buffer size.
  1558. //
  1559. if ( BufferDataSize == 0 ) {
  1560. BufferDataSize = sizeof(ULONG);
  1561. }
  1562. bufferSize = IPSecCalculateBufferSize(BufferDataSize);
  1563. IPSecBuffer = IPSecAllocateMemory(bufferSize, IPSEC_TAG_BUFFER_POOL);
  1564. if ( IPSecBuffer == NULL ) {
  1565. return NULL;
  1566. }
  1567. //
  1568. // Initialize the IPSec buffer structure and return it.
  1569. //
  1570. IPSecInitializeBuffer(IPSecBuffer, BufferDataSize);
  1571. IPSecBuffer->Tag = Tag;
  1572. return IPSecBuffer;
  1573. }
  1574. VOID
  1575. IPSecReturnBuffer (
  1576. IN PIPSEC_LA_BUFFER IPSecBuffer
  1577. )
  1578. /*++
  1579. Routine Description:
  1580. Returns an IPSec buffer to the appropriate global list, or frees
  1581. it if necessary.
  1582. Arguments:
  1583. IPSecBufferHeader - points to the IPSec_BUFFER_HEADER structure to return or free.
  1584. Return Value:
  1585. None
  1586. --*/
  1587. {
  1588. PNPAGED_LOOKASIDE_LIST lookasideList;
  1589. //
  1590. // If appropriate, return the buffer to one of the IPSec buffer
  1591. // lookaside lists.
  1592. //
  1593. if (IPSecBuffer->BufferLength <= g_ipsec.IPSecLargeBufferSize) {
  1594. if (IPSecBuffer->BufferLength==g_ipsec.IPSecSmallBufferSize) {
  1595. lookasideList = &g_ipsec.IPSecLookasideLists->SmallBufferList;
  1596. } else {
  1597. ASSERT (IPSecBuffer->BufferLength==g_ipsec.IPSecLargeBufferSize);
  1598. lookasideList = &g_ipsec.IPSecLookasideLists->LargeBufferList;
  1599. }
  1600. ExFreeToNPagedLookasideList( lookasideList, IPSecBuffer );
  1601. return;
  1602. }
  1603. IPSecFreeMemory(IPSecBuffer);
  1604. }
  1605. NTSTATUS
  1606. IPSecWriteEvent(
  1607. PDRIVER_OBJECT IPSecDriverObject,
  1608. IN ULONG EventCode,
  1609. IN NTSTATUS NtStatusCode,
  1610. IN ULONG OffloadStatus,
  1611. IN ULONG ExtraStatus1,
  1612. IN ULONG ExtraStatus2,
  1613. IN PVOID RawDataBuffer,
  1614. IN USHORT RawDataLength,
  1615. IN USHORT NumberOfInsertionStrings,
  1616. ...
  1617. )
  1618. #define LAST_NAMED_ARGUMENT NumberOfInsertionStrings
  1619. /*++
  1620. Routine Description:
  1621. This function allocates an I/O error log record, fills it in and writes it
  1622. to the I/O error log.
  1623. Arguments:
  1624. Return Value:
  1625. None.
  1626. --*/
  1627. {
  1628. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  1629. va_list ParmPtr; // Pointer to stack parms.
  1630. PCHAR DumpData;
  1631. LONG Length;
  1632. ULONG i, SizeOfRawData, RemainingSpace, TotalErrorLogEntryLength;
  1633. ULONG SizeOfStringData = 0;
  1634. PWSTR StringOffset, InsertionString;
  1635. if (NumberOfInsertionStrings != 0)
  1636. {
  1637. va_start (ParmPtr, LAST_NAMED_ARGUMENT);
  1638. for (i = 0; i < NumberOfInsertionStrings; i += 1)
  1639. {
  1640. InsertionString = va_arg (ParmPtr, PWSTR);
  1641. Length = wcslen (InsertionString);
  1642. while ((Length > 0) && (InsertionString[Length-1] == L' '))
  1643. {
  1644. Length--;
  1645. }
  1646. SizeOfStringData += (Length + 1) * sizeof(WCHAR);
  1647. }
  1648. }
  1649. //
  1650. // Ideally we want the packet to hold the servername and ExtraInformation.
  1651. // Usually the ExtraInformation gets truncated.
  1652. //
  1653. TotalErrorLogEntryLength = min (RawDataLength + sizeof(IO_ERROR_LOG_PACKET) + 1 + SizeOfStringData,
  1654. ERROR_LOG_MAXIMUM_SIZE);
  1655. RemainingSpace = TotalErrorLogEntryLength - FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData);
  1656. if (RemainingSpace > SizeOfStringData)
  1657. {
  1658. SizeOfRawData = RemainingSpace - SizeOfStringData;
  1659. }
  1660. else
  1661. {
  1662. SizeOfStringData = RemainingSpace;
  1663. SizeOfRawData = 0;
  1664. }
  1665. ErrorLogEntry = IoAllocateErrorLogEntry (IPSecDriverObject, (UCHAR) TotalErrorLogEntryLength);
  1666. if (ErrorLogEntry == NULL)
  1667. {
  1668. return(STATUS_INSUFFICIENT_RESOURCES);
  1669. }
  1670. //
  1671. // Fill in the error log entry
  1672. //
  1673. ErrorLogEntry->ErrorCode = EventCode;
  1674. ErrorLogEntry->UniqueErrorValue = OffloadStatus;
  1675. ErrorLogEntry->FinalStatus = NtStatusCode;
  1676. ErrorLogEntry->MajorFunctionCode = 0;
  1677. ErrorLogEntry->RetryCount = 0;
  1678. ErrorLogEntry->IoControlCode = 0;
  1679. ErrorLogEntry->DeviceOffset.LowPart = ExtraStatus1;
  1680. ErrorLogEntry->DeviceOffset.HighPart = ExtraStatus2;
  1681. ErrorLogEntry->DumpDataSize = 0;
  1682. ErrorLogEntry->NumberOfStrings = 0;
  1683. ErrorLogEntry->SequenceNumber = 0;
  1684. ErrorLogEntry->StringOffset = (USHORT) (ROUND_UP_COUNT (FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  1685. + SizeOfRawData, ALIGN_WORD));
  1686. //
  1687. // Append the dump data. This information is typically an SMB header.
  1688. //
  1689. if ((RawDataBuffer) && (SizeOfRawData))
  1690. {
  1691. DumpData = (PCHAR) ErrorLogEntry->DumpData;
  1692. Length = min (RawDataLength, (USHORT)SizeOfRawData);
  1693. RtlCopyMemory (DumpData, RawDataBuffer, Length);
  1694. ErrorLogEntry->DumpDataSize = (USHORT)Length;
  1695. }
  1696. //
  1697. // Add the debug informatuion strings
  1698. //
  1699. if (NumberOfInsertionStrings)
  1700. {
  1701. StringOffset = (PWSTR) ((PCHAR)ErrorLogEntry + ErrorLogEntry->StringOffset);
  1702. //
  1703. // Set up ParmPtr to point to first of the caller's parameters.
  1704. //
  1705. va_start(ParmPtr, LAST_NAMED_ARGUMENT);
  1706. for (i = 0 ; i < NumberOfInsertionStrings ; i+= 1)
  1707. {
  1708. InsertionString = va_arg(ParmPtr, PWSTR);
  1709. Length = wcslen(InsertionString);
  1710. while ( (Length > 0) && (InsertionString[Length-1] == L' '))
  1711. {
  1712. Length--;
  1713. }
  1714. if (((Length + 1) * sizeof(WCHAR)) > SizeOfStringData)
  1715. {
  1716. Length = (SizeOfStringData/sizeof(WCHAR)) - 1;
  1717. }
  1718. if (Length > 0)
  1719. {
  1720. RtlCopyMemory (StringOffset, InsertionString, Length*sizeof(WCHAR));
  1721. StringOffset += Length;
  1722. *StringOffset++ = L'\0';
  1723. SizeOfStringData -= (Length + 1) * sizeof(WCHAR);
  1724. ErrorLogEntry->NumberOfStrings += 1;
  1725. }
  1726. }
  1727. }
  1728. IoWriteErrorLogEntry(ErrorLogEntry);
  1729. return(STATUS_SUCCESS);
  1730. }
  1731. VOID
  1732. IPSecLogEvents(
  1733. IN PVOID Context
  1734. )
  1735. /*++
  1736. Routine Description:
  1737. Dumps events from the circular buffer to the eventlog when the
  1738. circular buffer overflows.
  1739. Arguments:
  1740. Context - unused.
  1741. Return Value:
  1742. None
  1743. --*/
  1744. {
  1745. PIPSEC_LOG_EVENT pLogEvent;
  1746. LONG LogSize;
  1747. PUCHAR pLog;
  1748. pLogEvent = (PIPSEC_LOG_EVENT)Context;
  1749. LogSize = 0;
  1750. pLog = (PUCHAR)pLogEvent + FIELD_OFFSET(IPSEC_LOG_EVENT, pLog[0]);
  1751. while (LogSize < pLogEvent->LogSize) {
  1752. PIPSEC_EVENT_CTX ctx = (PIPSEC_EVENT_CTX)pLog;
  1753. if (ctx->EventCode == EVENT_IPSEC_DROP_PACKET_INBOUND ||
  1754. ctx->EventCode == EVENT_IPSEC_DROP_PACKET_OUTBOUND) {
  1755. WCHAR IPAddrBufferS[(sizeof(IPAddr) * 4) + 1];
  1756. WCHAR IPAddrBufferD[(sizeof(IPAddr) * 4) + 1];
  1757. WCHAR IPProtocolBuffer[(sizeof(IPAddr) * 4) + 1];
  1758. WCHAR IPSPortBuffer[(sizeof(IPAddr) * 4) + 1];
  1759. WCHAR IPDPortBuffer[(sizeof(IPAddr) * 4) + 1];
  1760. PWCHAR stringlist[5];
  1761. IPHeader UNALIGNED *pIPH;
  1762. USHORT SrcPort=0;
  1763. USHORT DestPort=0;
  1764. ULONG HeaderLen;
  1765. pIPH = (IPHeader UNALIGNED *)ctx->pPacket;
  1766. HeaderLen=(pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  1767. IPSecIPAddrToUnicodeString( pIPH->iph_src,
  1768. IPAddrBufferS);
  1769. IPSecIPAddrToUnicodeString( pIPH->iph_dest,
  1770. IPAddrBufferD);
  1771. IPSecCountToUnicodeString ( pIPH->iph_protocol,
  1772. IPProtocolBuffer);
  1773. if (pIPH->iph_protocol == PROTOCOL_TCP ||
  1774. pIPH->iph_protocol == PROTOCOL_UDP) {
  1775. RtlCopyMemory(&SrcPort,&ctx->pPacket[HeaderLen],sizeof(USHORT));
  1776. RtlCopyMemory(&DestPort,&ctx->pPacket[HeaderLen+sizeof(USHORT)],sizeof(USHORT));
  1777. }
  1778. IPSecCountToUnicodeString ( NET_SHORT(SrcPort),
  1779. IPSPortBuffer);
  1780. IPSecCountToUnicodeString ( NET_SHORT(DestPort),
  1781. IPDPortBuffer);
  1782. IPSecWriteEvent(
  1783. g_ipsec.IPSecDriverObject,
  1784. ctx->EventCode,
  1785. ctx->DropStatus.IPSecStatus,
  1786. ctx->DropStatus.OffloadStatus,
  1787. ctx->DropStatus.Flags,
  1788. 0,
  1789. ctx->pPacket,
  1790. (USHORT)ctx->PacketSize,
  1791. 5,
  1792. IPAddrBufferS,
  1793. IPAddrBufferD,
  1794. IPProtocolBuffer,
  1795. IPSPortBuffer,
  1796. IPDPortBuffer);
  1797. } else if (ctx->Addr && ctx->EventCount > 0) {
  1798. WCHAR IPAddrBuffer[(sizeof(IPAddr) * 4) + 1];
  1799. WCHAR CountBuffer[MAX_COUNT_STRING_LEN + 1];
  1800. PWCHAR stringList[2];
  1801. IPSecIPAddrToUnicodeString( ctx->Addr,
  1802. IPAddrBuffer);
  1803. IPSecCountToUnicodeString( ctx->EventCount,
  1804. CountBuffer);
  1805. stringList[0] = CountBuffer;
  1806. stringList[1] = IPAddrBuffer;
  1807. LOG_EVENT(
  1808. g_ipsec.IPSecDriverObject,
  1809. ctx->EventCode,
  1810. ctx->UniqueEventValue,
  1811. 2,
  1812. stringList,
  1813. 0,
  1814. NULL);
  1815. } else if (ctx->Addr) {
  1816. WCHAR IPAddrBuffer[(sizeof(IPAddr) * 4) + 1];
  1817. PWCHAR stringList[1];
  1818. IPSecIPAddrToUnicodeString( ctx->Addr,
  1819. IPAddrBuffer);
  1820. stringList[0] = IPAddrBuffer;
  1821. LOG_EVENT(
  1822. g_ipsec.IPSecDriverObject,
  1823. ctx->EventCode,
  1824. ctx->UniqueEventValue,
  1825. 1,
  1826. stringList,
  1827. 0,
  1828. NULL);
  1829. } else {
  1830. LOG_EVENT(
  1831. g_ipsec.IPSecDriverObject,
  1832. ctx->EventCode,
  1833. ctx->UniqueEventValue,
  1834. 0,
  1835. NULL,
  1836. 0,
  1837. NULL);
  1838. }
  1839. if (ctx->pPacket) {
  1840. IPSecFreeLogBuffer(ctx->pPacket);
  1841. ctx->pPacket=NULL;
  1842. }
  1843. pLog += sizeof(IPSEC_EVENT_CTX);
  1844. LogSize += sizeof(IPSEC_EVENT_CTX);
  1845. }
  1846. IPSecFreeMemory(pLogEvent);
  1847. IPSEC_DECREMENT(g_ipsec.NumWorkers);
  1848. }
  1849. VOID
  1850. IPSecBufferEvent(
  1851. IN IPAddr Addr,
  1852. IN ULONG EventCode,
  1853. IN ULONG UniqueEventValue,
  1854. IN BOOLEAN fBufferEvent
  1855. )
  1856. /*++
  1857. Routine Description:
  1858. Buffers events in a circular buffer; dumps them to the eventlog when the
  1859. circular buffer overflows.
  1860. Arguments:
  1861. Addr - [OPTIONAL] the source IP addr of the offending peer.
  1862. EventCode - Identifies the error message.
  1863. UniqueEventValue - Identifies this instance of a given error message.
  1864. Return Value:
  1865. None
  1866. --*/
  1867. {
  1868. KIRQL kIrql;
  1869. if (!(g_ipsec.DiagnosticMode & IPSEC_DIAGNOSTIC_ENABLE_LOG)) {
  1870. return;
  1871. }
  1872. ACQUIRE_LOCK(&g_ipsec.EventLogLock, &kIrql);
  1873. if (fBufferEvent) {
  1874. PIPSEC_EVENT_CTX ctx;
  1875. g_ipsec.IPSecBufferedEvents++;
  1876. ctx = (PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc;
  1877. ctx--;
  1878. while (ctx >= (PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemory) {
  1879. if (ctx->Addr == Addr &&
  1880. ctx->EventCode == EventCode &&
  1881. ctx->UniqueEventValue == UniqueEventValue) {
  1882. //
  1883. // Found a duplicate; update count and exit.
  1884. //
  1885. ctx->EventCount++;
  1886. if (g_ipsec.IPSecBufferedEvents >= g_ipsec.EventQueueSize) {
  1887. goto logit;
  1888. }
  1889. RELEASE_LOCK(&g_ipsec.EventLogLock, kIrql);
  1890. return;
  1891. }
  1892. ctx--;
  1893. }
  1894. }
  1895. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->Addr = Addr;
  1896. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCode = EventCode;
  1897. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->UniqueEventValue = UniqueEventValue;
  1898. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->pPacket=NULL;
  1899. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->PacketSize=0;
  1900. if (fBufferEvent) {
  1901. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCount = 1;
  1902. } else {
  1903. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCount = 0;
  1904. }
  1905. g_ipsec.IPSecLogMemoryLoc += sizeof(IPSEC_EVENT_CTX);
  1906. logit:
  1907. if (!fBufferEvent ||
  1908. g_ipsec.IPSecLogMemoryLoc >= g_ipsec.IPSecLogMemoryEnd ||
  1909. g_ipsec.IPSecBufferedEvents >= g_ipsec.EventQueueSize) {
  1910. //
  1911. // Flush the logs.
  1912. //
  1913. IPSecQueueLogEvent();
  1914. }
  1915. RELEASE_LOCK(&g_ipsec.EventLogLock, kIrql);
  1916. }
  1917. NTSTATUS
  1918. CopyOutboundPacketToBuffer(
  1919. IN PUCHAR pIPHeader,
  1920. IN PVOID pData,
  1921. OUT PUCHAR * pPacket,
  1922. OUT ULONG * PacketSize
  1923. )
  1924. {
  1925. PNDIS_BUFFER pTemp;
  1926. ULONG Length;
  1927. ULONG dataLength=0;
  1928. IPHeader UNALIGNED *pIPH;
  1929. ULONG HeaderLen=0;
  1930. PUCHAR pBuffer;
  1931. ULONG CopyPos=0;
  1932. PUCHAR pPacketData;
  1933. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  1934. pTemp = (PNDIS_BUFFER)pData;
  1935. while (pTemp) {
  1936. pBuffer = NULL;
  1937. Length = 0;
  1938. NdisQueryBufferSafe(pTemp,
  1939. &pBuffer,
  1940. &Length,
  1941. NormalPagePriority);
  1942. if (!pBuffer) {
  1943. return STATUS_UNSUCCESSFUL;
  1944. }
  1945. dataLength += Length;
  1946. pTemp = NDIS_BUFFER_LINKAGE(pTemp);
  1947. }
  1948. HeaderLen=(pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  1949. dataLength += HeaderLen;
  1950. if (dataLength > IPSEC_LOG_PACKET_SIZE) {
  1951. dataLength = IPSEC_LOG_PACKET_SIZE;
  1952. }
  1953. if (dataLength < sizeof(IPHeader)) {
  1954. // doesn't even have a full ip header
  1955. return STATUS_UNSUCCESSFUL;
  1956. }
  1957. if ((pIPH->iph_protocol == PROTOCOL_TCP) ||
  1958. (pIPH->iph_protocol == PROTOCOL_UDP)) {
  1959. if (dataLength - HeaderLen < 8) {
  1960. // not enough room for ports
  1961. return STATUS_UNSUCCESSFUL;
  1962. }
  1963. }
  1964. *pPacket = IPSecAllocateLogBuffer(dataLength);
  1965. if (! (*pPacket)) {
  1966. return STATUS_UNSUCCESSFUL;
  1967. }
  1968. *PacketSize=dataLength;
  1969. pTemp = (PNDIS_BUFFER)pData;
  1970. CopyPos=0;
  1971. while (pTemp && CopyPos < dataLength) {
  1972. IPSecQueryNdisBuf(pTemp,&pPacketData,&Length);
  1973. if (CopyPos + Length > dataLength) {
  1974. Length = (dataLength - CopyPos);
  1975. }
  1976. RtlCopyMemory(*pPacket+CopyPos,pPacketData,Length);
  1977. CopyPos += Length;
  1978. pTemp = NDIS_BUFFER_LINKAGE(pTemp);
  1979. }
  1980. return STATUS_SUCCESS;
  1981. }
  1982. //
  1983. // pData is data after IPHeader, IPRcvBuf.
  1984. //
  1985. NTSTATUS
  1986. CopyInboundPacketToBuffer(
  1987. IN PUCHAR pIPHeader,
  1988. IN PVOID pData,
  1989. OUT PUCHAR * pPacket,
  1990. OUT ULONG * PacketSize
  1991. )
  1992. {
  1993. IPRcvBuf *pTemp;
  1994. ULONG Length;
  1995. ULONG dataLength=0;
  1996. IPHeader UNALIGNED *pIPH;
  1997. ULONG HeaderLen=0;
  1998. PUCHAR pBuffer;
  1999. ULONG CopyPos=0;
  2000. PUCHAR pPacketData;
  2001. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  2002. pTemp = (IPRcvBuf*)pData;
  2003. while (pTemp) {
  2004. pBuffer = NULL;
  2005. Length = 0;
  2006. IPSecQueryRcvBuf(pTemp,
  2007. &pBuffer,
  2008. &Length);
  2009. if (!pBuffer) {
  2010. return STATUS_UNSUCCESSFUL;
  2011. }
  2012. dataLength += Length;
  2013. pTemp = IPSEC_BUFFER_LINKAGE(pTemp);
  2014. }
  2015. HeaderLen=(pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  2016. dataLength += HeaderLen;
  2017. if (dataLength > IPSEC_LOG_PACKET_SIZE) {
  2018. dataLength = IPSEC_LOG_PACKET_SIZE;
  2019. }
  2020. // Sanity check length
  2021. if (dataLength < sizeof(IPHeader)) {
  2022. // doesn't even have a full ip header
  2023. return STATUS_UNSUCCESSFUL;
  2024. }
  2025. if ((pIPH->iph_protocol == PROTOCOL_TCP) ||
  2026. (pIPH->iph_protocol == PROTOCOL_UDP)) {
  2027. if (dataLength - HeaderLen < 8) {
  2028. // not enough room for ports
  2029. return STATUS_UNSUCCESSFUL;
  2030. }
  2031. }
  2032. *pPacket = IPSecAllocateLogBuffer(dataLength);
  2033. if (! (*pPacket)) {
  2034. return STATUS_UNSUCCESSFUL;
  2035. }
  2036. *PacketSize=dataLength;
  2037. pTemp = (IPRcvBuf*)pData;
  2038. RtlCopyMemory(*pPacket,pIPH,HeaderLen);
  2039. CopyPos=HeaderLen;
  2040. while (pTemp && CopyPos < dataLength) {
  2041. IPSecQueryRcvBuf(pTemp,&pPacketData,&Length);
  2042. if (CopyPos + Length > dataLength) {
  2043. Length = (dataLength - CopyPos);
  2044. }
  2045. RtlCopyMemory(*pPacket+CopyPos,pPacketData,Length);
  2046. CopyPos += Length;
  2047. pTemp = IPSEC_BUFFER_LINKAGE(pTemp);
  2048. }
  2049. return STATUS_SUCCESS;
  2050. }
  2051. VOID
  2052. IPSecBufferPacketDrop(
  2053. IN PUCHAR pIPHeader,
  2054. IN PVOID pData,
  2055. IN OUT PULONG pIpsecFlags,
  2056. IN PIPSEC_DROP_STATUS pDropStatus
  2057. )
  2058. /*++
  2059. Routine Description:
  2060. Buffers events in a circular buffer; dumps them to the eventlog when the
  2061. circular buffer overflows.
  2062. Arguments:
  2063. EventCode - Identifies the error message.
  2064. Return Value:
  2065. None
  2066. --*/
  2067. {
  2068. KIRQL kIrql;
  2069. PIPSEC_EVENT_CTX ctx;
  2070. IPHeader UNALIGNED *pIPH;
  2071. PNDIS_BUFFER pTemp;
  2072. PUCHAR pPacket=NULL;
  2073. ULONG PacketSize=0;
  2074. ULONG Status;
  2075. BOOL bLockHeld=FALSE;
  2076. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  2077. if (*pIpsecFlags & IPSEC_FLAG_INCOMING) {
  2078. if (!(g_ipsec.DiagnosticMode & IPSEC_DIAGNOSTIC_INBOUND)) {
  2079. // Don't log
  2080. goto out;
  2081. }
  2082. Status=CopyInboundPacketToBuffer(pIPHeader,
  2083. pData,
  2084. &pPacket,
  2085. &PacketSize);
  2086. } else {
  2087. if (!(g_ipsec.DiagnosticMode & IPSEC_DIAGNOSTIC_OUTBOUND)) {
  2088. //Don't log
  2089. goto out;
  2090. }
  2091. Status=CopyOutboundPacketToBuffer(pIPHeader,
  2092. pData,
  2093. &pPacket,
  2094. &PacketSize);
  2095. }
  2096. if (Status != STATUS_SUCCESS) {
  2097. goto out;
  2098. }
  2099. ACQUIRE_LOCK(&g_ipsec.EventLogLock, &kIrql);
  2100. bLockHeld=TRUE;
  2101. g_ipsec.IPSecBufferedEvents++;
  2102. ctx = (PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc;
  2103. ctx--;
  2104. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->Addr=pIPH->iph_src;
  2105. if (*pIpsecFlags & IPSEC_FLAG_INCOMING) {
  2106. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCode = EVENT_IPSEC_DROP_PACKET_INBOUND;
  2107. } else {
  2108. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCode = EVENT_IPSEC_DROP_PACKET_OUTBOUND;;
  2109. }
  2110. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCount = 1;
  2111. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->pPacket = pPacket;
  2112. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->PacketSize = PacketSize;
  2113. if (pDropStatus) {
  2114. RtlCopyMemory(&(((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->DropStatus),
  2115. pDropStatus,sizeof(IPSEC_DROP_STATUS));
  2116. } else {
  2117. RtlZeroMemory(&(((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->DropStatus),
  2118. sizeof(IPSEC_DROP_STATUS));
  2119. }
  2120. g_ipsec.IPSecLogMemoryLoc += sizeof(IPSEC_EVENT_CTX);
  2121. if (g_ipsec.IPSecLogMemoryLoc >= g_ipsec.IPSecLogMemoryEnd ||
  2122. g_ipsec.IPSecBufferedEvents >= g_ipsec.EventQueueSize) {
  2123. //
  2124. // Flush the logs.
  2125. //
  2126. IPSecQueueLogEvent();
  2127. }
  2128. out:
  2129. if (bLockHeld) {
  2130. RELEASE_LOCK(&g_ipsec.EventLogLock, kIrql);
  2131. }
  2132. }
  2133. VOID
  2134. IPSecQueueLogEvent(
  2135. VOID
  2136. )
  2137. /*++
  2138. Routine Description:
  2139. Copies the LogMemory to a temporary buffer and schedule an event to
  2140. flush logs.
  2141. Arguments:
  2142. None
  2143. Return Value:
  2144. None
  2145. Notes:
  2146. Called with EventLogLock held.
  2147. --*/
  2148. {
  2149. PIPSEC_LOG_EVENT pLogEvent;
  2150. LONG LogSize;
  2151. PUCHAR pLog;
  2152. LogSize = (LONG)(g_ipsec.IPSecLogMemoryLoc - g_ipsec.IPSecLogMemory);
  2153. //
  2154. // Reset the log memory so we can record again.
  2155. //
  2156. g_ipsec.IPSecLogMemoryLoc = g_ipsec.IPSecLogMemory;
  2157. g_ipsec.IPSecBufferedEvents = 0;
  2158. if (LogSize <= 0) {
  2159. ASSERT(FALSE);
  2160. return;
  2161. }
  2162. pLogEvent = IPSecAllocateMemory(LogSize + FIELD_OFFSET(IPSEC_LOG_EVENT, pLog[0]),
  2163. IPSEC_TAG_EVT_QUEUE);
  2164. if (!pLogEvent) {
  2165. return;
  2166. }
  2167. pLogEvent->LogSize = LogSize;
  2168. pLog = (PUCHAR)pLogEvent + FIELD_OFFSET(IPSEC_LOG_EVENT, pLog[0]);
  2169. RtlCopyMemory(pLog, g_ipsec.IPSecLogMemory, LogSize);
  2170. //
  2171. // Queue work item to dump these into the eventlog.
  2172. //
  2173. ExInitializeWorkItem(&pLogEvent->LogQueueItem, IPSecLogEvents, pLogEvent);
  2174. ExQueueWorkItem(&pLogEvent->LogQueueItem, DelayedWorkQueue);
  2175. IPSEC_INCREMENT(g_ipsec.NumWorkers);
  2176. }
  2177. #if FIPS
  2178. BOOLEAN
  2179. IPSecFipsInitialize(
  2180. VOID
  2181. )
  2182. /*++
  2183. Routine Description:
  2184. Initialize the FIPS library table.
  2185. Arguments:
  2186. Called at PASSIVE level.
  2187. Return Value:
  2188. TRUE/FALSE.
  2189. --*/
  2190. {
  2191. UNICODE_STRING DeviceName;
  2192. PDEVICE_OBJECT pFipsDeviceObject = NULL;
  2193. PIRP pIrp;
  2194. IO_STATUS_BLOCK StatusBlock;
  2195. KEVENT Event;
  2196. NTSTATUS status;
  2197. PAGED_CODE();
  2198. //
  2199. // Return success if FIPS already initialized.
  2200. //
  2201. if (IPSEC_DRIVER_INIT_FIPS()) {
  2202. return TRUE;
  2203. }
  2204. RtlInitUnicodeString(&DeviceName, FIPS_DEVICE_NAME);
  2205. //
  2206. // Get the file and device objects for FIPS.
  2207. //
  2208. status = IoGetDeviceObjectPointer( &DeviceName,
  2209. FILE_ALL_ACCESS,
  2210. &g_ipsec.FipsFileObject,
  2211. &pFipsDeviceObject);
  2212. if (!NT_SUCCESS(status)) {
  2213. g_ipsec.FipsFileObject = NULL;
  2214. return FALSE;
  2215. }
  2216. //
  2217. // Build the request to send to FIPS to get library table.
  2218. //
  2219. KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  2220. pIrp = IoBuildDeviceIoControlRequest( IOCTL_FIPS_GET_FUNCTION_TABLE,
  2221. pFipsDeviceObject,
  2222. NULL,
  2223. 0,
  2224. &g_ipsec.FipsFunctionTable,
  2225. sizeof(FIPS_FUNCTION_TABLE),
  2226. FALSE,
  2227. &Event,
  2228. &StatusBlock);
  2229. if (pIrp == NULL) {
  2230. IPSEC_DEBUG(LOAD, ("IoBuildDeviceIoControlRequest IOCTL_FIPS_GET_FUNCTION_TABLE failed.\n"));
  2231. ObDereferenceObject(g_ipsec.FipsFileObject);
  2232. g_ipsec.FipsFileObject = NULL;
  2233. return FALSE;
  2234. }
  2235. status = IoCallDriver(pFipsDeviceObject, pIrp);
  2236. if (status == STATUS_PENDING) {
  2237. status = KeWaitForSingleObject( &Event,
  2238. Executive,
  2239. KernelMode,
  2240. FALSE,
  2241. NULL);
  2242. if (status == STATUS_SUCCESS) {
  2243. status = StatusBlock.Status;
  2244. }
  2245. }
  2246. if (status != STATUS_SUCCESS) {
  2247. IPSEC_DEBUG(LOAD, ("IoCallDriver: IOCTL_FIPS_GET_FUNCTION_TABLE failed %#x\n", status));
  2248. ObDereferenceObject(g_ipsec.FipsFileObject);
  2249. g_ipsec.FipsFileObject = NULL;
  2250. return FALSE;
  2251. }
  2252. IPSEC_DRIVER_INIT_FIPS() = TRUE;
  2253. return TRUE;
  2254. }
  2255. #endif
  2256. BOOLEAN
  2257. IPSecCryptoInitialize(
  2258. VOID
  2259. )
  2260. /*++
  2261. Routine Description:
  2262. Initialize RNG and FIPS library table.
  2263. Arguments:
  2264. None
  2265. Return Value:
  2266. TRUE/FALSE
  2267. --*/
  2268. {
  2269. PAGED_CODE();
  2270. if (IPSEC_DRIVER_INIT_CRYPTO()) {
  2271. return TRUE;
  2272. }
  2273. #if FIPS
  2274. //
  2275. // Init the FIPS crypto library.
  2276. //
  2277. if (!IPSecFipsInitialize()) {
  2278. return FALSE;
  2279. }
  2280. #endif
  2281. //
  2282. // Init the RC4 key for RNG.
  2283. //
  2284. if (!IPSEC_DRIVER_INIT_RNG()) {
  2285. InitializeRNG(NULL);
  2286. if (!IPSecInitRandom()) {
  2287. ShutdownRNG(NULL);
  2288. return FALSE;
  2289. }
  2290. IPSEC_DRIVER_INIT_RNG() = TRUE;
  2291. }
  2292. IPSEC_DRIVER_INIT_CRYPTO() = TRUE;
  2293. return TRUE;
  2294. }
  2295. BOOLEAN
  2296. IPSecCryptoDeinitialize(
  2297. VOID
  2298. )
  2299. /*++
  2300. Routine Description:
  2301. Deinitialize RNG and dereference FipsFileObject.
  2302. Arguments:
  2303. None
  2304. Return Value:
  2305. TRUE/FALSE
  2306. --*/
  2307. {
  2308. PAGED_CODE();
  2309. //
  2310. // Don't forget to shutdown RNG or we will leak memory.
  2311. //
  2312. if (IPSEC_DRIVER_INIT_RNG()) {
  2313. ShutdownRNG(NULL);
  2314. }
  2315. #if FIPS
  2316. //
  2317. // Dereference FipsFileObject.
  2318. //
  2319. if (g_ipsec.FipsFileObject) {
  2320. ObDereferenceObject(g_ipsec.FipsFileObject);
  2321. }
  2322. #endif
  2323. return TRUE;
  2324. }
  2325. NTSTATUS
  2326. IPSecRegisterProtocols(
  2327. PIPSEC_REGISTER_PROTOCOL pIpsecRegisterProtocol
  2328. )
  2329. {
  2330. if (pIpsecRegisterProtocol->RegisterProtocol == IPSEC_REGISTER_PROTOCOLS) {
  2331. if (!IPSEC_GET_VALUE(gdwInitEsp)) {
  2332. if (TCPIP_REGISTER_PROTOCOL(
  2333. PROTOCOL_ESP,
  2334. NULL,
  2335. NULL,
  2336. IPSecESPStatus,
  2337. NULL,
  2338. NULL,
  2339. NULL
  2340. )) {
  2341. IPSEC_SET_VALUE(gdwInitEsp, 1);
  2342. }
  2343. else {
  2344. ASSERT(FALSE);
  2345. return (STATUS_INSUFFICIENT_RESOURCES);
  2346. }
  2347. }
  2348. if (!IPSEC_GET_VALUE(gdwInitAh)) {
  2349. if (TCPIP_REGISTER_PROTOCOL(
  2350. PROTOCOL_AH,
  2351. NULL,
  2352. NULL,
  2353. IPSecAHStatus,
  2354. NULL,
  2355. NULL,
  2356. NULL
  2357. )) {
  2358. IPSEC_SET_VALUE(gdwInitAh, 1);
  2359. }
  2360. else {
  2361. ASSERT(FALSE);
  2362. TCPIP_DEREGISTER_PROTOCOL(PROTOCOL_ESP);
  2363. IPSEC_SET_VALUE(gdwInitEsp, 0);
  2364. return (STATUS_INSUFFICIENT_RESOURCES);
  2365. }
  2366. }
  2367. }
  2368. else if (pIpsecRegisterProtocol->RegisterProtocol == IPSEC_DEREGISTER_PROTOCOLS) {
  2369. if (IPSEC_GET_VALUE(gdwInitEsp)) {
  2370. TCPIP_DEREGISTER_PROTOCOL(PROTOCOL_ESP);
  2371. IPSEC_SET_VALUE(gdwInitEsp, 0);
  2372. }
  2373. if (IPSEC_GET_VALUE(gdwInitAh)) {
  2374. TCPIP_DEREGISTER_PROTOCOL(PROTOCOL_AH);
  2375. IPSEC_SET_VALUE(gdwInitAh, 0);
  2376. }
  2377. }
  2378. else {
  2379. return (STATUS_INVALID_PARAMETER);
  2380. }
  2381. return (STATUS_SUCCESS);
  2382. }