Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1378 lines
39 KiB

#include <ndis.h>
#include <efilter.h>
#include <tfilter.h>
#include <ffilter.h>
#include "debug.h"
#include "loop.h"
#if DBG
extern LONG LoopDebugLevel = DBG_LEVEL_FATAL;
extern LONG LoopDebugComponent = DBG_COMP_ALL;
#endif
NDIS_STATUS
LoopAddAdapter(
IN NDIS_HANDLE MacAdapterContext,
IN NDIS_HANDLE ConfigurationHandle,
IN PNDIS_STRING AdapterName
);
NDIS_STATUS
LoopCloseAdapter(
IN NDIS_HANDLE MacBindingHandle
);
NDIS_STATUS
LoopOpenAdapter(
OUT PNDIS_STATUS OpenErrorStatus,
OUT NDIS_HANDLE *MacBindingHandle,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE NdisBindingContext,
IN NDIS_HANDLE MacAdapterContext,
IN UINT OpenOptions,
IN PSTRING AddressingOptions OPTIONAL
);
VOID
LoopRemoveAdapter(
IN NDIS_HANDLE MacAdapterContext
);
NDIS_STATUS
LoopReset(
IN NDIS_HANDLE MacBindingHandle
);
NDIS_STATUS
LoopTransferData(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE MacReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer,
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred
);
VOID
LoopUnload(
IN NDIS_HANDLE MacMacContext
);
STATIC
NDIS_STATUS
LoopRegisterAdapter(
IN NDIS_HANDLE LoopMacHandle,
IN PNDIS_STRING AdapterName,
IN NDIS_MEDIUM AdapterMedium,
IN PVOID NetAddress,
IN NDIS_HANDLE ConfigurationHandle
);
STATIC
NDIS_STATUS
LoopChangeFilter(
IN UINT OldFilterClasses,
IN UINT NewFilterClasses,
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
);
STATIC
VOID
LoopCloseAction(
IN NDIS_HANDLE MacBindingHandle
);
STATIC
NDIS_STATUS
LoopEthChangeAddress(
IN UINT OldFilterCount,
IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
IN UINT NewFilterCouunt,
IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
);
STATIC
NDIS_STATUS
LoopTrChangeAddress(
IN TR_FUNCTIONAL_ADDRESS OldFunctionalAddresses,
IN TR_FUNCTIONAL_ADDRESS NewFunctionalAddresses,
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
);
STATIC
NDIS_STATUS
LoopFddiChangeAddress(
IN UINT OldLongAddressCount,
IN CHAR OldLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
IN UINT NewLongAddressCouunt,
IN CHAR NewLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
IN UINT OldShortAddressCount,
IN CHAR OldShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
IN UINT NewShortAddressCouunt,
IN CHAR NewShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
);
STATIC NDIS_HANDLE LoopWrapperHandle;
STATIC NDIS_HANDLE LoopMacHandle;
// !! need to verify filters !!
#define PACKET_FILTER_802_3 0xF07F
#define PACKET_FILTER_802_5 0xF07F
#define PACKET_FILTER_DIX 0xF07F
#define PACKET_FILTER_FDDI 0xF07F
#define PACKET_FILTER_LTALK 0x8009
#define PACKET_FILTER_ARCNET 0x8009
static const NDIS_PHYSICAL_ADDRESS physicalConst = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NDIS_STATUS Status;
NDIS_MAC_CHARACTERISTICS LoopChar;
NDIS_STRING MacName = NDIS_STRING_CONST("LoopBack");
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, (" --> DriverEntry\n"));
NdisInitializeWrapper(
&LoopWrapperHandle,
DriverObject,
RegistryPath,
NULL
);
LoopChar.MajorNdisVersion = LOOP_NDIS_MAJOR_VERSION;
LoopChar.MinorNdisVersion = LOOP_NDIS_MINOR_VERSION;
LoopChar.OpenAdapterHandler = LoopOpenAdapter;
LoopChar.CloseAdapterHandler = LoopCloseAdapter;
LoopChar.RequestHandler = LoopRequest;
LoopChar.SendHandler = LoopSend;
LoopChar.TransferDataHandler = LoopTransferData;
LoopChar.ResetHandler = LoopReset;
LoopChar.UnloadMacHandler = LoopUnload;
LoopChar.QueryGlobalStatisticsHandler = LoopQueryGlobalStats;
LoopChar.AddAdapterHandler = LoopAddAdapter;
LoopChar.RemoveAdapterHandler = LoopRemoveAdapter;
LoopChar.Name = MacName;
NdisRegisterMac(
&Status,
&LoopMacHandle,
LoopWrapperHandle,
NULL,
&LoopChar,
sizeof(LoopChar)
);
if (Status == NDIS_STATUS_SUCCESS)
return STATUS_SUCCESS;
// Can only get here if something went wrong registering the MAC or
// all of the adapters
NdisTerminateWrapper(LoopWrapperHandle, DriverObject);
return STATUS_UNSUCCESSFUL;
}
NDIS_STATUS
LoopAddAdapter(
IN NDIS_HANDLE MacAdapterContext,
IN NDIS_HANDLE ConfigurationHandle,
IN PNDIS_STRING AdapterName
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NDIS_HANDLE ConfigHandle;
PNDIS_CONFIGURATION_PARAMETER Parameter;
NDIS_STRING MediumKey = NDIS_STRING_CONST("Medium");
PUCHAR NetAddressBuffer[6];
PVOID NetAddress;
UINT Length;
NDIS_MEDIUM AdapterMedium;
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, (" --> LoopAddAdapter\n"));
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, ("Reading Config Info\n"));
// configuration info present, let's get it
NdisOpenConfiguration(
&Status,
&ConfigHandle,
ConfigurationHandle
);
if (Status != NDIS_STATUS_SUCCESS) {
// would like to log this, but adapter not registered yet
DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
("Unable to open configuration database!\n"));
return Status;
}
NdisReadConfiguration(
&Status,
&Parameter,
ConfigHandle,
&MediumKey,
NdisParameterInteger
);
AdapterMedium = (NDIS_MEDIUM)Parameter->ParameterData.IntegerData;
if ((Status != NDIS_STATUS_SUCCESS) ||
!((AdapterMedium == NdisMedium802_3) ||
(AdapterMedium == NdisMedium802_5) ||
(AdapterMedium == NdisMediumFddi) ||
(AdapterMedium == NdisMediumLocalTalk) ||
(AdapterMedium == NdisMediumArcnet878_2))) {
// would like to log this, but adapter not registered yet
DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
("Unable to find 'Medium' keyword or invalid value!\n"));
NdisCloseConfiguration(ConfigHandle);
return Status;
}
NdisReadNetworkAddress(
&Status,
&NetAddress,
&Length,
ConfigHandle
);
if (Status == NDIS_STATUS_SUCCESS) {
// verify the address is appropriate for the specific media and
// ensure that the locally administered address bit is set
switch (AdapterMedium) {
case NdisMedium802_3:
if ((Length != ETH_LENGTH_OF_ADDRESS) ||
ETH_IS_MULTICAST(NetAddress) ||
!(((PUCHAR)NetAddress)[0] & 0x02)) { // U/L bit
Length = 0;
}
break;
case NdisMedium802_5:
if ((Length != TR_LENGTH_OF_ADDRESS) ||
(((PUCHAR)NetAddress)[0] & 0x80) || // I/G bit
!(((PUCHAR)NetAddress)[0] & 0x40)) { // U/L bit
Length = 0;
}
break;
case NdisMediumFddi:
if ((Length != FDDI_LENGTH_OF_LONG_ADDRESS) ||
(((PUCHAR)NetAddress)[0] & 0x01) || // I/G bit
!(((PUCHAR)NetAddress)[0] & 0x02)) { // U/L bit
Length = 0;
}
break;
case NdisMediumLocalTalk:
if ((Length != 1) || LOOP_LT_IS_BROADCAST(*(PUCHAR)NetAddress)) {
Length = 0;
}
break;
case NdisMediumArcnet878_2:
if ((Length != 1) || LOOP_ARC_IS_BROADCAST(*(PUCHAR)NetAddress)) {
Length = 0;
}
break;
}
if (Length == 0) {
DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
("Invalid NetAddress in registry!\n"));
NdisCloseConfiguration(ConfigHandle);
return NDIS_STATUS_FAILURE;
}
// have to save away the address as the info may be gone
// when we close the registry. we assume the length will
// be 6 bytes max
NdisMoveMemory(
NetAddressBuffer,
NetAddress,
Length
);
NetAddress = (PVOID)NetAddressBuffer;
}
else
NetAddress = NULL;
NdisCloseConfiguration(ConfigHandle);
Status = LoopRegisterAdapter(
LoopMacHandle,
AdapterName,
AdapterMedium,
NetAddress,
ConfigurationHandle
);
return Status;
}
NDIS_STATUS
LoopCloseAdapter(
IN NDIS_HANDLE MacBindingHandle
)
{
PLOOP_ADAPTER Adapter;
PLOOP_OPEN Open;
NDIS_STATUS StatusToReturn;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopCloseAdapter\n"));
Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
NdisAcquireSpinLock(&Adapter->Lock);
Adapter->References++;
Open = PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
("Closing Open %lx, reference count = %ld\n",Open,Open->References));
if (!Open->BindingClosing) {
Open->BindingClosing = TRUE;
RemoveEntryList(&Open->OpenList);
Adapter->OpenCount--;
Adapter->References--;
//
// shouldn't be called unless there isn't anything running in the
// binding. if there is we're hosed.
//
switch (Adapter->Medium) {
case NdisMedium802_3:
case NdisMediumDix:
StatusToReturn = EthDeleteFilterOpenAdapter(
Adapter->Filter.Eth,
Open->NdisFilterHandle,
NULL
);
// needs to handle pending delete, but should be ok
// since our close action routine doesn't pend
break;
case NdisMedium802_5:
StatusToReturn = TrDeleteFilterOpenAdapter(
Adapter->Filter.Tr,
Open->NdisFilterHandle,
NULL
);
// needs to handle pending delete, but should be ok
// since our close action routine doesn't pend
break;
case NdisMediumFddi:
StatusToReturn = FddiDeleteFilterOpenAdapter(
Adapter->Filter.Fddi,
Open->NdisFilterHandle,
NULL
);
// needs to handle pending delete, but should be ok
// since our close action routine doesn't pend
break;
case NdisMediumLocalTalk:
case NdisMediumArcnet878_2:
break;
default:
ASSERT(FALSE);
break;
}
NdisFreeMemory(
Open,
sizeof(LOOP_OPEN),
0
);
StatusToReturn = NDIS_STATUS_SUCCESS;
}
else
StatusToReturn = NDIS_STATUS_CLOSING;
Adapter->References--;
NdisReleaseSpinLock(&Adapter->Lock);
return StatusToReturn;
}
NDIS_STATUS
LoopOpenAdapter(
OUT PNDIS_STATUS OpenErrorStatus,
OUT NDIS_HANDLE *MacBindingHandle,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE NdisBindingContext,
IN NDIS_HANDLE MacAdapterContext,
IN UINT OpenOptions,
IN PSTRING AddressingOptions OPTIONAL
)
{
PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
PLOOP_OPEN NewOpen;
NDIS_STATUS StatusToReturn;
UINT i;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopOpenAdapter\n"));
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
("Opening binding for Adapter %lx\n",Adapter));
for (i=0;i < MediumArraySize; i++) {
if (MediumArray[i] == Adapter->Medium)
break;
}
if (i == MediumArraySize)
return NDIS_STATUS_UNSUPPORTED_MEDIA;
*SelectedMediumIndex = i;
NdisAcquireSpinLock(&Adapter->Lock);
Adapter->References++;
NdisAllocateMemory(
(PVOID)&NewOpen,
sizeof(LOOP_OPEN),
0,
physicalConst
);
if (NewOpen != NULL) {
//
// Setup new Open Binding struct
//
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, ("new Open = %lx\n",NewOpen));
NdisZeroMemory(
NewOpen,
sizeof(LOOP_OPEN)
);
switch (Adapter->Medium) {
case NdisMedium802_3:
case NdisMediumDix:
StatusToReturn = (NDIS_STATUS)EthNoteFilterOpenAdapter(
Adapter->Filter.Eth,
NewOpen,
NdisBindingContext,
&NewOpen->NdisFilterHandle
);
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, ("new EthFilter Open = %lx\n",NewOpen->NdisFilterHandle));
break;
case NdisMedium802_5:
StatusToReturn = (NDIS_STATUS)TrNoteFilterOpenAdapter(
Adapter->Filter.Tr,
NewOpen,
NdisBindingContext,
&NewOpen->NdisFilterHandle
);
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, ("new TrFilter Open = %lx\n",NewOpen->NdisFilterHandle));
break;
case NdisMediumFddi:
StatusToReturn = (NDIS_STATUS)FddiNoteFilterOpenAdapter(
Adapter->Filter.Fddi,
NewOpen,
NdisBindingContext,
&NewOpen->NdisFilterHandle
);
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, ("new FddiFilter Open = %lx\n",NewOpen->NdisFilterHandle));
break;
default:
StatusToReturn = (NDIS_STATUS)TRUE;
break;
}
if (!StatusToReturn) {
DBGPRINT(DBG_COMP_MEMORY, DBG_LEVEL_ERR,
("unable to create filter for binding %lx\n",NewOpen));
NdisWriteErrorLogEntry(
Adapter->NdisAdapterHandle,
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
0
);
NdisFreeMemory(
NewOpen,
sizeof(LOOP_OPEN),
0);
Adapter->References--;
NdisReleaseSpinLock(&Adapter->Lock);
return NDIS_STATUS_FAILURE;
}
*MacBindingHandle = BINDING_HANDLE_FROM_PLOOP_OPEN(NewOpen);
InitializeListHead(&NewOpen->OpenList);
NewOpen->BindingClosing = FALSE;
NewOpen->Flags = 0;
NewOpen->NdisBindingContext = NdisBindingContext;
NewOpen->OwningLoop = Adapter;
NewOpen->References = 1;
NewOpen->CurrentLookAhead = LOOP_MAX_LOOKAHEAD;
NewOpen->CurrentPacketFilter = 0;
//
// Add the binding to the owning adapter
//
InsertTailList(&Adapter->OpenBindings,&NewOpen->OpenList);
Adapter->OpenCount++;
Adapter->References++;
Adapter->MaxLookAhead = LOOP_MAX_LOOKAHEAD;
StatusToReturn = NDIS_STATUS_SUCCESS;
}
else {
DBGPRINT(DBG_COMP_MEMORY, DBG_LEVEL_ERR,
("unable to allocate binding struct for adapter %lx\n",Adapter));
NdisWriteErrorLogEntry(
Adapter->NdisAdapterHandle,
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
0
);
StatusToReturn = NDIS_STATUS_RESOURCES;
}
Adapter->References--;
NdisReleaseSpinLock(&Adapter->Lock);
return StatusToReturn;
}
VOID
LoopRemoveAdapter(
IN NDIS_HANDLE MacAdapterContext
)
//
// All bindings should be closed before this gets called
//
{
PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
BOOLEAN TimerCancel;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopRemoveAdapter\n"));
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
("Removing adapter %lx\n",Adapter));
NdisCancelTimer(&Adapter->LoopTimer,&TimerCancel);
switch (Adapter->Medium) {
case NdisMedium802_3:
case NdisMediumDix:
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
("deleting EthFilter %lx\n",Adapter->Filter.Eth));
EthDeleteFilter(Adapter->Filter.Eth);
break;
case NdisMedium802_5:
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
("deleting TrFilter %lx\n",Adapter->Filter.Tr));
TrDeleteFilter(Adapter->Filter.Tr);
break;
case NdisMediumFddi:
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
("deleting FddiFilter %lx\n",Adapter->Filter.Fddi));
FddiDeleteFilter(Adapter->Filter.Fddi);
break;
default:
break;
}
NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
NdisFreeSpinLock(&Adapter->Lock);
NdisFreeMemory(
Adapter->DeviceName.Buffer,
Adapter->DeviceNameLength,
0
);
NdisFreeMemory(
Adapter,
sizeof(LOOP_ADAPTER),
0
);
}
NDIS_STATUS
LoopReset(
IN NDIS_HANDLE MacBindingHandle
)
{
PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopReset\n"));
NdisAcquireSpinLock(&Adapter->Lock);
Adapter->References++;
if (!Adapter->ResetInProgress) {
PLOOP_OPEN Open = PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
if (!Open->BindingClosing) {
Open->References++;
//
// notify all bindings of beginning of reset
//
{
PLOOP_OPEN Open;
PLIST_ENTRY CurrentLink;
CurrentLink = Adapter->OpenBindings.Flink;
while(CurrentLink != &Adapter->OpenBindings) {
Open = CONTAINING_RECORD(
CurrentLink,
LOOP_OPEN,
OpenList
);
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
("Signaling reset start to binding %lx\n",Open));
if (Open->BindingClosing) {
CurrentLink = CurrentLink->Flink;
continue;
}
Open->References++;
NdisReleaseSpinLock(&Adapter->Lock);
NdisIndicateStatus(
Open->NdisBindingContext,
NDIS_STATUS_RESET_START,
NULL,
0
);
NdisAcquireSpinLock(&Adapter->Lock);
Open->References--;
CurrentLink = CurrentLink->Flink;
}
}
Adapter->ResetInProgress = TRUE;
//
// Loop through the loopback queue and abort any pending sends
//
{
PNDIS_PACKET AbortPacket;
PLOOP_PACKET_RESERVED Reserved;
PLOOP_OPEN Open;
while (Adapter->Loopback != NULL) {
AbortPacket = Adapter->Loopback;
Reserved = PLOOP_RESERVED_FROM_PACKET(AbortPacket);
Adapter->Loopback = Reserved->Next;
Open = PLOOP_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
NdisReleaseSpinLock(&Adapter->Lock);
NdisCompleteSend(
Open->NdisBindingContext,
AbortPacket,
NDIS_STATUS_REQUEST_ABORTED
);
NdisAcquireSpinLock(&Adapter->Lock);
Open->References--;
}
Adapter->CurrentLoopback = NULL;
Adapter->LastLoopback = NULL;
}
//
// notify all bindings of reset end
//
{
PLOOP_OPEN Open;
PLIST_ENTRY CurrentLink;
CurrentLink = Adapter->OpenBindings.Flink;
while(CurrentLink != &Adapter->OpenBindings) {
Open = CONTAINING_RECORD(
CurrentLink,
LOOP_OPEN,
OpenList
);
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
("Signaling reset end to binding %lx\n",Open));
if (Open->BindingClosing) {
CurrentLink = CurrentLink->Flink;
continue;
}
Open->References++;
NdisReleaseSpinLock(&Adapter->Lock);
NdisIndicateStatus(
Open->NdisBindingContext,
NDIS_STATUS_RESET_END,
NULL,
0
);
NdisAcquireSpinLock(&Adapter->Lock);
Open->References--;
CurrentLink = CurrentLink->Flink;
}
}
Open->References--;
Adapter->ResetInProgress = FALSE;
}
else
Status = NDIS_STATUS_CLOSING;
}
else
Status = NDIS_STATUS_RESET_IN_PROGRESS;
Adapter->References--;
NdisReleaseSpinLock(&Adapter->Lock);
return Status;
}
NDIS_STATUS
LoopTransferData(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE MacReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer,
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred
)
{
PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
NDIS_STATUS StatusToReturn;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopTransferData\n"));
NdisAcquireSpinLock(&Adapter->Lock);
Adapter->References++;
if (!Adapter->ResetInProgress) {
PLOOP_OPEN Open = PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
if (!Open->BindingClosing) {
Open->References++;
NdisReleaseSpinLock(&Adapter->Lock);
if (MacReceiveContext == NULL) {
NdisCopyFromPacketToPacket(
Packet,
0,
BytesToTransfer,
Adapter->CurrentLoopback,
ByteOffset+(PLOOP_RESERVED_FROM_PACKET(Adapter->CurrentLoopback)->HeaderLength),
BytesTransferred
);
StatusToReturn = NDIS_STATUS_SUCCESS;
}
else {
//
// shouldn't get here as we never pass a non-NULL receive context
//
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_FATAL,
("transfer data failed! passed a receive context of %lx\n",MacReceiveContext));
StatusToReturn = NDIS_STATUS_FAILURE;
}
NdisAcquireSpinLock(&Adapter->Lock);
Open->References--;
}
else
StatusToReturn = NDIS_STATUS_REQUEST_ABORTED;
}
else
StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
Adapter->References--;
NdisReleaseSpinLock(&Adapter->Lock);
return StatusToReturn;
}
VOID
LoopUnload(
IN NDIS_HANDLE MacMacContext
)
{
NDIS_STATUS Status;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopUnload\n"));
NdisDeregisterMac(
&Status,
LoopMacHandle
);
NdisTerminateWrapper(
LoopWrapperHandle,
NULL
);
}
STATIC
NDIS_STATUS
LoopRegisterAdapter(
IN NDIS_HANDLE LoopMacHandle,
IN PNDIS_STRING AdapterName,
IN NDIS_MEDIUM AdapterMedium,
IN PVOID NetAddress,
IN NDIS_HANDLE ConfigurationHandle
)
{
static const MEDIA_INFO MediaParams[] = {
/* NdisMedium802_3 */ { 1500, 14, PACKET_FILTER_802_3, 100000},
/* NdisMedium802_5 */ { 4082, 14, PACKET_FILTER_802_5, 40000},
/* NdisMediumFddi */ { 4486, 13, PACKET_FILTER_FDDI, 1000000},
/* NdisMediumWan */ { 0, 0, 0, 0},
/* NdisMediumLocalTalk */ { 600, 3, PACKET_FILTER_LTALK, 2300},
/* NdisMediumDix */ { 1500, 14, PACKET_FILTER_DIX, 100000},
/* NdisMediumArcnetRaw */ { 1512, 3, PACKET_FILTER_ARCNET, 25000},
/* NdisMediumArcnet878_2 */ {1512, 3, PACKET_FILTER_ARCNET, 25000} };
//
// Pointer to the adapter
//
PLOOP_ADAPTER Adapter;
//
// status of various NDIS calls
//
NDIS_STATUS Status;
//
// info for registering the adapter
//
NDIS_ADAPTER_INFORMATION AdapterInfo;
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, (" --> LoopRegisterAdapter\n"));
//
// allocate the adapter block
//
NdisAllocateMemory(
(PVOID)&Adapter,
sizeof(LOOP_ADAPTER),
0,
physicalConst
);
if (Adapter != NULL) {
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, ("new Adapter = %lx\n",Adapter));
NdisZeroMemory(
Adapter,
sizeof(LOOP_ADAPTER)
);
Adapter->NdisMacHandle = LoopMacHandle;
//
// allocate memory for the name of the device
//
NdisAllocateMemory(
(PVOID)&Adapter->DeviceName.Buffer,
AdapterName->Length+2,
0,
physicalConst
);
if (Adapter->DeviceName.Buffer != NULL) {
Adapter->DeviceNameLength = AdapterName->Length+2;
Adapter->DeviceName.MaximumLength = AdapterName->Length+2;
NdisZeroMemory(
Adapter->DeviceName.Buffer,
AdapterName->Length+2
);
#ifdef NDIS_NT
RtlCopyUnicodeString(
&Adapter->DeviceName,
AdapterName
);
#else
#error Need to copy a NDIS_STRING.
#endif
//
// set up the AdapterInfo structure
//
NdisZeroMemory(
&AdapterInfo,
sizeof(NDIS_ADAPTER_INFORMATION)
);
AdapterInfo.DmaChannel = 0;
AdapterInfo.Master = FALSE;
AdapterInfo.Dma32BitAddresses = FALSE;
AdapterInfo.AdapterType = NdisInterfaceInternal;
AdapterInfo.PhysicalMapRegistersNeeded = 0;
AdapterInfo.MaximumPhysicalMapping = 0;
AdapterInfo.NumberOfPortDescriptors = 0;
if ((Status = NdisRegisterAdapter(
&Adapter->NdisAdapterHandle,
Adapter->NdisMacHandle,
Adapter,
ConfigurationHandle,
AdapterName,
&AdapterInfo
)) == NDIS_STATUS_SUCCESS) {
InitializeListHead(&Adapter->OpenBindings);
Adapter->OpenCount = 0;
NdisAllocateSpinLock(&Adapter->Lock);
Adapter->InTimerProc = FALSE;
Adapter->TimerSet = FALSE;
Adapter->References = 1;
Adapter->Loopback = NULL;
Adapter->LastLoopback = NULL;
Adapter->CurrentLoopback = NULL;
NdisZeroMemory(
&Adapter->LoopBuffer,
LOOP_MAX_LOOKAHEAD
);
Adapter->ResetInProgress = FALSE;
Adapter->MaxLookAhead = 0;
Adapter->Medium = AdapterMedium;
Adapter->MediumLinkSpeed = MediaParams[(UINT)AdapterMedium].LinkSpeed;
Adapter->MediumMinPacketLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen;
Adapter->MediumMaxPacketLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen+
MediaParams[(UINT)AdapterMedium].MaxFrameLen;
Adapter->MediumMacHeaderLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen;
Adapter->MediumMaxFrameLen = MediaParams[(UINT)AdapterMedium].MaxFrameLen;
Adapter->MediumPacketFilters = MediaParams[(UINT)AdapterMedium].PacketFilters;
switch (AdapterMedium) {
case NdisMedium802_3:
case NdisMediumDix:
NdisMoveMemory(
(PVOID)&Adapter->PermanentAddress,
LOOP_ETH_CARD_ADDRESS,
ETH_LENGTH_OF_ADDRESS
);
if (NetAddress != NULL) {
NdisMoveMemory(
(PVOID)&Adapter->CurrentAddress,
NetAddress,
ETH_LENGTH_OF_ADDRESS
);
}
else {
NdisMoveMemory(
(PVOID)&Adapter->CurrentAddress,
LOOP_ETH_CARD_ADDRESS,
ETH_LENGTH_OF_ADDRESS
);
}
Status = (NDIS_STATUS)EthCreateFilter(
LOOP_ETH_MAX_MULTICAST_ADDRESS,
LoopEthChangeAddress,
LoopChangeFilter,
LoopCloseAction,
Adapter->CurrentAddress,
&Adapter->Lock,
&Adapter->Filter.Eth
);
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
("new EthFilter = %lx\n",Adapter->Filter.Eth));
break;
case NdisMedium802_5:
NdisMoveMemory(
(PVOID)&Adapter->PermanentAddress,
LOOP_TR_CARD_ADDRESS,
TR_LENGTH_OF_ADDRESS
);
if (NetAddress != NULL) {
NdisMoveMemory(
(PVOID)&Adapter->CurrentAddress,
NetAddress,
TR_LENGTH_OF_ADDRESS
);
}
else {
NdisMoveMemory(
(PVOID)&Adapter->CurrentAddress,
LOOP_TR_CARD_ADDRESS,
TR_LENGTH_OF_ADDRESS
);
}
Status = (NDIS_STATUS)TrCreateFilter(
LoopTrChangeAddress,
LoopTrChangeAddress,
LoopChangeFilter,
LoopCloseAction,
Adapter->CurrentAddress,
&Adapter->Lock,
&Adapter->Filter.Tr
);
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
("new TrFilter = %lx\n",Adapter->Filter.Tr));
break;
case NdisMediumFddi:
// the short address will simply be the first 2
// bytes of the long address
NdisMoveMemory(
(PVOID)&Adapter->PermanentAddress,
LOOP_FDDI_CARD_ADDRESS,
FDDI_LENGTH_OF_LONG_ADDRESS
);
if (NetAddress != NULL) {
NdisMoveMemory(
(PVOID)&Adapter->CurrentAddress,
NetAddress,
FDDI_LENGTH_OF_LONG_ADDRESS
);
}
else {
NdisMoveMemory(
(PVOID)&Adapter->CurrentAddress,
LOOP_FDDI_CARD_ADDRESS,
FDDI_LENGTH_OF_LONG_ADDRESS
);
}
Status = (NDIS_STATUS)FddiCreateFilter(
LOOP_FDDI_MAX_MULTICAST_LONG,
LOOP_FDDI_MAX_MULTICAST_SHORT,
LoopFddiChangeAddress,
LoopChangeFilter,
LoopCloseAction,
Adapter->CurrentAddress,
Adapter->CurrentAddress,
&Adapter->Lock,
&Adapter->Filter.Fddi
);
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
("new FddiFilter = %lx\n",Adapter->Filter.Fddi));
break;
case NdisMediumLocalTalk:
Adapter->PermanentAddress[0] = LOOP_LTALK_CARD_ADDRESS;
if (NetAddress != NULL)
Adapter->CurrentAddress[0] = ((PUCHAR)NetAddress)[0];
else
Adapter->CurrentAddress[0] = LOOP_LTALK_CARD_ADDRESS;
// dumb line to satisfy the following status check
Status = (NDIS_STATUS)TRUE;
break;
case NdisMediumArcnet878_2:
Adapter->PermanentAddress[0] = LOOP_ARC_CARD_ADDRESS;
if (NetAddress != NULL)
Adapter->CurrentAddress[0] = ((PUCHAR)NetAddress)[0];
else
Adapter->CurrentAddress[0] = LOOP_ARC_CARD_ADDRESS;
// dumb line to satisfy the following status check
Status = (NDIS_STATUS)TRUE;
break;
default:
// shouldn't get here...
ASSERTMSG("LoopRegisterAdapter: received invalid medium\n",FALSE);
break;
}
if (!Status) {
DBGPRINT(DBG_COMP_MEMORY,DBG_LEVEL_FATAL,
("%wS: Unable to configure media specific information\n",AdapterName));
NdisWriteErrorLogEntry(
Adapter->NdisAdapterHandle,
NDIS_ERROR_CODE_DRIVER_FAILURE,
0
);
NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
NdisFreeSpinLock(&Adapter->Lock);
NdisFreeMemory(
Adapter->DeviceName.Buffer,
Adapter->DeviceNameLength,
0
);
NdisFreeMemory(
Adapter,
sizeof(LOOP_ADAPTER),
0
);
return NDIS_STATUS_FAILURE;
}
NdisInitializeTimer(
&(Adapter->LoopTimer),
LoopTimerProc,
(PVOID)Adapter
);
NdisZeroMemory(
&Adapter->GeneralMandatory,
GM_ARRAY_SIZE * sizeof(ULONG)
);
return NDIS_STATUS_SUCCESS;
}
else {
//
// NdisRegisterAdapter failed
//
DBGPRINT(DBG_COMP_MEMORY,DBG_LEVEL_FATAL,
("%wS: Unable to register adapter, Error = %x\n",AdapterName,Status));
NdisFreeMemory(
Adapter->DeviceName.Buffer,
Adapter->DeviceNameLength,
0
);
NdisFreeMemory(
Adapter,
sizeof(LOOP_ADAPTER),
0
);
return Status;
}
}
else {
//
// failed to allocate device name
//
DBGPRINT(DBG_COMP_MEMORY,DBG_LEVEL_FATAL,
("%wS: Unable to allocate the device name\n",AdapterName));
NdisFreeMemory(
Adapter,
sizeof(LOOP_ADAPTER),
0
);
return NDIS_STATUS_RESOURCES;
}
}
else {
//
// failed to allocate Adapter object
//
DBGPRINT(DBG_COMP_MEMORY,DBG_LEVEL_FATAL,
("%wS: Unable to allocate the adapter object\n",AdapterName));
return NDIS_STATUS_RESOURCES;
}
}
STATIC
NDIS_STATUS
LoopChangeFilter(
IN UINT OldFilterClasses,
IN UINT NewFilterClasses,
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
)
{
PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
NDIS_STATUS StatusToReturn;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopChangeFilter\n"));
if (!Adapter->ResetInProgress)
StatusToReturn = NDIS_STATUS_SUCCESS;
else
StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
return StatusToReturn;
}
STATIC
VOID
LoopCloseAction(
IN NDIS_HANDLE MacBindingHandle
)
{
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopCloseAction\n"));
PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->References--;
}
STATIC
NDIS_STATUS
LoopEthChangeAddress(
IN UINT OldFilterCount,
IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
IN UINT NewFilterCouunt,
IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
)
{
PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
NDIS_STATUS StatusToReturn;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopEthChangeAddress\n"));
if (!Adapter->ResetInProgress)
StatusToReturn = NDIS_STATUS_SUCCESS;
else
StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
return StatusToReturn;
}
STATIC
NDIS_STATUS
LoopTrChangeAddress(
IN TR_FUNCTIONAL_ADDRESS OldFunctionalAddresses,
IN TR_FUNCTIONAL_ADDRESS NewFunctionalAddresses,
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
)
{
PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
NDIS_STATUS StatusToReturn;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopTrChangeAddress\n"));
if (!Adapter->ResetInProgress)
StatusToReturn = NDIS_STATUS_SUCCESS;
else
StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
return StatusToReturn;
}
STATIC
NDIS_STATUS
LoopFddiChangeAddress(
IN UINT OldLongAddressCount,
IN CHAR OldLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
IN UINT NewLongAddressCouunt,
IN CHAR NewLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
IN UINT OldShortAddressCount,
IN CHAR OldShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
IN UINT NewShortAddressCouunt,
IN CHAR NewShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_REQUEST NdisRequest,
IN BOOLEAN Set
)
{
PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
NDIS_STATUS StatusToReturn;
DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopFddiChangeAddress\n"));
if (!Adapter->ResetInProgress)
StatusToReturn = NDIS_STATUS_SUCCESS;
else
StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
return StatusToReturn;
}