⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lan.c

📁 一个类似windows
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS TCP/IP protocol driver
 * FILE:        datalink/lan.c
 * PURPOSE:     Local Area Network media routines
 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
 * REVISIONS:
 *   CSH 01/08-2000 Created
 *   arty -- Separate service 09/2004
 */

#include "precomp.h"

ULONG DebugTraceLevel = 0x7ffffff;
PDEVICE_OBJECT LanDeviceObject  = NULL;

NDIS_STATUS NDISCall(
    PLAN_ADAPTER Adapter,
    NDIS_REQUEST_TYPE Type,
    NDIS_OID OID,
    PVOID Buffer,
    UINT Length)
/*
 * FUNCTION: Send a request to NDIS
 * ARGUMENTS:
 *     Adapter     = Pointer to a LAN_ADAPTER structure
 *     Type        = Type of request (Set or Query)
 *     OID         = Value to be set/queried for
 *     Buffer      = Pointer to a buffer to use
 *     Length      = Number of bytes in Buffer
 * RETURNS:
 *     Status of operation
 */
{
    NDIS_REQUEST Request;
    NDIS_STATUS NdisStatus;

    Request.RequestType = Type;
    if (Type == NdisRequestSetInformation) {
        Request.DATA.SET_INFORMATION.Oid                     = OID;
        Request.DATA.SET_INFORMATION.InformationBuffer       = Buffer;
        Request.DATA.SET_INFORMATION.InformationBufferLength = Length;
    } else {
        Request.DATA.QUERY_INFORMATION.Oid                     = OID;
        Request.DATA.QUERY_INFORMATION.InformationBuffer       = Buffer;
        Request.DATA.QUERY_INFORMATION.InformationBufferLength = Length;
    }

    if (Adapter->State != LAN_STATE_RESETTING) {
        NdisRequest(&NdisStatus, Adapter->NdisHandle, &Request);
    } else {
        NdisStatus = NDIS_STATUS_NOT_ACCEPTED;
    }

    /* Wait for NDIS to complete the request */
    if (NdisStatus == NDIS_STATUS_PENDING) {
        KeWaitForSingleObject(&Adapter->Event,
                              UserRequest,
                              KernelMode,
                              FALSE,
                              NULL);
        NdisStatus = Adapter->NdisStatus;
    }

    return NdisStatus;
}


VOID FreeAdapter(
    PLAN_ADAPTER Adapter)
/*
 * FUNCTION: Frees memory for a LAN_ADAPTER structure
 * ARGUMENTS:
 *     Adapter = Pointer to LAN_ADAPTER structure to free
 */
{
    exFreePool(Adapter);
}


VOID STDCALL ProtocolOpenAdapterComplete(
    NDIS_HANDLE BindingContext,
    NDIS_STATUS Status,
    NDIS_STATUS OpenErrorStatus)
/*
 * FUNCTION: Called by NDIS to complete opening of an adapter
 * ARGUMENTS:
 *     BindingContext  = Pointer to a device context (LAN_ADAPTER)
 *     Status          = Status of the operation
 *     OpenErrorStatus = Additional status information
 */
{
    PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;

    LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));

    KeSetEvent(&Adapter->Event, 0, FALSE);
}


VOID STDCALL ProtocolCloseAdapterComplete(
    NDIS_HANDLE BindingContext,
    NDIS_STATUS Status)
/*
 * FUNCTION: Called by NDIS to complete closing an adapter
 * ARGUMENTS:
 *     BindingContext = Pointer to a device context (LAN_ADAPTER)
 *     Status         = Status of the operation
 */
{
    PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;

    LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));

    Adapter->NdisStatus = Status;

    KeSetEvent(&Adapter->Event, 0, FALSE);
}


VOID STDCALL ProtocolResetComplete(
    NDIS_HANDLE BindingContext,
    NDIS_STATUS Status)
/*
 * FUNCTION: Called by NDIS to complete resetting an adapter
 * ARGUMENTS:
 *     BindingContext = Pointer to a device context (LAN_ADAPTER)
 *     Status         = Status of the operation
 */
{
    LA_DbgPrint(MID_TRACE, ("Called.\n"));
}


VOID STDCALL ProtocolRequestComplete(
    NDIS_HANDLE BindingContext,
    PNDIS_REQUEST NdisRequest,
    NDIS_STATUS Status)
/*
 * FUNCTION: Called by NDIS to complete a request
 * ARGUMENTS:
 *     BindingContext = Pointer to a device context (LAN_ADAPTER)
 *     NdisRequest    = Pointer to an object describing the request
 *     Status         = Status of the operation
 */
{
    PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;

    LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));

    /* Save status of request and signal an event */
    Adapter->NdisStatus = Status;

    KeSetEvent(&Adapter->Event, 0, FALSE);
}


VOID STDCALL ProtocolSendComplete(
    NDIS_HANDLE BindingContext,
    PNDIS_PACKET Packet,
    NDIS_STATUS Status)
/*
 * FUNCTION: Called by NDIS to complete sending process
 * ARGUMENTS:
 *     BindingContext = Pointer to a device context (LAN_ADAPTER)
 *     Packet         = Pointer to a packet descriptor
 *     Status         = Status of the operation
 */
{
    /*PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;*/

    LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
    /*(*PC(Packet)->DLComplete)(Adapter->Context, Packet, Status);*/
    LA_DbgPrint(DEBUG_DATALINK, ("Finished\n"));
}


VOID STDCALL ProtocolTransferDataComplete(
    NDIS_HANDLE BindingContext,
    PNDIS_PACKET Packet,
    NDIS_STATUS Status,
    UINT BytesTransferred)
/*
 * FUNCTION: Called by NDIS to complete reception of data
 * ARGUMENTS:
 *     BindingContext   = Pointer to a device context (LAN_ADAPTER)
 *     Packet           = Pointer to a packet descriptor
 *     Status           = Status of the operation
 *     BytesTransferred = Number of bytes transferred
 * NOTES:
 *     If the packet was successfully received, determine the protocol
 *     type and pass it to the correct receive handler
 */
{
    PLIST_ENTRY ListEntry, ReadListEntry;
    PLAN_PROTOCOL Proto;
    PLAN_PACKET_HEADER Header;
    PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension;
    UINT i;
    UINT PacketType;
    UINT ContigSize;
    PIRP ReadIrp;
    KIRQL OldIrql;
    LAN_PACKET LPPacket;
    PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;

    LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));

    KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );

    if (Status == NDIS_STATUS_SUCCESS) {
        PNDIS_BUFFER NdisBuffer;

        NdisGetFirstBufferFromPacket(Packet,
                                     &NdisBuffer,
                                     &LPPacket.EthHeader,
                                     &ContigSize,
                                     &LPPacket.TotalSize);

	LPPacket.TotalSize = BytesTransferred;

        /* Determine which upper layer protocol that should receive
           this packet and pass it to the correct receive handler */

        /*OskitDumpBuffer( IPPacket.Header, BytesTransferred );*/

        PacketType = LPPacket.EthHeader->EType;

	LA_DbgPrint
	    (DEBUG_DATALINK,
	     ("Ether Type = %x Total = %d Packet %x Payload %x\n",
	      PacketType, LPPacket.TotalSize, LPPacket.EthHeader,
	      LPPacket.EthHeader + 1));

	NdisBuffer->Next = NULL;

	for( ListEntry = DeviceExt->ProtocolListHead.Flink;
	     ListEntry != &DeviceExt->ProtocolListHead;
	     ListEntry = ListEntry->Flink ) {
	    Proto = CONTAINING_RECORD(ListEntry, LAN_PROTOCOL, ListEntry);
	    LA_DbgPrint(MID_TRACE,("Examining protocol %x\n", Proto));
	    for( i = 0; i < Proto->NumEtherTypes; i++ ) {
		LA_DbgPrint(MID_TRACE,(".Accepts proto %x\n",
				       Proto->EtherType[i]));
		if( Proto->EtherType[i] == PacketType &&
		    !IsListEmpty( &Proto->ReadIrpListHead ) ) {
		    ReadListEntry = RemoveHeadList( &Proto->ReadIrpListHead );
		    ReadIrp = CONTAINING_RECORD(ReadListEntry, IRP,
						Tail.Overlay.ListEntry );
		    LA_DbgPrint(MID_TRACE,("..Irp %x\n", ReadIrp));
		    _SEH_TRY {
			Header = ReadIrp->AssociatedIrp.SystemBuffer;
			LA_DbgPrint
			    (MID_TRACE,
			     ("Writing packet at %x\n", Header));
			Header->Fixed.Adapter = Adapter->Index;
			Header->Fixed.AddressType = Adapter->Media;
			Header->Fixed.AddressLen = IEEE_802_ADDR_LENGTH;
			Header->Fixed.PacketType = PacketType;
			RtlCopyMemory( Header->Address,
				       LPPacket.EthHeader->SrcAddr,
				       IEEE_802_ADDR_LENGTH );
			if( Proto->Buffered ) {
			    LA_DbgPrint(MID_TRACE,("Buffered copy\n"));
			    RtlCopyMemory
				( Header->Address +
				  IEEE_802_ADDR_LENGTH,
				  LPPacket.EthHeader + 1,
				  LPPacket.TotalSize -
				  sizeof(*LPPacket.EthHeader) );
			    Header->Fixed.Mdl = NULL;
			} else
			    Header->Fixed.Mdl = NdisBuffer;

			ReadIrp->IoStatus.Status = 0;
			ReadIrp->IoStatus.Information =
			    (Header->Address + IEEE_802_ADDR_LENGTH +
			     LPPacket.TotalSize -
			     sizeof(*LPPacket.EthHeader)) -
			    (PCHAR)Header;

			LA_DbgPrint(MID_TRACE,("Bytes returned %d\n",
					       ReadIrp->IoStatus.Information));

			IoCompleteRequest( ReadIrp, IO_NETWORK_INCREMENT );
		    } _SEH_HANDLE {
			LA_DbgPrint
			    (MIN_TRACE,
			     ("Failed write to packet in client\n"));
			ReadIrp->IoStatus.Status = STATUS_ACCESS_VIOLATION;
			ReadIrp->IoStatus.Information = 0;
			IoCompleteRequest( ReadIrp, IO_NETWORK_INCREMENT );
		    } _SEH_END;
		    break;
		}
	    }
	}
    }

    KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );

    FreeNdisPacket( Packet );
}


NDIS_STATUS STDCALL ProtocolReceive(
    NDIS_HANDLE BindingContext,
    NDIS_HANDLE MacReceiveContext,
    PVOID HeaderBuffer,
    UINT HeaderBufferSize,
    PVOID LookaheadBuffer,
    UINT LookaheadBufferSize,
    UINT PacketSize)
/*
 * FUNCTION: Called by NDIS when a packet has been received on the physical link
 * ARGUMENTS:
 *     BindingContext      = Pointer to a device context (LAN_ADAPTER)
 *     MacReceiveContext   = Handle used by underlying NIC driver
 *     HeaderBuffer        = Pointer to a buffer containing the packet header
 *     HeaderBufferSize    = Number of bytes in HeaderBuffer
 *     LookaheadBuffer     = Pointer to a buffer containing buffered packet data
 *     LookaheadBufferSize = Size of LookaheadBuffer. May be less than asked for
 *     PacketSize          = Overall size of the packet (not including header)
 * RETURNS:
 *     Status of operation
 */
{
    USHORT EType;
    UINT PacketType, BytesTransferred;
    PCHAR BufferData;
    NDIS_STATUS NdisStatus;
    PNDIS_PACKET NdisPacket;
    PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;

    LA_DbgPrint(DEBUG_DATALINK, ("Called. (packetsize %d)\n",PacketSize));

    if (Adapter->State != LAN_STATE_STARTED) {
        LA_DbgPrint(DEBUG_DATALINK, ("Adapter is stopped.\n"));
        return NDIS_STATUS_NOT_ACCEPTED;
    }

    if (HeaderBufferSize < Adapter->HeaderSize) {
        LA_DbgPrint(DEBUG_DATALINK, ("Runt frame received.\n"));
        return NDIS_STATUS_NOT_ACCEPTED;
    }

    PacketType = EType;

    /* Get a transfer data packet */
    KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
    NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Adapter->MTU );
    if( NdisStatus != NDIS_STATUS_SUCCESS ) return NDIS_STATUS_NOT_ACCEPTED;
    LA_DbgPrint(DEBUG_DATALINK, ("pretransfer LookaheadBufferSize %d packsize %d\n",LookaheadBufferSize,PacketSize));
    {
	UINT temp;
	temp = PacketSize;
	GetDataPtr( NdisPacket, 0, &BufferData, &temp );
    }

    LA_DbgPrint(DEBUG_DATALINK, ("pretransfer LookaheadBufferSize %d HeaderBufferSize %d packsize %d\n",LookaheadBufferSize,HeaderBufferSize,PacketSize));
    /* Get the data */
    NdisTransferData(&NdisStatus,
		     Adapter->NdisHandle,
		     MacReceiveContext,
		     0,
		     PacketSize + HeaderBufferSize,
		     NdisPacket,
		     &BytesTransferred);

    LA_DbgPrint(DEBUG_DATALINK, ("Calling complete\n"));

    if (NdisStatus != NDIS_STATUS_PENDING)
	ProtocolTransferDataComplete(BindingContext,
				     NdisPacket,
				     NdisStatus,
				     PacketSize + HeaderBufferSize);

    /* Release the packet descriptor */
    KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
    LA_DbgPrint(DEBUG_DATALINK, ("leaving\n"));

    return NDIS_STATUS_SUCCESS;
}


VOID STDCALL ProtocolReceiveComplete(
    NDIS_HANDLE BindingContext)
/*
 * FUNCTION: Called by NDIS when we're done receiving data
 * ARGUMENTS:
 *     BindingContext = Pointer to a device context (LAN_ADAPTER)
 */
{
    LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
}


VOID STDCALL ProtocolStatus(
    NDIS_HANDLE BindingContext,
    NDIS_STATUS GenerelStatus,
    PVOID StatusBuffer,
    UINT StatusBufferSize)
/*
 * FUNCTION: Called by NDIS when the underlying driver has changed state
 * ARGUMENTS:
 *     BindingContext   = Pointer to a device context (LAN_ADAPTER)
 *     GenerelStatus    = A generel status code
 *     StatusBuffer     = Pointer to a buffer with medium-specific data
 *     StatusBufferSize = Number of bytes in StatusBuffer
 */
{
    LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
}


VOID STDCALL ProtocolStatusComplete(
    NDIS_HANDLE NdisBindingContext)
/*
 * FUNCTION: Called by NDIS when a status-change has occurred
 * ARGUMENTS:
 *     BindingContext = Pointer to a device context (LAN_ADAPTER)
 */
{
    LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
}

VOID STDCALL ProtocolBindAdapter(
    OUT PNDIS_STATUS   Status,
    IN  NDIS_HANDLE    BindContext,
    IN  PNDIS_STRING   DeviceName,
    IN  PVOID          SystemSpecific1,
    IN  PVOID          SystemSpecific2)
/*
 * FUNCTION: Called by NDIS during NdisRegisterProtocol to set up initial
 *           bindings, and periodically thereafer as new adapters come online
 * ARGUMENTS:
 *     Status: Return value to NDIS
 *     BindContext: Handle provided by NDIS to track pending binding operations
 *     DeviceName: Name of the miniport device to bind to
 *     SystemSpecific1: Pointer to a registry path with protocol-specific configuration information
 *     SystemSpecific2: Unused & must not be touched
 */
{
    /* XXX confirm that this is still true, or re-word the following comment */
    /* we get to ignore BindContext because we will never pend an operation with NDIS */
    LA_DbgPrint(DEBUG_DATALINK, ("Called with registry path %wZ\n", SystemSpecific1));
    *Status = LANRegisterAdapter(DeviceName, SystemSpecific1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -