📄 lan.c
字号:
}
VOID LANTransmit(
PLAN_ADAPTER Adapter,
PNDIS_PACKET NdisPacket,
PVOID LinkAddress,
USHORT Type)
/*
* FUNCTION: Transmits a packet
* ARGUMENTS:
* Context = Pointer to context information (LAN_ADAPTER)
* NdisPacket = Pointer to NDIS packet to send
* LinkAddress = Pointer to link address of destination (NULL = broadcast)
* Type = LAN protocol type (LAN_PROTO_*)
*/
{
NDIS_STATUS NdisStatus;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
if (Adapter->State == LAN_STATE_STARTED) {
NdisSend(&NdisStatus, Adapter->NdisHandle, NdisPacket);
if (NdisStatus != NDIS_STATUS_PENDING)
ProtocolSendComplete((NDIS_HANDLE)Adapter, NdisPacket, NdisStatus);
} else {
ProtocolSendComplete((NDIS_HANDLE)Adapter, NdisPacket, NDIS_STATUS_CLOSED);
}
}
/* For use internally */
UINT LANTransmitInternal(PLAN_PACKET_HEADER ToWrite, UINT OverallLength) {
NDIS_STATUS NdisStatus;
PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension;
PLAN_ADAPTER Adapter;
PETH_HEADER EthHeader;
KIRQL OldIrql;
PNDIS_PACKET NdisPacket;
UINT Size, PayloadSize = OverallLength -
((ToWrite->Address + ToWrite->Fixed.AddressLen) - (PCHAR)ToWrite);
NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL,
PayloadSize + sizeof(ETH_HEADER) );
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
if( !NT_SUCCESS(NdisStatus) ) goto end;
Adapter = FindAdapterByIndex( DeviceExt, ToWrite->Fixed.Adapter );
if( !Adapter ) goto end;
GetDataPtr( NdisPacket, 0, (PCHAR *)&EthHeader, &Size );
if( !EthHeader ) goto end;
LA_DbgPrint(MID_TRACE,("Writing %d bytes of Dst\n",
ToWrite->Fixed.AddressLen));
/* Handle broadcast for other media types here */
if( ToWrite->Fixed.AddressLen )
RtlCopyMemory( EthHeader->DstAddr,
ToWrite->Address,
ToWrite->Fixed.AddressLen );
else
memset( EthHeader->DstAddr, -1, sizeof(EthHeader->DstAddr) );
LA_DbgPrint(MID_TRACE,("Writing %d bytes of Src\n", Adapter->HWAddressLength));
RtlCopyMemory( EthHeader->SrcAddr,
Adapter->HWAddress,
Adapter->HWAddressLength );
LA_DbgPrint(MID_TRACE,("Writing %d bytes of payload\n", PayloadSize));
EthHeader->EType = ToWrite->Fixed.PacketType;
RtlCopyMemory( EthHeader + 1,
ToWrite->Address + ToWrite->Fixed.AddressLen,
PayloadSize );
LANTransmit( Adapter, NdisPacket, ToWrite->Address,
ToWrite->Fixed.PacketType );
end:
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
return OverallLength;
}
VOID BindAdapter(PLAN_ADAPTER Adapter, PNDIS_STRING RegistryPath)
/*
* FUNCTION: Binds a LAN adapter to IP layer
* ARGUMENTS:
* Adapter = Pointer to LAN_ADAPTER structure
* NOTES:
* We set the lookahead buffer size, set the packet filter and
* bind the adapter to IP layer
*/
{
/*NDIS_STATUS NdisStatus;*/
/*ULONG Lookahead = LOOKAHEAD_SIZE;*/
/*NTSTATUS Status;*/
/*HANDLE RegHandle = 0;*/
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
}
NDIS_STATUS LANRegisterAdapter( PNDIS_STRING AdapterName,
PNDIS_STRING RegistryPath)
/*
* FUNCTION: Registers protocol with an NDIS adapter
* ARGUMENTS:
* AdapterName = Pointer to string with name of adapter to register
* Adapter = Address of pointer to a LAN_ADAPTER structure
* RETURNS:
* Status of operation
*/
{
PLAN_ADAPTER Adapter;
NDIS_MEDIUM MediaArray[MAX_MEDIA];
NDIS_STATUS NdisStatus;
NDIS_STATUS OpenStatus;
UINT MediaIndex;
UINT AddressOID;
UINT Speed;
PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
Adapter = exAllocatePool(NonPagedPool, sizeof(LAN_ADAPTER));
if (!Adapter) {
LA_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NDIS_STATUS_RESOURCES;
}
RtlZeroMemory(Adapter, sizeof(LAN_ADAPTER));
/* Put adapter in stopped state */
Adapter->State = LAN_STATE_STOPPED;
Adapter->Index = DeviceExt->AdapterId++;
InitializeListHead( &Adapter->AddressList );
InitializeListHead( &Adapter->ForeignList );
/* Initialize protecting spin lock */
KeInitializeSpinLock(&Adapter->Lock);
KeInitializeEvent(&Adapter->Event, SynchronizationEvent, FALSE);
/* Initialize array with media IDs we support */
MediaArray[MEDIA_ETH] = NdisMedium802_3;
LA_DbgPrint(DEBUG_DATALINK,("opening adapter %wZ\n", AdapterName));
/* Open the adapter. */
NdisOpenAdapter(&NdisStatus,
&OpenStatus,
&Adapter->NdisHandle,
&MediaIndex,
MediaArray,
MAX_MEDIA,
DeviceExt->NdisProtocolHandle,
Adapter,
AdapterName,
0,
NULL);
/* Wait until the adapter is opened */
if (NdisStatus == NDIS_STATUS_PENDING)
KeWaitForSingleObject(&Adapter->Event, UserRequest, KernelMode, FALSE, NULL);
else if (NdisStatus != NDIS_STATUS_SUCCESS) {
exFreePool(Adapter);
return NdisStatus;
}
Adapter->Media = MediaArray[MediaIndex];
/* Fill LAN_ADAPTER structure with some adapter specific information */
switch (Adapter->Media) {
case NdisMedium802_3:
Adapter->HWAddressLength = IEEE_802_ADDR_LENGTH;
Adapter->BCastMask = BCAST_ETH_MASK;
Adapter->BCastCheck = BCAST_ETH_CHECK;
Adapter->BCastOffset = BCAST_ETH_OFFSET;
Adapter->HeaderSize = sizeof(ETH_HEADER);
Adapter->MinFrameSize = 60;
AddressOID = OID_802_3_CURRENT_ADDRESS;
Adapter->PacketFilter =
NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_DIRECTED |
NDIS_PACKET_TYPE_MULTICAST;
break;
default:
/* Unsupported media */
LA_DbgPrint(MIN_TRACE, ("Unsupported media.\n"));
exFreePool(Adapter);
return NDIS_STATUS_NOT_SUPPORTED;
}
/* Get maximum frame size */
NdisStatus = NDISCall(Adapter,
NdisRequestQueryInformation,
OID_GEN_MAXIMUM_FRAME_SIZE,
&Adapter->MTU,
sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
exFreePool(Adapter);
return NdisStatus;
}
/* Get maximum packet size */
NdisStatus = NDISCall(Adapter,
NdisRequestQueryInformation,
OID_GEN_MAXIMUM_TOTAL_SIZE,
&Adapter->MaxPacketSize,
sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
LA_DbgPrint(MIN_TRACE, ("Query for maximum packet size failed.\n"));
exFreePool(Adapter);
return NdisStatus;
}
/* Get maximum number of packets we can pass to NdisSend(Packets) at one time */
NdisStatus = NDISCall(Adapter,
NdisRequestQueryInformation,
OID_GEN_MAXIMUM_SEND_PACKETS,
&Adapter->MaxSendPackets,
sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS)
/* Legacy NIC drivers may not support this query, if it fails we
assume it can send at least one packet per call to NdisSend(Packets) */
Adapter->MaxSendPackets = 1;
/* Get current hardware address */
NdisStatus = NDISCall(Adapter,
NdisRequestQueryInformation,
AddressOID,
Adapter->HWAddress,
Adapter->HWAddressLength);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
LA_DbgPrint(MIN_TRACE, ("Query for current hardware address failed.\n"));
exFreePool(Adapter);
return NdisStatus;
}
/* Get maximum link speed */
NdisStatus = NDISCall(Adapter,
NdisRequestQueryInformation,
OID_GEN_LINK_SPEED,
&Speed,
sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
LA_DbgPrint(MIN_TRACE, ("Query for maximum link speed failed.\n"));
exFreePool(Adapter);
return NdisStatus;
}
/* Convert returned link speed to bps (it is in 100bps increments) */
Adapter->Speed = Speed * 100L;
/* Add adapter to the adapter list */
ExInterlockedInsertTailList(&DeviceExt->AdapterListHead,
&Adapter->ListEntry,
&DeviceExt->Lock);
Adapter->RegistryPath.Buffer =
ExAllocatePool( NonPagedPool, RegistryPath->MaximumLength );
if( !Adapter->RegistryPath.Buffer )
return NDIS_STATUS_RESOURCES;
RtlCopyUnicodeString( &Adapter->RegistryPath,
RegistryPath );
NdisStatus = NDISCall(Adapter,
NdisRequestSetInformation,
OID_GEN_CURRENT_LOOKAHEAD,
&Adapter->Lookahead,
sizeof(ULONG));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
LA_DbgPrint(MID_TRACE,
("Could not set lookahead buffer size (0x%X).\n",
NdisStatus));
return NdisStatus;
}
/* Set packet filter so we can send and receive packets */
NdisStatus = NDISCall(Adapter,
NdisRequestSetInformation,
OID_GEN_CURRENT_PACKET_FILTER,
&Adapter->PacketFilter,
sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
LA_DbgPrint(MID_TRACE, ("Could not set packet filter (0x%X).\n",
NdisStatus));
return NdisStatus;
}
Adapter->State = LAN_STATE_STARTED;
LA_DbgPrint(DEBUG_DATALINK, ("Leaving.\n"));
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS LANUnregisterAdapter(
PLAN_ADAPTER Adapter)
/*
* FUNCTION: Unregisters protocol with NDIS adapter
* ARGUMENTS:
* Adapter = Pointer to a LAN_ADAPTER structure
* RETURNS:
* Status of operation
*/
{
KIRQL OldIrql;
NDIS_HANDLE NdisHandle;
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
/* Unlink the adapter from the list */
RemoveEntryList(&Adapter->ListEntry);
KeAcquireSpinLock(&Adapter->Lock, &OldIrql);
NdisHandle = Adapter->NdisHandle;
if (NdisHandle) {
Adapter->NdisHandle = NULL;
KeReleaseSpinLock(&Adapter->Lock, OldIrql);
NdisCloseAdapter(&NdisStatus, NdisHandle);
if (NdisStatus == NDIS_STATUS_PENDING) {
KeWaitForSingleObject(&Adapter->Event,
UserRequest,
KernelMode,
FALSE,
NULL);
NdisStatus = Adapter->NdisStatus;
}
} else
KeReleaseSpinLock(&Adapter->Lock, OldIrql);
FreeAdapter(Adapter);
return NDIS_STATUS_SUCCESS;
}
NTSTATUS LANRegisterProtocol(PNDIS_STRING Name)
/*
* FUNCTION: Registers this protocol driver with NDIS
* ARGUMENTS:
* Name = Name of this protocol driver
* RETURNS:
* Status of operation
*/
{
NDIS_STATUS NdisStatus;
NDIS_PROTOCOL_CHARACTERISTICS ProtChars;
PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
InitializeListHead(&DeviceExt->AdapterListHead);
InitializeListHead(&DeviceExt->ProtocolListHead);
/* Set up protocol characteristics */
RtlZeroMemory(&ProtChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
ProtChars.MajorNdisVersion = NDIS_VERSION_MAJOR;
ProtChars.MinorNdisVersion = NDIS_VERSION_MINOR;
ProtChars.Name.Length = Name->Length;
ProtChars.Name.Buffer = Name->Buffer;
ProtChars.Name.MaximumLength = Name->MaximumLength;
ProtChars.OpenAdapterCompleteHandler = ProtocolOpenAdapterComplete;
ProtChars.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete;
ProtChars.ResetCompleteHandler = ProtocolResetComplete;
ProtChars.RequestCompleteHandler = ProtocolRequestComplete;
ProtChars.SendCompleteHandler = ProtocolSendComplete;
ProtChars.TransferDataCompleteHandler = ProtocolTransferDataComplete;
ProtChars.ReceiveHandler = ProtocolReceive;
ProtChars.ReceiveCompleteHandler = ProtocolReceiveComplete;
ProtChars.StatusHandler = ProtocolStatus;
ProtChars.StatusCompleteHandler = ProtocolStatusComplete;
ProtChars.BindAdapterHandler = ProtocolBindAdapter;
/* Try to register protocol */
NdisRegisterProtocol(&NdisStatus,
&DeviceExt->NdisProtocolHandle,
&ProtChars,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if (NdisStatus != NDIS_STATUS_SUCCESS)
{
LA_DbgPrint(MID_TRACE, ("NdisRegisterProtocol failed, status 0x%x\n", NdisStatus));
return (NTSTATUS)NdisStatus;
}
return STATUS_SUCCESS;
}
VOID LANUnregisterProtocol(VOID)
/*
* FUNCTION: Unregisters this protocol driver with NDIS
* NOTES: Does not care wether we are already registered
*/
{
PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
NDIS_STATUS NdisStatus;
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
PLAN_ADAPTER Current;
KIRQL OldIrql;
KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql);
/* Search the list and remove every adapter we find */
CurrentEntry = DeviceExt->AdapterListHead.Flink;
while (CurrentEntry != &DeviceExt->AdapterListHead) {
NextEntry = CurrentEntry->Flink;
Current = CONTAINING_RECORD(CurrentEntry, LAN_ADAPTER, ListEntry);
/* Unregister it */
LANUnregisterAdapter(Current);
CurrentEntry = NextEntry;
}
NdisDeregisterProtocol(&NdisStatus, DeviceExt->NdisProtocolHandle);
}
NTSTATUS STDCALL
LanCreateProtocol( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
PLAN_PROTOCOL Proto;
PFILE_FULL_EA_INFORMATION EaInfo;
PLAN_DEVICE_EXT DeviceExt =
(PLAN_DEVICE_EXT)DeviceObject->DeviceExtension;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PCHAR ProtoNumbersToMatch;
UINT Size = sizeof( *Proto );
NTSTATUS Status = STATUS_SUCCESS;
EaInfo = Irp->AssociatedIrp.SystemBuffer;
Size += EaInfo->EaValueLength;
Proto = ExAllocatePool( NonPagedPool, Size );
if( !Proto ) {
Status = Irp->IoStatus.Status = STATUS_NO_MEMORY;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
return Status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -