summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isn/ipx/ipxtypes.h
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/tdi/isn/ipx/ipxtypes.h')
-rw-r--r--private/ntos/tdi/isn/ipx/ipxtypes.h2144
1 files changed, 2144 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/ipx/ipxtypes.h b/private/ntos/tdi/isn/ipx/ipxtypes.h
new file mode 100644
index 000000000..a353a65b4
--- /dev/null
+++ b/private/ntos/tdi/isn/ipx/ipxtypes.h
@@ -0,0 +1,2144 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ ipxtypes.h
+
+Abstract:
+
+ This module contains definitions specific to the
+ IPX module of the ISN transport.
+
+Author:
+
+ Adam Barr (adamba) 2-September-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Sanjay Anand (SanjayAn) 3-Oct-1995
+ Changes to support transfer of buffer ownership to transports - tagged [CH]
+
+ Sanjay Anand (SanjayAn) 27-Oct-1995
+ Changes to support Plug and Play (in _PNP_POWER)
+
+--*/
+
+#ifdef SNMP
+#include <hipxmib.h>
+#endif SNMP
+
+//
+// Definition of the protocol reserved field of a send packet.
+//
+
+typedef struct _IPX_SEND_RESERVED {
+ UCHAR Identifier; // 0 for IPX packets
+ BOOLEAN SendInProgress; // used in an NdisSend
+ BOOLEAN OwnedByAddress; // packet is owned by an address
+ UCHAR DestinationType; // one of DEF, BCAST, MCAST
+ struct _IPX_PADDING_BUFFER * PaddingBuffer; // if one was allocated
+ PNDIS_BUFFER PreviousTail; // if padding buffer was appended
+#ifdef _PNP_POWER
+ IPX_LOCAL_TARGET LocalTarget;
+ USHORT CurrentNicId; // current binding being tried for net 0 sends
+ ULONG PacketLength; // length that comes into IpxSendFrame initially
+ BOOLEAN Net0SendSucceeded; // at least one NdisSend succeeded for net 0 sends
+#endif
+ SINGLE_LIST_ENTRY PoolLinkage; // when on free queue
+ LIST_ENTRY GlobalLinkage; // all packets are on this
+ LIST_ENTRY WaitLinkage; // when on WaitingForRoute/WaitingRipPackets
+#ifdef IPX_TRACK_POOL
+ PVOID Pool; // send pool it was allocated from
+#endif
+ struct _ADDRESS * Address; // that owns this packet, if ones does
+
+ //
+ // The next fields are used differently depending on whether
+ // the packet is being used for a datagram send or a rip request.
+ //
+
+ union {
+ struct {
+ PREQUEST Request; // send datagram request
+ struct _ADDRESS_FILE * AddressFile; // that this send is on
+ USHORT CurrentNicId; // current binding being tried for net 0 sends
+ BOOLEAN Net0SendSucceeded; // at least one NdisSend succeeded for net 0 sends
+ BOOLEAN OutgoingSap; // packet is sent from the SAP socket
+ } SR_DG;
+ struct {
+ ULONG Network; // net we are looking for
+ USHORT CurrentNicId; // current binding being tried
+ UCHAR RetryCount; // number of times sent; 0xfe = response, 0xff = down
+ BOOLEAN RouteFound; // network has been found
+ USHORT SendTime; // timer expirations when sent.
+ BOOLEAN NoIdAdvance; // don't advance CurrentNicId this time.
+ } SR_RIP;
+ } u;
+
+ PUCHAR Header; // points to the MAC/IPX header
+ PNDIS_BUFFER HeaderBuffer; // the NDIS_BUFFER describing Header;
+#if BACK_FILL
+ BOOLEAN BackFill; // 1 if we are using SMB's extended header
+ PNDIS_BUFFER IpxHeader; // Place holder for our IpxHeader
+ PNDIS_BUFFER MacHeader; // Place holder for our mac header
+ PVOID MappedSystemVa;
+ PVOID ByteOffset;
+ LONG UserLength;
+#endif
+} IPX_SEND_RESERVED, *PIPX_SEND_RESERVED;
+
+//
+// Values for the DestinationType field.
+//
+
+#define DESTINATION_DEF 1
+#define DESTINATION_BCAST 2
+#define DESTINATION_MCAST 3
+
+//
+// Used to indicate to IpxReceiveIndication that this is a loopback packet
+// Assumption: Ndis cannot return this as the NdisBindingHandle value since
+// that is a pointer (our pointers shd in kernel space, if not in Nonpaged pool).
+//
+#define IPX_LOOPBACK_COOKIE 0x00460007
+
+//
+// MIN/MAX macros
+//
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#ifdef _PNP_POWER
+
+//
+// In order to avoid a lock to read a value, this is used.
+// As long as the final value has made it to _b by the time
+// the check is made, this works fine.
+//
+
+#define ASSIGN_LOOP(_a, _b) \
+ do { \
+ _a = _b; \
+ } while ( _a != _b );
+
+//
+// Gets the value of a Ulong (possibly a pointer) by adding 0 in an interlocked manner.
+// This relies on the fact that the return of the ExchangeAdd will be the value prior to
+// addition. Since the value added is 0, the final value stays the same.
+//
+#define GET_VALUE(x) \
+ InterlockedExchangeAdd((PULONG)&(x), 0)
+
+#define SET_VALUE(x,y) \
+ InterlockedExchange((PLONG)&(x), (LONG)(y))
+
+/*
+PBINDING
+NIC_ID_TO_BINDING (
+ IN PDEVICE _device,
+ IN USHORT _nicid
+ );
+*/
+//
+// We need to ensure that the binding array pointer is valid hence use the interlocked operation.
+// Also, the binding pointer read out of the array should be valid. Since the bindings are never
+// freed (IPX maintains a pool of bindings), the pointer thus retrieved will always point to
+// memory that belongs to us, which in the worst case could point to a re-claimed binding block.
+//
+// BUGBUGZZ: we can eliminate the second interlock if we always ensure that the bindings in an array
+// dont change i.e. when we move around bindings, do them in a copy and make that the master (thru'
+// a single ulong exchange).
+//
+// A problem that still remains here is that even if we get a valid (IPX owned non-paged) ptr out of
+// the array, we still cannot atomically get a ref on the binding
+// We might need those locks after all.... (revisit post SUR when the delete is enabled).
+//
+
+//
+// NicId cast to SHORT so DemandDial Nic (0xffff) maps to -1.
+//
+#define NIC_ID_TO_BINDING(_device, _nicid) \
+ ((PBINDING)GET_VALUE( ((PBIND_ARRAY_ELEM) GET_VALUE( (_device)->Bindings) )[(SHORT)_nicid].Binding ))
+
+/*
+PBINDING
+NIC_ID_TO_BINDING_NO_ILOCK (
+ IN PDEVICE _device,
+ IN USHORT _nicid
+ );
+*/
+//
+// No interlocked operations are used here to get to the binding. This is used in the PnP add/delete
+// adapter paths on the assumption that NDIS will serialize the addition/deletion of cards. [JammelH: 5/15/96]
+//
+#define NIC_ID_TO_BINDING_NO_ILOCK(_device, _nicid) \
+ ((_device)->Bindings[_nicid].Binding)
+
+/*
+VOID
+INSERT_BINDING(
+ IN PDEVICE _device,
+ IN USHORT _nicid,
+ IN PBINDING _binding
+ )
+*/
+//
+// We dont do a get_value for the first arg of the macro since we are the writer and
+// this value cannot change from under us here (NDIS will not give us two PnP Add adapter
+// indications simultaneously).
+//
+#define INSERT_BINDING(_device, _nicid, _binding) \
+ SET_VALUE((_device)->Bindings[_nicid].Binding, (_binding));
+
+/*
+VOID
+SET_VERSION(
+ IN PDEVICE _device,
+ IN USHORT _nicid
+ )
+*/
+#define SET_VERSION(_device, _nicid) \
+ SET_VALUE((_device)->Bindings[_nicid].Version, ++(_device)->BindingVersionNumber);
+
+/*
+PBINDING
+NIC_HANDLE_TO_BINDING (
+ IN PDEVICE _device,
+ IN PNIC_HANDLE _nichandle,
+ );
+*/
+#ifdef _PNP_LATER
+#define NIC_HANDLE_TO_BINDING(_device, _nichandle) \
+ (((_nichandle)->Signature == IPX_BINDING_SIGNATURE) && \
+ ((_nichandle)->Version == (_device)->Bindings[(_nichandle)->NicId].Version)) ? \
+ (_device)->Bindings[(_nichandle)->NicId].Binding : NULL;
+#else
+
+#define NIC_HANDLE_TO_BINDING(_device, _nichandle) \
+ NIC_ID_TO_BINDING(_device, (_nichandle)->NicId);
+#endif
+
+/*
+VOID
+FILL_LOCAL_TARGET(
+ IN PLOCAL_TARGET _localtarget,
+ IN USHORT _nicid
+ )
+*/
+
+#define FILL_LOCAL_TARGET(_localtarget, _nicid) \
+ NIC_HANDLE_FROM_NIC((_localtarget)->NicHandle, _nicid)
+
+#define NIC_FROM_LOCAL_TARGET(_localtarget) \
+ (_localtarget)->NicHandle.NicId
+
+#endif _PNP_POWER
+
+//
+// Definition of the protocol reserved field of a receive packet.
+//
+
+typedef struct _IPX_RECEIVE_RESERVED {
+ UCHAR Identifier; // 0 for IPX packets
+ BOOLEAN TransferInProgress; // used in an NdisTransferData
+ BOOLEAN OwnedByAddress; // packet is owned by an address
+#ifdef IPX_TRACK_POOL
+ PVOID Pool; // send pool it was allocated from
+#endif
+ struct _ADDRESS * Address; // that owns this packet, if ones does
+ PREQUEST SingleRequest; // if transfer is for one only
+ struct _IPX_RECEIVE_BUFFER * ReceiveBuffer; // if transfer is for multiple requests
+ SINGLE_LIST_ENTRY PoolLinkage; // when on free queue
+ LIST_ENTRY GlobalLinkage; // all packets are on this
+ LIST_ENTRY Requests; // waiting on this transfer
+ PVOID pContext;
+ ULONG Index;
+} IPX_RECEIVE_RESERVED, *PIPX_RECEIVE_RESERVED;
+
+//
+// The amount of data we need in our standard header, rounded up
+// to the next longword bounday.
+//
+// [BUGBUGZZ] Make this declaration in one place
+//
+#define PACKET_HEADER_SIZE (MAC_HEADER_SIZE + IPX_HEADER_SIZE + RIP_PACKET_SIZE)
+
+//
+// Types to abstract NDIS packets. This is to allow us to
+// switch from using our own memory for packets to using
+// authentically allocated NDIS packets.
+//
+
+// #define IPX_OWN_PACKETS 1
+
+#define IpxAllocateSendPacket(_Device,_SendPacket,_Status) { \
+ NdisReinitializePacket((PNDIS_PACKET)(PACKET(_SendPacket))); \
+ *(_Status) = STATUS_SUCCESS; \
+}
+
+#define IpxAllocateReceivePacket(_Device,_ReceivePacket,_Status) { \
+ NdisReinitializePacket((PNDIS_PACKET)(PACKET(_ReceivePacket))); \
+ *(_Status) = STATUS_SUCCESS; \
+}
+
+#ifdef IPX_OWN_PACKETS
+
+#define NDIS_PACKET_SIZE 48
+// #define NDIS_PACKET_SIZE FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0])
+
+typedef struct _IPX_SEND_PACKET {
+ UCHAR Data[NDIS_PACKET_SIZE+sizeof(IPX_SEND_RESERVED)];
+} IPX_SEND_PACKET, *PIPX_SEND_PACKET;
+
+typedef struct _IPX_RECEIVE_PACKET {
+ UCHAR Data[NDIS_PACKET_SIZE+sizeof(IPX_RECEIVE_RESERVED)];
+} IPX_RECEIVE_PACKET, *PIPX_RECEIVE_PACKET;
+
+#define PACKET(_Packet) ((PNDIS_PACKET)((_Packet)->Data))
+
+#define IpxFreeSendPacket(_Device,_Packet)
+
+#define IpxFreeReceivePacket(_Device,_Packet)
+
+#else // IPX_OWN_PACKETS
+
+typedef struct _IPX_SEND_PACKET {
+ PNDIS_PACKET Packet;
+ NDIS_HANDLE PoolHandle;
+} IPX_SEND_PACKET, *PIPX_SEND_PACKET;
+
+typedef struct _IPX_RECEIVE_PACKET {
+ PNDIS_PACKET Packet;
+ NDIS_HANDLE PoolHandle;
+} IPX_RECEIVE_PACKET, *PIPX_RECEIVE_PACKET;
+
+#define PACKET(_Packet) ((_Packet)->Packet)
+
+#define IpxAllocateSingleSendPacket(_Device,_SendPacket,_Status) { \
+ NdisAllocatePacketPool(_Status, &(_SendPacket)->PoolHandle,1,sizeof(IPX_SEND_RESERVED)); \
+ if (*(_Status) == NDIS_STATUS_SUCCESS) { \
+ NdisAllocatePacket(_Status, &(_SendPacket)->Packet, (_SendPacket)->PoolHandle); \
+ if (*(_Status) == NDIS_STATUS_SUCCESS) { \
+ (_Device)->MemoryUsage += \
+ (FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0])+ \
+ FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0])+ \
+ sizeof(IPX_SEND_RESERVED)); \
+ } else {\
+ IPX_DEBUG (PACKET, ("Could not allocate Ndis packet memory\n"));\
+ }\
+ } else {\
+ IPX_DEBUG (PACKET, ("Could not allocate Ndis pool memory\n"));\
+ }\
+}
+
+#define IpxAllocateSingleReceivePacket(_Device,_ReceivePacket,_Status) { \
+ NdisAllocatePacketPool(_Status, &(_ReceivePacket)->PoolHandle,1,sizeof(IPX_RECEIVE_RESERVED)); \
+ if (*(_Status) == NDIS_STATUS_SUCCESS) { \
+ NdisAllocatePacket(_Status, &(_ReceivePacket)->Packet, (_ReceivePacket)->PoolHandle); \
+ if (*(_Status) == NDIS_STATUS_SUCCESS) { \
+ (_Device)->MemoryUsage += \
+ (FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0])+ \
+ FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0])+ \
+ sizeof(IPX_RECEIVE_RESERVED)); \
+ } else {\
+ IPX_DEBUG (PACKET, ("Could not allocate Ndis packet memory\n"));\
+ }\
+ } else {\
+ IPX_DEBUG (PACKET, ("Could not allocate Ndis pool memory\n"));\
+ }\
+}
+
+#define IpxFreeSingleSendPacket(_Device,_Packet) { \
+ NdisFreePacket((_Packet).Packet); \
+ NdisFreePacketPool((_Packet).PoolHandle); \
+ (_Device)->MemoryUsage -= \
+ (FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0])+ \
+ FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0])+ \
+ sizeof(IPX_SEND_RESERVED)); \
+}
+#define IpxFreeSingleReceivePacket(_Device,_Packet) { \
+ NdisFreePacket((_Packet).Packet); \
+ NdisFreePacketPool((_Packet).PoolHandle); \
+ (_Device)->MemoryUsage -= \
+ (FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0])+ \
+ FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0])+ \
+ sizeof(IPX_RECEIVE_RESERVED)); \
+}
+
+#define IpxFreeSendPacket(_Device,_Packet) NdisFreePacket(PACKET(_Packet))
+
+#define IpxFreeReceivePacket(_Device,_Packet) NdisFreePacket(PACKET(_Packet))
+
+#endif // IPX_OWN_PACKETS
+
+#define SEND_RESERVED(_Packet) ((PIPX_SEND_RESERVED)((PACKET(_Packet))->ProtocolReserved))
+#define RECEIVE_RESERVED(_Packet) ((PIPX_RECEIVE_RESERVED)((PACKET(_Packet))->ProtocolReserved))
+
+
+//
+// This is the structure that contains a receive buffer for
+// datagrams that are going to multiple recipients.
+//
+
+typedef struct _IPX_RECEIVE_BUFFER {
+ LIST_ENTRY GlobalLinkage; // all buffers are on this
+#ifdef IPX_TRACK_POOL
+ PVOID Pool; // receive buffer pool was allocated from
+#endif
+ SINGLE_LIST_ENTRY PoolLinkage; // when on free list
+ PNDIS_BUFFER NdisBuffer; // length of the NDIS buffer
+ ULONG DataLength; // length of the data
+ PUCHAR Data; // the actual data
+} IPX_RECEIVE_BUFFER, *PIPX_RECEIVE_BUFFER;
+
+
+//
+// This is the structure that contains a padding buffer for
+// padding ethernet frames out to an even number of bytes.
+//
+
+typedef struct _IPX_PADDING_BUFFER {
+ LIST_ENTRY GlobalLinkage; // all buffers are on this
+ SINGLE_LIST_ENTRY PoolLinkage; // when on free list
+ PNDIS_BUFFER NdisBuffer; // length of the NDIS buffer
+ ULONG DataLength; // length of the data
+ UCHAR Data[1]; // the actual pad data
+} IPX_PADDING_BUFFER, *PIPX_PADDING_BUFFER;
+
+#ifdef IPX_OWN_PACKETS
+
+typedef struct _IPX_SEND_POOL {
+ LIST_ENTRY Linkage;
+ UINT PacketCount;
+ UINT PacketFree;
+ IPX_SEND_PACKET Packets[1];
+} IPX_SEND_POOL, *PIPX_SEND_POOL;
+
+typedef struct _IPX_RECEIVE_POOL {
+ LIST_ENTRY Linkage;
+ UINT PacketCount;
+ UINT PacketFree;
+ IPX_RECEIVE_PACKET Packets[1];
+} IPX_RECEIVE_POOL, *PIPX_RECEIVE_POOL;
+#else
+
+typedef struct _IPX_PACKET_POOL {
+ LIST_ENTRY Linkage;
+ PUCHAR Header;
+ NDIS_HANDLE PoolHandle;
+} IPX_PACKET_POOL, *PIPX_PACKET_POOL;
+
+typedef IPX_PACKET_POOL IPX_RECEIVE_POOL, *PIPX_RECEIVE_POOL;
+typedef IPX_PACKET_POOL IPX_SEND_POOL, *PIPX_SEND_POOL;
+
+#endif // IPX_OWN_PACKETS
+
+typedef struct _IPX_RECEIVE_BUFFER_POOL {
+ LIST_ENTRY Linkage;
+ UINT BufferCount;
+ UINT BufferFree;
+ IPX_RECEIVE_BUFFER Buffers[1];
+ // after the packets the data buffers are allocated also.
+} IPX_RECEIVE_BUFFER_POOL, *PIPX_RECEIVE_BUFFER_POOL;
+
+//
+// Number of upper drivers we support.
+//
+
+#define UPPER_DRIVER_COUNT 3
+
+
+
+//
+// Tags for memory allocation.
+//
+
+#define MEMORY_CONFIG 0
+#define MEMORY_ADAPTER 1
+#define MEMORY_ADDRESS 2
+#define MEMORY_PACKET 3
+#define MEMORY_RIP 4
+#define MEMORY_SOURCE_ROUTE 5
+#define MEMORY_BINDING 6
+#define MEMORY_QUERY 7
+
+#define MEMORY_MAX 8
+
+#if DBG
+
+//
+// Holds the allocations for a specific memory type.
+//
+
+typedef struct _MEMORY_TAG {
+ ULONG Tag;
+ ULONG BytesAllocated;
+} MEMORY_TAG, *PMEMORY_TAG;
+
+EXTERNAL_LOCK(IpxMemoryInterlock);
+extern MEMORY_TAG IpxMemoryTag[MEMORY_MAX];
+
+#endif
+
+
+//
+// This defines the reasons we delete rip entries for a binding.
+//
+
+typedef enum _IPX_BINDING_CHANGE_TYPE {
+ IpxBindingDeleted,
+ IpxBindingMoved,
+ IpxBindingDown
+} IPX_BINDING_CHANGE_TYPE, *PIPX_BINDING_CHANGE_TYPE;
+
+
+//
+// This structure contains information about a single
+// source routing entry.
+//
+
+typedef struct _SOURCE_ROUTE {
+
+ struct _SOURCE_ROUTE * Next; // next in hash list
+
+ UCHAR MacAddress[6]; // remote MAC address
+ UCHAR TimeSinceUsed; // timer expirations since last used
+ UCHAR SourceRoutingLength; // length of the data
+
+ UCHAR SourceRouting[1]; // source routing data, stored as received in
+
+} SOURCE_ROUTE, *PSOURCE_ROUTE;
+
+#define SOURCE_ROUTE_SIZE(_SourceRoutingLength) \
+ (FIELD_OFFSET(SOURCE_ROUTE, SourceRouting[0]) + (_SourceRoutingLength))
+
+#define SOURCE_ROUTE_HASH_SIZE 16
+
+//
+// ULONG
+// MacSourceRoutingHash(
+// IN PUCHAR MacAddress
+// )
+//
+// /*++
+//
+// Routine Description:
+//
+// This routine returns a hash value based on the MAC address
+// that is pointed to. It will be between 0 and SOURCE_ROUTE_HASH_SIZE.
+//
+// Arguments:
+//
+// MacAddress - The MAC address. NOTE: The source-routing bit may
+// or may not be on in the first byte, this routine will handle
+// that.
+//
+// Return Value:
+//
+// The hash value.
+//
+// --*/
+//
+
+#define MacSourceRoutingHash(_MacAddress) \
+ ((ULONG)((_MacAddress)[5] % SOURCE_ROUTE_HASH_SIZE))
+
+
+
+//
+// this structure describes a single NDIS adapter that IPX is
+// bound to.
+//
+
+struct _DEVICE;
+
+typedef struct _ADAPTER {
+
+ CSHORT Type; // type of this structure
+ USHORT Size; // size of this structure
+
+#if DBG
+ UCHAR Signature1[4]; // contains "IAD1"
+#endif
+
+#ifdef _PNP_POWER
+ ULONG ReferenceCount;
+#endif
+
+ ULONG BindingCount; // number bound to this adapter
+
+ //
+ // Handle returned by the NDIS wrapper after we bind to it.
+ //
+
+ NDIS_HANDLE NdisBindingHandle;
+
+ //
+ // The queue of (currently receive only) requests waiting to complete.
+ //
+
+ LIST_ENTRY RequestCompletionQueue;
+
+ //
+ // IPX header normal offsets for directed and
+ // broadcast/multicast frames.
+ //
+
+ ULONG DefHeaderSizes[ISN_FRAME_TYPE_MAX];
+ ULONG BcMcHeaderSizes[ISN_FRAME_TYPE_MAX];
+
+ //
+ // List of buffers to be used for transfers.
+ //
+
+ ULONG AllocatedReceiveBuffers;
+ LIST_ENTRY ReceiveBufferPoolList;
+ SLIST_HEADER ReceiveBufferList;
+
+ //
+ // List of ethernet padding buffers.
+ //
+
+ ULONG AllocatedPaddingBuffers;
+ SINGLE_LIST_ENTRY PaddingBufferList;
+
+ struct _BINDING * Bindings[ISN_FRAME_TYPE_MAX]; // the binding for each frame type.
+
+ //
+ // TRUE if broadcast reception is enabled on this adapter.
+ //
+
+ BOOLEAN BroadcastEnabled;
+
+ //
+ // TRUE if we have enabled an auto-detected frame type
+ // on this adapter -- used to prevent multiple ones.
+ //
+
+ BOOLEAN AutoDetectFound;
+
+ //
+ // TRUE if we got a response to at least one of our
+ // auto-detect frames.
+ //
+
+ BOOLEAN AutoDetectResponse;
+
+ //
+ // This is TRUE if we are auto-detecting and we have
+ // found the default auto-detect type on the net.
+ //
+
+ BOOLEAN DefaultAutoDetected;
+
+ //
+ // For WAN adapters, we support multiple bindings per
+ // adapter, all with the same frame type. For them we
+ // demultiplex using the local mac address. This stores
+ // the range of device NIC IDs associated with this
+ // particular address.
+ //
+
+ USHORT FirstWanNicId;
+ USHORT LastWanNicId;
+ ULONG WanNicIdCount;
+
+ //
+ // This is based on the configuration.
+ //
+
+ USHORT BindSap; // usually 0x8137
+ USHORT BindSapNetworkOrder; // usually 0x3781
+ BOOLEAN SourceRouting;
+ BOOLEAN EnableFunctionalAddress;
+ BOOLEAN EnableWanRouter;
+ ULONG ConfigMaxPacketSize;
+
+ //
+ // TRUE if the tree is empty, so we can check quickly.
+ //
+
+ BOOLEAN SourceRoutingEmpty[IDENTIFIER_TOTAL];
+
+ //
+ // These are kept around for error logging, and stored right
+ // after this structure.
+ //
+
+ PWCHAR AdapterName;
+ ULONG AdapterNameLength;
+
+ struct _DEVICE * Device;
+
+ CTELock Lock;
+ CTELock * DeviceLock;
+
+ //
+ // some MAC addresses we use in the transport
+ //
+
+ HARDWARE_ADDRESS LocalMacAddress; // our local hardware address.
+
+ //
+ // The value of Device->SourceRoutingTime the last time
+ // we checked the list for timeouts (this is so we can
+ // tell in the timeout code when two bindings point to the
+ // same adapter).
+ //
+
+ CHAR LastSourceRoutingTime;
+
+ //
+ // These are used while initializing the MAC driver.
+ //
+
+ KEVENT NdisRequestEvent; // used for pended requests.
+ NDIS_STATUS NdisRequestStatus; // records request status.
+ NDIS_STATUS OpenErrorStatus; // if Status is NDIS_STATUS_OPEN_FAILED.
+
+ //
+ // This is the Mac type we must build the packet header for and know the
+ // offsets for.
+ //
+
+ NDIS_INFORMATION MacInfo;
+
+ ULONG MaxReceivePacketSize; // does not include the MAC header
+ ULONG MaxSendPacketSize; // includes the MAC header
+ ULONG ReceiveBufferSpace; // as queried from the card
+
+ //
+ // This information is used to keep track of the speed of
+ // the underlying medium.
+ //
+
+ ULONG MediumSpeed; // in units of 100 bytes/sec
+
+ //
+ // The source routing tree for each of the identifiers
+ //
+
+ PSOURCE_ROUTE SourceRoutingHeads[IDENTIFIER_TOTAL][SOURCE_ROUTE_HASH_SIZE];
+
+} ADAPTER, * PADAPTER;
+
+#define ASSERT_ADAPTER(_Adapter) \
+ CTEAssert (((_Adapter)->Type == IPX_ADAPTER_SIGNATURE) && ((_Adapter)->Size == sizeof(ADAPTER)))
+
+
+//
+// These are the media and frame type specific MAC header
+// constructors that we call in the main TDI send path.
+//
+
+typedef NDIS_STATUS
+(*IPX_SEND_FRAME_HANDLER) (
+ IN PADAPTER Adapter,
+ IN PIPX_LOCAL_TARGET LocalTarget,
+ IN PNDIS_PACKET Packet,
+ IN ULONG PacketLength,
+ IN ULONG IncludedHeaderLength
+ );
+
+//
+// These are the states a WAN line can be in.
+//
+typedef enum _WAN_LINE_STATE{
+ LINE_DOWN,
+ LINE_UP,
+ LINE_CONFIG
+} WAN_LINE_STATE, *PWAN_LINE_STATE;
+
+#define BREF_BOUND 1
+#ifdef _PNP_POWER
+#define BREF_DEVICE_ACCESS 2
+#define BREF_ADAPTER_ACCESS 3
+#endif
+
+//
+// [FW] New flag to indicate the KFWD opened an adapter
+//
+#define BREF_FWDOPEN 4
+
+#define BREF_TOTAL 5
+
+typedef struct _BINDING {
+
+#if DBG
+ ULONG RefTypes[BREF_TOTAL];
+#endif
+
+ CSHORT Type; // type of this structure
+ USHORT Size; // size of this structure
+
+#if DBG
+ UCHAR Signature1[4]; // contains "IBI1"
+#endif
+
+ ULONG ReferenceCount;
+
+#ifdef _PNP_POWER
+ SINGLE_LIST_ENTRY PoolLinkage; // when on free queue
+#endif
+
+ //
+ // Adapter this binding is on.
+ //
+
+ PADAPTER Adapter;
+
+ //
+ // ID identifying us to the system (will be the index
+ // in Device->Bindings[]).
+ //
+
+ USHORT NicId;
+
+ //
+ // For LANs these will be the same as the adapter's, for WANs
+ // they change on line up indications.
+ //
+
+ ULONG MaxSendPacketSize;
+ ULONG MediumSpeed; // in units of 100 bytes/sec
+ HARDWARE_ADDRESS LocalMacAddress; // our local hardware address.
+
+ //
+ // This is used for WAN lines, all sends go to this address
+ // which is given on line up.
+ //
+
+ HARDWARE_ADDRESS RemoteMacAddress;
+
+ //
+ // For WAN lines, holds the remote address indicated to us
+ // in the IPXCP_CONFIGURATION structure -- this is used to
+ // select a binding to send to when WanGlobalNetworkNumber
+ // is TRUE.
+ //
+
+ UCHAR WanRemoteNode[6];
+
+ //
+ // TRUE if this binding was set up to allow auto-detection,
+ // instead of being configured explicitly in the registry.
+ //
+
+ BOOLEAN AutoDetect;
+
+ //
+ // TRUE if this binding was set up for auto-detection AND
+ // was the default in the registry.
+ //
+
+ BOOLEAN DefaultAutoDetect;
+
+ //
+ // During auto-detect when we are processing responses from
+ // various networks, these keep track of how many responses
+ // we have received that match the current guess at the
+ // network number, and how many don't (the current guess
+ // is stored in TentativeNetworkAddress).
+ //
+
+ USHORT MatchingResponses;
+ USHORT NonMatchingResponses;
+
+ //
+ // During auto-detect, stores the current guess at the
+ // network number.
+ //
+
+ ULONG TentativeNetworkAddress;
+
+ //
+ // TRUE if this binding is part of a binding set.
+ //
+
+ BOOLEAN BindingSetMember;
+
+ //
+ // TRUE if this binding should receive broadcasts (this
+ // rotates through the members of a binding set).
+ //
+
+ BOOLEAN ReceiveBroadcast;
+
+ //
+ // TRUE for WAN lines if we are up.
+ //
+ // BOOLEAN LineUp;
+ WAN_LINE_STATE LineUp;
+
+ //
+ // TRUE if this is a WAN line and is dialout.
+ //
+
+ BOOLEAN DialOutAsync;
+
+ union {
+
+ //
+ // Used when a binding is active, if it is a member
+ // of a binding set.
+ //
+
+ struct {
+
+ //
+ // Used to link members of a binding set in a circular list.
+ // NULL for non-set members.
+ //
+
+ struct _BINDING * NextBinding;
+
+ //
+ // If this binding is a master of a binding set, this points
+ // to the binding to use for the next send. For other members
+ // of a binding set it is NULL. We use this to determine
+ // if a binding is a master or not.
+ //
+
+ struct _BINDING * CurrentSendBinding;
+
+ //
+ // For binding set members, points to the master binding
+ // (if this is the master it points to itself).
+ //
+
+ struct _BINDING * MasterBinding;
+
+ };
+
+ //
+ // This is used when we are first binding to adapters,
+ // and the device's Bindings array is not yet allocated.
+ //
+
+ LIST_ENTRY InitialLinkage;
+
+ };
+
+ //
+ // Used by rip to keep track of unused wan lines.
+ //
+
+ ULONG WanInactivityCounter;
+
+ //
+ // Our local address, we don't use the socket but we keep
+ // it here so we can do quick copies. It contains the
+ // real network that we are bound to and our node
+ // address on that net (typically the adapter's MAC
+ // address but it will change for WANs).
+ //
+
+ TDI_ADDRESS_IPX LocalAddress;
+
+ IPX_SEND_FRAME_HANDLER SendFrameHandler;
+
+ struct _DEVICE * Device;
+
+ CTELock * DeviceLock;
+
+ ULONG DefHeaderSize; // IPX header offset for directed frames
+ ULONG BcMcHeaderSize; // IPX header offset for broadcast/multicast
+
+ ULONG AnnouncedMaxDatagramSize; // what we advertise -- assumes worst-case SR
+ ULONG RealMaxDatagramSize; // what will really break the card
+ ULONG MaxLookaheadData;
+
+ //
+ // Configuration parameters. We overlay all of them except
+ // FrameType over the worker thread item we use to delay
+ // deletion -- all the others are not needed once the
+ // binding is up. Some of the config parameters are stored
+ // in the adapter, these are the ones that are modified
+ // per-binding.
+ //
+
+ ULONG FrameType;
+ union {
+ struct {
+ ULONG ConfiguredNetworkNumber;
+ BOOLEAN AllRouteDirected;
+ BOOLEAN AllRouteBroadcast;
+ BOOLEAN AllRouteMulticast;
+ };
+ WORK_QUEUE_ITEM WanDelayedQueueItem;
+ };
+
+ ULONG FwdAdapterContext; // [FW]
+
+ ULONG InterfaceIndex; // [FW]
+
+ ULONG ConnectionId; // [FW] used to match TimeSinceLastActivity IOCtls
+
+ ULONG IpxwanConfigRequired; // [FW] used to indicate to the adapter dll whether the line up is for Router or IpxWan.
+
+ BOOLEAN fInfoIndicated; //Info indicated to user app
+
+#ifdef _PNP_POWER
+ //
+ // Indicates whether this binding was indicated to the ISN driver
+ //
+ BOOLEAN IsnInformed[UPPER_DRIVER_COUNT];
+
+ //
+ // Keeps the NetAddressRegistrationHandle.
+ //
+ HANDLE TdiRegistrationHandle;
+#endif
+} BINDING, * PBINDING;
+
+
+#ifdef _PNP_POWER
+typedef struct _IPX_BINDING_POOL {
+ LIST_ENTRY Linkage;
+ UINT BindingCount;
+ BINDING Bindings[1];
+} IPX_BINDING_POOL, *PIPX_BINDING_POOL;
+#endif
+
+//
+// This structure defines the control structure for a single
+// router table segment.
+//
+
+typedef struct _ROUTER_SEGMENT {
+ LIST_ENTRY WaitingForRoute; // packets waiting for a route in this segment
+ LIST_ENTRY FindWaitingForRoute; // find route requests waiting for a route in this segment
+ LIST_ENTRY WaitingLocalTarget; // QUERY_IPX_LOCAL_TARGETs waiting for a route in this segment
+ LIST_ENTRY WaitingReripNetnum; // MIPX_RERIPNETNUMs waiting for a route in this segment
+ LIST_ENTRY Entries;
+ PLIST_ENTRY EnumerateLocation;
+} ROUTER_SEGMENT, *PROUTER_SEGMENT;
+
+
+//
+// Number of buckets in the address hash table. This is
+// a multiple of 2 so hashing is quick.
+//
+
+#define IPX_ADDRESS_HASH_COUNT 16
+
+//
+// Routine to convert a socket to a hash index. We use the
+// high bits because it is stored reversed.
+//
+
+#define IPX_HASH_SOCKET(_S) ((((_S) & 0xff00) >> 8) % IPX_ADDRESS_HASH_COUNT)
+
+//
+// This macro gets the socket hash right out of the IPX header.
+//
+
+#define IPX_DEST_SOCKET_HASH(_IpxHeader) (((PUCHAR)&(_IpxHeader)->DestinationSocket)[1] % IPX_ADDRESS_HASH_COUNT)
+
+
+//
+// This structure defines the per-device structure for IPX
+// (one of these is allocated globally).
+//
+
+#define DREF_CREATE 0
+#define DREF_LOADED 1
+#define DREF_ADAPTER 2
+#define DREF_ADDRESS 3
+#define DREF_SR_TIMER 4
+#define DREF_RIP_TIMER 5
+#define DREF_LONG_TIMER 6
+#define DREF_RIP_PACKET 7
+#define DREF_ADDRESS_NOTIFY 8
+#define DREF_LINE_CHANGE 9
+#define DREF_NIC_NOTIFY 10
+
+#define DREF_TOTAL 12
+
+#ifdef _PNP_POWER
+//
+// Pre-allocated binding array size
+//
+#define MAX_BINDINGS 50
+#endif _PNP_POWER
+
+#ifdef _PNP_POWER
+//
+// Our new binding array is composed of the following binding
+// array element
+//
+typedef struct _BIND_ARRAY_ELEM {
+ PBINDING Binding;
+ ULONG Version;
+} BIND_ARRAY_ELEM, *PBIND_ARRAY_ELEM;
+
+#endif _PNP_POWER
+
+typedef struct _DEVICE {
+
+#if DBG
+ ULONG RefTypes[DREF_TOTAL];
+#endif
+
+ CSHORT Type; // type of this structure
+ USHORT Size; // size of this structure
+
+#if DBG
+ UCHAR Signature1[4]; // contains "IDC1"
+#endif
+
+ CTELock Interlock; // GLOBAL lock for reference count.
+ // (used in ExInterlockedXxx calls)
+
+ //
+ // These are temporary versions of these counters, during
+ // timer expiration we update the real ones.
+ //
+
+ ULONG TempDatagramBytesSent;
+ ULONG TempDatagramsSent;
+ ULONG TempDatagramBytesReceived;
+ ULONG TempDatagramsReceived;
+
+ //
+ // Configuration parameters.
+ //
+
+ BOOLEAN EthernetPadToEven;
+ BOOLEAN SingleNetworkActive;
+ BOOLEAN DisableDialoutSap;
+
+ //
+ // TRUE if we have multiple cards but a virtual network of 0.
+ //
+
+ BOOLEAN MultiCardZeroVirtual;
+
+ CTELock Lock;
+
+ //
+ // Lock to access the sequenced lists in the device.
+ //
+ CTELock SListsLock;
+
+ LONG ReferenceCount; // activity count/this provider.
+
+#ifdef _PNP_POWER
+
+ //
+ // Lock used to control the access to a binding (either from the
+ // binding array in the device or from the binding array in the
+ // adapter.
+ //
+ CTELock BindAccessLock;
+
+ //
+ // Registry Path for use when PnP adapters appear.
+ //
+ PWSTR RegistryPathBuffer;
+
+ UNICODE_STRING RegistryPath;
+
+ //
+ // Binding array has the Version number too
+ //
+ PBIND_ARRAY_ELEM Bindings; // allocated when number is determined.
+ ULONG BindingCount; // total allocated in Bindings.
+
+ //
+ // Monotonically increasing version number kept in bindings.
+ // Hopefully this will not wrap around...
+ //
+ ULONG BindingVersionNumber;
+#else
+ //
+ // During init we hold all bindings in a queue, but after we
+ // know the approximate number we allocate an array.
+ //
+
+ union {
+ LIST_ENTRY InitialBindingList; // only used during init.
+ struct {
+ PBINDING * Bindings; // allocated when number is determined.
+ ULONG BindingCount; // total allocated in Bindings.
+ };
+ };
+#endif _PNP_POWER
+
+
+ //
+ // ValidBindings is the number of bindings in the array which may
+ // be valid (they are lan bindings or down wan binding placeholders).
+ // It will be less than BindingCount by the number of auto-detect
+ // bindings that are thrown away. HighestExternalNicId is ValidBindings
+ // minus any binding set slaves which are moved to the end of the
+ // array. SapNicCount is like HighestExternalNicId except that
+ // if WanGlobalNetworkNumber is TRUE it will count all WAN bindings
+ // as one. HighestExternalType20NicId is like HighestExternalNicId
+ // except it stops when all the remaining bindings are down wan
+ // lines, or dialin wan lines if DisableDialinNetbios bit 1 is on.
+ //
+
+ USHORT ValidBindings;
+ USHORT HighestExternalNicId;
+ USHORT SapNicCount;
+ USHORT HighestType20NicId;
+#ifdef _PNP_POWER
+ //
+ // Keeps track of the last LAN binding's position in the binding array
+ //
+ USHORT HighestLanNicId;
+
+ //
+ // This keeps track of the current size of the binding array
+ //
+ USHORT MaxBindings;
+#endif _PNP_POWER
+
+ //
+ // [FW] To keep track of the number of WAN lines currently UP
+ //
+ USHORT UpWanLineCount;
+
+ LIST_ENTRY GlobalSendPacketList;
+ LIST_ENTRY GlobalReceivePacketList;
+ LIST_ENTRY GlobalReceiveBufferList;
+
+#if BACK_FILL
+ LIST_ENTRY GlobalBackFillPacketList;
+#endif
+
+ //
+ // Action requests from SAP waiting for an adapter status to change.
+ //
+
+ LIST_ENTRY AddressNotifyQueue;
+
+ //
+ // Action requests from nwrdr waiting for the WAN line
+ // to go up/down.
+ //
+
+ LIST_ENTRY LineChangeQueue;
+
+ //
+ // Action requests from forwarder waiting for the NIC change notification
+ //
+ LIST_ENTRY NicNtfQueue;
+ LIST_ENTRY NicNtfComplQueue;
+
+ //
+ // All packet pools are chained on these lists.
+ //
+
+ LIST_ENTRY SendPoolList;
+ LIST_ENTRY ReceivePoolList;
+
+
+#if BACK_FILL
+ LIST_ENTRY BackFillPoolList;
+ SLIST_HEADER BackFillPacketList;
+#endif
+
+#ifdef _PNP_POWER
+ LIST_ENTRY BindingPoolList;
+ SLIST_HEADER BindingList;
+#endif
+
+ SLIST_HEADER SendPacketList;
+ SLIST_HEADER ReceivePacketList;
+ PIPX_PADDING_BUFFER PaddingBuffer;
+
+ UCHAR State;
+
+ UCHAR FrameTypeDefault;
+
+ //
+ // This holds state if SingleNetworkActive is TRUE. If
+ // it is TRUE then WAN nets are active; if it is FALSE
+ // then LAN nets are active.
+ //
+
+ BOOLEAN ActiveNetworkWan;
+
+ //
+ // TRUE if we have a virtual network.
+ //
+
+ BOOLEAN VirtualNetwork;
+
+ //
+ // If we are set up for SingleNetworkActive, we may have
+ // to start our broadcast of net 0 frames somewhere other
+ // than NIC ID 1, so that we don't send to the wrong type.
+ //
+
+ USHORT FirstLanNicId;
+ USHORT FirstWanNicId;
+
+ //
+ // This holds the total memory allocated for the above structures.
+ //
+
+ LONG MemoryUsage;
+ LONG MemoryLimit;
+
+ //
+ // How many of various resources have been allocated.
+ //
+
+ ULONG AllocatedDatagrams;
+ ULONG AllocatedReceivePackets;
+ ULONG AllocatedPaddingBuffers;
+
+ //
+ // Other configuration parameters.
+ //
+
+ ULONG InitDatagrams;
+ ULONG MaxDatagrams;
+ ULONG RipAgeTime;
+ ULONG RipCount;
+ ULONG RipTimeout;
+ ULONG RipUsageTime;
+ ULONG SourceRouteUsageTime;
+ USHORT SocketStart;
+ USHORT SocketEnd;
+ ULONG SocketUniqueness;
+ ULONG VirtualNetworkNumber;
+ ULONG EthernetExtraPadding;
+ BOOLEAN DedicatedRouter;
+ BOOLEAN VirtualNetworkOptional;
+ UCHAR DisableDialinNetbios;
+
+ //
+ // These are currently not read from the registry.
+ //
+
+ ULONG InitReceivePackets;
+ ULONG InitReceiveBuffers;
+ ULONG MaxReceivePackets;
+ ULONG MaxReceiveBuffers;
+
+#ifdef _PNP_POWER
+ ULONG MaxPoolBindings;
+ ULONG AllocatedBindings;
+ ULONG InitBindings;
+#endif
+
+ //
+ // This contains the next unique indentified to use as
+ // the FsContext in the file object associated with an
+ // open of the control channel.
+ //
+
+ LARGE_INTEGER ControlChannelIdentifier;
+
+ //
+ // This registry parameter controls whether IPX checks (and discards)
+ // packets with mismatched Source addresses in the receive path.
+ //
+ BOOLEAN VerifySourceAddress;
+
+ //
+ // Where the current socket allocation is.
+ //
+ USHORT CurrentSocket;
+
+ //
+ // Number of segments in the RIP database.
+ //
+
+ ULONG SegmentCount;
+
+ //
+ // Points to an array of locks for the RIP database (these
+ // are stored outside of the ROUTER_SEGMENT so the array
+ // can be exposed to the RIP upper driver as one piece).
+ //
+
+ CTELock *SegmentLocks;
+
+ //
+ // Points to an array of ROUTER_SEGMENT fields for
+ // various RIP control fields.
+ //
+
+ ROUTER_SEGMENT *Segments;
+
+ //
+ // Queue of RIP packets waiting to be sent.
+ //
+
+ LIST_ENTRY WaitingRipPackets;
+ ULONG RipPacketCount;
+
+ //
+ // Timer that keeps RIP requests RIP_GRANULARITY ms apart.
+ //
+
+ BOOLEAN RipShortTimerActive;
+ USHORT RipSendTime;
+ CTETimer RipShortTimer;
+
+ //
+ // Timer that runs to age out unused rip entries (if the
+ // router is not bound) and re-rip every so often for
+ // active entries.
+ //
+
+ CTETimer RipLongTimer;
+
+ //
+ // This controls the source routing timeout code.
+ //
+
+ BOOLEAN SourceRoutingUsed; // TRUE if any 802.5 bindings exist.
+ CHAR SourceRoutingTime; // incremented each time timer fires.
+ CTETimer SourceRoutingTimer; // runs every minute.
+
+ //
+ // [FW] Kicks in every minute if at least one WAN line is up. Increments
+ // the WAN incativity counter on all UP WAN bindings.
+ //
+ CTETimer WanInactivityTimer;
+
+ //
+ // These are the merging of the binding values.
+ //
+
+ ULONG LinkSpeed;
+ ULONG MacOptions;
+
+ //
+ // Where we tell upper drivers to put their headers.
+ //
+
+ ULONG IncludedHeaderOffset;
+
+ //
+ // A pre-allocated header containing our node and network,
+ // plus an unused socket (so the structure is a known size
+ // for easy copying).
+ //
+
+ TDI_ADDRESS_IPX SourceAddress;
+
+ //
+ // The following field is an array of list heads of ADDRESS objects that
+ // are defined for this transport provider. To edit the list, you must
+ // hold the spinlock of the device context object.
+ //
+
+ LIST_ENTRY AddressDatabases[IPX_ADDRESS_HASH_COUNT]; // list of defined transport addresses.
+
+ //
+ // Holds the last address we looked up.
+ //
+
+ PVOID LastAddress;
+
+ NDIS_HANDLE NdisBufferPoolHandle;
+
+ //
+ // The following structure contains statistics counters for use
+ // by TdiQueryInformation and TdiSetInformation. They should not
+ // be used for maintenance of internal data structures.
+ //
+
+ TDI_PROVIDER_INFO Information; // information about this provider.
+
+ //
+ // Information.MaxDatagramSize is the minimum size we can
+ // send to all bindings assuming worst-case source routing;
+ // this is the value that won't break any network drivers.
+ //
+
+ ULONG RealMaxDatagramSize;
+
+#if DBG
+ UCHAR Signature2[4]; // contains "IDC2"
+#endif
+
+ //
+ // Indicates whether each upper driver is bound
+ // (Netbios = 0, SPX = 1, RIP = 2).
+ //
+
+ BOOLEAN ForwarderBound;
+
+ BOOLEAN UpperDriverBound[UPPER_DRIVER_COUNT];
+
+ //
+ // TRUE if any driver is bound.
+ //
+
+ BOOLEAN AnyUpperDriverBound;
+
+ //
+ // Whether a receive complete should be indicated to
+ // this upper driver.
+ //
+
+ BOOLEAN ReceiveCompletePending[UPPER_DRIVER_COUNT];
+
+ //
+ // Control channel identifier for each of the upper
+ // drivers' bindings.
+ //
+
+ LARGE_INTEGER UpperDriverControlChannel[UPPER_DRIVER_COUNT];
+
+ //
+ // Entry points and other information for each of the
+ // upper drivers.
+ //
+
+ IPX_INTERNAL_BIND_INPUT UpperDrivers[UPPER_DRIVER_COUNT];
+
+ //
+ // How many upper drivers want broadcast enabled.
+ //
+
+ ULONG EnableBroadcastCount;
+
+ //
+ // Indicates if an enable broadcast operation is in
+ // progress.
+ //
+
+ BOOLEAN EnableBroadcastPending;
+
+ //
+ // Indicates if a disable broadcast operation is in
+ // progress.
+ //
+
+ BOOLEAN DisableBroadcastPending;
+
+ //
+ // Indicates if the current operation should be
+ // reversed when it is finished.
+ //
+
+ BOOLEAN ReverseBroadcastOperation;
+
+ //
+ // TRUE if RIP wants a single network number for all WANs
+ //
+
+ BOOLEAN WanGlobalNetworkNumber;
+
+ //
+ // If WanGlobalNetworkNumber is TRUE, then this holds the
+ // actual value of the network number, once we know it.
+ //
+
+ ULONG GlobalWanNetwork;
+
+ //
+ // Set to TRUE if WanGlobalNetworkNumber is TRUE and we
+ // have already completed a queued notify from SAP. In
+ // this case GlobalWanNetwork will be set correctly.
+ //
+
+ BOOLEAN GlobalNetworkIndicated;
+
+ //
+ // TRUE if we need to act as a RIP announcer/responder
+ // for our virtual net.
+ //
+
+ BOOLEAN RipResponder;
+
+ //
+ // TRUE if we have already logged an error because someone
+ // sent a SAP response but we have multiple cards with no
+ // virtual network.
+ //
+
+ BOOLEAN SapWarningLogged;
+
+ //
+ // Used to queue up a worker thread to perform
+ // broadcast operations.
+ //
+
+ WORK_QUEUE_ITEM BroadcastOperationQueueItem;
+
+#ifdef _PNP_POWER
+ //
+ // Used to queue up a worker thread to perform
+ // PnP indications to upper drivers.
+ //
+
+ WORK_QUEUE_ITEM PnPIndicationsQueueItem;
+#endif
+
+ //
+ // This event is used when unloading to signal that
+ // the reference count is now 0.
+ //
+
+ KEVENT UnloadEvent;
+ BOOLEAN UnloadWaiting;
+
+ //
+ // Counters for most of the statistics that IPX maintains;
+ // some of these are kept elsewhere. Including the structure
+ // itself wastes a little space but ensures that the alignment
+ // inside the structure is correct.
+ //
+
+ TDI_PROVIDER_STATISTICS Statistics;
+
+
+ //
+ // This is TRUE if we have any adapters where we are
+ // auto-detecting the frame type.
+ //
+
+ BOOLEAN AutoDetect;
+
+ //
+ // This is TRUE if we are auto-detecting and we have
+ // found the default auto-detect type on the net.
+ //
+
+ BOOLEAN DefaultAutoDetected;
+
+ //
+ // Our state during auto-detect. After we are done this
+ // will stay at AutoDetectDone;
+ //
+
+ UCHAR AutoDetectState;
+
+ //
+ // If we are auto-detecting, this event is used to stall
+ // our initialization code while we do auto-detection --
+ // this is so we have a constant view of the world once
+ // we return from DriverEntry.
+ //
+
+ KEVENT AutoDetectEvent;
+
+ //
+ // Counters for "active" time.
+ //
+
+ LARGE_INTEGER IpxStartTime;
+
+ //
+ // This resource guards access to the ShareAccess
+ // and SecurityDescriptor fields in addresses.
+ //
+
+ ERESOURCE AddressResource;
+
+ //
+ // Points back to the system device object.
+ //
+
+ PDEVICE_OBJECT DeviceObject;
+
+#ifdef _PNP_POWER
+ //
+ // Used to store the Tdi registration handle for deviceobject notifications.
+ //
+ HANDLE TdiRegistrationHandle;
+
+ //
+ // Used to store the TA_ADDRESS which is indicated up to Tdi clients as adapters appear.
+ //
+ PTA_ADDRESS TdiRegistrationAddress;
+#endif
+
+#ifdef SNMP
+ NOVIPXMIB_BASE MibBase;
+#endif SNMP
+
+ //
+ // These are kept around for error logging, and stored right
+ // after this structure.
+ //
+
+ PWCHAR DeviceName;
+ ULONG DeviceNameLength;
+
+} DEVICE, * PDEVICE;
+
+
+extern PDEVICE IpxDevice;
+extern PIPX_PADDING_BUFFER IpxPaddingBuffer;
+#if DBG
+EXTERNAL_LOCK(IpxGlobalInterlock);
+#endif
+
+#ifdef SNMP
+#define IPX_MIB_ENTRY(Device, Variable) ((Device)->MibBase.Variable)
+#endif SNMP
+
+//
+// device state definitions
+//
+
+#define DEVICE_STATE_CLOSED 0x00
+#define DEVICE_STATE_OPEN 0x01
+#define DEVICE_STATE_STOPPING 0x02
+
+#ifdef _PNP_POWER
+
+//
+// New state which comes between CLOSED and OPEN. At this state,
+// there are no adapters in the system and so no network activity
+// is possible.
+//
+#define DEVICE_STATE_LOADED 0x03
+#endif _PNP_POWER
+
+//
+// This is the state of our auto-detect if we do it.
+//
+
+#define AUTO_DETECT_STATE_INIT 0x00 // still initializing the device
+#define AUTO_DETECT_STATE_RUNNING 0x01 // sent ffffffff query, waiting for responses
+#define AUTO_DETECT_STATE_PROCESSING 0x02 // processing the responses
+#define AUTO_DETECT_STATE_DONE 0x03 // detection is done, IPX is active
+
+
+
+#define IPX_TDI_RESOURCES 9
+
+
+//
+// This structure is pointed to by the FsContext field in the FILE_OBJECT
+// for this Address. This structure is the base for all activities on
+// the open file object within the transport provider. All active connections
+// on the address point to this structure, although no queues exist here to do
+// work from. This structure also maintains a reference to an ADDRESS
+// structure, which describes the address that it is bound to.
+//
+
+#define AFREF_CREATE 0
+#define AFREF_RCV_DGRAM 1
+#define AFREF_SEND_DGRAM 2
+#define AFREF_VERIFY 3
+#define AFREF_INDICATION 4
+
+#define AFREF_TOTAL 8
+
+typedef struct _ADDRESS_FILE {
+
+#if DBG
+ ULONG RefTypes[AFREF_TOTAL];
+#endif
+
+ CSHORT Type;
+ CSHORT Size;
+
+ LIST_ENTRY Linkage; // next address file on this address.
+ // also used for linkage in the
+ // look-aside list
+
+ ULONG ReferenceCount; // number of references to this object.
+
+ //
+ // the current state of the address file structure; this is either open or
+ // closing
+ //
+
+ UCHAR State;
+
+ CTELock * AddressLock;
+
+ //
+ // The following fields are kept for housekeeping purposes.
+ //
+
+ PREQUEST Request; // the request used for open or close
+ struct _ADDRESS *Address; // address to which we are bound.
+#ifdef ISN_NT
+ PFILE_OBJECT FileObject; // easy backlink to file object.
+#endif
+ struct _DEVICE *Device; // device to which we are attached.
+
+ //
+ //
+ // TRUE if ExtendedAddressing, ReceiveIpxHeader,
+ // FilterOnPacketType, or ReceiveFlagAddressing is TRUE.
+ //
+
+ BOOLEAN SpecialReceiveProcessing;
+
+ //
+ // The remote address of a send datagram includes the
+ // packet type. and on a receive datagram includes
+ // the packet type AND a flags byte indicating information
+ // about the frame (was it broadcast, was it sent from
+ // this machine).
+ //
+
+ BOOLEAN ExtendedAddressing;
+
+ //
+ // TRUE if the address on a receive datagram includes
+ // the packet type and a flags byte (like ExtendedAddressing),
+ // but on send the address is normal (no packet type).
+ //
+
+ BOOLEAN ReceiveFlagsAddressing;
+
+ //
+ // Is the IPX header received with the data.
+ //
+
+ BOOLEAN ReceiveIpxHeader;
+
+ //
+ // The packet type to use if it is unspecified in the send.
+ //
+
+ UCHAR DefaultPacketType;
+
+ //
+ // TRUE if packet type filtering is enabled.
+ //
+
+ BOOLEAN FilterOnPacketType;
+
+ //
+ // The packet type to filter on.
+ //
+
+ UCHAR FilteredType;
+
+ //
+ // Does this address file want broadcast packets.
+ //
+
+ BOOLEAN EnableBroadcast;
+
+ //
+ // This is set to TRUE if this is the SAP socket -- we
+ // put this under SpecialReceiveProcessing to avoid
+ // hitting the main path.
+ //
+
+ BOOLEAN IsSapSocket;
+
+ //
+ // The following queue is used to queue receive datagram requests
+ // on this address file. Send datagram requests are queued on the
+ // address itself. These queues are managed by the EXECUTIVE interlocked
+ // list management routines. The actual objects which get queued to this
+ // structure are request control blocks (RCBs).
+ //
+
+ LIST_ENTRY ReceiveDatagramQueue; // FIFO of outstanding TdiReceiveDatagrams.
+
+ //
+ // This holds the request used to close this address file,
+ // for pended completion.
+ //
+
+ PREQUEST CloseRequest;
+
+ //
+ // handler for kernel event actions. First we have a set of booleans that
+ // indicate whether or not this address has an event handler of the given
+ // type registered.
+ //
+
+ //
+ // [CH] Added the chained receive handlers.
+ //
+
+ BOOLEAN RegisteredReceiveDatagramHandler;
+ BOOLEAN RegisteredChainedReceiveDatagramHandler;
+ BOOLEAN RegisteredErrorHandler;
+
+ //
+ // The following function pointer always points to a TDI_IND_RECEIVE_DATAGRAM
+ // event handler for the address. If the NULL handler is specified in a
+ // TdiSetEventHandler, this this points to an internal routine which does
+ // not accept the incoming data.
+ //
+
+ PTDI_IND_RECEIVE_DATAGRAM ReceiveDatagramHandler;
+ PVOID ReceiveDatagramHandlerContext;
+ PTDI_IND_CHAINED_RECEIVE_DATAGRAM ChainedReceiveDatagramHandler;
+ PVOID ChainedReceiveDatagramHandlerContext;
+
+ //
+ // The following function pointer always points to a TDI_IND_ERROR
+ // handler for the address. If the NULL handler is specified in a
+ // TdiSetEventHandler, this this points to an internal routine which
+ // simply returns successfully.
+ //
+
+ PTDI_IND_ERROR ErrorHandler;
+ PVOID ErrorHandlerContext;
+
+} ADDRESS_FILE, *PADDRESS_FILE;
+
+#define ADDRESSFILE_STATE_OPENING 0x00 // not yet open for business
+#define ADDRESSFILE_STATE_OPEN 0x01 // open for business
+#define ADDRESSFILE_STATE_CLOSING 0x02 // closing
+
+
+//
+// This structure defines an ADDRESS, or active transport address,
+// maintained by the transport provider. It contains all the visible
+// components of the address (such as the TSAP and network name components),
+// and it also contains other maintenance parts, such as a reference count,
+// ACL, and so on. All outstanding connection-oriented and connectionless
+// data transfer requests are queued here.
+//
+
+#define AREF_ADDRESS_FILE 0
+#define AREF_LOOKUP 1
+#define AREF_RECEIVE 2
+
+#define AREF_TOTAL 4
+
+typedef struct _ADDRESS {
+
+#if DBG
+ ULONG RefTypes[AREF_TOTAL];
+#endif
+
+ USHORT Size;
+ CSHORT Type;
+
+/* ULONGs to allow for Interlocked operations.
+
+ BOOLEAN SendPacketInUse; // put these after so header is aligned.
+
+ BOOLEAN ReceivePacketInUse;
+#if BACK_FILL
+ BOOLEAN BackFillPacketInUse;
+#endif
+*/
+
+ ULONG SendPacketInUse; // put these after so header is aligned.
+
+ ULONG ReceivePacketInUse;
+#if BACK_FILL
+ ULONG BackFillPacketInUse;
+#endif
+
+ LIST_ENTRY Linkage; // next address/this device object.
+ ULONG ReferenceCount; // number of references to this object.
+
+ CTELock Lock;
+
+ //
+ // The following fields comprise the actual address itself.
+ //
+
+ PREQUEST Request; // pointer to address creation request.
+
+ USHORT Socket; // the socket this address corresponds to.
+ USHORT SendSourceSocket; // used for sends; may be == Socket or 0
+
+ //
+ // The following fields are used to maintain state about this address.
+ //
+
+ BOOLEAN Stopping;
+ ULONG Flags; // attributes of the address.
+ struct _DEVICE *Device; // device context to which we are attached.
+ CTELock * DeviceLock;
+
+ //
+ // The following queues is used to hold send datagrams for this
+ // address. Receive datagrams are queued to the address file. Requests are
+ // processed in a first-in, first-out manner, so that the very next request
+ // to be serviced is always at the head of its respective queue. These
+ // queues are managed by the EXECUTIVE interlocked list management routines.
+ // The actual objects which get queued to this structure are request control
+ // blocks (RCBs).
+ //
+
+ LIST_ENTRY AddressFileDatabase; // list of defined address file objects
+
+ //
+ // Holds our source address, used for construcing datagrams
+ // quickly.
+ //
+
+ TDI_ADDRESS_IPX LocalAddress;
+
+ IPX_SEND_PACKET SendPacket;
+ IPX_RECEIVE_PACKET ReceivePacket;
+
+#if BACK_FILL
+ IPX_SEND_PACKET BackFillPacket;
+#endif
+
+
+ UCHAR SendPacketHeader[IPX_MAXIMUM_MAC + sizeof(IPX_HEADER)];
+
+#ifdef ISN_NT
+
+ //
+ // These two can be a union because they are not used
+ // concurrently.
+ //
+
+ union {
+
+ //
+ // This structure is used for checking share access.
+ //
+
+ SHARE_ACCESS ShareAccess;
+
+ //
+ // Used for delaying IpxDestroyAddress to a thread so
+ // we can access the security descriptor.
+ //
+
+ WORK_QUEUE_ITEM DestroyAddressQueueItem;
+
+ } u;
+
+ //
+ // This structure is used to hold ACLs on the address.
+
+ PSECURITY_DESCRIPTOR SecurityDescriptor;
+
+#endif
+
+ ULONG Index;
+ BOOLEAN RtAdd;
+
+} ADDRESS, *PADDRESS;
+
+#define ADDRESS_FLAGS_STOPPING 0x00000001
+
+//
+// In order to increase the range of ControlChannelIds, we have a large integer to represent
+// monotonically increasing ControlChannelIdentifiers. This large integer is packed into the
+// 6 Bytes as follows:
+//
+// REQUEST_OPEN_CONTEXT(_Request) - 4 bytes
+// Upper 2 bytes of REQUEST_OPEN_TYPE(_Request) - 2 bytes
+//
+// IPX_CC_MASK is used to mask out the upper 2 bytes of the OPEN_TYPE.
+// MAX_CCID is 2^48.
+//
+#define IPX_CC_MASK 0x0000ffff
+
+#define MAX_CCID 0xffffffffffff
+
+#define CCID_FROM_REQUEST(_ccid, _Request) \
+ (_ccid).LowPart = (ULONG)(REQUEST_OPEN_CONTEXT(_Request)); \
+ (_ccid).HighPart = ((ULONG)(REQUEST_OPEN_TYPE(_Request)) >> 16);
+
+//#define USER_BUFFER_OFFSET FIELD_OFFSET(RTRCV_BUFFER, DgrmLength)
+#define USER_BUFFER_OFFSET FIELD_OFFSET(RTRCV_BUFFER, Options)
+//
+// This structure keeps track of the WINS recv Irp and any datagram
+// queued to go up to WINS (name service datagrams)
+//
+#define REFRT_TOTAL 8
+
+#define RT_CREATE 0
+#define RT_CLEANUP 1
+#define RT_CLOSE 2
+#define RT_SEND 3
+#define RT_RCV 4
+#define RT_IRPIN 5
+#define RT_BUFF 6
+#define RT_EXTRACT 7
+
+
+#define RT_EMPTY 0
+#define RT_OPEN 1
+#define RT_CLOSING 2
+#define RT_CLOSED 3
+
+
+#define RT_IRP_MAX 1000
+#define RT_BUFF_MAX 1000
+
+//
+// Max. memory allocated for queueing buffers to be received by the RT
+// manager
+//
+#define RT_MAX_BUFF_MEM 65000 //bytes
+
+//
+// Get Index corresponding to the address object opened by RT. BTW We
+// can not have more than one Address file (client) for a RT address.
+//
+#define RT_ADDRESS_INDEX(_pIrp) (((ULONG)REQUEST_OPEN_TYPE(_pIrp)) - ROUTER_ADDRESS_FILE)
+
+typedef struct _RT_IRP {
+ PADDRESS_FILE AddressFile;
+ LIST_ENTRY RcvIrpList;
+ ULONG NoOfRcvIrps;
+ LIST_ENTRY RcvList; // linked list of Datagrams Q'd to rcv
+ ULONG NoOfRcvBuffs; // linked list of Datagrams Q'd to rcv
+ BOOLEAN State;
+ } RT_IRP, *PRT_IRP;
+
+typedef struct
+{
+#if DBG
+ ULONG RefTypes[REFRT_TOTAL];
+#endif
+
+ CSHORT Type; // type of this structure
+ USHORT Size; // size of this structure
+
+#if DBG
+ UCHAR Signature[4]; // contains "IBI1"
+#endif
+ LIST_ENTRY CompletedIrps; // linked list of Datagrams Q'd to rcv
+ LIST_ENTRY HolderIrpsList; // Holds Irps
+ CTELock Lock;
+ ULONG ReferenceCount;
+ ULONG RcvMemoryAllocated; // bytes buffered so far
+ ULONG RcvMemoryMax; // max # of bytes to buffer on Rcv
+ PDEVICE pDevice; // the devicecontext used by wins
+ UCHAR NoOfAdds;
+ RT_IRP AddFl[IPX_RT_MAX_ADDRESSES];
+} RT_INFO, *PRT_INFO;
+
+//
+// RT Rcv Buffer structure
+//
+typedef struct
+{
+ LIST_ENTRY Linkage;
+ ULONG TotalAllocSize;
+ ULONG UserBufferLengthToPass;
+ IPX_DATAGRAM_OPTIONS2 Options;
+
+} RTRCV_BUFFER, *PRTRCV_BUFFER;
+
+#define OFFSET_OPTIONS_IN_RCVBUFF FIELD_OFFSET(RTRCV_BUFFER, Options)
+#define OFFSET_PKT_IN_RCVBUFF (FIELD_OFFSET(RTRCV_BUFFER, Options) + FIELD_OFFSET(IPX_DATAGRAM_OPTIONS2, Data))
+#define OFFSET_PKT_IN_OPTIONS FIELD_OFFSET(IPX_DATAGRAM_OPTIONS2, Data)
+
+extern PRT_INFO pRtInfo;
+
+//
+// We keep the demand-dial binding at the beginning of the binding array; this keeps
+// track of the number of extra bindings that we have.
+// Currently 1 (for demand-dial), we could also keep other bindings like the loopback
+// binding, etc.
+//
+#define DEMAND_DIAL_NIC_ID DEMAND_DIAL_ADAPTER_CONTEXT
+#define LOOPBACK_NIC_ID VIRTUAL_NET_ADAPTER_CONTEXT
+
+#define EXTRA_BINDINGS 2