Leaked source code of windows server 2003
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.

3551 lines
100 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\ip\fltrdrvr\driver.c
  5. Abstract:
  6. Revision History:
  7. --*/
  8. #include "globals.h"
  9. #include <ipinfo.h>
  10. #include <ntddtcp.h>
  11. #include <tdiinfo.h>
  12. #define DEFAULT_DIRECTORY L"DosDevices"
  13. #define DEFAULT_FLTRDRVR_NAME L"IPFILTERDRIVER"
  14. typedef enum
  15. {
  16. NULL_INTERFACE = 0,
  17. OLD_INTERFACE,
  18. NEW_INTERFACE
  19. } INTTYPE, *PINTTTYPE;
  20. FILTER_DRIVER g_filters;
  21. DWORD g_dwCacheSize;
  22. DWORD g_dwHashLists;
  23. BOOL g_bDriverRunning;
  24. KSPIN_LOCK g_lOutFilterLock;
  25. KSPIN_LOCK g_lInFilterLock;
  26. KSPIN_LOCK g_FcbSpin;
  27. MRSW_LOCK g_IpTableLock;
  28. LIST_ENTRY g_freeOutFilters;
  29. LIST_ENTRY g_freeInFilters;
  30. LIST_ENTRY g_leFcbs;
  31. DWORD g_dwMakingNewTable;
  32. DWORD g_dwNumHitsDefaultIn;
  33. DWORD g_dwNumHitsDefaultOut;
  34. DWORD g_FragThresholdSize = MINIMUM_FRAGMENT_OFFSET;
  35. ULONG AddrModulus;
  36. IPAddrEntry *AddrTable;
  37. PADDRESSARRAY * AddrHashTable;
  38. PADDRESSARRAY * AddrSubnetHashTable;
  39. NPAGED_LOOKASIDE_LIST filter_slist;
  40. PAGED_LOOKASIDE_LIST paged_slist;
  41. ERESOURCE FilterAddressLock;
  42. EXTENSION_DRIVER g_Extension;
  43. ULONG g_ulBoundInterfaceCount;
  44. //
  45. // Fragment cache related variables & globals.
  46. //
  47. KTIMER g_ktTimer;
  48. KDPC g_kdTimerDpc;
  49. NPAGED_LOOKASIDE_LIST g_llFragCacheBlocks;
  50. LONGLONG g_llInactivityTime;
  51. KSPIN_LOCK g_kslFragLock;
  52. DWORD g_dwFragTableSize;
  53. PLIST_ENTRY g_pleFragTable;
  54. DWORD g_dwNumFragsAllocs;
  55. //
  56. // Variables to control the debug output.
  57. //
  58. ULONG TraceClassesEnabled = 0;
  59. WCHAR TraceClassesEnabledName[] = L"TraceClassesEnabled";
  60. WCHAR ParametersName[] = L"Parameters";
  61. #ifdef DRIVER_PERF
  62. DWORD g_dwNumPackets,g_dwFragments,g_dwCache1,g_dwCache2;
  63. DWORD g_dwWalk1,g_dwWalk2,g_dwForw,g_dwWalkCache;
  64. KSPIN_LOCK g_slPerfLock;
  65. LARGE_INTEGER g_liTotalTime;
  66. #endif
  67. VOID ClearFragCache();
  68. VOID
  69. FragCacheTimerRoutine(
  70. PKDPC Dpc,
  71. PVOID DeferredContext,
  72. PVOID SystemArgument1,
  73. PVOID SystemArgument2
  74. );
  75. NTSTATUS
  76. OpenRegKey(
  77. PHANDLE phRegHandle,
  78. PUNICODE_STRING pusKeyName
  79. );
  80. NTSTATUS
  81. GetRegDWORDValue(
  82. HANDLE KeyHandle,
  83. PWCHAR ValueName,
  84. PULONG ValueData
  85. );
  86. //
  87. // Forward references.
  88. //
  89. NTSTATUS
  90. OpenNewHandle(PFILE_OBJECT FileObject);
  91. NTSTATUS
  92. CloseFcb(PPFFCB Fcb, PFILE_OBJECT FileObject);
  93. PPAGED_FILTER_INTERFACE
  94. FindInterfaceOnHandle(PFILE_OBJECT FileObject,
  95. PVOID pvValue);
  96. DWORD
  97. LocalIpLook(DWORD Addr);
  98. BOOLEAN
  99. PfFastIoDeviceControl (
  100. IN struct _FILE_OBJECT *FileObject,
  101. IN BOOLEAN Wait,
  102. IN PVOID InputBuffer OPTIONAL,
  103. IN ULONG InputBufferLength,
  104. OUT PVOID OutputBuffer OPTIONAL,
  105. IN ULONG OutputBufferLength,
  106. IN ULONG IoControlCode,
  107. OUT PIO_STATUS_BLOCK IoStatus,
  108. IN struct _DEVICE_OBJECT *DeviceObject
  109. );
  110. NTSTATUS
  111. LockFcb(
  112. IN struct _FILE_OBJECT *FileObject);
  113. VOID
  114. PFReadRegistryParameters(PUNICODE_STRING RegistryPath);
  115. NTSTATUS
  116. InitFragCacheParameters(
  117. IN PUNICODE_STRING RegistryPath
  118. );
  119. VOID
  120. UnLockFcb(
  121. IN struct _FILE_OBJECT *FileObject);
  122. NTSTATUS
  123. GetSynCountTotal(PFILTER_DRIVER_GET_SYN_COUNT OutputBuffer);
  124. NTSTATUS
  125. DeleteByHandle(
  126. IN PPFFCB Fcb,
  127. IN PPAGED_FILTER_INTERFACE pPage,
  128. IN PVOID * ppHandles,
  129. IN DWORD dwLength);
  130. FAST_IO_DISPATCH PfFastIoDispatch =
  131. {
  132. 11,
  133. NULL,
  134. NULL,
  135. NULL,
  136. NULL,
  137. NULL,
  138. NULL,
  139. NULL,
  140. NULL,
  141. NULL,
  142. PfFastIoDeviceControl
  143. };
  144. #pragma alloc_text(PAGED, DoIpIoctl)
  145. //#pragma alloc_text(PAGED, OpenNewHandle)
  146. #pragma alloc_text(PAGED, FindInterfaceOnHandle)
  147. #pragma alloc_text(PAGED, PfFastIoDeviceControl)
  148. #pragma alloc_text(INIT, DriverEntry, PFReadRegistryParameters)
  149. VOID
  150. FcbLockDown(PPFFCB Fcb)
  151. {
  152. KIRQL kirql;
  153. KeAcquireSpinLock(&g_FcbSpin, &kirql);
  154. if(!(Fcb->dwFlags & PF_FCB_CLOSED))
  155. {
  156. InterlockedDecrement(&Fcb->UseCount);
  157. Fcb->dwFlags |= PF_FCB_CLOSED;
  158. }
  159. KeReleaseSpinLock(&g_FcbSpin, kirql);
  160. }
  161. BOOLEAN FASTCALL
  162. ValidateHeader(
  163. PRTR_INFO_BLOCK_HEADER Header,
  164. ULONG Size
  165. )
  166. /*++
  167. Routine Description:
  168. Copied from NAT driver sources. Author: AboladeG
  169. This routine is invoked to ensure that the given header is consistent.
  170. This is the case if
  171. * the header's size is less than or equal to 'Size'
  172. * each entry in the header is contained in 'Header->Size'.
  173. * the data for each entry is contained in 'Header->Size'.
  174. Arguments:
  175. Header - the header to be validated
  176. Size - the size of the buffer in which 'Header' appears
  177. Return Value:
  178. BOOLEAN - TRUE if valid, FALSE otherwise.
  179. --*/
  180. {
  181. ULONG i;
  182. ULONG64 Length;
  183. //
  184. // Check that the base structure is present
  185. //
  186. if (Size < FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry) ||
  187. Size < Header->Size) {
  188. return FALSE;
  189. }
  190. //
  191. // Check that the table of contents is present
  192. //
  193. Length = (ULONG64)Header->TocEntriesCount * sizeof(RTR_TOC_ENTRY);
  194. if (Length > MAXLONG) {
  195. return FALSE;
  196. }
  197. Length += FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry);
  198. if (Length > Header->Size) {
  199. return FALSE;
  200. }
  201. //
  202. // Check that all the data is present
  203. //
  204. for (i = 0; i < Header->TocEntriesCount; i++) {
  205. Length =
  206. (ULONG64)Header->TocEntry[i].Count * Header->TocEntry[i].InfoSize;
  207. if (Length > MAXLONG) {
  208. return FALSE;
  209. }
  210. if ((Length + Header->TocEntry[i].Offset) > Header->Size) {
  211. return FALSE;
  212. }
  213. }
  214. return TRUE;
  215. } // ValidateHeader
  216. NTSTATUS
  217. DriverEntry(
  218. IN PDRIVER_OBJECT DriverObject,
  219. IN PUNICODE_STRING RegistryPath
  220. )
  221. /*++
  222. Routine Description
  223. Called when the driver is loaded. It creates the device object and sets up the DOS name.
  224. Also does the initialization of standard entry points and its own global data
  225. Arguments
  226. DriverObject
  227. RegistryPath
  228. Return Value
  229. NTSTATUS
  230. --*/
  231. {
  232. INT i;
  233. PDEVICE_OBJECT deviceObject = NULL;
  234. NTSTATUS ntStatus;
  235. WCHAR deviceNameBuffer[] = DD_IPFLTRDRVR_DEVICE_NAME;
  236. UNICODE_STRING deviceNameUnicodeString;
  237. UNICODE_STRING String;
  238. OBJECT_ATTRIBUTES ObjectAttributes;
  239. HANDLE ParametersKey;
  240. HANDLE ServiceKey;
  241. TRACE0("Filter Driver: Entering DriverEntry\n") ;
  242. #if DBG
  243. //
  244. // Open the registry key
  245. //
  246. InitializeObjectAttributes(
  247. &ObjectAttributes,
  248. RegistryPath,
  249. OBJ_CASE_INSENSITIVE,
  250. NULL,
  251. NULL
  252. );
  253. ntStatus = ZwOpenKey(&ServiceKey, KEY_READ, &ObjectAttributes);
  254. if (NT_SUCCESS(ntStatus)) {
  255. RtlInitUnicodeString(&String, ParametersName);
  256. InitializeObjectAttributes(
  257. &ObjectAttributes,
  258. &String,
  259. OBJ_CASE_INSENSITIVE,
  260. ServiceKey,
  261. NULL
  262. );
  263. ntStatus = ZwOpenKey(&ParametersKey, KEY_READ, &ObjectAttributes);
  264. ZwClose(ServiceKey);
  265. if (NT_SUCCESS(ntStatus)) {
  266. UCHAR Buffer[32];
  267. ULONG BytesRead;
  268. PKEY_VALUE_PARTIAL_INFORMATION Value;
  269. RtlInitUnicodeString(&String, TraceClassesEnabledName);
  270. ntStatus =
  271. ZwQueryValueKey(
  272. ParametersKey,
  273. &String,
  274. KeyValuePartialInformation,
  275. (PKEY_VALUE_PARTIAL_INFORMATION)Buffer,
  276. sizeof(Buffer),
  277. &BytesRead
  278. );
  279. if (NT_SUCCESS(ntStatus) &&
  280. ((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Type == REG_DWORD
  281. ) {
  282. TraceClassesEnabled =
  283. *(PULONG)((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Data;
  284. }
  285. DbgPrint("MSPFLTEX: TraceClassesEnabled=0x%08x\n", TraceClassesEnabled);
  286. ZwClose(ParametersKey);
  287. }
  288. }
  289. #endif
  290. //
  291. // Initialize the lock and the list
  292. //
  293. InitializeMRSWLock(&g_filters.ifListLock);
  294. InitializeListHead(&g_filters.leIfListHead);
  295. InitializeListHead(&g_leFcbs);
  296. g_filters.ppInCache = NULL;
  297. g_filters.ppOutCache = NULL;
  298. g_bDriverRunning = FALSE;
  299. InitializeMRSWLock(&g_IpTableLock);
  300. KeInitializeSpinLock(&g_lOutFilterLock);
  301. KeInitializeSpinLock(&g_lInFilterLock);
  302. KeInitializeSpinLock(&g_FcbSpin);
  303. InitializeListHead(&g_freeOutFilters);
  304. InitializeListHead(&g_freeInFilters);
  305. g_dwNumHitsDefaultIn = g_dwNumHitsDefaultOut = 0;
  306. #ifdef DRIVER_PERF
  307. g_dwFragments = g_dwCache1 = g_dwCache2 = g_dwNumPackets = 0;
  308. g_dwWalk1 = g_dwWalk2 = g_dwForw = g_dwWalkCache = 0;
  309. g_liTotalTime.HighPart = g_liTotalTime.LowPart = 0;
  310. KeInitializeSpinLock(&g_slPerfLock);
  311. #endif
  312. //
  313. // Initialize interface cache.
  314. //
  315. g_ulBoundInterfaceCount = 0;
  316. g_filters.pInterfaceCache = (PCACHE_ENTRY)
  317. ExAllocatePoolWithTag(
  318. NonPagedPool,
  319. (CACHE_SIZE * sizeof(CACHE_ENTRY)),
  320. 'hCnI'
  321. );
  322. if(g_filters.pInterfaceCache == NULL)
  323. {
  324. return STATUS_NO_MEMORY;
  325. }
  326. InitializeCache(g_filters.pInterfaceCache);
  327. //
  328. // Initialize fragment cache.
  329. //
  330. InitFragCacheParameters(RegistryPath);
  331. //
  332. // Initialize Extension Data
  333. //
  334. InitializeMRSWLock(&g_Extension.ExtLock);
  335. g_Extension.ExtPointer = NULL;
  336. g_Extension.ExtFileObject = NULL;
  337. //
  338. // Create a device object
  339. //
  340. RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer);
  341. __try
  342. {
  343. ntStatus = IoCreateDevice (DriverObject,
  344. 0,
  345. &deviceNameUnicodeString,
  346. FILE_DEVICE_NETWORK,
  347. FILE_DEVICE_SECURE_OPEN,
  348. FALSE, // Exclusive
  349. &deviceObject
  350. );
  351. if (NT_SUCCESS(ntStatus))
  352. {
  353. //
  354. // Initialize the driver object
  355. //
  356. DriverObject->DriverUnload = FilterDriverUnload;
  357. DriverObject->FastIoDispatch = &PfFastIoDispatch;
  358. DriverObject->DriverStartIo = NULL;
  359. for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  360. {
  361. DriverObject->MajorFunction[i] = FilterDriverDispatch;
  362. }
  363. }
  364. else
  365. {
  366. ERROR((
  367. "IPFLTDRV: Couldn't get device pointer to Filt Driver 0x%08x\n",
  368. ntStatus
  369. ));
  370. __leave;
  371. }
  372. SetupExternalNaming (&deviceNameUnicodeString) ;
  373. }
  374. __finally
  375. {
  376. if(!NT_SUCCESS(ntStatus))
  377. {
  378. ERROR(("IPFLTDRV: Error in DriverEntry routine\n"));
  379. }
  380. else
  381. {
  382. ExInitializeResourceLite ( &FilterListResourceLock );
  383. ExInitializeResourceLite ( &FilterAddressLock );
  384. CALLTRACE(("IPFLTDRV: DriverEntry routine successful\n"));
  385. }
  386. if(NT_SUCCESS(ntStatus))
  387. {
  388. PFReadRegistryParameters(RegistryPath);
  389. }
  390. }
  391. return ntStatus;
  392. }
  393. NTSTATUS
  394. FilterDriverDispatch(
  395. IN PDEVICE_OBJECT DeviceObject,
  396. IN PIRP Irp
  397. )
  398. /*++
  399. Routine Description
  400. Dispatch Routine for the filter driver. Gets the current irp stack location, validates
  401. the parameters and calls the necessary routing (which is ioctl.c)
  402. Arguments
  403. DeviceObject
  404. Irp
  405. Return Value
  406. Status as returned by the worker functions
  407. --*/
  408. {
  409. PIO_STACK_LOCATION irpStack;
  410. PVOID pvIoBuffer;
  411. ULONG inputBufferLength;
  412. ULONG outputBufferLength;
  413. ULONG ioControlCode;
  414. NTSTATUS ntStatus;
  415. DWORD dwSize = 0;
  416. Irp->IoStatus.Status = STATUS_SUCCESS;
  417. Irp->IoStatus.Information = 0;
  418. //
  419. // Get a pointer to the current location in the Irp. This is where
  420. // the function codes and parameters are located.
  421. //
  422. irpStack = IoGetCurrentIrpStackLocation(Irp);
  423. //
  424. // Get the pointer to the input/output buffer and it's length
  425. //
  426. pvIoBuffer = Irp->AssociatedIrp.SystemBuffer;
  427. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  428. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  429. CALLTRACE(("IPFLTDRV: FilterDriverDispatch\n"));
  430. switch (irpStack->MajorFunction)
  431. {
  432. case IRP_MJ_CREATE:
  433. {
  434. TRACE(CONFIG,(
  435. "IPFLTDRV: IRP_MJ_CREATE, FileObject=%08x\n",
  436. irpStack->FileObject
  437. ));
  438. //
  439. // Initialize the driver. The first time it gets a create IRP, it starts up the
  440. // filtering.
  441. //
  442. ntStatus = STATUS_SUCCESS;
  443. if(!g_bDriverRunning)
  444. {
  445. KeEnterCriticalRegion();
  446. ExAcquireResourceExclusiveLite( &FilterListResourceLock, TRUE);
  447. if (g_bDriverRunning || InitFilterDriver())
  448. {
  449. g_bDriverRunning = TRUE;
  450. }
  451. else
  452. {
  453. ntStatus = STATUS_UNSUCCESSFUL ;
  454. }
  455. ExReleaseResourceLite( &FilterListResourceLock );
  456. KeLeaveCriticalRegion();
  457. }
  458. if(NT_SUCCESS(ntStatus))
  459. {
  460. ntStatus = OpenNewHandle(irpStack->FileObject);
  461. }
  462. break;
  463. }
  464. case IRP_MJ_CLEANUP:
  465. {
  466. CALLTRACE(("IPFLTDRV: IRP_MJ_CLEANUP\n"));
  467. //
  468. // Closing the file handle to the driver doesnt shut the driver down
  469. //
  470. ntStatus = STATUS_SUCCESS;
  471. break;
  472. }
  473. case IRP_MJ_CLOSE:
  474. {
  475. //
  476. // All done with this file object and this FCB. Run
  477. // down the interfaces getting rid of them
  478. //
  479. ntStatus = LockFcb(irpStack->FileObject);
  480. if(NT_SUCCESS(ntStatus))
  481. {
  482. PPFFCB Fcb = irpStack->FileObject->FsContext2;
  483. FcbLockDown(Fcb);
  484. UnLockFcb(irpStack->FileObject);
  485. }
  486. break;
  487. }
  488. case IRP_MJ_DEVICE_CONTROL:
  489. {
  490. CALLTRACE(("IPFLTDRV: IRP_MJ_DEVICE_CONTROL\n"));
  491. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  492. switch (ioControlCode)
  493. {
  494. #if FWPF
  495. case IOCTL_CLEAR_INTERFACE_BINDING:
  496. {
  497. PINTERFACEBINDING pBind;
  498. PPAGED_FILTER_INTERFACE pPage;
  499. CALLTRACE(("IPFLTDRV: IOCTL_CLEAR_INTERFACE_BINDING called\n"));
  500. dwSize = sizeof(*pBind);
  501. if(inputBufferLength < sizeof(*pBind))
  502. {
  503. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  504. break;
  505. }
  506. if(outputBufferLength < sizeof(*pBind))
  507. {
  508. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  509. break;
  510. }
  511. pBind = (PINTERFACEBINDING)pvIoBuffer;
  512. ntStatus = LockFcb(irpStack->FileObject);
  513. if(!NT_SUCCESS(ntStatus))
  514. {
  515. break;
  516. }
  517. pPage = FindInterfaceOnHandle(irpStack->FileObject,
  518. pBind->pvDriverContext);
  519. if(!pPage)
  520. {
  521. ntStatus = STATUS_INVALID_PARAMETER;
  522. }
  523. else
  524. {
  525. ntStatus = ClearInterfaceBinding(pPage, pBind);
  526. }
  527. UnLockFcb(irpStack->FileObject);
  528. break;
  529. }
  530. case IOCTL_SET_INTERFACE_BINDING:
  531. {
  532. PINTERFACEBINDING pBind;
  533. PPAGED_FILTER_INTERFACE pPage;
  534. CALLTRACE(("IPFLTDRV: IOCTL_SET_INTERFACE_BINDING called\n"));
  535. dwSize = sizeof(*pBind);
  536. if(inputBufferLength < sizeof(*pBind))
  537. {
  538. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  539. break;
  540. }
  541. if(outputBufferLength < sizeof(*pBind))
  542. {
  543. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  544. break;
  545. }
  546. pBind = (PINTERFACEBINDING)pvIoBuffer;
  547. ntStatus = LockFcb(irpStack->FileObject);
  548. if(!NT_SUCCESS(ntStatus))
  549. {
  550. break;
  551. }
  552. pPage = FindInterfaceOnHandle(irpStack->FileObject,
  553. pBind->pvDriverContext);
  554. if(!pPage)
  555. {
  556. ntStatus = STATUS_INVALID_PARAMETER;
  557. }
  558. else
  559. {
  560. ntStatus = SetInterfaceBinding(pBind, pPage);
  561. }
  562. UnLockFcb(irpStack->FileObject);
  563. break;
  564. }
  565. case IOCTL_SET_INTERFACE_BINDING2:
  566. {
  567. PINTERFACEBINDING2 pBind2;
  568. PPAGED_FILTER_INTERFACE pPage;
  569. CALLTRACE(("IPFLTDRV: IOCTL_SET_INTERFACE_BINDING2 called\n"));
  570. dwSize = sizeof(*pBind2);
  571. if(inputBufferLength < sizeof(*pBind2))
  572. {
  573. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  574. break;
  575. }
  576. if(outputBufferLength < sizeof(*pBind2))
  577. {
  578. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  579. break;
  580. }
  581. pBind2 = (PINTERFACEBINDING2)pvIoBuffer;
  582. ntStatus = LockFcb(irpStack->FileObject);
  583. if(!NT_SUCCESS(ntStatus))
  584. {
  585. break;
  586. }
  587. pPage = FindInterfaceOnHandle(irpStack->FileObject,
  588. pBind2->pvDriverContext);
  589. if(!pPage)
  590. {
  591. ntStatus = STATUS_INVALID_PARAMETER;
  592. }
  593. else
  594. {
  595. ntStatus = SetInterfaceBinding2(pBind2, pPage);
  596. }
  597. UnLockFcb(irpStack->FileObject);
  598. break;
  599. }
  600. case IOCTL_PF_GET_INTERFACE_PARAMETERS:
  601. {
  602. PPFGETINTERFACEPARAMETERS pp;
  603. PPAGED_FILTER_INTERFACE pPage;
  604. CALLTRACE(("IPFLTDRV: GET_INTERFACE_PARAMETERS called\n"));
  605. dwSize = sizeof(*pp);
  606. if(inputBufferLength < (sizeof(*pp) - sizeof(FILTER_STATS_EX)))
  607. {
  608. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  609. break;
  610. }
  611. if(outputBufferLength < (sizeof(*pp) - sizeof(FILTER_STATS_EX)))
  612. {
  613. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  614. break;
  615. }
  616. pp = (PPFGETINTERFACEPARAMETERS)pvIoBuffer;
  617. ntStatus = LockFcb(irpStack->FileObject);
  618. if(!NT_SUCCESS(ntStatus))
  619. {
  620. break;
  621. }
  622. if(pp->dwFlags & GET_BY_INDEX)
  623. {
  624. pPage = 0;
  625. }
  626. else
  627. {
  628. pPage = FindInterfaceOnHandle(irpStack->FileObject,
  629. pp->pvDriverContext);
  630. if(!pPage)
  631. {
  632. ntStatus = STATUS_INVALID_PARAMETER;
  633. UnLockFcb(irpStack->FileObject);
  634. break;
  635. }
  636. }
  637. dwSize = outputBufferLength;
  638. ntStatus = GetInterfaceParameters(pPage,
  639. pp,
  640. &dwSize);
  641. UnLockFcb(irpStack->FileObject);
  642. break;
  643. }
  644. case IOCTL_PF_CREATE_AND_SET_INTERFACE_PARAMETERS:
  645. {
  646. //
  647. // create a new style interface.
  648. //
  649. PPFINTERFACEPARAMETERS pInfo;
  650. CALLTRACE(("IPFLTDRV: IOCTL_CREATE_AND_SET called\n"));
  651. dwSize = sizeof(PFINTERFACEPARAMETERS);
  652. //
  653. // Both input and output Buffer lengths should be the same a nd
  654. //
  655. if(inputBufferLength != dwSize)
  656. {
  657. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  658. break;
  659. }
  660. if(outputBufferLength != dwSize)
  661. {
  662. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  663. break;
  664. }
  665. pInfo = (PPFINTERFACEPARAMETERS)pvIoBuffer;
  666. //
  667. // now establish the interface
  668. //
  669. ntStatus = LockFcb(irpStack->FileObject);
  670. if(!NT_SUCCESS(ntStatus))
  671. {
  672. break;
  673. }
  674. ntStatus = AddNewInterface(pInfo,
  675. irpStack->FileObject->FsContext2);
  676. UnLockFcb(irpStack->FileObject);
  677. break;
  678. }
  679. case IOCTL_PF_CREATE_LOG:
  680. {
  681. PPFPAGEDLOG pPage;
  682. PPFLOG ppfLog;
  683. CALLTRACE(("IPFLTDRV: IOCTL_PF_CREATE_LOG\n"));
  684. //
  685. // Check the size
  686. //
  687. dwSize = sizeof(PFLOG);
  688. if((inputBufferLength < dwSize)
  689. ||
  690. (outputBufferLength < dwSize))
  691. {
  692. ntStatus = STATUS_BUFFER_TOO_SMALL;
  693. break;
  694. }
  695. ppfLog = (PPFLOG)pvIoBuffer;
  696. ntStatus = LockFcb(irpStack->FileObject);
  697. if(!NT_SUCCESS(ntStatus))
  698. {
  699. break;
  700. }
  701. ntStatus = PfLogCreateLog(
  702. ppfLog,
  703. irpStack->FileObject->FsContext2,
  704. Irp);
  705. UnLockFcb(irpStack->FileObject);
  706. break;
  707. }
  708. case IOCTL_PF_DELETE_LOG:
  709. {
  710. CALLTRACE(("IPFLTDRV: IOCTL_PF_DELETE_LOG\n"));
  711. //
  712. // Check the size
  713. //
  714. dwSize = sizeof(PFDELETELOG);
  715. if(inputBufferLength < dwSize)
  716. {
  717. ntStatus = STATUS_BUFFER_TOO_SMALL;
  718. break;
  719. }
  720. ntStatus = LockFcb(irpStack->FileObject);
  721. if(!NT_SUCCESS(ntStatus))
  722. {
  723. break;
  724. }
  725. ntStatus = PfDeleteLog(
  726. (PPFDELETELOG)pvIoBuffer,
  727. irpStack->FileObject->FsContext2);
  728. UnLockFcb(irpStack->FileObject);
  729. break;
  730. }
  731. case IOCTL_SET_LOG_BUFFER:
  732. {
  733. CALLTRACE(("IPFLTDRV: IOCTL_SET_LOG_BUFFER\n"));
  734. //
  735. // Check the size
  736. //
  737. dwSize = sizeof(PFSETBUFFER);
  738. if((inputBufferLength < dwSize)
  739. ||
  740. (outputBufferLength < dwSize))
  741. {
  742. ntStatus = STATUS_BUFFER_TOO_SMALL;
  743. break;
  744. }
  745. ntStatus = LockFcb(irpStack->FileObject);
  746. if(!NT_SUCCESS(ntStatus))
  747. {
  748. break;
  749. }
  750. ntStatus = PfLogSetBuffer(
  751. (PPFSETBUFFER)pvIoBuffer,
  752. irpStack->FileObject->FsContext2,
  753. Irp);
  754. UnLockFcb(irpStack->FileObject);
  755. break;
  756. }
  757. case IOCTL_PF_DELETE_BY_HANDLE:
  758. {
  759. PPAGED_FILTER_INTERFACE pPage;
  760. CALLTRACE(("IPFLTDRV: IOCTL_PF_DELETE_BY_HANDLE\n"));
  761. if(inputBufferLength < sizeof(PFDELETEBYHANDLE))
  762. {
  763. ntStatus = STATUS_BUFFER_TOO_SMALL;
  764. break;
  765. }
  766. ntStatus = LockFcb(irpStack->FileObject);
  767. if(!NT_SUCCESS(ntStatus))
  768. {
  769. break;
  770. }
  771. pPage = FindInterfaceOnHandle(
  772. irpStack->FileObject,
  773. ((PPFDELETEBYHANDLE)pvIoBuffer)->pvDriverContext);
  774. if(!pPage)
  775. {
  776. ntStatus = STATUS_INVALID_PARAMETER;
  777. }
  778. else
  779. {
  780. ntStatus = DeleteByHandle(
  781. (PPFFCB)irpStack->FileObject->FsContext2,
  782. pPage,
  783. &((PPFDELETEBYHANDLE)pvIoBuffer)->pvHandles[0],
  784. inputBufferLength - sizeof(PVOID));
  785. }
  786. UnLockFcb(irpStack->FileObject);
  787. break;
  788. }
  789. case IOCTL_DELETE_INTERFACE_FILTERS_EX:
  790. {
  791. PPAGED_FILTER_INTERFACE pPage;
  792. CALLTRACE(("IPFLTDRV: IOCTL_UNSET_INTERFACE_FILTERSEX\n"));
  793. //
  794. // The minimum size is without any TOCs
  795. //
  796. dwSize = sizeof(FILTER_DRIVER_SET_FILTERS) - sizeof(RTR_TOC_ENTRY);
  797. if(inputBufferLength < dwSize)
  798. {
  799. ntStatus = STATUS_BUFFER_TOO_SMALL;
  800. break;
  801. }
  802. //
  803. // Verify the sizes if individual entries in the buffer.
  804. //
  805. if (!ValidateHeader(
  806. &((PFILTER_DRIVER_SET_FILTERS)pvIoBuffer)->ribhInfoBlock,
  807. inputBufferLength -
  808. FIELD_OFFSET(FILTER_DRIVER_SET_FILTERS, ribhInfoBlock)
  809. )) {
  810. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  811. break;
  812. }
  813. ntStatus = LockFcb(irpStack->FileObject);
  814. if(!NT_SUCCESS(ntStatus))
  815. {
  816. break;
  817. }
  818. pPage = FindInterfaceOnHandle(
  819. irpStack->FileObject,
  820. ((PFILTER_DRIVER_SET_FILTERS)pvIoBuffer)->pvDriverContext);
  821. if(!pPage)
  822. {
  823. ntStatus = STATUS_INVALID_PARAMETER;
  824. }
  825. else
  826. {
  827. ntStatus = UnSetFiltersEx(
  828. (PPFFCB)irpStack->FileObject->FsContext2,
  829. pPage,
  830. inputBufferLength,
  831. (PFILTER_DRIVER_SET_FILTERS)pvIoBuffer);
  832. }
  833. UnLockFcb(irpStack->FileObject);
  834. break;
  835. }
  836. case IOCTL_SET_INTERFACE_FILTERS_EX:
  837. {
  838. PPAGED_FILTER_INTERFACE pPage;
  839. CALLTRACE(("IPFLTDRV: IOCTL_SET_INTERFACE_FILTERSEX\n"));
  840. //
  841. // The minimum size is without any TOCs
  842. //
  843. dwSize = sizeof(FILTER_DRIVER_SET_FILTERS) - sizeof(RTR_TOC_ENTRY);
  844. if(inputBufferLength < dwSize)
  845. {
  846. ntStatus = STATUS_BUFFER_TOO_SMALL;
  847. break;
  848. }
  849. //
  850. // Verify the sizes if individual entries in the buffer.
  851. //
  852. if (!ValidateHeader(
  853. &((PFILTER_DRIVER_SET_FILTERS)pvIoBuffer)->ribhInfoBlock,
  854. inputBufferLength -
  855. FIELD_OFFSET(FILTER_DRIVER_SET_FILTERS, ribhInfoBlock)
  856. )) {
  857. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  858. break;
  859. }
  860. ntStatus = LockFcb(irpStack->FileObject);
  861. if(!NT_SUCCESS(ntStatus))
  862. {
  863. break;
  864. }
  865. pPage = FindInterfaceOnHandle(
  866. irpStack->FileObject,
  867. ((PFILTER_DRIVER_SET_FILTERS)pvIoBuffer)->pvDriverContext);
  868. if(!pPage)
  869. {
  870. ntStatus = STATUS_INVALID_PARAMETER;
  871. }
  872. else
  873. {
  874. ntStatus = SetFiltersEx(
  875. (PPFFCB)irpStack->FileObject->FsContext2,
  876. pPage,
  877. inputBufferLength,
  878. (PFILTER_DRIVER_SET_FILTERS)pvIoBuffer);
  879. }
  880. UnLockFcb(irpStack->FileObject);
  881. break;
  882. }
  883. case IOCTL_DELETE_INTERFACEEX:
  884. {
  885. PFILTER_DRIVER_DELETE_INTERFACE pDel;
  886. PPAGED_FILTER_INTERFACE pPage;
  887. CALLTRACE(("IPFLTDRV: IOCTL_DELETE_INTERFACE\n"));
  888. pDel = (PFILTER_DRIVER_DELETE_INTERFACE)pvIoBuffer;
  889. dwSize = sizeof(FILTER_DRIVER_DELETE_INTERFACE);
  890. if(inputBufferLength != dwSize)
  891. {
  892. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  893. break;
  894. }
  895. ntStatus = LockFcb(irpStack->FileObject);
  896. if(!NT_SUCCESS(ntStatus))
  897. {
  898. break;
  899. }
  900. pPage = FindInterfaceOnHandle(irpStack->FileObject,
  901. pDel->pvDriverContext);
  902. if(pPage)
  903. {
  904. RemoveEntryList(&pPage->leIfLink);
  905. ntStatus = DeletePagedInterface(
  906. (PPFFCB)irpStack->FileObject->FsContext2,
  907. pPage);
  908. }
  909. else
  910. {
  911. ntStatus = STATUS_INVALID_PARAMETER;
  912. }
  913. UnLockFcb(irpStack->FileObject);
  914. break;
  915. }
  916. case IOCTL_SET_LATE_BOUND_FILTERSEX:
  917. {
  918. PFILTER_DRIVER_BINDING_INFO pBindInfo;
  919. PPAGED_FILTER_INTERFACE pPage;
  920. CALLTRACE(("FilterDriver: IOCTL_SET_LATE_BOUND_FILTERS\n"));
  921. pBindInfo = (PFILTER_DRIVER_BINDING_INFO)pvIoBuffer;
  922. dwSize = sizeof(FILTER_DRIVER_BINDING_INFO);
  923. if(inputBufferLength isnot dwSize)
  924. {
  925. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  926. break;
  927. }
  928. ntStatus = LockFcb(irpStack->FileObject);
  929. if(!NT_SUCCESS(ntStatus))
  930. {
  931. break;
  932. }
  933. pPage = FindInterfaceOnHandle(irpStack->FileObject,
  934. pBindInfo->pvDriverContext);
  935. if(pPage)
  936. {
  937. ntStatus = UpdateBindingInformationEx(pBindInfo,
  938. pPage);
  939. }
  940. else
  941. {
  942. ntStatus = STATUS_INVALID_PARAMETER;
  943. }
  944. UnLockFcb(irpStack->FileObject);
  945. break;
  946. }
  947. #endif // FWPF
  948. #if STEELHEAD
  949. case IOCTL_CREATE_INTERFACE:
  950. {
  951. //
  952. // the old style of creating an interface.
  953. // just pass it through to the underlying code
  954. //
  955. PFILTER_DRIVER_CREATE_INTERFACE pInfo;
  956. CALLTRACE(("IPFLTDRV: IOCTL_CREATE_INTERFACE\n"));
  957. dwSize = sizeof(FILTER_DRIVER_CREATE_INTERFACE);
  958. //
  959. // Both input and output Buffer lengths should be the same and
  960. //
  961. if(inputBufferLength != dwSize)
  962. {
  963. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  964. break;
  965. }
  966. if(outputBufferLength != dwSize)
  967. {
  968. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  969. break;
  970. }
  971. pInfo = (PFILTER_DRIVER_CREATE_INTERFACE)pvIoBuffer;
  972. ntStatus = AddInterface(
  973. pInfo->pvRtrMgrContext,
  974. pInfo->dwIfIndex,
  975. pInfo->dwAdapterId,
  976. irpStack->FileObject->FsContext2,
  977. &pInfo->pvDriverContext);
  978. if(NT_SUCCESS(ntStatus))
  979. {
  980. dwSize = sizeof(FILTER_DRIVER_CREATE_INTERFACE);
  981. }
  982. break;
  983. }
  984. case IOCTL_SET_INTERFACE_FILTERS:
  985. {
  986. CALLTRACE(("IPFLTDRV: IOCTL_SET_INTERFACE_FILTERS\n"));
  987. //
  988. // The minimum size is without any TOCs
  989. //
  990. dwSize = sizeof(FILTER_DRIVER_SET_FILTERS) - sizeof(RTR_TOC_ENTRY);
  991. if(inputBufferLength < dwSize)
  992. {
  993. ntStatus = STATUS_BUFFER_TOO_SMALL;
  994. break;
  995. }
  996. ntStatus = SetFilters((PFILTER_DRIVER_SET_FILTERS)pvIoBuffer);
  997. break;
  998. }
  999. case IOCTL_SET_LATE_BOUND_FILTERS:
  1000. {
  1001. PFILTER_DRIVER_BINDING_INFO pBindInfo;
  1002. CALLTRACE(("IPFLTDRV: IOCTL_SET_LATE_BOUND_FILTERS\n"));
  1003. pBindInfo = (PFILTER_DRIVER_BINDING_INFO)pvIoBuffer;
  1004. dwSize = sizeof(FILTER_DRIVER_BINDING_INFO);
  1005. if(inputBufferLength isnot dwSize)
  1006. {
  1007. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  1008. break;
  1009. }
  1010. ntStatus = UpdateBindingInformation(pBindInfo,
  1011. pBindInfo->pvDriverContext);
  1012. break;
  1013. }
  1014. case IOCTL_DELETE_INTERFACE:
  1015. {
  1016. PFILTER_DRIVER_DELETE_INTERFACE pDel;
  1017. CALLTRACE(("IPFLTDRV: IOCTL_DELETE_INTERFACE\n"));
  1018. pDel = (PFILTER_DRIVER_DELETE_INTERFACE)pvIoBuffer;
  1019. dwSize = sizeof(FILTER_DRIVER_DELETE_INTERFACE);
  1020. if(inputBufferLength isnot dwSize)
  1021. {
  1022. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  1023. break;
  1024. }
  1025. ntStatus = DeleteInterface(pDel->pvDriverContext);
  1026. break;
  1027. }
  1028. #endif // STEELHEAD
  1029. case IOCTL_TEST_PACKET:
  1030. {
  1031. PFILTER_DRIVER_TEST_PACKET pPacketInfo;
  1032. PPAGED_FILTER_INTERFACE pInPage, pOutPage;
  1033. FORWARD_ACTION eaResult;
  1034. UNALIGNED IPHeader *pHeader;
  1035. DWORD dwSizeOfHeader;
  1036. PBYTE pbRest;
  1037. DWORD dwSizeOfData;
  1038. CALLTRACE(("IPFLTDRV IOCTL_TEST_PACKET\n"));
  1039. pPacketInfo = (PFILTER_DRIVER_TEST_PACKET)pvIoBuffer;
  1040. dwSize = FIELD_OFFSET(FILTER_DRIVER_TEST_PACKET,
  1041. bIpPacket[0]);
  1042. if(inputBufferLength < dwSize)
  1043. {
  1044. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1045. break;
  1046. }
  1047. if(outputBufferLength < dwSize)
  1048. {
  1049. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1050. break;
  1051. }
  1052. pHeader = (IPHeader*)(pPacketInfo->bIpPacket);
  1053. dwSizeOfHeader = ((pHeader->iph_verlen)&0x0f)<<2;
  1054. pbRest = (PBYTE)pHeader + dwSizeOfHeader;
  1055. //
  1056. // make sure the header fits
  1057. //
  1058. dwSizeOfData = inputBufferLength - dwSize;
  1059. if(dwSizeOfData < dwSizeOfHeader)
  1060. {
  1061. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1062. break;
  1063. }
  1064. //
  1065. // it does. Make sure the data fits
  1066. //
  1067. if(dwSizeOfData < RtlUshortByteSwap(pHeader->iph_length))
  1068. {
  1069. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1070. break;
  1071. }
  1072. dwSizeOfData -= dwSizeOfHeader;
  1073. //
  1074. // Find the paged interface corresponding to the
  1075. // context
  1076. //
  1077. ntStatus = LockFcb(irpStack->FileObject);
  1078. if(!NT_SUCCESS(ntStatus))
  1079. {
  1080. break;
  1081. }
  1082. pInPage = FindInterfaceOnHandle(
  1083. irpStack->FileObject,
  1084. pPacketInfo->pvInInterfaceContext
  1085. );
  1086. pOutPage = FindInterfaceOnHandle(
  1087. irpStack->FileObject,
  1088. pPacketInfo->pvOutInterfaceContext
  1089. );
  1090. //
  1091. // pInPage and pOutPage can be NULL
  1092. //
  1093. eaResult = MatchFilterp(
  1094. pHeader,
  1095. pbRest,
  1096. dwSizeOfData,
  1097. INVALID_IF_INDEX,
  1098. INVALID_IF_INDEX,
  1099. NULL_IP_ADDR,
  1100. NULL_IP_ADDR,
  1101. pInPage ? pInPage->pFilter : NULL,
  1102. pOutPage ? pOutPage->pFilter : NULL,
  1103. FALSE,
  1104. TRUE
  1105. );
  1106. UnLockFcb(irpStack->FileObject);
  1107. ntStatus = STATUS_SUCCESS;
  1108. pPacketInfo->eaResult = eaResult;
  1109. //
  1110. // We dont need to copy the full packet out
  1111. //
  1112. dwSize = sizeof(FILTER_DRIVER_TEST_PACKET);
  1113. break;
  1114. }
  1115. case IOCTL_PF_SET_EXTENSION_POINTER:
  1116. {
  1117. PPF_SET_EXTENSION_HOOK_INFO ExtensionInfo;
  1118. TRACE(CONFIG,(
  1119. "ipfltdrv: IOCTL_PF_SET_EXTENSION_POINTER Called, inputLength=%d\n",
  1120. inputBufferLength
  1121. ));
  1122. if (Irp->RequestorMode != KernelMode)
  1123. {
  1124. ntStatus = STATUS_ACCESS_DENIED;
  1125. break;
  1126. }
  1127. ExtensionInfo = (PPF_SET_EXTENSION_HOOK_INFO)pvIoBuffer;
  1128. if (inputBufferLength < sizeof(PF_SET_EXTENSION_HOOK_INFO))
  1129. {
  1130. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1131. break;
  1132. }
  1133. ntStatus = SetExtensionPointer(
  1134. ExtensionInfo,
  1135. irpStack->FileObject
  1136. );
  1137. break;
  1138. }
  1139. #if STEELHEAD
  1140. case IOCTL_GET_FILTER_INFO:
  1141. {
  1142. PFILTER_DRIVER_GET_FILTERS pInfo;
  1143. PFILTER_INTERFACE pIf;
  1144. LOCK_STATS LockState;
  1145. CALLTRACE(("IPFLTDRV: IOCTL_GET_FILTER_INFO\n"));
  1146. pInfo = (PFILTER_DRIVER_GET_FILTERS)pvIoBuffer;
  1147. pIf = (PFILTER_INTERFACE)(pInfo->pvDriverContext);
  1148. //
  1149. // If we cant even report the number of filters, lets get out
  1150. //
  1151. if(inputBufferLength < (sizeof(FILTER_DRIVER_GET_FILTERS) - sizeof(FILTER_STATS)))
  1152. {
  1153. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1154. break;
  1155. }
  1156. if(outputBufferLength < (sizeof(FILTER_DRIVER_GET_FILTERS) - sizeof(FILTER_STATS)))
  1157. {
  1158. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1159. break;
  1160. }
  1161. //
  1162. // Ok we have enough space to plug in the number of filters
  1163. //
  1164. AcquireReadLock(&g_filters.ifListLock,&LockState);
  1165. pInfo->interfaces.eaInAction = pIf->eaInAction;
  1166. pInfo->interfaces.eaOutAction = pIf->eaOutAction;
  1167. pInfo->interfaces.dwNumInFilters = pIf->dwNumInFilters;
  1168. pInfo->interfaces.dwNumOutFilters = pIf->dwNumOutFilters;
  1169. dwSize = SIZEOF_FILTERS(pIf);
  1170. if(inputBufferLength < dwSize)
  1171. {
  1172. dwSize = sizeof(FILTER_DRIVER_GET_FILTERS) - sizeof(FILTER_STATS);
  1173. ntStatus = STATUS_SUCCESS;
  1174. ReleaseReadLock(&g_filters.ifListLock,&LockState);
  1175. break;
  1176. }
  1177. if(outputBufferLength < dwSize)
  1178. {
  1179. dwSize = sizeof(FILTER_DRIVER_GET_FILTERS) - sizeof(FILTER_STATS);
  1180. ntStatus = STATUS_SUCCESS;
  1181. ReleaseReadLock(&g_filters.ifListLock,&LockState);
  1182. break;
  1183. }
  1184. ntStatus = GetFilters(pIf,
  1185. FALSE,
  1186. &(pInfo->interfaces));
  1187. pInfo->dwDefaultHitsIn = g_dwNumHitsDefaultIn;
  1188. pInfo->dwDefaultHitsOut = g_dwNumHitsDefaultOut;
  1189. ReleaseReadLock(&g_filters.ifListLock,kIrql);
  1190. break;
  1191. }
  1192. #endif
  1193. case IOCTL_GET_FILTER_TIMES:
  1194. {
  1195. PFILTER_DRIVER_GET_TIMES pInfo;
  1196. PFILTER_INTERFACE pIf;
  1197. KIRQL kIrql;
  1198. CALLTRACE(("IPFLTDRV: IOCTL_GET_FILTER_TIMES\n"));
  1199. dwSize = sizeof(FILTER_DRIVER_GET_TIMES);
  1200. if(outputBufferLength < sizeof(FILTER_DRIVER_GET_TIMES))
  1201. {
  1202. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1203. break;
  1204. }
  1205. pInfo = (PFILTER_DRIVER_GET_TIMES)pvIoBuffer;
  1206. #ifdef DRIVER_PERF
  1207. pInfo->dwFragments = g_dwFragments;
  1208. pInfo->dwCache1 = g_dwCache1;
  1209. pInfo->dwCache2 = g_dwCache2;
  1210. pInfo->dwNumPackets = g_dwNumPackets;
  1211. pInfo->dwWalk1 = g_dwWalk1;
  1212. pInfo->dwWalk2 = g_dwWalk2;
  1213. pInfo->dwForw = g_dwForw;
  1214. pInfo->dwWalkCache = g_dwWalkCache;
  1215. pInfo->liTotalTime.HighPart = g_liTotalTime.HighPart;
  1216. pInfo->liTotalTime.LowPart = g_liTotalTime.LowPart;
  1217. #else
  1218. pInfo->dwFragments = 0;
  1219. pInfo->dwCache1 = 0;
  1220. pInfo->dwCache2 = 0;
  1221. pInfo->dwNumPackets = 0;
  1222. pInfo->dwWalk1 = 0;
  1223. pInfo->dwWalk2 = 0;
  1224. pInfo->dwForw = 0;
  1225. pInfo->dwWalkCache = 0;
  1226. pInfo->liTotalTime.HighPart = 0;
  1227. pInfo->liTotalTime.LowPart = 0;
  1228. #endif
  1229. ntStatus = STATUS_SUCCESS;
  1230. break;
  1231. }
  1232. default:
  1233. {
  1234. ERROR(("IPFLTDRV: unknown IOCTL\n"));
  1235. ntStatus = STATUS_INVALID_PARAMETER;
  1236. break;
  1237. }
  1238. }
  1239. break;
  1240. }
  1241. default:
  1242. {
  1243. ERROR(("IPFLTDRV:: unknown IRP_MJ_XXX\n"));
  1244. ntStatus = STATUS_INVALID_PARAMETER;
  1245. break;
  1246. }
  1247. }
  1248. if(ntStatus != STATUS_PENDING)
  1249. {
  1250. Irp->IoStatus.Status = ntStatus;
  1251. Irp->IoStatus.Information = dwSize;
  1252. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1253. }
  1254. return(ntStatus);
  1255. }
  1256. VOID
  1257. FilterDriverUnload(
  1258. IN PDRIVER_OBJECT DriverObject
  1259. )
  1260. /*++
  1261. Routine Description
  1262. Called when the driver is unloaded. This shuts down the filtering (if it hasnt been shut
  1263. down already) and removes the DOS name
  1264. Arguments
  1265. DriverObject
  1266. Return Value
  1267. None
  1268. --*/
  1269. {
  1270. CALLTRACE(("IPFLTDRV: FilterDriverUnload\n"));
  1271. CloseFilterDriver();
  1272. TearDownExternalNaming();
  1273. IoDeleteDevice(DriverObject->DeviceObject);
  1274. }
  1275. VOID
  1276. SetupExternalNaming (
  1277. IN PUNICODE_STRING ntname
  1278. )
  1279. /*++
  1280. Routine Description
  1281. Inserts the input name as the DOS name
  1282. Arguments
  1283. ntname - Name of driver
  1284. Return Value
  1285. None
  1286. --*/
  1287. {
  1288. UNICODE_STRING ObjectDirectory;
  1289. UNICODE_STRING SymbolicLinkName;
  1290. UNICODE_STRING fullLinkName;
  1291. BYTE buffer[100] ;
  1292. //
  1293. // Form the full symbolic link name we wish to create.
  1294. //
  1295. RtlInitUnicodeString (&fullLinkName, NULL);
  1296. RtlInitUnicodeString (&ObjectDirectory, DEFAULT_DIRECTORY);
  1297. RtlInitUnicodeString(&SymbolicLinkName, DEFAULT_FLTRDRVR_NAME);
  1298. fullLinkName.MaximumLength = (sizeof(L"\\")*2) + ObjectDirectory.Length
  1299. + SymbolicLinkName.Length + sizeof(WCHAR);
  1300. fullLinkName.Buffer = (WCHAR *)buffer ;
  1301. RtlZeroMemory (fullLinkName.Buffer, fullLinkName.MaximumLength);
  1302. RtlAppendUnicodeToString (&fullLinkName, L"\\");
  1303. RtlAppendUnicodeStringToString (&fullLinkName, &ObjectDirectory);
  1304. RtlAppendUnicodeToString (&fullLinkName, L"\\");
  1305. RtlAppendUnicodeStringToString (&fullLinkName, &SymbolicLinkName);
  1306. if (!NT_SUCCESS(IoCreateSymbolicLink (&fullLinkName, ntname)))
  1307. {
  1308. ERROR((
  1309. "IPFLTDRV: ERROR win32 device name could not be created \n"
  1310. ));
  1311. }
  1312. }
  1313. VOID
  1314. TearDownExternalNaming()
  1315. /*++
  1316. Routine Description
  1317. Removes the DOS name from the registry
  1318. Called when the driver is unloaded
  1319. Arguments
  1320. None
  1321. Return Value
  1322. None
  1323. --*/
  1324. {
  1325. UNICODE_STRING ObjectDirectory;
  1326. UNICODE_STRING SymbolicLinkName;
  1327. UNICODE_STRING fullLinkName;
  1328. BYTE buffer[100] ;
  1329. RtlInitUnicodeString (&fullLinkName, NULL);
  1330. RtlInitUnicodeString (&ObjectDirectory, DEFAULT_DIRECTORY);
  1331. RtlInitUnicodeString(&SymbolicLinkName, DEFAULT_FLTRDRVR_NAME);
  1332. fullLinkName.MaximumLength = (sizeof(L"\\")*2) + ObjectDirectory.Length
  1333. + SymbolicLinkName.Length + sizeof(WCHAR);
  1334. fullLinkName.Buffer = (WCHAR *)buffer ;
  1335. RtlZeroMemory (fullLinkName.Buffer, fullLinkName.MaximumLength);
  1336. RtlAppendUnicodeToString (&fullLinkName, L"\\");
  1337. RtlAppendUnicodeStringToString (&fullLinkName, &ObjectDirectory);
  1338. RtlAppendUnicodeToString (&fullLinkName, L"\\");
  1339. RtlAppendUnicodeStringToString (&fullLinkName, &SymbolicLinkName);
  1340. if (!NT_SUCCESS(IoDeleteSymbolicLink (&fullLinkName)))
  1341. {
  1342. ERROR((
  1343. "IPFLTDRV: ERROR win32 device name could not be deleted\n"
  1344. ));
  1345. }
  1346. }
  1347. BOOL
  1348. InitFilterDriver()
  1349. /*++
  1350. Routine Description
  1351. Starts the driver. Allocates memory for the cache and cache entries. Clears the entries
  1352. Sends an IOCTL to the Forwarder to set up its entry point (which starts the filtering
  1353. process in the forwarder)
  1354. Arguments
  1355. None
  1356. Return Value
  1357. TRUE if successful
  1358. --*/
  1359. {
  1360. NTSTATUS status;
  1361. BOOL bRet;
  1362. SYSTEM_BASIC_INFORMATION PerfInfo;
  1363. status = ZwQuerySystemInformation(
  1364. SystemBasicInformation,
  1365. &PerfInfo,
  1366. sizeof(PerfInfo),
  1367. NULL
  1368. );
  1369. //
  1370. // adjust cache and hash sizes based on the memory
  1371. //
  1372. if(PerfInfo.NumberOfPhysicalPages <= 8000)
  1373. {
  1374. //
  1375. // 32 MB or smaller. A very chincy server
  1376. //
  1377. g_dwCacheSize = 257;
  1378. g_dwHashLists = 127;
  1379. }
  1380. else if(PerfInfo.NumberOfPhysicalPages < 16000)
  1381. {
  1382. //
  1383. // 32-64 MB. Better.
  1384. //
  1385. g_dwCacheSize = 311;
  1386. g_dwHashLists = 311;
  1387. }
  1388. else if(PerfInfo.NumberOfPhysicalPages < 32000)
  1389. {
  1390. //
  1391. // 64 - 128 MB.
  1392. //
  1393. g_dwCacheSize = 511;
  1394. g_dwHashLists = 511;
  1395. }
  1396. else
  1397. {
  1398. //
  1399. // big machine
  1400. //
  1401. g_dwCacheSize = 511;
  1402. g_dwHashLists = 1023;
  1403. }
  1404. InitLogs();
  1405. __try
  1406. {
  1407. bRet = TRUE;
  1408. if(!AllocateCacheStructures())
  1409. {
  1410. ERROR(("IPFLTDRV: Couldnt allocate cache structures\n"));
  1411. bRet = FALSE;
  1412. __leave;
  1413. }
  1414. //
  1415. // Clean the cache
  1416. //
  1417. ClearCache();
  1418. //
  1419. // Now send and Irp to IP Forwarder and give him our entry point
  1420. // Do it twice, once to make sure it is cleared and to
  1421. // erase any previous filter contexts and once to do what
  1422. // we want it to do.
  1423. //
  1424. status = SetForwarderEntryPoint(NULL);
  1425. status = SetForwarderEntryPoint(MatchFilter);
  1426. if(status isnot STATUS_SUCCESS)
  1427. {
  1428. ERROR((
  1429. "IPFLTDRV: IOCTL to IP Forwarder failed - status \n",
  1430. status
  1431. ));
  1432. bRet = FALSE;
  1433. __leave;
  1434. }
  1435. }
  1436. __finally
  1437. {
  1438. LARGE_INTEGER liDueTime;
  1439. if(!bRet)
  1440. {
  1441. FreeExistingCache();
  1442. }
  1443. else
  1444. {
  1445. ExInitializeNPagedLookasideList(
  1446. &filter_slist,
  1447. ExAllocatePoolWithTag,
  1448. ExFreePool,
  1449. 0,
  1450. sizeof(FILTER),
  1451. (ULONG)'2liF',
  1452. 100);
  1453. ExInitializePagedLookasideList(
  1454. &paged_slist,
  1455. ExAllocatePoolWithTag,
  1456. ExFreePool,
  1457. 0,
  1458. sizeof(PAGED_FILTER),
  1459. (ULONG)'2liF',
  1460. 100);
  1461. ExInitializeNPagedLookasideList(
  1462. &g_llFragCacheBlocks,
  1463. NULL,
  1464. NULL,
  1465. 0,
  1466. sizeof(FRAG_INFO),
  1467. 'ftlF',
  1468. 32);
  1469. //
  1470. // Set the timer for fragment cache.
  1471. //
  1472. KeInitializeDpc(
  1473. &g_kdTimerDpc,
  1474. FragCacheTimerRoutine,
  1475. NULL);
  1476. KeInitializeTimer(&g_ktTimer);
  1477. liDueTime.QuadPart = (ULONGLONG)TIMER_IN_MILLISECS * (ULONGLONG)SYS_UNITS_IN_ONE_MILLISEC;
  1478. liDueTime.QuadPart = -liDueTime.QuadPart;
  1479. KeSetTimerEx(
  1480. &g_ktTimer,
  1481. liDueTime,
  1482. TIMER_IN_MILLISECS,
  1483. &g_kdTimerDpc);
  1484. }
  1485. }
  1486. return bRet;
  1487. }
  1488. BOOL
  1489. CloseFilterDriver()
  1490. /*++
  1491. Routine Description
  1492. Shuts down the driver.
  1493. Arguments
  1494. Return Value
  1495. --*/
  1496. {
  1497. NTSTATUS status;
  1498. LOCK_STATE LockState;
  1499. PLIST_ENTRY pleHead;
  1500. BOOL bStopForw = TRUE;
  1501. PFREEFILTER pFree, pFree1;
  1502. PPFFCB Fcb;
  1503. //
  1504. // The first thing to do is send an IOCTL to forwarder to tell him to stop sending
  1505. // us anymore packets.
  1506. //
  1507. status = SetForwarderEntryPoint(NULL);
  1508. if(!NT_SUCCESS(status))
  1509. {
  1510. //
  1511. // This means we could not tell IP Forwarder
  1512. // to stop filtering packets so we cant go away.
  1513. //
  1514. ERROR((
  1515. "IPFLTDRV: CloseFilterDriver - SetForwardEntryPoint() was UNSUCCESSFUL, Error-0x%08x\n",
  1516. status
  1517. ));
  1518. bStopForw = FALSE;
  1519. }
  1520. //
  1521. // remove the FCBS
  1522. //
  1523. while(TRUE)
  1524. {
  1525. NTSTATUS ntStatus;
  1526. FILE_OBJECT fo;
  1527. KIRQL kirql;
  1528. BOOL fDone = TRUE;
  1529. KeAcquireSpinLock(&g_FcbSpin, &kirql);
  1530. for(pleHead = g_leFcbs.Flink;
  1531. pleHead != &g_leFcbs;
  1532. pleHead = pleHead->Flink)
  1533. {
  1534. Fcb = CONTAINING_RECORD(pleHead, PFFCB, leList);
  1535. //
  1536. // This can happen if some other thread is closing the FCB.
  1537. //
  1538. if(Fcb->dwFlags & PF_FCB_CLOSED)
  1539. {
  1540. continue;
  1541. }
  1542. KeReleaseSpinLock(&g_FcbSpin, kirql);
  1543. fDone = FALSE;
  1544. fo.FsContext2 = (PVOID)Fcb;
  1545. ntStatus = LockFcb(&fo);
  1546. if(!NT_SUCCESS(ntStatus))
  1547. {
  1548. break;
  1549. }
  1550. FcbLockDown(Fcb);
  1551. UnLockFcb(&fo);
  1552. break;
  1553. }
  1554. if(fDone)
  1555. {
  1556. KeReleaseSpinLock(&g_FcbSpin, kirql);
  1557. break;
  1558. }
  1559. }
  1560. ExDeleteResourceLite ( &FilterListResourceLock );
  1561. ExDeleteResourceLite ( &FilterAddressLock );
  1562. AcquireWriteLock(&(g_filters.ifListLock),&LockState);
  1563. while(!IsListEmpty(&g_filters.leIfListHead))
  1564. {
  1565. PFILTER_INTERFACE pIf;
  1566. pleHead = g_filters.leIfListHead.Flink;
  1567. pIf = CONTAINING_RECORD(pleHead,FILTER_INTERFACE,leIfLink);
  1568. DeleteFilters(pIf,
  1569. IN_FILTER_SET);
  1570. DeleteFilters(pIf,
  1571. OUT_FILTER_SET);
  1572. //
  1573. // Set the number of filters to 0 and the default action to forward so
  1574. // that if we havent been able to stop the forwarder from calling us,
  1575. // atleast no packets get filtered
  1576. //
  1577. pIf->dwNumInFilters = 0;
  1578. pIf->dwNumOutFilters = 0;
  1579. pIf->eaInAction = FORWARD;
  1580. pIf->eaOutAction = FORWARD;
  1581. if(bStopForw)
  1582. {
  1583. //
  1584. // We could stop the forwarder so lets blow away the interface
  1585. //
  1586. RemoveHeadList(&g_filters.leIfListHead);
  1587. ExFreePool(pIf);
  1588. }
  1589. }
  1590. ClearCache();
  1591. if(bStopForw)
  1592. {
  1593. //
  1594. // If we could stop the forwarder, blow away the cache
  1595. //
  1596. FreeExistingCache();
  1597. }
  1598. ReleaseWriteLock(&g_filters.ifListLock,&LockState);
  1599. if(g_bDriverRunning)
  1600. {
  1601. //
  1602. // Fragment cache related cleanup.
  1603. // remove the timer
  1604. //
  1605. if(KeCancelTimer(&g_ktTimer) is FALSE)
  1606. {
  1607. //
  1608. // Tmer was not in the system queue. Maybe we should sleep
  1609. // or something
  1610. //
  1611. ERROR(("IPFLTDRV: Timer NOT in system queue\n"));
  1612. DbgBreakPoint();
  1613. }
  1614. ExDeleteNPagedLookasideList( &filter_slist );
  1615. ExDeletePagedLookasideList( &paged_slist );
  1616. ExDeleteNPagedLookasideList(&g_llFragCacheBlocks);
  1617. }
  1618. if(AddrTable)
  1619. {
  1620. ExFreePool(AddrTable);
  1621. AddrTable = 0;
  1622. }
  1623. if(AddrHashTable)
  1624. {
  1625. ExFreePool(AddrHashTable);
  1626. AddrHashTable = 0;
  1627. }
  1628. if(AddrSubnetHashTable)
  1629. {
  1630. ExFreePool(AddrSubnetHashTable);
  1631. AddrSubnetHashTable = 0;
  1632. }
  1633. if (g_pleFragTable)
  1634. {
  1635. ExFreePool(g_pleFragTable);
  1636. g_pleFragTable = 0;
  1637. }
  1638. if(g_filters.pInterfaceCache)
  1639. {
  1640. ExFreePool(g_filters.pInterfaceCache);
  1641. g_filters.pInterfaceCache = NULL;
  1642. }
  1643. TRACE(CONFIG,(
  1644. "IPFLTDRV: BoundInterfaceCnt=%d\n",
  1645. g_ulBoundInterfaceCount
  1646. ));
  1647. if(bStopForw)
  1648. {
  1649. CALLTRACE(("IPFLTDRV: CloseFilterDriver - returning SUCCESS\n"));
  1650. return STATUS_SUCCESS;
  1651. }
  1652. else
  1653. {
  1654. ERROR(("CloseFilterDriver - returning UNSUCCESSFUL\n"));
  1655. return STATUS_UNSUCCESSFUL;
  1656. }
  1657. }
  1658. NTSTATUS
  1659. SetForwarderEntryPoint(
  1660. IN IPPacketFilterPtr pfnMatch
  1661. )
  1662. /*++
  1663. Routine Description
  1664. Sets the entry point to IP Forwarder. Used to start and stop the forwarding code in
  1665. the forwarder
  1666. Arguments
  1667. pfnMatch Pointer to the function that implements the filter matching code
  1668. NULL will stop forwarding, while any other value will cause the forwarder to
  1669. invoke the function pointed to. Thus if on stopping, the IOCTL to the
  1670. forwarder doesnt succeed, and the filter driver goes away, the system will
  1671. blue screen
  1672. Return Value
  1673. NTSTATUS
  1674. --*/
  1675. {
  1676. NTSTATUS status;
  1677. IP_SET_FILTER_HOOK_INFO functionInfo;
  1678. functionInfo.FilterPtr = pfnMatch;
  1679. status = DoIpIoctl(
  1680. DD_IP_DEVICE_NAME,
  1681. IOCTL_IP_SET_FILTER_POINTER,
  1682. (PVOID)&functionInfo,
  1683. sizeof(functionInfo),
  1684. NULL,
  1685. 0,
  1686. NULL);
  1687. return(status);
  1688. }
  1689. NTSTATUS
  1690. DoIpIoctl(
  1691. IN PWCHAR DriverName,
  1692. IN DWORD Ioctl,
  1693. IN PVOID pvInArg,
  1694. IN DWORD dwInSize,
  1695. IN PVOID pvOutArg,
  1696. IN DWORD dwOutSize,
  1697. OUT PDWORD pdwInfo OPTIONAL)
  1698. /*++
  1699. Routine Description:
  1700. Do an IOCTL to the stack. Used for a varity of purposes
  1701. --*/
  1702. {
  1703. NTSTATUS status;
  1704. UNICODE_STRING nameString;
  1705. OBJECT_ATTRIBUTES Atts;
  1706. IO_STATUS_BLOCK ioStatusBlock;
  1707. HANDLE Handle;
  1708. PAGED_CODE();
  1709. RtlInitUnicodeString(&nameString, DriverName);
  1710. InitializeObjectAttributes(&Atts,
  1711. &nameString,
  1712. OBJ_CASE_INSENSITIVE,
  1713. NULL,
  1714. NULL);
  1715. status = ZwCreateFile(&Handle,
  1716. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  1717. &Atts,
  1718. &ioStatusBlock,
  1719. NULL,
  1720. FILE_ATTRIBUTE_NORMAL,
  1721. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1722. FILE_OPEN_IF,
  1723. 0,
  1724. NULL,
  1725. 0);
  1726. if (!NT_SUCCESS(status))
  1727. {
  1728. ERROR(("IPFLTDRV: Couldnt open IP Forwarder - status %d\n",status));
  1729. return STATUS_UNSUCCESSFUL;
  1730. }
  1731. //
  1732. // Submit the request to the forwarder
  1733. //
  1734. status = ZwDeviceIoControlFile(
  1735. Handle,
  1736. NULL,
  1737. NULL,
  1738. NULL,
  1739. &ioStatusBlock,
  1740. Ioctl,
  1741. pvInArg,
  1742. dwInSize,
  1743. pvOutArg,
  1744. dwOutSize);
  1745. if(!NT_SUCCESS(status))
  1746. {
  1747. ERROR((
  1748. "IPFLTDRV: DoIpIoctl: IOCTL request failed - status %x\n",
  1749. status
  1750. ));
  1751. }
  1752. else
  1753. {
  1754. if(pdwInfo)
  1755. {
  1756. *pdwInfo = (DWORD)ioStatusBlock.Information;
  1757. }
  1758. }
  1759. //
  1760. // Close the device.
  1761. //
  1762. ZwClose(Handle);
  1763. return status;
  1764. }
  1765. BOOL
  1766. AllocateCacheStructures()
  1767. /*++
  1768. Routine Description
  1769. Allocates the necessary memory for cache (which is an array of pointers to
  1770. cache entries)
  1771. Allocates necessary number of cache entries (but doesnt initialize them)
  1772. Allocates a small number of entries and puts them on the free list (doesnt
  1773. initialize these either)
  1774. Arguments
  1775. None
  1776. Return Value
  1777. True if the function completely succeeds, else FALSE. If FALSE, it is upto
  1778. the CALLER to do a rollback and clear any allocated memory
  1779. --*/
  1780. {
  1781. DWORD i;
  1782. KIRQL kiCurrIrql;
  1783. CALLTRACE(("IPFLTDRV: AllocateCacheStructures\n"));
  1784. g_filters.ppInCache = ExAllocatePoolWithTag(NonPagedPool,
  1785. g_dwCacheSize * sizeof(PFILTER_INCACHE),
  1786. 'hCnI');
  1787. if(g_filters.ppInCache is NULL)
  1788. {
  1789. ERROR(("IPFLTDRV: Couldnt allocate memory for Input Cache\n"));
  1790. return FALSE;
  1791. }
  1792. g_filters.ppOutCache = ExAllocatePoolWithTag(NonPagedPool,
  1793. g_dwCacheSize * sizeof(PFILTER_OUTCACHE),
  1794. 'CtuO');
  1795. if(g_filters.ppOutCache is NULL)
  1796. {
  1797. ERROR(("IPFLTDRV: Couldnt allocate memory for Output Cache\n"));
  1798. return FALSE;
  1799. }
  1800. for(i = 0; i < g_dwCacheSize; i++)
  1801. {
  1802. g_filters.ppInCache[i] = NULL;
  1803. g_filters.ppOutCache[i] = NULL;
  1804. }
  1805. for(i = 0; i < g_dwCacheSize; i++)
  1806. {
  1807. PFILTER_INCACHE pTemp1;
  1808. PFILTER_OUTCACHE pTemp2;
  1809. pTemp1 = ExAllocatePoolWithTag(NonPagedPool,
  1810. sizeof(FILTER_INCACHE),
  1811. 'NI');
  1812. if(pTemp1 is NULL)
  1813. {
  1814. return FALSE;
  1815. }
  1816. g_filters.ppInCache[i] = pTemp1;
  1817. pTemp2 = ExAllocatePoolWithTag(NonPagedPool,
  1818. sizeof(FILTER_OUTCACHE),
  1819. 'TUO');
  1820. if(pTemp2 is NULL)
  1821. {
  1822. return FALSE;
  1823. }
  1824. g_filters.ppOutCache[i] = pTemp2;
  1825. }
  1826. TRACE(CACHE,("IPFLTDRV: Allocated cache structures\n"));
  1827. TRACE(CACHE,("IPFLTDRV: Creating in and out free list..."));
  1828. for(i = 0; i < FREE_LIST_SIZE; i++)
  1829. {
  1830. PFILTER_INCACHE pTemp1;
  1831. PFILTER_OUTCACHE pTemp2;
  1832. pTemp1 = ExAllocatePoolWithTag(NonPagedPool,
  1833. sizeof(FILTER_INCACHE),
  1834. 'FNI');
  1835. if(pTemp1 is NULL)
  1836. {
  1837. return FALSE;
  1838. }
  1839. InitializeListHead(&pTemp1->leFreeLink);
  1840. InsertHeadList(&g_freeInFilters,&pTemp1->leFreeLink);
  1841. pTemp2 = ExAllocatePoolWithTag(NonPagedPool,
  1842. sizeof(FILTER_OUTCACHE),
  1843. 'FTUO');
  1844. if(pTemp2 is NULL)
  1845. {
  1846. return FALSE;
  1847. }
  1848. InitializeListHead(&pTemp2->leFreeLink);
  1849. InsertHeadList(&g_freeOutFilters,&pTemp2->leFreeLink);
  1850. }
  1851. KeAcquireSpinLock(
  1852. &g_kslFragLock,
  1853. &kiCurrIrql);
  1854. g_pleFragTable = ExAllocatePoolWithTag(
  1855. NonPagedPool,
  1856. g_dwFragTableSize * sizeof(LIST_ENTRY),
  1857. '2tlF');
  1858. if(!g_pleFragTable)
  1859. {
  1860. ERROR(("IPFLTDRV: Couldnt allocate frag table\n"));
  1861. KeReleaseSpinLock(
  1862. &g_kslFragLock,
  1863. kiCurrIrql);
  1864. return FALSE;
  1865. }
  1866. TRACE(FRAG,("IPFLTDRV: Initializing fragment cache\n"));
  1867. for(i = 0; i < g_dwFragTableSize; i++)
  1868. {
  1869. InitializeListHead(&(g_pleFragTable[i]));
  1870. }
  1871. KeReleaseSpinLock(
  1872. &g_kslFragLock,
  1873. kiCurrIrql);
  1874. CALLTRACE(("IPFLTDRV: AllocateCacheStructures Done\n"));
  1875. return TRUE;
  1876. }
  1877. VOID
  1878. FreeExistingCache()
  1879. /*++
  1880. Routine Description
  1881. Frees all the cache entries, free entries and cache pointer array
  1882. Arguments
  1883. None
  1884. Return Value
  1885. None
  1886. --*/
  1887. {
  1888. DWORD i;
  1889. KIRQL kiCurrIrql;
  1890. CALLTRACE(("IPFLTDRV: FreeExistingCache\n"));
  1891. if(g_filters.ppInCache isnot NULL)
  1892. {
  1893. for(i = 0; i < g_dwCacheSize; i ++)
  1894. {
  1895. if(g_filters.ppInCache[i] isnot NULL)
  1896. {
  1897. ExFreePool(g_filters.ppInCache[i]);
  1898. }
  1899. }
  1900. ExFreePool(g_filters.ppInCache);
  1901. g_filters.ppInCache = NULL;
  1902. }
  1903. TRACE(CACHE,("IPFLTDRV: Done freeing In cache\n"));
  1904. TRACE(CACHE,("IPFLTDRV: Freeing existing out cache\n"));
  1905. if(g_filters.ppOutCache isnot NULL)
  1906. {
  1907. for(i = 0; i < g_dwCacheSize; i ++)
  1908. {
  1909. if(g_filters.ppOutCache[i] isnot NULL)
  1910. {
  1911. ExFreePool(g_filters.ppOutCache[i]);
  1912. }
  1913. }
  1914. ExFreePool(g_filters.ppOutCache);
  1915. g_filters.ppOutCache = NULL;
  1916. }
  1917. TRACE(CACHE,("IPFLTDRV: Done freeing Out cache\n"));
  1918. TRACE(CACHE,("IPFLTDRV: Freeing free in filters\n"));
  1919. while(!IsListEmpty(&g_freeInFilters))
  1920. {
  1921. PFILTER_INCACHE pIn;
  1922. PLIST_ENTRY pleHead;
  1923. pleHead = RemoveHeadList(&g_freeInFilters);
  1924. pIn = CONTAINING_RECORD(pleHead,FILTER_INCACHE,leFreeLink);
  1925. ExFreePool(pIn);
  1926. }
  1927. TRACE(CACHE,("IPFLTDRV: Done freeing free in filters\n"));
  1928. TRACE(CACHE,("IPFLTDRV: Freeing free out filters\n"));
  1929. while(!IsListEmpty(&g_freeOutFilters))
  1930. {
  1931. PFILTER_OUTCACHE pOut;
  1932. PLIST_ENTRY pleHead;
  1933. pleHead = RemoveHeadList(&g_freeOutFilters);
  1934. pOut = CONTAINING_RECORD(pleHead,FILTER_OUTCACHE,leFreeLink);
  1935. ExFreePool(pOut);
  1936. }
  1937. TRACE(CACHE,("IPFLTDRV: Done freeing free out filters\n"));
  1938. TRACE(FRAG,("IPFLTDRV: Freeing fragment cache\n"));
  1939. ClearFragCache();
  1940. TRACE(CACHE,("IPFLTDRV: Done freeing fragment cache\n"));
  1941. CALLTRACE(("IPFLTDRV: FreeExistingCache Done\n"));
  1942. }
  1943. NTSTATUS
  1944. OpenNewHandle(PFILE_OBJECT FileObject)
  1945. /*++
  1946. Routine Description:
  1947. Open a new handle to the driver. Allocate FCB from the paged pool
  1948. and initialize it. If no memory available, fail. If success
  1949. store the FCB pointer into the file object.
  1950. --*/
  1951. {
  1952. PPFFCB Fcb;
  1953. KIRQL kirql;
  1954. //
  1955. // Allocate an FCB for this handle.
  1956. //
  1957. Fcb = ExAllocatePoolWithTag(NonPagedPool,
  1958. sizeof(*Fcb),
  1959. 'pfFC');
  1960. if(Fcb)
  1961. {
  1962. FileObject->FsContext2 = (PVOID)Fcb;
  1963. Fcb->dwFlags = 0;
  1964. Fcb->UseCount = 1;
  1965. InitializeListHead(&Fcb->leInterfaces);
  1966. InitializeListHead(&Fcb->leLogs);
  1967. ExInitializeResourceLite ( &Fcb->Resource );
  1968. ExAcquireSpinLock(&g_FcbSpin, &kirql);
  1969. InsertTailList(&g_leFcbs, &Fcb->leList);
  1970. ExReleaseSpinLock(&g_FcbSpin, kirql);
  1971. return(STATUS_SUCCESS);
  1972. }
  1973. return(STATUS_NO_MEMORY);
  1974. }
  1975. PPAGED_FILTER_INTERFACE
  1976. FindInterfaceOnHandle(PFILE_OBJECT FileObject,
  1977. PVOID pvValue)
  1978. /*++
  1979. Routine Description:
  1980. Find the paged interface for the call. If none found
  1981. return a NULL. Uses the caller-supplied DriverContext to
  1982. search the contexts on this handle. In general, there should
  1983. not be many such handles.
  1984. --*/
  1985. {
  1986. PPFFCB Fcb = FileObject->FsContext2;
  1987. PPAGED_FILTER_INTERFACE pPage;
  1988. PAGED_CODE();
  1989. for(pPage = (PPAGED_FILTER_INTERFACE)Fcb->leInterfaces.Flink;
  1990. (PLIST_ENTRY)pPage != &Fcb->leInterfaces;
  1991. pPage = (PPAGED_FILTER_INTERFACE)pPage->leIfLink.Flink)
  1992. {
  1993. if(pPage->pvDriverContext == pvValue)
  1994. {
  1995. return(pPage);
  1996. }
  1997. }
  1998. return(NULL);
  1999. }
  2000. NTSTATUS
  2001. CloseFcb(PPFFCB Fcb, PFILE_OBJECT FileObject)
  2002. /*++
  2003. Routine Description:
  2004. Called when an FCB has no more references. The caller must
  2005. have removed the FCB from the master list. It is immaterial whether
  2006. the CB resource is locked.
  2007. --*/
  2008. {
  2009. PPAGED_FILTER_INTERFACE pPage;
  2010. PFREEFILTER pList, pList1;
  2011. NTSTATUS ntStatus;
  2012. TRACE(CONFIG,(
  2013. "IPFLTDRV: CloseFcb, Fcb=0x%08x, FileObject=0x%08x\n", Fcb, FileObject
  2014. ));
  2015. //
  2016. // First clean up the logs
  2017. //
  2018. while(!IsListEmpty(&Fcb->leLogs))
  2019. {
  2020. PFDELETELOG DelLog;
  2021. DelLog.pfLogId = (PFLOGGER)Fcb->leLogs.Flink;
  2022. (VOID)PfDeleteLog(&DelLog, Fcb);
  2023. }
  2024. //
  2025. // Next, clean up the interfaces
  2026. //
  2027. while(!IsListEmpty(&Fcb->leInterfaces))
  2028. {
  2029. TRACE(CONFIG,("IPFLTDRV: Removing interface\n"));
  2030. pPage = (PPAGED_FILTER_INTERFACE)RemoveHeadList(&Fcb->leInterfaces);
  2031. (VOID)DeletePagedInterface(Fcb, pPage);
  2032. }
  2033. #if 0
  2034. //
  2035. // Can't do this because can't get the filter context from the stack.
  2036. //
  2037. if(Fcb->dwFlags & PF_FCB_OLD)
  2038. {
  2039. DeleteOldInterfaces(Fcb);
  2040. }
  2041. #endif
  2042. //
  2043. // Free the Fcb
  2044. //
  2045. ExDeleteResourceLite ( &Fcb->Resource );
  2046. ExFreePool(Fcb);
  2047. if(FileObject)
  2048. {
  2049. FileObject->FsContext2 = NULL;
  2050. }
  2051. return(STATUS_SUCCESS);
  2052. }
  2053. DWORD
  2054. GetIpStackIndex(IPAddr Addr, BOOL fNew)
  2055. /*++
  2056. Routine Description:
  2057. Get the stack index for the corresponding address and mask
  2058. --*/
  2059. {
  2060. DWORD dwResult;
  2061. DWORD dwInBufLen;
  2062. DWORD dwOutBufLen;
  2063. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  2064. TDIObjectID *ID;
  2065. BYTE *Context;
  2066. NTSTATUS Status;
  2067. IPSNMPInfo IPSnmpInfo;
  2068. IPAddrEntry *AddrTable1;
  2069. DWORD dwSpace, dwIpIndex;
  2070. DWORD dwFinalAddrSize;
  2071. DWORD dwFinalSize, dwX;
  2072. PADDRESSARRAY pa;
  2073. LOCK_STATE LockState;
  2074. KeEnterCriticalRegion();
  2075. ExAcquireResourceSharedLite( &FilterAddressLock, TRUE);
  2076. if(!AddrTable || fNew)
  2077. {
  2078. ExReleaseResourceLite(&FilterAddressLock );
  2079. ExAcquireResourceExclusiveLite( &FilterAddressLock, TRUE);
  2080. if(fNew && AddrTable)
  2081. {
  2082. //
  2083. // acquire the spin lock to synchronize with Match
  2084. // code running at DPC so we can "lock out"
  2085. // the table while we do the rest of this. Note
  2086. // we can't hold a spin lock while building the table
  2087. // because the calls into the IP stack hit pageable
  2088. // code
  2089. //
  2090. AcquireWriteLock(&g_IpTableLock, &LockState);
  2091. g_dwMakingNewTable = TRUE;
  2092. ReleaseWriteLock(&g_IpTableLock, &LockState);
  2093. ExFreePool( AddrTable );
  2094. AddrTable = 0;
  2095. }
  2096. }
  2097. if(!AddrTable)
  2098. {
  2099. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  2100. dwOutBufLen = sizeof(IPSNMPInfo);
  2101. ID = &(trqiInBuf.ID);
  2102. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  2103. ID->toi_entity.tei_instance = 0;
  2104. ID->toi_class = INFO_CLASS_PROTOCOL;
  2105. ID->toi_type = INFO_TYPE_PROVIDER;
  2106. ID->toi_id = IP_MIB_STATS_ID;
  2107. Context = (BYTE *) &(trqiInBuf.Context[0]);
  2108. RtlZeroMemory(Context, CONTEXT_SIZE);
  2109. Status = DoIpIoctl(
  2110. DD_TCP_DEVICE_NAME,
  2111. IOCTL_TCP_QUERY_INFORMATION_EX,
  2112. (PVOID)&trqiInBuf,
  2113. sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
  2114. (PVOID)&IPSnmpInfo,
  2115. dwOutBufLen,
  2116. NULL);
  2117. if(NT_SUCCESS(Status))
  2118. {
  2119. //
  2120. // allocate some memory to fetch the address table.
  2121. //
  2122. dwSpace = IPSnmpInfo.ipsi_numaddr + 10;
  2123. dwOutBufLen = dwSpace * sizeof(IPAddrEntry);
  2124. if(!AddrHashTable)
  2125. {
  2126. //
  2127. // the hash table size was not specified in the
  2128. // registry. Compute it based on the number of
  2129. // addresses. Try to keep the hash table less than
  2130. // half full.
  2131. //
  2132. if(!AddrModulus)
  2133. {
  2134. if(IPSnmpInfo.ipsi_numaddr < ADDRHASHLOWLEVEL)
  2135. {
  2136. AddrModulus = ADDRHASHLOW;
  2137. }
  2138. else if(IPSnmpInfo.ipsi_numaddr < ADDRHASHMEDLEVEL)
  2139. {
  2140. AddrModulus = ADDRHASHMED;
  2141. }
  2142. else
  2143. {
  2144. AddrModulus = ADDRHASHHIGH;
  2145. }
  2146. }
  2147. AddrHashTable = (PADDRESSARRAY *)ExAllocatePoolWithTag(
  2148. NonPagedPool,
  2149. AddrModulus *
  2150. sizeof(PADDRESSARRAY),
  2151. 'pfAh');
  2152. if(!AddrHashTable)
  2153. {
  2154. ERROR(("IPFLTDRV: Could not allocate AddrHashTable"));
  2155. g_dwMakingNewTable = FALSE;
  2156. ExReleaseResourceLite(&FilterAddressLock );
  2157. KeLeaveCriticalRegion();
  2158. return(UNKNOWN_IP_INDEX);
  2159. }
  2160. }
  2161. if(!AddrSubnetHashTable)
  2162. {
  2163. AddrSubnetHashTable = (PADDRESSARRAY *)ExAllocatePoolWithTag(
  2164. NonPagedPool,
  2165. AddrModulus *
  2166. sizeof(PADDRESSARRAY),
  2167. 'pfAh');
  2168. if(!AddrSubnetHashTable)
  2169. {
  2170. ERROR(("IPFLTDRV: Could not allocate AddrSubnetHashTable"));
  2171. g_dwMakingNewTable = FALSE;
  2172. ExReleaseResourceLite(&FilterAddressLock );
  2173. KeLeaveCriticalRegion();
  2174. return(UNKNOWN_IP_INDEX);
  2175. }
  2176. }
  2177. RtlZeroMemory(AddrHashTable, AddrModulus * sizeof(PADDRESSARRAY));
  2178. RtlZeroMemory(AddrSubnetHashTable,
  2179. AddrModulus * sizeof(PADDRESSARRAY));
  2180. AddrTable = (IPAddrEntry *)ExAllocatePoolWithTag(
  2181. NonPagedPool,
  2182. dwOutBufLen,
  2183. 'pfAt');
  2184. if(!AddrTable)
  2185. {
  2186. ERROR((
  2187. "IPFLTDRV: Could not allocate AddrTable of size %d\n",
  2188. dwSpace
  2189. ));
  2190. g_dwMakingNewTable = FALSE;
  2191. ExReleaseResourceLite(&FilterAddressLock );
  2192. KeLeaveCriticalRegion();
  2193. return(UNKNOWN_IP_INDEX);
  2194. }
  2195. }
  2196. else
  2197. {
  2198. ERROR((
  2199. "IPFLTDRV: GetIpStackIndex: DoIpIoctl failed, Status=%08x\n",
  2200. Status
  2201. ));
  2202. g_dwMakingNewTable = FALSE;
  2203. ExReleaseResourceLite(&FilterAddressLock );
  2204. KeLeaveCriticalRegion();
  2205. return(UNKNOWN_IP_INDEX);
  2206. }
  2207. ID->toi_type = INFO_TYPE_PROVIDER;
  2208. ID->toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
  2209. RtlZeroMemory( Context, CONTEXT_SIZE );
  2210. Status = DoIpIoctl(
  2211. DD_TCP_DEVICE_NAME,
  2212. IOCTL_TCP_QUERY_INFORMATION_EX,
  2213. (PVOID)&trqiInBuf,
  2214. dwInBufLen,
  2215. (PVOID)AddrTable,
  2216. dwOutBufLen,
  2217. &dwFinalAddrSize);
  2218. if(!NT_SUCCESS(Status))
  2219. {
  2220. ERROR(("IPFLTDRV: Reading IP addr table failed %x\n", Status));
  2221. ExFreePool(AddrTable);
  2222. AddrTable = 0;
  2223. g_dwMakingNewTable = FALSE;
  2224. ExReleaseResourceLite(&FilterAddressLock );
  2225. KeLeaveCriticalRegion();
  2226. return(UNKNOWN_IP_INDEX);
  2227. }
  2228. //
  2229. // Now to get sleazy. Convert each IPAddrEntry into an ADDRESSARRAY
  2230. // entry and hash it into the AddrHashTable. Note this depends
  2231. // on the structures having common definitions and on
  2232. // IPAddrEntry to be at least as large as ADDRESSARRAY. So be
  2233. // careful.
  2234. //
  2235. dwFinalSize = dwFinalAddrSize / sizeof(IPAddrEntry);
  2236. for(AddrTable1 = AddrTable;
  2237. dwFinalSize;
  2238. dwFinalSize--, AddrTable1++)
  2239. {
  2240. dwX = ADDRHASHX(AddrTable1->iae_addr);
  2241. pa = (PADDRESSARRAY)AddrTable1;
  2242. pa->ulSubnetBcastAddress = AddrTable1->iae_addr |
  2243. ~AddrTable1->iae_mask;
  2244. //
  2245. // Now hash it into the hash table
  2246. //
  2247. pa->pNext = AddrHashTable[dwX];
  2248. AddrHashTable[dwX] = pa;
  2249. //
  2250. // and do a hash on the subnet address as well
  2251. //
  2252. dwX = ADDRHASHX(pa->ulSubnetBcastAddress);
  2253. pa->pNextSubnet = AddrSubnetHashTable[dwX];
  2254. AddrSubnetHashTable[dwX] = pa;
  2255. }
  2256. //
  2257. // allow the DPC match code to use the table. Note
  2258. // this does not require interlocking since storing
  2259. // memory is atomic.
  2260. //
  2261. g_dwMakingNewTable = FALSE;
  2262. }
  2263. //
  2264. // search the table for the address.
  2265. //
  2266. dwIpIndex = LocalIpLook(Addr);
  2267. ExReleaseResourceLite(&FilterAddressLock );
  2268. KeLeaveCriticalRegion();
  2269. return(dwIpIndex);
  2270. }
  2271. BOOL
  2272. MatchLocalLook(DWORD Addr, DWORD dwIndex)
  2273. /*++
  2274. Routine Description:
  2275. Called from the Match code, probably at DPC level, to
  2276. check an address. If the address table is being rebuilt
  2277. just return success. See inner comment for more on this
  2278. --*/
  2279. {
  2280. BOOL fRet;
  2281. LOCK_STATE LockState;
  2282. if(!BMAddress(Addr))
  2283. {
  2284. //
  2285. // Look it up. Note that if the table is being rebuilt,
  2286. // this succeeds. This is a security hole but it is very
  2287. // small and nearly impossible to exploit effectively and
  2288. // the alternative, denying this, is even worse.
  2289. // ArnoldM 19-Sept-1997.
  2290. //
  2291. AcquireReadLock(&g_IpTableLock, &LockState);
  2292. if(AddrTable && !g_dwMakingNewTable)
  2293. {
  2294. DWORD dwLookupIndex = LocalIpLook(Addr);
  2295. //
  2296. // the address is acceptable if it belongs to
  2297. // the arriving interface or if it belongs to
  2298. // no interfaces. The latter is the route-through case.
  2299. //
  2300. if((dwIndex == dwLookupIndex)
  2301. ||
  2302. (dwLookupIndex == UNKNOWN_IP_INDEX) )
  2303. {
  2304. fRet = TRUE;
  2305. }
  2306. else
  2307. {
  2308. fRet = FALSE;
  2309. }
  2310. }
  2311. else
  2312. {
  2313. fRet = TRUE;
  2314. }
  2315. ReleaseReadLock(&g_IpTableLock, &LockState);
  2316. }
  2317. else
  2318. {
  2319. fRet = TRUE;
  2320. }
  2321. return(fRet);
  2322. }
  2323. DWORD
  2324. LocalIpLook(DWORD Addr)
  2325. /*++
  2326. Routine Description:
  2327. Called to lookup an address in the address hash tables. The caller
  2328. either must hold the g_IpTableLock read sping lock or must hold
  2329. the FilterAddressLock resource. This should never be called
  2330. while the address table is being built and holding one of
  2331. these locks insures this.
  2332. --*/
  2333. {
  2334. DWORD dwIpIndex, dwX;
  2335. PADDRESSARRAY pa;
  2336. dwX = ADDRHASHX(Addr);
  2337. for(pa = AddrHashTable[dwX]; pa; pa = pa->pNext)
  2338. {
  2339. if(pa->ulAddress == Addr)
  2340. {
  2341. dwIpIndex = pa->ulIndex;
  2342. goto alldone; // ugly but faster than a break and another test.
  2343. }
  2344. }
  2345. for(pa = AddrSubnetHashTable[dwX]; pa; pa = pa->pNextSubnet)
  2346. {
  2347. if(pa->ulSubnetBcastAddress == Addr)
  2348. {
  2349. dwIpIndex = pa->ulIndex;
  2350. goto alldone;
  2351. }
  2352. }
  2353. //
  2354. // not found. Deliver the bad news.
  2355. //
  2356. dwIpIndex = UNKNOWN_IP_INDEX;
  2357. alldone:
  2358. return(dwIpIndex);
  2359. }
  2360. BOOLEAN
  2361. PfFastIoDeviceControl (
  2362. IN struct _FILE_OBJECT *FileObject,
  2363. IN BOOLEAN Wait,
  2364. IN PVOID InputBuffer OPTIONAL,
  2365. IN ULONG InputBufferLength,
  2366. OUT PVOID OutputBuffer OPTIONAL,
  2367. IN ULONG OutputBufferLength,
  2368. IN ULONG IoControlCode,
  2369. OUT PIO_STATUS_BLOCK IoStatus,
  2370. IN struct _DEVICE_OBJECT *DeviceObject
  2371. )
  2372. {
  2373. DWORD dwSize;
  2374. PPAGED_FILTER_INTERFACE pPage;
  2375. NTSTATUS ntStatus;
  2376. BOOL fLockedFcb = FALSE;
  2377. MODE PreviousMode;
  2378. PreviousMode = ExGetPreviousMode();
  2379. try {
  2380. if (InputBufferLength) {
  2381. if (PreviousMode != KernelMode) {
  2382. ProbeForRead(InputBuffer, InputBufferLength, sizeof(UCHAR));
  2383. }
  2384. }
  2385. switch(IoControlCode)
  2386. {
  2387. default:
  2388. return(FALSE);
  2389. case IOCTL_PF_IP_ADDRESS_LOOKUP:
  2390. //
  2391. // do a dummy fetch to make it recompute.
  2392. //
  2393. if((InputBufferLength < sizeof(DWORD))
  2394. ||
  2395. (OutputBufferLength < sizeof(DWORD)) )
  2396. {
  2397. return(FALSE);
  2398. }
  2399. *(PDWORD)OutputBuffer = GetIpStackIndex(*(PDWORD)InputBuffer, TRUE);
  2400. ntStatus = STATUS_SUCCESS;
  2401. break;
  2402. case IOCTL_PF_DELETE_BY_HANDLE:
  2403. if(InputBufferLength < sizeof(PFDELETEBYHANDLE))
  2404. {
  2405. return(FALSE);
  2406. }
  2407. ntStatus = LockFcb(FileObject);
  2408. if(!NT_SUCCESS(ntStatus))
  2409. {
  2410. return(FALSE);
  2411. }
  2412. fLockedFcb = TRUE;
  2413. pPage = FindInterfaceOnHandle(
  2414. FileObject,
  2415. ((PPFDELETEBYHANDLE)InputBuffer)->pvDriverContext);
  2416. if(!pPage)
  2417. {
  2418. UnLockFcb(FileObject);
  2419. return(FALSE);
  2420. }
  2421. ntStatus = DeleteByHandle(
  2422. (PPFFCB)FileObject->FsContext2,
  2423. pPage,
  2424. &((PPFDELETEBYHANDLE)InputBuffer)->pvHandles[0],
  2425. InputBufferLength - sizeof(PVOID));
  2426. UnLockFcb(FileObject);
  2427. fLockedFcb = FALSE;
  2428. break;
  2429. case IOCTL_DELETE_INTERFACE_FILTERS_EX:
  2430. {
  2431. //
  2432. // The minimum size is without any TOCs
  2433. //
  2434. dwSize = sizeof(FILTER_DRIVER_SET_FILTERS) - sizeof(RTR_TOC_ENTRY);
  2435. if(InputBufferLength < dwSize)
  2436. {
  2437. return(FALSE);
  2438. }
  2439. ntStatus = LockFcb(FileObject);
  2440. if(!NT_SUCCESS(ntStatus))
  2441. {
  2442. return(FALSE);
  2443. }
  2444. fLockedFcb = TRUE;
  2445. pPage = FindInterfaceOnHandle(
  2446. FileObject,
  2447. ((PFILTER_DRIVER_SET_FILTERS)InputBuffer)->pvDriverContext);
  2448. if(!pPage)
  2449. {
  2450. UnLockFcb(FileObject);
  2451. return(FALSE);
  2452. }
  2453. ntStatus = UnSetFiltersEx(
  2454. (PPFFCB)FileObject->FsContext2,
  2455. pPage,
  2456. InputBufferLength,
  2457. (PFILTER_DRIVER_SET_FILTERS)InputBuffer);
  2458. UnLockFcb(FileObject);
  2459. fLockedFcb = FALSE;
  2460. break;
  2461. }
  2462. case IOCTL_GET_SYN_COUNTS:
  2463. {
  2464. if(OutputBufferLength < sizeof(FILTER_DRIVER_GET_SYN_COUNT))
  2465. {
  2466. return(FALSE);
  2467. }
  2468. ntStatus = GetSynCountTotal(
  2469. (PFILTER_DRIVER_GET_SYN_COUNT)OutputBuffer);
  2470. break;
  2471. }
  2472. case IOCTL_SET_INTERFACE_FILTERS_EX:
  2473. {
  2474. //
  2475. // Make sure the caller is using symmetric buffers. If not
  2476. // do it the slow way
  2477. //
  2478. if((InputBuffer != OutputBuffer)
  2479. ||
  2480. (InputBufferLength != OutputBufferLength))
  2481. {
  2482. return(FALSE);
  2483. }
  2484. //
  2485. // The minimum size is without any TOCs
  2486. //
  2487. dwSize = sizeof(FILTER_DRIVER_SET_FILTERS) - sizeof(RTR_TOC_ENTRY);
  2488. if(InputBufferLength < dwSize)
  2489. {
  2490. return(FALSE);
  2491. }
  2492. ntStatus = LockFcb(FileObject);
  2493. if(!NT_SUCCESS(ntStatus))
  2494. {
  2495. return(FALSE);
  2496. }
  2497. fLockedFcb = TRUE;
  2498. pPage = FindInterfaceOnHandle(
  2499. FileObject,
  2500. ((PFILTER_DRIVER_SET_FILTERS)InputBuffer)->pvDriverContext);
  2501. if(!pPage)
  2502. {
  2503. UnLockFcb(FileObject);
  2504. return(FALSE);
  2505. }
  2506. ntStatus = SetFiltersEx(
  2507. (PPFFCB)FileObject->FsContext2,
  2508. pPage,
  2509. InputBufferLength,
  2510. (PFILTER_DRIVER_SET_FILTERS)InputBuffer);
  2511. UnLockFcb(FileObject);
  2512. fLockedFcb = FALSE;
  2513. break;
  2514. }
  2515. }
  2516. IoStatus->Status = ntStatus;
  2517. IoStatus->Information = OutputBufferLength;
  2518. return(TRUE);
  2519. } except (EXCEPTION_EXECUTE_HANDLER) {
  2520. if (fLockedFcb) {
  2521. UnLockFcb(FileObject);
  2522. }
  2523. return(FALSE);
  2524. }
  2525. }
  2526. NTSTATUS
  2527. LockFcb(
  2528. IN struct _FILE_OBJECT *FileObject)
  2529. /*++
  2530. Routine Description:
  2531. Lock an FCB. Check if the FCB is on the master list and if
  2532. it is still valid. On success, returns with the FCB resource locked
  2533. and the FCB referenced.
  2534. --*/
  2535. {
  2536. PPFFCB Fcb = (PPFFCB)FileObject->FsContext2;
  2537. KIRQL kirql;
  2538. PLIST_ENTRY List;
  2539. PPFFCB Fcb1 = 0;
  2540. if ( Fcb == NULL )
  2541. return(STATUS_INVALID_PARAMETER);
  2542. KeAcquireSpinLock(&g_FcbSpin, &kirql);
  2543. for(List = g_leFcbs.Flink;
  2544. List != &g_leFcbs;
  2545. List = List->Flink)
  2546. {
  2547. Fcb1 = CONTAINING_RECORD(List, PFFCB, leList);
  2548. //
  2549. // use it if it is not being closed
  2550. //
  2551. if(Fcb1 == Fcb)
  2552. {
  2553. if( !(Fcb->dwFlags & PF_FCB_CLOSED) )
  2554. {
  2555. InterlockedIncrement(&Fcb->UseCount);
  2556. }
  2557. else
  2558. {
  2559. Fcb1 = 0;
  2560. }
  2561. break;
  2562. }
  2563. }
  2564. KeReleaseSpinLock(&g_FcbSpin, kirql);
  2565. if(Fcb != Fcb1)
  2566. {
  2567. //
  2568. // didn't find it.
  2569. //
  2570. return(STATUS_INVALID_PARAMETER);
  2571. }
  2572. //
  2573. // found it. Lock it up.
  2574. //
  2575. KeEnterCriticalRegion();
  2576. ExAcquireResourceExclusiveLite( &Fcb->Resource, TRUE );
  2577. //
  2578. // must look one more time to see if it has been closed. This can
  2579. // happen if the closer sneaked in. So we have to become the closer.
  2580. //
  2581. if(Fcb->dwFlags & PF_FCB_CLOSED)
  2582. {
  2583. //
  2584. // it was. Unlock it and return an error
  2585. //
  2586. UnLockFcb(FileObject);
  2587. return(STATUS_INVALID_PARAMETER);
  2588. }
  2589. return(STATUS_SUCCESS);
  2590. }
  2591. VOID
  2592. UnLockFcb(
  2593. IN struct _FILE_OBJECT *FileObject)
  2594. /*++
  2595. Routine Description:
  2596. Unlock and derefence an FCB. If the reference count becomes zero,
  2597. remove the FCB from the master list and close it.
  2598. --*/
  2599. {
  2600. PPFFCB Fcb = (PPFFCB)FileObject->FsContext2;
  2601. KIRQL kirql;
  2602. KeAcquireSpinLock(&g_FcbSpin, &kirql);
  2603. if(InterlockedDecrement(&Fcb->UseCount) <= 0)
  2604. {
  2605. ASSERT(Fcb->dwFlags & PF_FCB_CLOSED);
  2606. RemoveEntryList(&Fcb->leList);
  2607. KeReleaseSpinLock(&g_FcbSpin, kirql);
  2608. ExReleaseResourceLite( &Fcb->Resource );
  2609. KeLeaveCriticalRegion();
  2610. CloseFcb(Fcb, FileObject);
  2611. }
  2612. else
  2613. {
  2614. KeReleaseSpinLock(&g_FcbSpin, kirql);
  2615. ExReleaseResourceLite( &Fcb->Resource );
  2616. KeLeaveCriticalRegion();
  2617. }
  2618. }
  2619. NTSTATUS
  2620. InitFragCacheParameters(
  2621. IN PUNICODE_STRING RegistryPath
  2622. )
  2623. /*++
  2624. Routine Description
  2625. Called when the driver is loaded. It read the registry for the overrides
  2626. related to fragment cache
  2627. Arguments
  2628. RegistryPath
  2629. Return Value
  2630. NTSTATUS
  2631. --*/
  2632. {
  2633. INT i;
  2634. USHORT usRegLen;
  2635. PWCHAR pwcBuffer;
  2636. HANDLE hRegKey;
  2637. DWORD dwCheck;
  2638. NTSTATUS ntStatus;
  2639. UNICODE_STRING usParamString, usTempString;
  2640. CALLTRACE(("IPFLTDRV: InitFragCacheParams\n"));
  2641. //
  2642. // Fragment cache related intialiazation.
  2643. //
  2644. g_llInactivityTime = SECS_TO_TICKS(INACTIVITY_PERIOD);
  2645. g_dwFragTableSize = 127;
  2646. //
  2647. // Read the registry for parameters
  2648. //
  2649. usRegLen = RegistryPath->Length +
  2650. (sizeof(WCHAR) * (wcslen(L"\\Parameters") + 2));
  2651. pwcBuffer = ExAllocatePoolWithTag(NonPagedPool,
  2652. usRegLen,
  2653. '1tlF');
  2654. if(!pwcBuffer)
  2655. {
  2656. return STATUS_INSUFFICIENT_RESOURCES;
  2657. }
  2658. RtlZeroMemory(pwcBuffer, usRegLen);
  2659. usParamString.MaximumLength = usRegLen;
  2660. usParamString.Buffer = pwcBuffer;
  2661. RtlCopyUnicodeString(&usParamString, RegistryPath);
  2662. RtlInitUnicodeString(&usTempString, L"\\Parameters");
  2663. RtlAppendUnicodeStringToString(&usParamString, &usTempString);
  2664. ntStatus = OpenRegKey(&hRegKey, &usParamString);
  2665. ExFreePool(pwcBuffer);
  2666. if(NT_SUCCESS(ntStatus))
  2667. {
  2668. dwCheck = 0;
  2669. ntStatus = GetRegDWORDValue(
  2670. hRegKey,
  2671. L"FragmentLifetime",
  2672. &dwCheck);
  2673. if(NT_SUCCESS(ntStatus))
  2674. {
  2675. if(dwCheck > INACTIVITY_PERIOD)
  2676. {
  2677. g_llInactivityTime = SECS_TO_TICKS(dwCheck);
  2678. }
  2679. }
  2680. dwCheck = 0;
  2681. ntStatus = GetRegDWORDValue(hRegKey,
  2682. L"FragmentCacheSize",
  2683. &dwCheck);
  2684. if(NT_SUCCESS(ntStatus))
  2685. {
  2686. if(dwCheck > 127)
  2687. {
  2688. g_dwFragTableSize = dwCheck;
  2689. }
  2690. }
  2691. ZwClose(hRegKey);
  2692. }
  2693. TRACE(FRAG,(
  2694. "Filter:LifeTime %d.%d Cache Size %d\n",
  2695. ((PLARGE_INTEGER)&g_llInactivityTime)->HighPart,
  2696. ((PLARGE_INTEGER)&g_llInactivityTime)->LowPart,
  2697. g_dwFragTableSize
  2698. ));
  2699. KeInitializeSpinLock(&g_kslFragLock);
  2700. return(STATUS_SUCCESS);
  2701. }
  2702. VOID
  2703. PFReadRegistryParameters(PUNICODE_STRING RegistryPath)
  2704. /*++
  2705. Routine Description:
  2706. Called when the driver is loaded. Reads registry paramters
  2707. for configuring the driver
  2708. --*/
  2709. {
  2710. OBJECT_ATTRIBUTES ObjectAttributes;
  2711. HANDLE PFHandle;
  2712. HANDLE PFParHandle;
  2713. NTSTATUS Status;
  2714. UNICODE_STRING UnicodeString;
  2715. ULONG Storage[8];
  2716. PKEY_VALUE_PARTIAL_INFORMATION Value =
  2717. (PKEY_VALUE_PARTIAL_INFORMATION)Storage;
  2718. InitializeObjectAttributes(
  2719. &ObjectAttributes,
  2720. RegistryPath, // name
  2721. OBJ_CASE_INSENSITIVE, // attributes
  2722. NULL, // root
  2723. NULL // security descriptor
  2724. );
  2725. Status = ZwOpenKey (&PFHandle, KEY_READ, &ObjectAttributes);
  2726. RtlInitUnicodeString(&UnicodeString, L"Parameters");
  2727. if(NT_SUCCESS(Status))
  2728. {
  2729. InitializeObjectAttributes(
  2730. &ObjectAttributes,
  2731. &UnicodeString,
  2732. OBJ_CASE_INSENSITIVE,
  2733. PFHandle,
  2734. NULL
  2735. );
  2736. Status = ZwOpenKey (&PFParHandle, KEY_READ, &ObjectAttributes);
  2737. ZwClose(PFHandle);
  2738. if(NT_SUCCESS(Status))
  2739. {
  2740. ULONG BytesRead;
  2741. RtlInitUnicodeString(&UnicodeString, L"AddressHashSize");
  2742. Status = ZwQueryValueKey(
  2743. PFParHandle,
  2744. &UnicodeString,
  2745. KeyValuePartialInformation,
  2746. Value,
  2747. sizeof(Storage),
  2748. &BytesRead);
  2749. if(NT_SUCCESS(Status)
  2750. &&
  2751. (Value->Type == REG_DWORD) )
  2752. {
  2753. AddrModulus = *(PULONG)Value->Data;
  2754. }
  2755. RtlInitUnicodeString(&UnicodeString, L"FragmentThreshold");
  2756. Status = ZwQueryValueKey(
  2757. PFParHandle,
  2758. &UnicodeString,
  2759. KeyValuePartialInformation,
  2760. Value,
  2761. sizeof(Storage),
  2762. &BytesRead);
  2763. if(NT_SUCCESS(Status)
  2764. &&
  2765. (Value->Type == REG_DWORD) )
  2766. {
  2767. g_FragThresholdSize = *(PULONG)Value->Data;
  2768. }
  2769. ZwClose(PFParHandle);
  2770. }
  2771. }
  2772. }
  2773. #pragma alloc_text(PAGE, GetRegDWORDValue)
  2774. NTSTATUS
  2775. GetRegDWORDValue(
  2776. HANDLE KeyHandle,
  2777. PWCHAR ValueName,
  2778. PULONG ValueData
  2779. )
  2780. {
  2781. NTSTATUS status;
  2782. ULONG resultLength;
  2783. PKEY_VALUE_FULL_INFORMATION keyValueFullInformation;
  2784. UCHAR keybuf[128];
  2785. UNICODE_STRING UValueName;
  2786. PAGED_CODE();
  2787. RtlInitUnicodeString(&UValueName, ValueName);
  2788. keyValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)keybuf;
  2789. RtlZeroMemory(keyValueFullInformation, sizeof(keyValueFullInformation));
  2790. status = ZwQueryValueKey(KeyHandle,
  2791. &UValueName,
  2792. KeyValueFullInformation,
  2793. keyValueFullInformation,
  2794. 128,
  2795. &resultLength);
  2796. if (NT_SUCCESS(status)) {
  2797. if (keyValueFullInformation->Type != REG_DWORD) {
  2798. status = STATUS_INVALID_PARAMETER_MIX;
  2799. } else {
  2800. *ValueData = *((ULONG UNALIGNED *)((PCHAR)keyValueFullInformation +
  2801. keyValueFullInformation->DataOffset));
  2802. }
  2803. }
  2804. return status;
  2805. }
  2806. #pragma alloc_text(PAGE, OpenRegKey)
  2807. NTSTATUS
  2808. OpenRegKey(
  2809. PHANDLE phRegHandle,
  2810. PUNICODE_STRING pusKeyName
  2811. )
  2812. {
  2813. NTSTATUS Status;
  2814. OBJECT_ATTRIBUTES ObjectAttributes;
  2815. PAGED_CODE();
  2816. RtlZeroMemory(&ObjectAttributes,
  2817. sizeof(OBJECT_ATTRIBUTES));
  2818. InitializeObjectAttributes(&ObjectAttributes,
  2819. pusKeyName,
  2820. OBJ_CASE_INSENSITIVE,
  2821. NULL,
  2822. NULL);
  2823. Status = ZwOpenKey(phRegHandle,
  2824. KEY_READ,
  2825. &ObjectAttributes);
  2826. return Status;
  2827. }