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

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
nfilter.h
Abstract:
Header file for the address filtering library for NDIS MAC's.
Author:
Jameel Hyder (jameelh) July 1998
Environment:
Notes:
--*/
#ifndef _NULL_FILTER_DEFS_
#define _NULL_FILTER_DEFS_
typedef
VOID
(*NULL_DEFERRED_CLOSE)(
IN NDIS_HANDLE BindingHandle
);
//
// The binding info is threaded on a single list.
//
typedef X_BINDING_INFO NULL_BINDING_INFO,*PNULL_BINDING_INFO;
typedef X_FILTER NULL_FILTER,*PNULL_FILTER;
//
// Exported functions
//
EXPORT
BOOLEAN
nullCreateFilter(
OUT PNULL_FILTER * Filter
);
EXPORT
VOID
nullDeleteFilter(
IN PNULL_FILTER Filter
);
EXPORT
NDIS_STATUS
nullDeleteFilterOpenAdapter(
IN PNULL_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle
);
VOID
nullRemoveAndFreeBinding(
IN PNULL_FILTER Filter,
IN PNULL_BINDING_INFO Binding,
IN BOOLEAN fCallCloseAction
);
VOID
FASTCALL
nullFilterLockHandler(
IN PNULL_FILTER Filter,
IN OUT PLOCK_STATE pLockState
);
/*++
Routine Description:
Multiple-reader-single-writer locking scheme for Filter DB
Use refCounts to keep track of how many readers are doing reads.
Use per-processor refCounts to reduce bus traffic.
Writers are serialized by means of a spin lock. Then they wait for
readers to finish reading by waiting till refCounts for all processors
go to zero. Rely on snoopy caches to get the sum right without doing
interlocked operations
--*/
#define TEST_SPIN_LOCK(_L) ((_L) != 0)
#define NDIS_READ_LOCK(_L, _pLS) \
{ \
UINT refcount; \
ULONG Prc; \
\
RAISE_IRQL_TO_DISPATCH(&(_pLS)->OldIrql); \
\
/* go ahead and bump up the ref count IF no writes are underway */ \
Prc = CURRENT_PROCESSOR; \
refcount = InterlockedIncrement((PLONG)&(_L)->RefCount[Prc].RefCount); \
\
/* Test if spin lock is held, i.e., write is underway */ \
/* if (KeTestSpinLock(&(_L)->SpinLock) == TRUE) */ \
/* This processor already is holding the lock, just */ \
/* allow him to take it again or else we run into a */ \
/* dead-lock situation with the writer */ \
if (TEST_SPIN_LOCK((_L)->SpinLock) && \
(refcount == 1) && \
((_L)->Context != CURRENT_THREAD)) \
{ \
(_L)->RefCount[Prc].RefCount--; \
ACQUIRE_SPIN_LOCK_DPC(&(_L)->SpinLock); \
(_L)->RefCount[Prc].RefCount++; \
RELEASE_SPIN_LOCK_DPC(&(_L)->SpinLock); \
} \
(_pLS)->LockState = READ_LOCK_STATE_FREE; \
}
#define NDIS_READ_LOCK_DPC(_L, _pLS) \
{ \
UINT refcount; \
ULONG Prc; \
\
/* go ahead and bump up the ref count IF no writes are underway */ \
Prc = CURRENT_PROCESSOR; \
refcount = InterlockedIncrement((PLONG)&(_L)->RefCount[Prc].RefCount); \
\
/* Test if spin lock is held, i.e., write is underway */ \
/* if (KeTestSpinLock(&(_L)->SpinLock) == TRUE) */ \
/* This processor already is holding the lock, just */ \
/* allow him to take it again or else we run into a */ \
/* dead-lock situation with the writer */ \
if (TEST_SPIN_LOCK((_L)->SpinLock) && \
(refcount == 1) && \
((_L)->Context != CURRENT_THREAD)) \
{ \
(_L)->RefCount[Prc].RefCount--; \
ACQUIRE_SPIN_LOCK_DPC(&(_L)->SpinLock); \
(_L)->RefCount[Prc].RefCount++; \
RELEASE_SPIN_LOCK_DPC(&(_L)->SpinLock); \
} \
(_pLS)->LockState = READ_LOCK_STATE_FREE; \
}
#define NDIS_WRITE_LOCK_STATE_UNKNOWN(_L, _pLS) \
{ \
UINT i, refcount; \
ULONG Prc; \
\
/* \
* This means we need to attempt to acquire the lock, \
* if we do not already own it. \
* Set the state accordingly. \
*/ \
if ((_L)->Context == CURRENT_THREAD) \
{ \
(_pLS)->LockState = LOCK_STATE_ALREADY_ACQUIRED; \
} \
else \
{ \
ACQUIRE_SPIN_LOCK(&(_L)->SpinLock, &(_pLS)->OldIrql); \
\
Prc = KeGetCurrentProcessorNumber(); \
refcount = (_L)->RefCount[Prc].RefCount; \
(_L)->RefCount[Prc].RefCount = 0; \
\
/* wait for all readers to exit */ \
for (i=0; i < ndisNumberOfProcessors; i++) \
{ \
volatile UINT *_p = &(_L)->RefCount[i].RefCount; \
\
while (*_p != 0) \
NDIS_INTERNAL_STALL(50); \
} \
\
(_L)->RefCount[Prc].RefCount = refcount; \
(_L)->Context = CURRENT_THREAD; \
(_pLS)->LockState = WRITE_LOCK_STATE_FREE; \
} \
}
#define NDIS_READ_LOCK_STATE_FREE(_L, _pLS) \
{ \
ULONG Prc; \
ASSERT(CURRENT_IRQL == DISPATCH_LEVEL); \
Prc = CURRENT_PROCESSOR; \
ASSERT((_L)->RefCount[Prc].RefCount > 0); \
(_L)->RefCount[Prc].RefCount--; \
(_pLS)->LockState = LOCK_STATE_UNKNOWN; \
if ((_pLS)->OldIrql < DISPATCH_LEVEL) \
{ \
KeLowerIrql((_pLS)->OldIrql); \
} \
}
#define NDIS_READ_LOCK_STATE_FREE_DPC(_L, _pLS) \
{ \
ULONG Prc; \
ASSERT(CURRENT_IRQL == DISPATCH_LEVEL); \
Prc = CURRENT_PROCESSOR; \
ASSERT((INT)(_L)->RefCount[Prc].RefCount > 0); \
(_L)->RefCount[Prc].RefCount--; \
(_pLS)->LockState = LOCK_STATE_UNKNOWN; \
}
#define NDIS_WRITE_LOCK_STATE_FREE(_L, _pLS) \
{ \
/* We acquired it. Now we need to free it */ \
ASSERT(CURRENT_IRQL == DISPATCH_LEVEL); \
ASSERT((_L)->Context == CURRENT_THREAD); \
(_pLS)->LockState = LOCK_STATE_UNKNOWN; \
(_L)->Context = NULL; \
RELEASE_SPIN_LOCK(&(_L)->SpinLock, (_pLS)->OldIrql); \
}
#define NDIS_LOCK_STATE_ALREADY_ACQUIRED(_L, _pLS) \
{ \
ASSERT((_L)->Context == CURRENT_THREAD); \
/* Nothing to do */ \
}
#define xLockHandler(_L, _pLS) \
{ \
switch ((_pLS)->LockState) \
{ \
case READ_LOCK: \
NDIS_READ_LOCK(_L, _pLS); \
break; \
\
case WRITE_LOCK_STATE_UNKNOWN: \
NDIS_WRITE_LOCK_STATE_UNKNOWN(_L, _pLS); \
break; \
\
case READ_LOCK_STATE_FREE: \
NDIS_READ_LOCK_STATE_FREE(_L, _pLS); \
break; \
\
case WRITE_LOCK_STATE_FREE: \
NDIS_WRITE_LOCK_STATE_FREE(_L, _pLS); \
break; \
\
case LOCK_STATE_ALREADY_ACQUIRED: \
NDIS_LOCK_STATE_ALREADY_ACQUIRED(_L, _pLS); \
/* Nothing to do */ \
break; \
\
default: \
ASSERT(0); \
break; \
} \
}
#define NDIS_INITIALIZE_RCVD_PACKET(_P, _NSR, _M) \
{ \
_NSR->RefCount = -1; \
_NSR->XRefCount = 0; \
_NSR->Miniport = _M; \
/* \
* Ensure that we force re-calculation. \
*/ \
(_P)->Private.ValidCounts = FALSE; \
}
#define NDIS_ACQUIRE_PACKET_LOCK_DPC(_NSR) ACQUIRE_SPIN_LOCK_DPC(&(_NSR)->Lock)
#define NDIS_RELEASE_PACKET_LOCK_DPC(_NSR) RELEASE_SPIN_LOCK_DPC(&(_NSR)->Lock)
#define ADJUST_PACKET_REFCOUNT(_NSR, _pRC) \
{ \
*(_pRC) = InterlockedDecrement(&(_NSR)->RefCount); \
}
#ifdef TRACK_RECEIVED_PACKETS
//
// NSR->XRefCount = Number of times protocol said it will call NdisReturnPacket
// NSR->RefCount = is decremented every time protocol calls NdisReturnPackets
//
#define COALESCE_PACKET_REFCOUNT_DPC(_Packet, _M, _NSR, _pOob, _pRC) \
{ \
LONG _LocalXRef = (_NSR)->XRefCount; \
if (_LocalXRef != 0) \
{ \
LONG _LocalRef; \
ASSERT((_pOob)->Status != NDIS_STATUS_RESOURCES); \
_LocalRef = InterlockedExchangeAdd(&(_NSR)->RefCount, (_LocalXRef + 1)); \
*(_pRC) = _LocalRef + _LocalXRef + 1; \
if ((*(_pRC) > 0) && (!MINIPORT_TEST_FLAG((_M), fMINIPORT_DESERIALIZE))) \
{ \
NDIS_SET_PACKET_STATUS(_Packet, NDIS_STATUS_PENDING); \
} \
if ((*(_pRC) == 0) && ((_NSR)->RefCount != 0)) \
{ \
DbgPrint("Packet %p is being returned back to the miniport" \
" but the ref count is not zero.\n", _Packet); \
DbgBreakPoint(); \
} \
} \
else \
{ \
_NSR->RefCount = *(_pRC) = 0; \
} \
}
#define TACKLE_REF_COUNT(_M, _P, _S, _O) \
{ \
LONG RefCount; \
\
/* \
* We started off with the RefCount set to -1. \
* NdisReturnPackets may have been called which will further reduce it. \
* Add back the RefCount returned by the protocol \
* and account for the initial -1. \
*/ \
COALESCE_PACKET_REFCOUNT_DPC(_P, _M, _S, _O, &RefCount); \
\
NDIS_APPEND_RCV_LOGFILE(_P, _M, CurThread, \
7, OrgPacketStackLocation+1, _S->RefCount, _S->XRefCount, NDIS_GET_PACKET_STATUS(_P)); \
\
\
if (RefCount == 0) \
{ \
POP_PACKET_STACK(_P); \
if ((_O)->Status != NDIS_STATUS_RESOURCES) \
{ \
if (MINIPORT_TEST_FLAG((_M), fMINIPORT_DESERIALIZE)) \
{ \
/* \
* Return packets which are truly free, \
* but only for deserialized drivers \
*/ \
W_RETURN_PACKET_HANDLER Handler; \
if (_S->RefCount != 0) \
{ \
DbgPrint("Packet %p is being returned back to the " \
"miniport but the ref count is not zero.\n", _P); \
DbgBreakPoint(); \
} \
if ((_P)->Private.Head == NULL) \
{ \
DbgPrint("Packet %p is being returned back to the miniport with NULL Head.\n", _P); \
DbgBreakPoint(); \
} \
\
if (!MINIPORT_TEST_FLAG(_M, fMINIPORT_INTERMEDIATE_DRIVER)) \
{ \
ULONG SL; \
if ((SL = CURR_STACK_LOCATION(_P)) != -1) \
{ \
DbgPrint("Packet %p is being returned back to the non-IM miniport"\
" with stack location %lx.\n", Packet, SL); \
DbgBreakPoint(); \
} \
} \
\
Handler = (_M)->DriverHandle->MiniportCharacteristics.ReturnPacketHandler;\
(_S)->Miniport = NULL; \
(_O)->Status = NDIS_STATUS_PENDING; \
\
NDIS_APPEND_RCV_LOGFILE(_P, _M, CurThread, \
8, OrgPacketStackLocation+1, _S->RefCount, _S->XRefCount, NDIS_GET_PACKET_STATUS(_P)); \
\
\
(*Handler)((_M)->MiniportAdapterContext, _P); \
} \
else \
{ \
{ \
ULONG SL; \
if ((SL = CURR_STACK_LOCATION(_P)) != -1) \
{ \
DbgPrint("Packet %p is being returned back to the non-IM miniport"\
" with stack location %lx.\n", Packet, SL); \
DbgBreakPoint(); \
} \
} \
\
if ((NDIS_GET_PACKET_STATUS(_P) == NDIS_STATUS_RESOURCES)) \
{ \
NDIS_STATUS _OStatus = (NDIS_STATUS)NDIS_PER_PACKET_INFO_FROM_PACKET(_P, OriginalStatus); \
\
if (_OStatus != NDIS_STATUS_RESOURCES) \
{ \
DbgPrint("Packet %p is being returned back to the non-deserialized miniport"\
" with packet status changed from %lx to NDIS_STATUS_RESOURCES.\n", _P, _OStatus); \
DbgBreakPoint(); \
} \
\
} \
\
(_O)->Status = NDIS_STATUS_SUCCESS; \
NDIS_APPEND_RCV_LOGFILE(_P, _M, CurThread, \
9, OrgPacketStackLocation+1, _S->RefCount, _S->XRefCount, NDIS_GET_PACKET_STATUS(_P)); \
\
} \
} \
} \
else if (MINIPORT_TEST_FLAG((_M), fMINIPORT_INTERMEDIATE_DRIVER)) \
{ \
InterlockedIncrement((PLONG)&(_M)->IndicatedPacketsCount); \
} \
}
#else
//
// NSR->XRefCount = Number of times protocol said it will call NdisReturnPacket
// NSR->RefCount = is decremented every time protocol calls NdisReturnPackets
//
#define COALESCE_PACKET_REFCOUNT_DPC(_Packet, _M, _NSR, _pOob, _pRC) \
{ \
LONG _LocalXRef = (_NSR)->XRefCount; \
if (_LocalXRef != 0) \
{ \
LONG _LocalRef; \
ASSERT((_pOob)->Status != NDIS_STATUS_RESOURCES); \
_LocalRef = InterlockedExchangeAdd(&(_NSR)->RefCount, (_LocalXRef + 1)); \
*(_pRC) = _LocalRef + _LocalXRef + 1; \
if ((*(_pRC) > 0) && (!MINIPORT_TEST_FLAG((_M), fMINIPORT_DESERIALIZE))) \
{ \
NDIS_SET_PACKET_STATUS(_Packet, NDIS_STATUS_PENDING); \
} \
} \
else \
{ \
_NSR->RefCount = *(_pRC) = 0; \
} \
}
#define TACKLE_REF_COUNT(_M, _P, _S, _O) \
{ \
LONG RefCount; \
\
/* \
* We started off with the RefCount set to -1. \
* NdisReturnPackets may have been called which will further reduce it. \
* Add back the RefCount returned by the protocol \
* and account for the initial -1. \
*/ \
COALESCE_PACKET_REFCOUNT_DPC(_P, _M, _S, _O, &RefCount); \
\
if (RefCount == 0) \
{ \
POP_PACKET_STACK(_P); \
if ((_O)->Status != NDIS_STATUS_RESOURCES) \
{ \
if (MINIPORT_TEST_FLAG((_M), fMINIPORT_DESERIALIZE)) \
{ \
/* \
* Return packets which are truly free, \
* but only for deserialized drivers \
*/ \
W_RETURN_PACKET_HANDLER Handler; \
\
Handler = (_M)->DriverHandle->MiniportCharacteristics.ReturnPacketHandler;\
(_S)->Miniport = NULL; \
(_O)->Status = NDIS_STATUS_PENDING; \
\
(*Handler)((_M)->MiniportAdapterContext, _P); \
} \
else \
{ \
(_O)->Status = NDIS_STATUS_SUCCESS; \
} \
} \
} \
else if (MINIPORT_TEST_FLAG((_M), fMINIPORT_INTERMEDIATE_DRIVER)) \
{ \
InterlockedIncrement((PLONG)&(_M)->IndicatedPacketsCount); \
} \
}
#endif
#endif // _NULL_FILTER_DEFS_