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.

482 lines
29 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. nfilter.h
  5. Abstract:
  6. Header file for the address filtering library for NDIS MAC's.
  7. Author:
  8. Jameel Hyder (jameelh) July 1998
  9. Environment:
  10. Notes:
  11. --*/
  12. #ifndef _NULL_FILTER_DEFS_
  13. #define _NULL_FILTER_DEFS_
  14. typedef
  15. VOID
  16. (*NULL_DEFERRED_CLOSE)(
  17. IN NDIS_HANDLE BindingHandle
  18. );
  19. //
  20. // The binding info is threaded on a single list.
  21. //
  22. typedef X_BINDING_INFO NULL_BINDING_INFO,*PNULL_BINDING_INFO;
  23. typedef X_FILTER NULL_FILTER,*PNULL_FILTER;
  24. //
  25. // Exported functions
  26. //
  27. EXPORT
  28. BOOLEAN
  29. nullCreateFilter(
  30. OUT PNULL_FILTER * Filter
  31. );
  32. EXPORT
  33. VOID
  34. nullDeleteFilter(
  35. IN PNULL_FILTER Filter
  36. );
  37. EXPORT
  38. NDIS_STATUS
  39. nullDeleteFilterOpenAdapter(
  40. IN PNULL_FILTER Filter,
  41. IN NDIS_HANDLE NdisFilterHandle
  42. );
  43. VOID
  44. nullRemoveAndFreeBinding(
  45. IN PNULL_FILTER Filter,
  46. IN PNULL_BINDING_INFO Binding,
  47. IN BOOLEAN fCallCloseAction
  48. );
  49. VOID
  50. FASTCALL
  51. nullFilterLockHandler(
  52. IN PNULL_FILTER Filter,
  53. IN OUT PLOCK_STATE pLockState
  54. );
  55. /*++
  56. Routine Description:
  57. Multiple-reader-single-writer locking scheme for Filter DB
  58. Use refCounts to keep track of how many readers are doing reads.
  59. Use per-processor refCounts to reduce bus traffic.
  60. Writers are serialized by means of a spin lock. Then they wait for
  61. readers to finish reading by waiting till refCounts for all processors
  62. go to zero. Rely on snoopy caches to get the sum right without doing
  63. interlocked operations
  64. --*/
  65. #define TEST_SPIN_LOCK(_L) ((_L) != 0)
  66. #define NDIS_READ_LOCK(_L, _pLS) \
  67. { \
  68. UINT refcount; \
  69. ULONG Prc; \
  70. \
  71. RAISE_IRQL_TO_DISPATCH(&(_pLS)->OldIrql); \
  72. \
  73. /* go ahead and bump up the ref count IF no writes are underway */ \
  74. Prc = CURRENT_PROCESSOR; \
  75. refcount = InterlockedIncrement((PLONG)&(_L)->RefCount[Prc].RefCount); \
  76. \
  77. /* Test if spin lock is held, i.e., write is underway */ \
  78. /* if (KeTestSpinLock(&(_L)->SpinLock) == TRUE) */ \
  79. /* This processor already is holding the lock, just */ \
  80. /* allow him to take it again or else we run into a */ \
  81. /* dead-lock situation with the writer */ \
  82. if (TEST_SPIN_LOCK((_L)->SpinLock) && \
  83. (refcount == 1) && \
  84. ((_L)->Context != CURRENT_THREAD)) \
  85. { \
  86. (_L)->RefCount[Prc].RefCount--; \
  87. ACQUIRE_SPIN_LOCK_DPC(&(_L)->SpinLock); \
  88. (_L)->RefCount[Prc].RefCount++; \
  89. RELEASE_SPIN_LOCK_DPC(&(_L)->SpinLock); \
  90. } \
  91. (_pLS)->LockState = READ_LOCK_STATE_FREE; \
  92. }
  93. #define NDIS_READ_LOCK_DPC(_L, _pLS) \
  94. { \
  95. UINT refcount; \
  96. ULONG Prc; \
  97. \
  98. /* go ahead and bump up the ref count IF no writes are underway */ \
  99. Prc = CURRENT_PROCESSOR; \
  100. refcount = InterlockedIncrement((PLONG)&(_L)->RefCount[Prc].RefCount); \
  101. \
  102. /* Test if spin lock is held, i.e., write is underway */ \
  103. /* if (KeTestSpinLock(&(_L)->SpinLock) == TRUE) */ \
  104. /* This processor already is holding the lock, just */ \
  105. /* allow him to take it again or else we run into a */ \
  106. /* dead-lock situation with the writer */ \
  107. if (TEST_SPIN_LOCK((_L)->SpinLock) && \
  108. (refcount == 1) && \
  109. ((_L)->Context != CURRENT_THREAD)) \
  110. { \
  111. (_L)->RefCount[Prc].RefCount--; \
  112. ACQUIRE_SPIN_LOCK_DPC(&(_L)->SpinLock); \
  113. (_L)->RefCount[Prc].RefCount++; \
  114. RELEASE_SPIN_LOCK_DPC(&(_L)->SpinLock); \
  115. } \
  116. (_pLS)->LockState = READ_LOCK_STATE_FREE; \
  117. }
  118. #define NDIS_WRITE_LOCK_STATE_UNKNOWN(_L, _pLS) \
  119. { \
  120. UINT i, refcount; \
  121. ULONG Prc; \
  122. \
  123. /* \
  124. * This means we need to attempt to acquire the lock, \
  125. * if we do not already own it. \
  126. * Set the state accordingly. \
  127. */ \
  128. if ((_L)->Context == CURRENT_THREAD) \
  129. { \
  130. (_pLS)->LockState = LOCK_STATE_ALREADY_ACQUIRED; \
  131. } \
  132. else \
  133. { \
  134. ACQUIRE_SPIN_LOCK(&(_L)->SpinLock, &(_pLS)->OldIrql); \
  135. \
  136. Prc = KeGetCurrentProcessorNumber(); \
  137. refcount = (_L)->RefCount[Prc].RefCount; \
  138. (_L)->RefCount[Prc].RefCount = 0; \
  139. \
  140. /* wait for all readers to exit */ \
  141. for (i=0; i < ndisNumberOfProcessors; i++) \
  142. { \
  143. volatile UINT *_p = &(_L)->RefCount[i].RefCount; \
  144. \
  145. while (*_p != 0) \
  146. NDIS_INTERNAL_STALL(50); \
  147. } \
  148. \
  149. (_L)->RefCount[Prc].RefCount = refcount; \
  150. (_L)->Context = CURRENT_THREAD; \
  151. (_pLS)->LockState = WRITE_LOCK_STATE_FREE; \
  152. } \
  153. }
  154. #define NDIS_READ_LOCK_STATE_FREE(_L, _pLS) \
  155. { \
  156. ULONG Prc; \
  157. ASSERT(CURRENT_IRQL == DISPATCH_LEVEL); \
  158. Prc = CURRENT_PROCESSOR; \
  159. ASSERT((_L)->RefCount[Prc].RefCount > 0); \
  160. (_L)->RefCount[Prc].RefCount--; \
  161. (_pLS)->LockState = LOCK_STATE_UNKNOWN; \
  162. if ((_pLS)->OldIrql < DISPATCH_LEVEL) \
  163. { \
  164. KeLowerIrql((_pLS)->OldIrql); \
  165. } \
  166. }
  167. #define NDIS_READ_LOCK_STATE_FREE_DPC(_L, _pLS) \
  168. { \
  169. ULONG Prc; \
  170. ASSERT(CURRENT_IRQL == DISPATCH_LEVEL); \
  171. Prc = CURRENT_PROCESSOR; \
  172. ASSERT((INT)(_L)->RefCount[Prc].RefCount > 0); \
  173. (_L)->RefCount[Prc].RefCount--; \
  174. (_pLS)->LockState = LOCK_STATE_UNKNOWN; \
  175. }
  176. #define NDIS_WRITE_LOCK_STATE_FREE(_L, _pLS) \
  177. { \
  178. /* We acquired it. Now we need to free it */ \
  179. ASSERT(CURRENT_IRQL == DISPATCH_LEVEL); \
  180. ASSERT((_L)->Context == CURRENT_THREAD); \
  181. (_pLS)->LockState = LOCK_STATE_UNKNOWN; \
  182. (_L)->Context = NULL; \
  183. RELEASE_SPIN_LOCK(&(_L)->SpinLock, (_pLS)->OldIrql); \
  184. }
  185. #define NDIS_LOCK_STATE_ALREADY_ACQUIRED(_L, _pLS) \
  186. { \
  187. ASSERT((_L)->Context == CURRENT_THREAD); \
  188. /* Nothing to do */ \
  189. }
  190. #define xLockHandler(_L, _pLS) \
  191. { \
  192. switch ((_pLS)->LockState) \
  193. { \
  194. case READ_LOCK: \
  195. NDIS_READ_LOCK(_L, _pLS); \
  196. break; \
  197. \
  198. case WRITE_LOCK_STATE_UNKNOWN: \
  199. NDIS_WRITE_LOCK_STATE_UNKNOWN(_L, _pLS); \
  200. break; \
  201. \
  202. case READ_LOCK_STATE_FREE: \
  203. NDIS_READ_LOCK_STATE_FREE(_L, _pLS); \
  204. break; \
  205. \
  206. case WRITE_LOCK_STATE_FREE: \
  207. NDIS_WRITE_LOCK_STATE_FREE(_L, _pLS); \
  208. break; \
  209. \
  210. case LOCK_STATE_ALREADY_ACQUIRED: \
  211. NDIS_LOCK_STATE_ALREADY_ACQUIRED(_L, _pLS); \
  212. /* Nothing to do */ \
  213. break; \
  214. \
  215. default: \
  216. ASSERT(0); \
  217. break; \
  218. } \
  219. }
  220. #define NDIS_INITIALIZE_RCVD_PACKET(_P, _NSR, _M) \
  221. { \
  222. _NSR->RefCount = -1; \
  223. _NSR->XRefCount = 0; \
  224. _NSR->Miniport = _M; \
  225. /* \
  226. * Ensure that we force re-calculation. \
  227. */ \
  228. (_P)->Private.ValidCounts = FALSE; \
  229. }
  230. #define NDIS_ACQUIRE_PACKET_LOCK_DPC(_NSR) ACQUIRE_SPIN_LOCK_DPC(&(_NSR)->Lock)
  231. #define NDIS_RELEASE_PACKET_LOCK_DPC(_NSR) RELEASE_SPIN_LOCK_DPC(&(_NSR)->Lock)
  232. #define ADJUST_PACKET_REFCOUNT(_NSR, _pRC) \
  233. { \
  234. *(_pRC) = InterlockedDecrement(&(_NSR)->RefCount); \
  235. }
  236. #ifdef TRACK_RECEIVED_PACKETS
  237. //
  238. // NSR->XRefCount = Number of times protocol said it will call NdisReturnPacket
  239. // NSR->RefCount = is decremented every time protocol calls NdisReturnPackets
  240. //
  241. #define COALESCE_PACKET_REFCOUNT_DPC(_Packet, _M, _NSR, _pOob, _pRC) \
  242. { \
  243. LONG _LocalXRef = (_NSR)->XRefCount; \
  244. if (_LocalXRef != 0) \
  245. { \
  246. LONG _LocalRef; \
  247. ASSERT((_pOob)->Status != NDIS_STATUS_RESOURCES); \
  248. _LocalRef = InterlockedExchangeAdd(&(_NSR)->RefCount, (_LocalXRef + 1)); \
  249. *(_pRC) = _LocalRef + _LocalXRef + 1; \
  250. if ((*(_pRC) > 0) && (!MINIPORT_TEST_FLAG((_M), fMINIPORT_DESERIALIZE))) \
  251. { \
  252. NDIS_SET_PACKET_STATUS(_Packet, NDIS_STATUS_PENDING); \
  253. } \
  254. if ((*(_pRC) == 0) && ((_NSR)->RefCount != 0)) \
  255. { \
  256. DbgPrint("Packet %p is being returned back to the miniport" \
  257. " but the ref count is not zero.\n", _Packet); \
  258. DbgBreakPoint(); \
  259. } \
  260. } \
  261. else \
  262. { \
  263. _NSR->RefCount = *(_pRC) = 0; \
  264. } \
  265. }
  266. #define TACKLE_REF_COUNT(_M, _P, _S, _O) \
  267. { \
  268. LONG RefCount; \
  269. \
  270. /* \
  271. * We started off with the RefCount set to -1. \
  272. * NdisReturnPackets may have been called which will further reduce it. \
  273. * Add back the RefCount returned by the protocol \
  274. * and account for the initial -1. \
  275. */ \
  276. COALESCE_PACKET_REFCOUNT_DPC(_P, _M, _S, _O, &RefCount); \
  277. \
  278. NDIS_APPEND_RCV_LOGFILE(_P, _M, CurThread, \
  279. 7, OrgPacketStackLocation+1, _S->RefCount, _S->XRefCount, NDIS_GET_PACKET_STATUS(_P)); \
  280. \
  281. \
  282. if (RefCount == 0) \
  283. { \
  284. POP_PACKET_STACK(_P); \
  285. if ((_O)->Status != NDIS_STATUS_RESOURCES) \
  286. { \
  287. if (MINIPORT_TEST_FLAG((_M), fMINIPORT_DESERIALIZE)) \
  288. { \
  289. /* \
  290. * Return packets which are truly free, \
  291. * but only for deserialized drivers \
  292. */ \
  293. W_RETURN_PACKET_HANDLER Handler; \
  294. if (_S->RefCount != 0) \
  295. { \
  296. DbgPrint("Packet %p is being returned back to the " \
  297. "miniport but the ref count is not zero.\n", _P); \
  298. DbgBreakPoint(); \
  299. } \
  300. if ((_P)->Private.Head == NULL) \
  301. { \
  302. DbgPrint("Packet %p is being returned back to the miniport with NULL Head.\n", _P); \
  303. DbgBreakPoint(); \
  304. } \
  305. \
  306. if (!MINIPORT_TEST_FLAG(_M, fMINIPORT_INTERMEDIATE_DRIVER)) \
  307. { \
  308. ULONG SL; \
  309. if ((SL = CURR_STACK_LOCATION(_P)) != -1) \
  310. { \
  311. DbgPrint("Packet %p is being returned back to the non-IM miniport"\
  312. " with stack location %lx.\n", Packet, SL); \
  313. DbgBreakPoint(); \
  314. } \
  315. } \
  316. \
  317. Handler = (_M)->DriverHandle->MiniportCharacteristics.ReturnPacketHandler;\
  318. (_S)->Miniport = NULL; \
  319. (_O)->Status = NDIS_STATUS_PENDING; \
  320. \
  321. NDIS_APPEND_RCV_LOGFILE(_P, _M, CurThread, \
  322. 8, OrgPacketStackLocation+1, _S->RefCount, _S->XRefCount, NDIS_GET_PACKET_STATUS(_P)); \
  323. \
  324. \
  325. (*Handler)((_M)->MiniportAdapterContext, _P); \
  326. } \
  327. else \
  328. { \
  329. { \
  330. ULONG SL; \
  331. if ((SL = CURR_STACK_LOCATION(_P)) != -1) \
  332. { \
  333. DbgPrint("Packet %p is being returned back to the non-IM miniport"\
  334. " with stack location %lx.\n", Packet, SL); \
  335. DbgBreakPoint(); \
  336. } \
  337. } \
  338. \
  339. if ((NDIS_GET_PACKET_STATUS(_P) == NDIS_STATUS_RESOURCES)) \
  340. { \
  341. NDIS_STATUS _OStatus = (NDIS_STATUS)NDIS_PER_PACKET_INFO_FROM_PACKET(_P, OriginalStatus); \
  342. \
  343. if (_OStatus != NDIS_STATUS_RESOURCES) \
  344. { \
  345. DbgPrint("Packet %p is being returned back to the non-deserialized miniport"\
  346. " with packet status changed from %lx to NDIS_STATUS_RESOURCES.\n", _P, _OStatus); \
  347. DbgBreakPoint(); \
  348. } \
  349. \
  350. } \
  351. \
  352. (_O)->Status = NDIS_STATUS_SUCCESS; \
  353. NDIS_APPEND_RCV_LOGFILE(_P, _M, CurThread, \
  354. 9, OrgPacketStackLocation+1, _S->RefCount, _S->XRefCount, NDIS_GET_PACKET_STATUS(_P)); \
  355. \
  356. } \
  357. } \
  358. } \
  359. else if (MINIPORT_TEST_FLAG((_M), fMINIPORT_INTERMEDIATE_DRIVER)) \
  360. { \
  361. InterlockedIncrement((PLONG)&(_M)->IndicatedPacketsCount); \
  362. } \
  363. }
  364. #else
  365. //
  366. // NSR->XRefCount = Number of times protocol said it will call NdisReturnPacket
  367. // NSR->RefCount = is decremented every time protocol calls NdisReturnPackets
  368. //
  369. #define COALESCE_PACKET_REFCOUNT_DPC(_Packet, _M, _NSR, _pOob, _pRC) \
  370. { \
  371. LONG _LocalXRef = (_NSR)->XRefCount; \
  372. if (_LocalXRef != 0) \
  373. { \
  374. LONG _LocalRef; \
  375. ASSERT((_pOob)->Status != NDIS_STATUS_RESOURCES); \
  376. _LocalRef = InterlockedExchangeAdd(&(_NSR)->RefCount, (_LocalXRef + 1)); \
  377. *(_pRC) = _LocalRef + _LocalXRef + 1; \
  378. if ((*(_pRC) > 0) && (!MINIPORT_TEST_FLAG((_M), fMINIPORT_DESERIALIZE))) \
  379. { \
  380. NDIS_SET_PACKET_STATUS(_Packet, NDIS_STATUS_PENDING); \
  381. } \
  382. } \
  383. else \
  384. { \
  385. _NSR->RefCount = *(_pRC) = 0; \
  386. } \
  387. }
  388. #define TACKLE_REF_COUNT(_M, _P, _S, _O) \
  389. { \
  390. LONG RefCount; \
  391. \
  392. /* \
  393. * We started off with the RefCount set to -1. \
  394. * NdisReturnPackets may have been called which will further reduce it. \
  395. * Add back the RefCount returned by the protocol \
  396. * and account for the initial -1. \
  397. */ \
  398. COALESCE_PACKET_REFCOUNT_DPC(_P, _M, _S, _O, &RefCount); \
  399. \
  400. if (RefCount == 0) \
  401. { \
  402. POP_PACKET_STACK(_P); \
  403. if ((_O)->Status != NDIS_STATUS_RESOURCES) \
  404. { \
  405. if (MINIPORT_TEST_FLAG((_M), fMINIPORT_DESERIALIZE)) \
  406. { \
  407. /* \
  408. * Return packets which are truly free, \
  409. * but only for deserialized drivers \
  410. */ \
  411. W_RETURN_PACKET_HANDLER Handler; \
  412. \
  413. Handler = (_M)->DriverHandle->MiniportCharacteristics.ReturnPacketHandler;\
  414. (_S)->Miniport = NULL; \
  415. (_O)->Status = NDIS_STATUS_PENDING; \
  416. \
  417. (*Handler)((_M)->MiniportAdapterContext, _P); \
  418. } \
  419. else \
  420. { \
  421. (_O)->Status = NDIS_STATUS_SUCCESS; \
  422. } \
  423. } \
  424. } \
  425. else if (MINIPORT_TEST_FLAG((_M), fMINIPORT_INTERMEDIATE_DRIVER)) \
  426. { \
  427. InterlockedIncrement((PLONG)&(_M)->IndicatedPacketsCount); \
  428. } \
  429. }
  430. #endif
  431. #endif // _NULL_FILTER_DEFS_