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.

705 lines
15 KiB

  1. /*++
  2. Copyright (c) 1995-1997 Microsoft Corporation
  3. Module Name:
  4. fltapis.hxx
  5. Abstract:
  6. Definitions for the WIN32 filter APIs
  7. Author:
  8. Arnold Miller (arnoldm) 24-Sept-1997
  9. Revision History:
  10. --*/
  11. #ifndef _FLTAPIS_HXX
  12. #define _FILTAPI_HXX
  13. extern "C"
  14. {
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <align.h>
  19. #include <windows.h>
  20. #include <ntioapi.h>
  21. #include <stdio.h>
  22. #include <stdarg.h>
  23. #include <stdlib.h>
  24. #include <winsock2.h>
  25. #include <ntddip.h>
  26. #include <ipfltdrv.h>
  27. #include "iphlpapi.h"
  28. #include "fltdefs.h"
  29. #include <tchar.h>
  30. }
  31. #if 0
  32. #ifdef DBG
  33. #define DBG_BUFFER 4096
  34. #ifdef __cplusplus
  35. extern "C" {
  36. #endif
  37. inline
  38. void __cdecl DbgPrintFunction(const TCHAR * format, ...)
  39. {
  40. va_list argptr;
  41. // Don't mess up the LastError.
  42. DWORD LastError = GetLastError();
  43. TCHAR DbgBuffer[DBG_BUFFER] = TEXT("");
  44. TCHAR * ptr;
  45. va_start(argptr, format);
  46. ptr = DbgBuffer + lstrlen(DbgBuffer);
  47. _vstprintf(ptr, format, argptr);
  48. OutputDebugString(DbgBuffer);
  49. va_end(argptr);
  50. // Don't mess up the LastError.
  51. SetLastError(LastError);
  52. }
  53. #ifdef __cplusplus
  54. }
  55. #endif
  56. #define _DBGPRINT(x) DbgPrintFunction x
  57. #if i386
  58. #define _DbgBreak() { __asm int 3 }
  59. #else // !i386
  60. #define _DbgBreak() DebugBreak()
  61. #endif // i386
  62. #define _DBGASSERT(x) \
  63. if (!(x)) { \
  64. _DBGPRINT(("Assertion!: %s, at %s line %d\n", #x, __FILE__, __LINE__)); \
  65. _DbgBreak(); \
  66. }
  67. #else // !DBG
  68. #define _DbgBreak()
  69. #define _DBGPRINT(x)
  70. #define _DBGASSERT(x)
  71. #endif // DBG
  72. #endif
  73. DWORD
  74. StartIpFilterDriver(VOID);
  75. BOOL
  76. ValidateIndex(DWORD dwIndex);
  77. class PacketFilterInterface;
  78. typedef PVOID INTERFACE_HANDLE;
  79. typedef PVOID FILTER_HANDLE, *PFILTER_HANDLE;
  80. #define SPIN_COUNT 1000
  81. #define RESOURCE_SPIN_COUNT 500
  82. #define HANDLE_INCREMENT 20
  83. class HandleContainer
  84. //
  85. // A class to manage handles. It is designed to handle a modest number
  86. // of handles.
  87. //
  88. {
  89. private:
  90. PVOID * _pTable;
  91. DWORD _dwMaxHandle;
  92. DWORD _dwHandlesInUse;
  93. DWORD _dwNextHandle;
  94. public:
  95. HandleContainer( VOID )
  96. {
  97. _pTable = 0;
  98. _dwMaxHandle = _dwHandlesInUse = _dwNextHandle = 0;
  99. }
  100. ~HandleContainer( VOID )
  101. {
  102. delete _pTable;
  103. }
  104. DWORD
  105. NewHandle(PVOID pPointer, PDWORD pdwHandle)
  106. {
  107. if(((3 * _dwMaxHandle) / 4) <= _dwHandlesInUse)
  108. {
  109. //
  110. // table too full. Make it bigger
  111. //
  112. PVOID * pNewTable = new PVOID[_dwMaxHandle + HANDLE_INCREMENT];
  113. if(!pNewTable)
  114. {
  115. return(GetLastError());
  116. }
  117. //
  118. // got it. Copy old handles into new table and start scan
  119. // at the beginning of the new space
  120. //
  121. if(_pTable)
  122. {
  123. memcpy(pNewTable, _pTable, _dwMaxHandle * sizeof(PVOID *));
  124. }
  125. memset(&pNewTable[_dwMaxHandle], 0, HANDLE_INCREMENT * sizeof(PVOID *));
  126. _dwMaxHandle += HANDLE_INCREMENT;
  127. delete _pTable;
  128. _pTable = pNewTable;
  129. }
  130. //
  131. // look for a handle
  132. //
  133. for(;;)
  134. {
  135. if(!_pTable[_dwNextHandle])
  136. {
  137. _pTable[_dwNextHandle] = pPointer;
  138. *pdwHandle = ++_dwNextHandle;
  139. _dwHandlesInUse++;
  140. if(_dwNextHandle >= _dwMaxHandle)
  141. {
  142. _dwNextHandle = 0;
  143. }
  144. break;
  145. }
  146. _dwNextHandle++;
  147. if(_dwNextHandle >= _dwMaxHandle)
  148. {
  149. _dwNextHandle = 0;
  150. }
  151. }
  152. return(ERROR_SUCCESS);
  153. }
  154. DWORD
  155. DeleteHandle( DWORD dwHandle)
  156. {
  157. DWORD err;
  158. if((--dwHandle < _dwMaxHandle) && _pTable[dwHandle])
  159. {
  160. _pTable[dwHandle] = 0;
  161. _dwHandlesInUse--;
  162. err = ERROR_SUCCESS;
  163. }
  164. else
  165. {
  166. err = ERROR_INVALID_HANDLE;
  167. }
  168. return(err);
  169. }
  170. PVOID
  171. FetchHandleValue( DWORD dwHandle)
  172. {
  173. if(--dwHandle < _dwMaxHandle)
  174. {
  175. return((PCHAR)_pTable[dwHandle]);
  176. }
  177. return(0);
  178. }
  179. };
  180. //
  181. // Filter class. This encapsulates all of the data structures
  182. // and logic to deal with the creating and deleting interfaces.
  183. // It also manages the handle to the driver.
  184. //
  185. class InterfaceContainer
  186. {
  187. private:
  188. HANDLE _hDriver; // driver handle
  189. RTL_RESOURCE _Resource;
  190. CRITICAL_SECTION _csDriverLock;
  191. DWORD _status;
  192. NTSTATUS _ntStatus;
  193. HandleContainer _hcHandles;
  194. PFLOGGER _Log;
  195. BOOL _Inited;
  196. VOID
  197. _AcquireShared( VOID )
  198. {
  199. RtlAcquireResourceShared(&_Resource, TRUE);
  200. }
  201. VOID
  202. _AcquireExclusive( VOID )
  203. {
  204. RtlAcquireResourceExclusive(&_Resource, TRUE);
  205. }
  206. VOID
  207. _Release( VOID )
  208. {
  209. RtlReleaseResource(&_Resource);
  210. }
  211. VOID
  212. _InitResource()
  213. {
  214. RtlInitializeResource(&_Resource);
  215. // SetCriticalSectionSpinCount(&_Resource.CriticalSection,
  216. // RESOURCE_SPIN_COUNT);
  217. }
  218. VOID
  219. _DestroyResource()
  220. {
  221. RtlDeleteResource(&_Resource);
  222. }
  223. VOID
  224. _LockDriver( VOID )
  225. {
  226. EnterCriticalSection(&_csDriverLock);
  227. }
  228. VOID
  229. _UnLockDriver( VOID )
  230. {
  231. LeaveCriticalSection(&_csDriverLock);
  232. }
  233. VOID
  234. _OpenDriver();
  235. VOID
  236. _CloseDriver();
  237. DWORD
  238. _DriverReady()
  239. {
  240. if(!_hDriver)
  241. {
  242. _LockDriver();
  243. if(!_hDriver)
  244. {
  245. _OpenDriver();
  246. }
  247. _UnLockDriver();
  248. }
  249. if(_hDriver != INVALID_HANDLE_VALUE)
  250. {
  251. return(ERROR_SUCCESS);
  252. }
  253. return(ERROR_NOT_READY);
  254. }
  255. public:
  256. InterfaceContainer()
  257. {
  258. //InitInterfaceContainer();
  259. _Inited = FALSE;
  260. }
  261. VOID
  262. InitInterfaceContainer();
  263. ~InterfaceContainer()
  264. {
  265. UnInitInterfaceContainer();
  266. }
  267. VOID
  268. UnInitInterfaceContainer()
  269. {
  270. if(_Inited)
  271. {
  272. _DestroyResource();
  273. DeleteCriticalSection(&_csDriverLock);
  274. _CloseDriver();
  275. _Inited = FALSE;
  276. }
  277. }
  278. DWORD
  279. AddInterface(
  280. DWORD dwName,
  281. PFFORWARD_ACTION inAction,
  282. PFFORWARD_ACTION outAction,
  283. BOOL fUseLog,
  284. BOOL fUnique,
  285. INTERFACE_HANDLE *ppInterface);
  286. DWORD
  287. FindInterfaceAndRef(
  288. INTERFACE_HANDLE pInterface,
  289. PacketFilterInterface ** ppInterface);
  290. VOID
  291. Deref( VOID )
  292. {
  293. _Release();
  294. }
  295. DWORD
  296. DeleteInterface(
  297. INTERFACE_HANDLE pInterface);
  298. VOID
  299. AddressUpdateNotification();
  300. DWORD
  301. MakeLog( HANDLE hEvent );
  302. DWORD
  303. DeleteLog( VOID );
  304. DWORD
  305. SetLogBuffer(
  306. PBYTE pbBuffer,
  307. DWORD dwSize,
  308. DWORD dwThreshold,
  309. DWORD dwEntries,
  310. PDWORD pdwLoggedEntries,
  311. PDWORD pdwLostEntries,
  312. PDWORD pdwSizeUsed);
  313. DWORD
  314. CoerceDriverError(NTSTATUS Status)
  315. {
  316. return(RtlNtStatusToDosError(Status));
  317. }
  318. };
  319. //
  320. // flags for PacketFilterInterface
  321. //
  322. #define PFI_FLAGS_BOUND 0x1
  323. class PacketFilterInterface
  324. {
  325. private:
  326. CRITICAL_SECTION _cs;
  327. HANDLE _hDriver;
  328. PVOID _pvDriverContext;
  329. DWORD _dwFlags;
  330. DWORD _err;
  331. DWORD _dwEpoch; // bind epoch
  332. DWORD
  333. _CommonBind(PFBINDINGTYPE dwBindType, DWORD dwData, DWORD LinkData);
  334. BOOL
  335. _IsBound( VOID )
  336. {
  337. return((_dwFlags & PFI_FLAGS_BOUND) != 0);
  338. }
  339. VOID
  340. _SetBound( VOID )
  341. {
  342. _dwFlags |= PFI_FLAGS_BOUND;
  343. }
  344. VOID
  345. _ClearBound( VOID )
  346. {
  347. _dwFlags &= ~PFI_FLAGS_BOUND;
  348. }
  349. VOID
  350. _Lock( VOID )
  351. {
  352. EnterCriticalSection(&_cs);
  353. }
  354. VOID
  355. _UnLock( VOID )
  356. {
  357. LeaveCriticalSection(&_cs);
  358. }
  359. DWORD
  360. _AddFilters(PFETYPE pfe,
  361. DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
  362. DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut,
  363. PFILTER_HANDLE pfHandle);
  364. DWORD
  365. _DeleteFiltersByFilter(PFETYPE pfe,
  366. DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
  367. DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut);
  368. PFILTER_DRIVER_SET_FILTERS
  369. _SetFilterBlock(PFETYPE pfe,
  370. DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
  371. DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut,
  372. PDWORD pdwSize,
  373. PFILTER_DESCRIPTOR2 * ppfdIn,
  374. PFILTER_DESCRIPTOR2 * ppfdOut);
  375. VOID
  376. _FreeSetBlock(PFILTER_DRIVER_SET_FILTERS pSet)
  377. {
  378. delete (PBYTE)pSet;
  379. }
  380. VOID
  381. _CopyFilterHandles(PFILTER_DESCRIPTOR2 pfd1,
  382. PFILTER_DESCRIPTOR2 pfd2,
  383. PFILTER_HANDLE pfHandle);
  384. DWORD
  385. _MarshallFilter(PFETYPE pfe,
  386. PPF_FILTER_DESCRIPTOR pFilt,
  387. PFILTER_INFOEX pInfo);
  388. VOID
  389. _MarshallCommonStats(PPF_INTERFACE_STATS ppfStats,
  390. PPFGETINTERFACEPARAMETERS pfGetip)
  391. {
  392. memcpy(ppfStats, pfGetip, _IfBaseSize());
  393. }
  394. DWORD
  395. _IpBaseSize( VOID )
  396. {
  397. return(sizeof(PFGETINTERFACEPARAMETERS) - sizeof(FILTER_STATS_EX));
  398. }
  399. DWORD
  400. _IfBaseSize( VOID )
  401. {
  402. return(sizeof(PF_INTERFACE_STATS) - sizeof(PF_FILTER_STATS));
  403. }
  404. DWORD
  405. _PfFilterSize( VOID )
  406. {
  407. //
  408. // N.B. The 4 below is the number of addresses in
  409. // the structure. If this changes, be careful
  410. //
  411. return((sizeof(PF_FILTER_STATS) + (4 * sizeof(DWORD))));
  412. }
  413. DWORD
  414. _IpSizeFromifSize(DWORD dwSize)
  415. {
  416. DWORD dwTemp;
  417. if(dwSize < _IfBaseSize())
  418. {
  419. return(dwSize);
  420. }
  421. dwTemp = dwSize - _IfBaseSize();
  422. //
  423. // compute # of filters
  424. //
  425. dwTemp /= _PfFilterSize();
  426. dwTemp = _IpBaseSize() + (dwTemp * sizeof(FILTER_STATS_EX));
  427. return(dwTemp);
  428. }
  429. DWORD
  430. _IfSizeFromipSize(DWORD dwSize)
  431. {
  432. DWORD dwTemp;
  433. if(dwSize <= _IpBaseSize())
  434. {
  435. return(dwSize);
  436. }
  437. dwTemp = (dwSize - _IpBaseSize()) / sizeof(FILTER_STATS_EX);
  438. //
  439. // dwTemp is the number of filters
  440. //
  441. dwTemp = _IfBaseSize() + (_PfFilterSize() * dwTemp);
  442. return(dwTemp);
  443. }
  444. VOID
  445. _MarshallStatFilter(PFILTER_STATS_EX pstat,
  446. PPF_FILTER_STATS pfstats,
  447. PDWORD * ppdwAddress);
  448. public:
  449. PacketFilterInterface(
  450. HANDLE hDriver,
  451. DWORD dwName,
  452. PFLOGGER pfLog,
  453. BOOL fUnique,
  454. FORWARD_ACTION inAction,
  455. FORWARD_ACTION outAction);
  456. ~PacketFilterInterface();
  457. DWORD
  458. BindByIndex(DWORD dwIndex, DWORD LinkAddress)
  459. {
  460. return(_CommonBind(PF_BIND_INTERFACEINDEX, dwIndex, LinkAddress));
  461. }
  462. DWORD
  463. BindByAddress(DWORD dwAddress)
  464. {
  465. return(_CommonBind(PF_BIND_IPV4ADDRESS, dwAddress, 0));
  466. }
  467. DWORD
  468. TestPacket(PacketFilterInterface * pIn,
  469. PacketFilterInterface * pOut,
  470. DWORD cBytes,
  471. PBYTE pbPacket,
  472. PPFFORWARD_ACTION ppAction);
  473. DWORD
  474. UnBindInterface( VOID );
  475. DWORD
  476. DeleteFiltersByHandle(DWORD cFilters, PFILTER_HANDLE pvHandles);
  477. DWORD
  478. DeleteFiltersByFilter(DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
  479. DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut)
  480. {
  481. return(
  482. _DeleteFiltersByFilter(PFE_FILTER, cInFilters, pfiltIn,
  483. cOutFilters, pfiltOut));
  484. }
  485. DWORD
  486. AddFilters(DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
  487. DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut,
  488. PFILTER_HANDLE pfHandle)
  489. {
  490. return(
  491. _AddFilters(PFE_FILTER, cInFilters, pfiltIn,
  492. cOutFilters, pfiltOut,
  493. pfHandle));
  494. }
  495. DWORD
  496. RebindFilters(PPF_LATEBIND_INFO pLateBindInfo);
  497. DWORD
  498. AddGlobalFilter(GLOBAL_FILTER gf);
  499. DWORD
  500. DeleteGlobalFilter(GLOBAL_FILTER gf);
  501. DWORD
  502. GetStatus( VOID )
  503. {
  504. return(_err);
  505. }
  506. DWORD
  507. GetStatistics(
  508. PPF_INTERFACE_STATS ppfStats,
  509. PDWORD pdwBufferSize,
  510. BOOL fResetCounters);
  511. PVOID
  512. GetDriverContext()
  513. {
  514. return(_pvDriverContext);
  515. }
  516. };
  517. //
  518. // Open the driver
  519. //
  520. inline
  521. VOID
  522. InterfaceContainer::_OpenDriver()
  523. {
  524. static BOOL bStarted = FALSE;
  525. UNICODE_STRING nameString;
  526. IO_STATUS_BLOCK ioStatusBlock;
  527. OBJECT_ATTRIBUTES objectAttributes;
  528. if (!bStarted) {
  529. StartIpFilterDriver();
  530. bStarted = TRUE;
  531. }
  532. RtlInitUnicodeString(&nameString,DD_IPFLTRDRVR_DEVICE_NAME);
  533. InitializeObjectAttributes(&objectAttributes, &nameString,
  534. OBJ_CASE_INSENSITIVE, NULL, NULL);
  535. _status = NtCreateFile(&_hDriver,
  536. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  537. &objectAttributes,
  538. &ioStatusBlock,
  539. NULL,
  540. FILE_ATTRIBUTE_NORMAL,
  541. FILE_SHARE_READ | FILE_SHARE_WRITE,
  542. FILE_OPEN_IF,
  543. 0,
  544. NULL,
  545. 0);
  546. if(!NT_SUCCESS(_status))
  547. {
  548. _hDriver = INVALID_HANDLE_VALUE;
  549. }
  550. }
  551. inline
  552. VOID
  553. InterfaceContainer::_CloseDriver()
  554. {
  555. if(_hDriver && (_hDriver != INVALID_HANDLE_VALUE))
  556. {
  557. NtClose(_hDriver);
  558. _hDriver = INVALID_HANDLE_VALUE;
  559. }
  560. }
  561. #endif