/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
ffilter.h
Abstract:
Header file for the address filtering library for NDIS MAC's.
Author:
Anthony V. Ercolano (tonye) creation-date 3-Aug-1990
Environment:
Runs in the context of a single MAC driver.
Notes:
None.
Revision History:
Sean Selitrennikoff (SeanSe) - converter efilter.* for FDDI support.
--*/
#ifndef _FDDI_FILTER_DEFS_
#define _FDDI_FILTER_DEFS_
#define FDDI_LENGTH_OF_LONG_ADDRESS 6
#define FDDI_LENGTH_OF_SHORT_ADDRESS 2
//
// ZZZ This is a little-endian specific check.
//
#define FDDI_IS_MULTICAST(Address, AddressLength, Result) \
{ \
PUCHAR _A = Address; \
*Result = (BOOLEAN)(_A[0] & ((UCHAR)0x01)); \
}
//
// Check whether the frame is SMT or not.
//
#define FDDI_IS_SMT(FcByte, Result) \
{ \
*Result = ((FcByte & ((UCHAR)0xf0)) == 0x40); \
}
//
// Check whether an address is broadcast.
//
#define FDDI_IS_BROADCAST(Address, AddressLength, Result) \
{ \
PUCHAR _A = Address; \
PUCHAR _E = _A + AddressLength;\
*Result = TRUE;\
for (; _A < _E ; _A++) {\
if (*_A != 0xFF) {\
*Result = FALSE;\
break;\
}\
}\
}
//
// This macro will compare network addresses.
//
// A - Is a network address.
//
// B - Is a network address.
//
// Result - The result of comparing two network address.
//
// Result < 0 Implies the B address is greater.
// Result > 0 Implies the A element is greater.
// Result = 0 Implies equality.
//
// Note that this is an arbitrary ordering. There is not
// defined relation on network addresses. This is ad-hoc!
//
//
#define FDDI_COMPARE_NETWORK_ADDRESSES(A,B,_AddressLength,Result) \
{ \
PUCHAR _A = (PUCHAR)(A); \
PUCHAR _B = (PUCHAR)(B); \
if ( *(USHORT UNALIGNED *)_A > \
*(USHORT UNALIGNED *)_B ) { \
*Result = 1; \
} else if ( *(USHORT UNALIGNED *)_A < \
*(USHORT UNALIGNED *)_B ) { \
*Result = (UINT)-1; \
} else if (_AddressLength == 2) { \
*Result = 0; \
} else if ( *(ULONG UNALIGNED *)&_A[2] > \
*(ULONG UNALIGNED *)&_B[2] ) { \
*Result = 1; \
} else if ( *(ULONG UNALIGNED *)&_A[2] < \
*(ULONG UNALIGNED *)&_B[2] ) { \
*Result = (UINT)-1; \
} else { \
*Result = 0; \
} \
}
//
// This macro will compare network addresses.
//
// A - Is a network address.
//
// B - Is a network address.
//
// Result - The result of comparing two network address.
//
// Result != 0 Implies inequality.
// Result == 0 Implies equality.
//
//
#define FDDI_COMPARE_NETWORK_ADDRESSES_EQ(A,B,_AddressLength,Result) \
{ \
PUCHAR _A = (PUCHAR)(A); \
PUCHAR _B = (PUCHAR)(B); \
if ( ( *(USHORT UNALIGNED *)_A == \
*(USHORT UNALIGNED *)_B ) && \
( ( (_AddressLength) == 2 ) || \
( *(ULONG UNALIGNED *)&_A[2] == \
*(ULONG UNALIGNED *)&_B[2] ) ) ) { \
*Result = 0; \
} else { \
*Result = 1; \
} \
}
//
// This macro is used to copy from one network address to
// another.
//
#define FDDI_COPY_NETWORK_ADDRESS(D,S,AddressLength) \
{ \
PCHAR _D = (D); \
PCHAR _S = (S); \
UINT _C = (AddressLength);\
for ( ; _C > 0 ; _D++, _S++, _C--) {\
*_D = *_S;\
}\
}
//
//UINT
//FDDI_QUERY_FILTER_CLASSES(
// IN PFDDI_FILTER Filter
// )
//
// This macro returns the currently enabled filter classes.
//
// NOTE: THIS MACRO ASSUMES THAT THE FILTER LOCK IS HELD.
//
#define FDDI_QUERY_FILTER_CLASSES(Filter) ((Filter)->CombinedPacketFilter)
//
//UINT
//FDDI_QUERY_PACKET_FILTER(
// IN PFDDI_FILTER Filter,
// IN NDIS_HANDLE NdisFilterHandle
// )
//
// This macro returns the currently enabled filter classes for a specific
// open instance.
//
// NOTE: THIS MACRO ASSUMES THAT THE FILTER LOCK IS HELD.
//
#define FDDI_QUERY_PACKET_FILTER(Filter, NdisFilterHandle) \
(((PFDDI_BINDING_INFO)(NdisFilterHandle))->PacketFilters)
//
//UINT
//FDDI_NUMBER_OF_GLOBAL_FILTER_LONG_ADDRESSES(
// IN PFDDI_FILTER Filter
// )
//
// This macro returns the number of multicast addresses in the
// multicast address list.
//
// NOTE: THIS MACRO ASSUMES THAT THE FILTER LOCK IS HELD.
//
#define FDDI_NUMBER_OF_GLOBAL_FILTER_LONG_ADDRESSES(Filter) ((Filter)->NumberOfLongAddresses)
//
//UINT
//FDDI_NUMBER_OF_GLOBAL_FILTER_SHORT_ADDRESSES(
// IN PFDDI_FILTER Filter
// )
//
// This macro returns the number of multicast addresses in the
// multicast address list.
//
// NOTE: THIS MACRO ASSUMES THAT THE FILTER LOCK IS HELD.
//
#define FDDI_NUMBER_OF_GLOBAL_FILTER_SHORT_ADDRESSES(Filter) ((Filter)->NumberOfShortAddresses)
//
// An action routine type. The routines are called
// when a filter type is set for the first time or
// no more bindings require a particular type of filter.
//
// NOTE: THIS ROUTINE SHOULD ASSUME THAT THE LOCK IS ACQUIRED.
//
typedef
NDIS_STATUS
(*FDDI_FILTER_CHANGE)(
IN UINT OldFilterClasses,
IN UINT NewFilterClasses,
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
);
//
// This action routine is called when a new multicast address
// list is given to the filter. The action routine is given
// arrays containing the old and new multicast addresses.
//
// NOTE: THIS ROUTINE SHOULD ASSUME THAT THE LOCK IS ACQUIRED.
//
typedef
NDIS_STATUS
(*FDDI_ADDRESS_CHANGE)(
IN UINT OldLongAddressCount,
IN CHAR OldLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
IN UINT NewLongAddressCount,
IN CHAR NewLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
IN UINT OldShortAddressCount,
IN CHAR OldShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
IN UINT NewShortAddressCount,
IN CHAR NewShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
);
//
// This action routine is called when the mac requests a close for
// a particular binding *WHILE THE BINDING IS BEING INDICATED TO
// THE PROTOCOL*. The filtering package can't get rid of the open
// right away. So this routine will be called as soon as the
// NdisIndicateReceive returns.
//
// NOTE: THIS ROUTINE SHOULD ASSUME THAT THE LOCK IS ACQUIRED.
//
typedef
VOID
(*FDDI_DEFERRED_CLOSE)(
IN NDIS_HANDLE MacBindingHandle
);
typedef ULONG FDDI_MASK,*PFDDI_MASK;
//
// Maximum number of opens the filter package will support. This is
// the max so that bit masks can be used instead of a spaghetti of
// pointers.
//
#define FDDI_FILTER_MAX_OPENS (sizeof(ULONG) * 8)
//
// The binding info is threaded on two lists. When
// the binding is free it is on a single freelist.
//
// When the binding is being used it is on a doubly linked
// index list.
//
typedef struct _FDDI_BINDING_INFO {
NDIS_HANDLE MacBindingHandle;
NDIS_HANDLE NdisBindingContext;
UINT PacketFilters;
ULONG References;
struct _FDDI_BINDING_INFO *NextOpen;
struct _FDDI_BINDING_INFO *PrevOpen;
BOOLEAN ReceivedAPacket;
UCHAR FilterIndex;
} FDDI_BINDING_INFO,*PFDDI_BINDING_INFO;
//
// An opaque type that contains a filter database.
// The MAC need not know how it is structured.
//
typedef struct _FDDI_FILTER {
//
// Spin lock used to protect the filter from multiple accesses.
//
PNDIS_SPIN_LOCK Lock;
//
// Pointer to an array of 6 character arrays holding the
// multicast addresses requested for filtering.
//
CHAR (*MulticastLongAddresses)[FDDI_LENGTH_OF_LONG_ADDRESS];
//
// Pointer to an array of FDDI_MASKS that work in conjuction with
// the MulticastLongAddress array. In the masks, a bit being enabled
// indicates that the binding with the given FilterIndex is using
// the corresponding address.
//
FDDI_MASK *BindingsUsingLongAddress;
//
// Pointer to an array of 2 character arrays holding the
// multicast addresses requested for filtering.
//
CHAR (*MulticastShortAddresses)[FDDI_LENGTH_OF_SHORT_ADDRESS];
//
// Pointer to an array of FDDI_MASKS that work in conjuction with
// the MulticastShortAddress array. In the masks, a bit being enabled
// indicates that the binding with the given FilterIndex is using
// the corresponding address.
//
FDDI_MASK *BindingsUsingShortAddress;
//
// Combination of all the filters of all the open bindings.
//
UINT CombinedPacketFilter;
//
// Pointer for traversing the open list.
//
PFDDI_BINDING_INFO OpenList;
//
// Action routines to be invoked on notable changes in the filter.
//
FDDI_ADDRESS_CHANGE AddressChangeAction;
FDDI_FILTER_CHANGE FilterChangeAction;
FDDI_DEFERRED_CLOSE CloseAction;
//
// The maximum number of long addresses used for filtering.
//
UINT MaximumMulticastLongAddresses;
//
// The maximum number of short addresses used for filtering.
//
UINT MaximumMulticastShortAddresses;
//
// The current number of addresses in the LongAddress filter.
//
UINT NumberOfLongAddresses;
//
// The current number of addresses in the ShortAddress filter.
//
UINT NumberOfShortAddresses;
//
// Bit mask of opens that are available.
//
ULONG FreeBindingMask;
//
// Long Address of the adapter.
//
UCHAR AdapterLongAddress[FDDI_LENGTH_OF_LONG_ADDRESS];
//
// Short Address of the adapter.
//
UCHAR AdapterShortAddress[FDDI_LENGTH_OF_SHORT_ADDRESS];
} FDDI_FILTER,*PFDDI_FILTER;
//
// Only for internal wrapper use.
//
VOID
FddiInitializePackage(
VOID
);
VOID
FddiReferencePackage(
VOID
);
VOID
FddiDereferencePackage(
VOID
);
//
// Exported routines
//
EXPORT
BOOLEAN
FddiCreateFilter(
IN UINT MaximumMulticastLongAddresses,
IN UINT MaximumMulticastShortAddresses,
IN FDDI_ADDRESS_CHANGE AddressChangeAction,
IN FDDI_FILTER_CHANGE FilterChangeAction,
IN FDDI_DEFERRED_CLOSE CloseAction,
IN PUCHAR AdapterLongAddress,
IN PUCHAR AdapterShortAddress,
IN PNDIS_SPIN_LOCK Lock,
OUT PFDDI_FILTER *Filter
);
EXPORT
VOID
FddiDeleteFilter(
IN PFDDI_FILTER Filter
);
EXPORT
BOOLEAN
FddiNoteFilterOpenAdapter(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE NdisBindingContext,
OUT PNDIS_HANDLE NdisFilterHandle
);
EXPORT
NDIS_STATUS
FddiDeleteFilterOpenAdapter(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle,
IN PNDIS_REQUEST NdisRequest
);
EXPORT
NDIS_STATUS
FddiChangeFilterLongAddresses(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle,
IN PNDIS_REQUEST NdisRequest,
IN UINT AddressCount,
IN CHAR Addresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
IN BOOLEAN Set
);
EXPORT
NDIS_STATUS
FddiChangeFilterShortAddresses(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle,
IN PNDIS_REQUEST NdisRequest,
IN UINT AddressCount,
IN CHAR Addresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
IN BOOLEAN Set
);
#define FddiShouldAddressLoopBackMacro(_Filter, _Address, _AddressLength, _pfLoopBack, _pfSelfDirected)\
{ \
/* \
* Holds the result of address determinations. \
*/ \
INT ResultOfAddressCheck; \
\
UINT CombinedFilters; \
\
CombinedFilters = FDDI_QUERY_FILTER_CLASSES(_Filter); \
\
*(_pfLoopBack) = FALSE; \
*(_pfSelfDirected) = FALSE; \
\
do \
{ \
if (CombinedFilters & NDIS_PACKET_TYPE_PROMISCUOUS) \
{ \
*(_pfLoopBack) = TRUE; \
break; \
} \
\
/* \
* First check if it *at least* has the multicast address bit. \
*/ \
\
FDDI_IS_MULTICAST( \
_Address, \
_AddressLength, \
&ResultOfAddressCheck \
); \
\
if (ResultOfAddressCheck) \
{ \
/* \
* It is at least a multicast address. Check to see if \
* it is a broadcast address. \
*/ \
\
FDDI_IS_BROADCAST( \
_Address, \
_AddressLength, \
&ResultOfAddressCheck \
); \
\
if (ResultOfAddressCheck) \
{ \
if (CombinedFilters & NDIS_PACKET_TYPE_BROADCAST) \
{ \
*(_pfLoopBack) = TRUE; \
break; \
} \
else \
{ \
break; \
} \
\
} else { \
\
if ((CombinedFilters & NDIS_PACKET_TYPE_ALL_MULTICAST) || \
(CombinedFilters & NDIS_PACKET_TYPE_MULTICAST)) \
{ \
*(_pfLoopBack) = TRUE; \
break; \
} \
else \
{ \
break; \
} \
} \
} \
else \
{ \
/* \
* Directed to ourself? \
*/ \
if (AddressLength == FDDI_LENGTH_OF_LONG_ADDRESS) \
{ \
FDDI_COMPARE_NETWORK_ADDRESSES_EQ((_Filter)->AdapterLongAddress, \
_Address, \
FDDI_LENGTH_OF_LONG_ADDRESS, \
&ResultOfAddressCheck \
); \
} \
else \
{ \
FDDI_COMPARE_NETWORK_ADDRESSES_EQ((_Filter)->AdapterShortAddress, \
_Address, \
FDDI_LENGTH_OF_SHORT_ADDRESS, \
&ResultOfAddressCheck \
); \
} \
\
if (ResultOfAddressCheck == 0) \
{ \
*(_pfLoopBack) = TRUE; \
*(_pfSelfDirected) = TRUE; \
break; \
} \
} \
} while (FALSE); \
}
EXPORT
BOOLEAN
FddiShouldAddressLoopBack(
IN PFDDI_FILTER Filter,
IN CHAR Address[],
IN UINT LengthOfAddress
);
EXPORT
NDIS_STATUS
FddiFilterAdjust(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle,
IN PNDIS_REQUEST NdisRequest,
IN UINT FilterClasses,
IN BOOLEAN Set
);
EXPORT
UINT
FddiNumberOfOpenFilterLongAddresses(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle
);
EXPORT
UINT
FddiNumberOfOpenFilterShortAddresses(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle
);
EXPORT
VOID
FddiQueryGlobalFilterLongAddresses(
OUT PNDIS_STATUS Status,
IN PFDDI_FILTER Filter,
IN UINT SizeOfArray,
OUT PUINT NumberOfAddresses,
IN OUT CHAR AddressArray[][FDDI_LENGTH_OF_LONG_ADDRESS]
);
EXPORT
VOID
FddiQueryGlobalFilterShortAddresses(
OUT PNDIS_STATUS Status,
IN PFDDI_FILTER Filter,
IN UINT SizeOfArray,
OUT PUINT NumberOfAddresses,
IN OUT CHAR AddressArray[][FDDI_LENGTH_OF_SHORT_ADDRESS]
);
EXPORT
VOID
FddiQueryOpenFilterLongAddresses(
OUT PNDIS_STATUS Status,
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle,
IN UINT SizeOfArray,
OUT PUINT NumberOfAddresses,
IN OUT CHAR AddressArray[][FDDI_LENGTH_OF_LONG_ADDRESS]
);
EXPORT
VOID
FddiQueryOpenFilterShortAddresses(
OUT PNDIS_STATUS Status,
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE NdisFilterHandle,
IN UINT SizeOfArray,
OUT PUINT NumberOfAddresses,
IN OUT CHAR AddressArray[][FDDI_LENGTH_OF_SHORT_ADDRESS]
);
EXPORT
VOID
FddiFilterIndicateReceive(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE MacReceiveContext,
IN PCHAR Address,
IN UINT AddressLength,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookaheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize
);
EXPORT
VOID
FddiFilterDprIndicateReceive(
IN PFDDI_FILTER Filter,
IN NDIS_HANDLE MacReceiveContext,
IN PCHAR Address,
IN UINT AddressLength,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookaheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize
);
EXPORT
VOID
FddiFilterIndicateReceiveComplete(
IN PFDDI_FILTER Filter
);
EXPORT
VOID
FddiFilterDprIndicateReceiveComplete(
IN PFDDI_FILTER Filter
);
#endif // _FDDI_FILTER_DEFS_