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

📄 lan.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
}


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 + -