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.
 
 
 
 
 
 

409 lines
12 KiB

/*++
Copyright(c) 1999-2000 Microsoft Corporation
Module Name:
bridge.h
Abstract:
Ethernet MAC level bridge.
Author:
Mark Aiken
(original bridge by Jameel Hyder)
Environment:
Kernel mode driver
Revision History:
Sept 1999 - Original version
Feb 2000 - Overhaul
--*/
#pragma warning( push, 3 )
// For Ethernet constants and macros
#include <xfilter.h>
// For ULONG_MAX
#include <limits.h>
#pragma warning( pop )
// Disable "conditional expression is constant" warning
#pragma warning( disable: 4127 )
// Disable "Unreferenced formal parameter" warning
#pragma warning( disable: 4100 )
// Disable "Bit field type other than int" warning
#pragma warning( disable: 4214 )
// Debugging defines
#include "brdgdbg.h"
// Singly-linked list implementation
#include "brdgslist.h"
// WAIT_REFCOUNT implementation
#include "brdgwref.h"
// Timer implementation
#include "brdgtimr.h"
// Hash table implementation
#include "brdghash.h"
// Cache implementation
#include "brdgcach.h"
// Our IOCTLs and control structures
#include "bioctl.h"
// Include the STA type declarations
#include "brdgstad.h"
// ===========================================================================
//
// CONSTANTS
//
// ===========================================================================
#define DEVICE_NAME L"\\Device\\Bridge"
#define SYMBOLIC_NAME L"\\DosDevices\\Bridge"
#define PROTOCOL_NAME L"BRIDGE"
//
// The IEEE-specified reserved Spanning Tree Algorithm group destination
// MAC address
//
// This exact address is specified as the "Bridge Group Address" and is used for
// transmitting STA packets. *Any* address with these first 5 bytes is reserved
// by the IEEE for future use (so there are 15 reserved but unused addresses).
//
// Frames addressed to ANY of the reserved addresses are never relayed by the bridge.
//
extern UCHAR STA_MAC_ADDR[ETH_LENGTH_OF_ADDRESS];
//
// Each queue draining thread blocks against one kernel event per adapter, plus
// the global kill event and the per-processor event to trigger a re-enumeration
// of adapters.
//
// This limits our maximum number of adapters, since the kernel can't block a
// thread against an unbounded number of objects.
//
#define MAX_ADAPTERS (MAXIMUM_WAIT_OBJECTS - 2)
// Registry key where we keep our global parameters
extern const PWCHAR gRegConfigPath;
// Size of an Ethernet frame header
#define ETHERNET_HEADER_SIZE ((2*ETH_LENGTH_OF_ADDRESS) + 2)
// Largest possible Ethernet packet (with header)
#define MAX_PACKET_SIZE 1514
// ===========================================================================
//
// TYPE DECLARATIONS
//
// ===========================================================================
struct _NDIS_REQUEST_BETTER;
// Completion function type for NDIS_REQUEST_BETTER
typedef VOID (*PCOMPLETION_FUNC)(struct _NDIS_REQUEST_BETTER*, PVOID);
//
// Structure for performing NDIS requests. Can block to wait for result or
// specify a custom completion routine.
//
typedef struct _NDIS_REQUEST_BETTER
{
NDIS_REQUEST Request;
NDIS_STATUS Status; // Final status of the request
NDIS_EVENT Event; // Event signaled when request completes
PCOMPLETION_FUNC pFunc; // Completion function
PVOID FuncArg; // Argument to completion function
} NDIS_REQUEST_BETTER, *PNDIS_REQUEST_BETTER;
typedef struct _ADAPTER_QUOTA
{
//
// Total number of packets this adapter is holding from each major pool.
//
// Note that the sum of all adapters' pool usage can be greater than the pool capacity,
// because base packets are shared. The quota scheme allows this.
//
// [0] == Copy packets
// [1] == Wrapper packets
//
ULONG UsedPackets[2];
} ADAPTER_QUOTA, *PADAPTER_QUOTA;
//
// Per adapter data structure
//
typedef struct _ADAPT ADAPT, *PADAPT;
typedef struct _ADAPT
{
PADAPT Next; // Next adapter in queue
LONG AdaptSize; // Size of structure (storage for DeviceName is at tail)
WAIT_REFCOUNT Refcount; // Refcount for the adapter
// State must be updated inside a write lock on gAdapterCharacteristicsLock,
// since an adapter's relaying status affects our miniport's virtual status.
// Only the STA code writes to this field; all other code should treat it as
// read-only.
PORT_STATE State;
//
// Various useful info about the adapter. None of these fields are ever changed after
// adapter initialization.
//
NDIS_STRING DeviceName;
NDIS_STRING DeviceDesc;
UCHAR MACAddr[ETH_LENGTH_OF_ADDRESS];
NDIS_MEDIUM PhysicalMedium; // Set to NO_MEDIUM if the NIC doesn't report something more specific
NDIS_HANDLE BindingHandle;
BOOLEAN bCompatibilityMode; // TRUE if the adapter is in compatibility mode
// These two fields are used while opening / closing an adapter
NDIS_EVENT Event;
NDIS_STATUS Status;
// This field is volatile
BOOLEAN bResetting;
// The queue and bServiceInProgress is protected by this spin lock
NDIS_SPIN_LOCK QueueLock;
BSINGLE_LIST_HEAD Queue;
BOOLEAN bServiceInProgress;
// This allows a caller to wait on the queue becoming empty. It is updated when an item is
// queued or dequeued.
WAIT_REFCOUNT QueueRefcount;
// Auto-clearing event to request servicing of the queue
KEVENT QueueEvent;
// These fields are locked by gAdapterCharacteristicsLock for all adapters together
ULONG MediaState; // NdisMediaStateConnected / NdisMediaStateDisconnected
ULONG LinkSpeed; // Units of 100bps (10MBps == 100,000)
// This structure is locked by gQuotaLock for all adapters together
ADAPTER_QUOTA Quota; // Quota information for this adapter
// Statistics
LARGE_INTEGER SentFrames; // All frames sent (including relay)
LARGE_INTEGER SentBytes; // All bytes sent (including relay)
LARGE_INTEGER SentLocalFrames; // Frames sent from the local machine
LARGE_INTEGER SentLocalBytes; // Bytes sent from the local machine
LARGE_INTEGER ReceivedFrames; // All received frames (including relay)
LARGE_INTEGER ReceivedBytes; // All received bytes (including relay)
STA_ADAPT_INFO STAInfo; // STA data for this adapter
// Set once from FALSE to TRUE when STA initialization on this adapter has completed.
// This flag is set inside the gSTALock.
BOOLEAN bSTAInited;
} ADAPT, *PADAPT;
// ===========================================================================
//
// INLINES / MACROS
//
// ===========================================================================
//
// Calculates the difference between a previously recorded time and now
// allowing for timer rollover
//
__forceinline
ULONG
BrdgDeltaSafe(
IN ULONG prevTime,
IN ULONG nowTime,
IN ULONG maxDelta
)
{
ULONG delta;
if( nowTime >= prevTime )
{
// Timer did not roll over
delta = nowTime - prevTime;
}
else
{
// Looks like timer rolled over
delta = ULONG_MAX - prevTime + nowTime;
}
SAFEASSERT( delta < maxDelta );
return delta;
}
//
// There is no defined InterlockedExchangeULong function in the kernel, just
// InterlockedExchange. Abstract out the cast.
//
__forceinline ULONG
InterlockedExchangeULong(
IN PULONG pULong,
IN ULONG NewValue
)
{
return (ULONG)InterlockedExchange( (PLONG)pULong, NewValue );
}
//
// Acquires an ADAPT structure checking whether the adapter is
// closing or not.
//
__forceinline BOOLEAN
BrdgAcquireAdapter(
IN PADAPT pAdapt
)
{
return BrdgIncrementWaitRef( &pAdapt->Refcount );
}
//
// Just increments a PADAPT's refcount; assumes that the refcount is already > 0
// Use when it is guaranteed that BrdgAcquireAdapter() has succeeded and
// the refcount is still > 0.
//
__forceinline VOID
BrdgReacquireAdapter(
IN PADAPT pAdapt
)
{
BrdgReincrementWaitRef( &pAdapt->Refcount );
}
//
// It is safe to acquire an adapter inside the gAdapterListLock or the gAddressLock
//
__forceinline VOID
BrdgAcquireAdapterInLock(
IN PADAPT pAdapt
)
{
BOOLEAN bIncremented;
SAFEASSERT( pAdapt->Refcount.state == WaitRefEnabled );
bIncremented = BrdgIncrementWaitRef( &pAdapt->Refcount );
SAFEASSERT( bIncremented );
}
//
// Releases a PADAPT structure (from either a BrdgAcquireAdapter() or BrdgReacquireAdapter()
// call)
//
__forceinline VOID
BrdgReleaseAdapter(
IN PADAPT pAdapt
)
{
BrdgDecrementWaitRef( &pAdapt->Refcount );
}
// ===========================================================================
//
// PROTOTYPES
//
// ===========================================================================
VOID
BrdgUnload(
IN PDRIVER_OBJECT DriverObject
);
NDIS_STATUS
BrdgDeferFunction(
VOID (*pFunc)(PVOID),
PVOID arg
);
NTSTATUS
BrdgReadRegUnicode(
IN PUNICODE_STRING KeyName,
IN PWCHAR pValueName,
OUT PWCHAR *String, // The string from the registry, freshly allocated
OUT PULONG StringSize // Size of allocated memory at String
);
NTSTATUS
BrdgReadRegDWord(
IN PUNICODE_STRING KeyName,
IN PWCHAR pValueName,
OUT PULONG Value
);
NTSTATUS
BrdgDispatchRequest(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);
NTSTATUS
BrdgOpenDevice (
IN LPWSTR pDeviceNameStr,
OUT PDEVICE_OBJECT *ppDeviceObject,
OUT HANDLE *pFileHandle,
OUT PFILE_OBJECT *ppFileObject
);
VOID
BrdgCloseDevice(
IN HANDLE FileHandle,
IN PFILE_OBJECT pFileObject,
IN PDEVICE_OBJECT pDeviceObject
);
VOID
BrdgShutdown(VOID);
BOOLEAN
BrdgIsRunningOnPersonal(VOID);
// ===========================================================================
//
// GLOBAL VARIABLE DECLARATIONS
//
// ===========================================================================
// NDIS handle for us as a protocol
extern NDIS_HANDLE gProtHandle;
// The adapter list
extern PADAPT gAdapterList;
// RW lock protecting the adapter list
extern NDIS_RW_LOCK gAdapterListLock;
// != 0 means we are shutting down
extern LONG gShuttingDown;
// Our driver object
extern PDRIVER_OBJECT gDriverObject;
// Our registry key where we can keep config information
extern UNICODE_STRING gRegistryPath;
// Set if the Bridge believes that tcp/ip has been loaded
extern BOOLEAN g_fIsTcpIpLoaded;