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

📄 miniport.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 5 页
字号:
//
void
MiniportSendComplete(
    MiniportAdapter *VA,
    SRPacket *srp,
    NDIS_STATUS Status)
{
    NDIS_PACKET *Packet = srp->Packet;

    UNREFERENCED_PARAMETER(Status);
    
    PrintfNdisStatus(__FUNCTION__,Status,FALSE);

    //
    // Return the original clear-text packet back to NDIS.
    //
    NdisMSendComplete(VA->MiniportHandle,
                      PC(Packet)->OrigPacket,
                      srp->ForwardStatus);

    //
    // This also frees Packet.
    //
    SRPacketFree(srp);
}

//* MiniportFreePacket
//
//  Helper function for MiniportTransmitPacket.
//
void
MiniportFreePacket(
    ProtocolAdapter *PA,
    NDIS_PACKET *Packet)
{
    UNREFERENCED_PARAMETER(PA);
    NdisFreePacketClone(Packet);
}

//* MiniportTransmitPacket
//
//  Called by layer 3 protocols wanting to tx a packet via VRR miniport.
//
void
MiniportTransmitPacket(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet)
{
    SRPacket *srp;
    EtherHeader UNALIGNED *Ether;
    NDIS_STATUS Status;
    uint IsTransportPacket = TRUE;
    uint IsIPv6NS = FALSE;

    InterlockedIncrement((PLONG)&VA->CountXmitLocally);

    //
    // For testing purposes we may want to supress all user tx.
    //
    if (VA->TxDropAllButHello == TRUE) {
        Status = NDIS_STATUS_RESOURCES;
        goto ErrorReturn;
    }
    VrrTrace(VA,3,"MP:Tx=entered",NULL,NULL,NULL,NULL,0,NULL,0);

    //
    // Allocate an SRPacket structure for this packet.
    //
    srp = ExAllocatePool(NonPagedPool, sizeof *srp);
    if (srp == NULL) {
        Status = NDIS_STATUS_RESOURCES;
        goto ErrorReturn;
    }
    RtlZeroMemory(srp, sizeof *srp);

    //
    // Encrypt the packet payload (including the EType).
    // This generates an IV.
    //
    Status = CryptoEncryptPacket(VA, Packet,
                                 sizeof(EtherHeader) - sizeof(ushort),
                                 srp->IV, &srp->Packet);
    if (Status != NDIS_STATUS_SUCCESS)
        goto ErrorFreeSRP;

    //
    // MiniportFreePacket will free the encrypted packet
    // using NdisFreePacketClone.
    //
    srp->PA = NULL;
    srp->FreePacket = MiniportFreePacket;

    //
    // This is a dummy value, so srp->PacketLength vs srp->PayloadOffset
    // comparisons will work properly. We do not need the actual
    // length of srp->Packet.
    //
    srp->PacketLength = 1;

    //
    // MiniportSendComplete will complete the original packet.
    //
    PC(srp->Packet)->OrigPacket = Packet;

    //
    // Initialize the virtual source & destination addresses
    // in the SRPacket. If our caller supplies a bogus
    // source address, we ignore it. This can happen,
    // for example when the IPv4 stack detects a duplicate address
    // it sends an ARP with the "wrong" source address.
    //
    Ether = NdisFirstBuffer(Packet)->MappedSystemVa;
    RtlCopyMemory(srp->Dest, Ether->Dest, SR_ADDR_LEN);
    RtlCopyMemory(srp->Source, VA->Address, SR_ADDR_LEN);
    RtlCopyMemory(srp->Origin, VA->Address, SR_ADDR_LEN);
    srp->FrameSeqNo = InterlockedIncrement((unsigned long *)&VrrGlobal.NextFrameSeqNo);
    srp->HopCount = 0;

    //
    // Special case handling for IPv6 NS and DHT application packets.
    //
    if (IPv6TrapOutboundNS(VA,Packet,Ether)) {
        //
        // IPv6: trap outbound IPv6 NS. We just handled special cases for
        // magic DHT addresses, and for other IPv6 addresses we drop through
        // and send to nearest(VRR) by unicast transmission.
        //
        RtlCopyMemory(srp->Dest, Ether->Dest, SR_ADDR_LEN);
        IsIPv6NS = TRUE;
        VrrTrace(VA,3,"MP:Tx=TrapOutNS",NULL,NULL,Ether->Dest,NULL,0,NULL,0);
    }
#if BROADCAST_SUPPORTED
    else if (IsBroadcastRelay(VA)==FALSE && IPv4TrapOutboundARPRequest(VA,Packet,Ether)) {
#else
    else if (IPv4TrapOutboundARPRequest(VA,Packet,Ether))
#endif
        //
        // Catch outbound ARP request for resolution in DHT service, and cause
        // the original packet to be dropped by DHTMagicL2 test (below).
        //
        RtlCopyMemory(srp->Dest, DHTMagicL2, SR_ADDR_LEN);
        VrrTrace(VA,3,"MP:Tx=TrapOutARP",NULL,NULL,Ether->Dest,NULL,0,NULL,0);
    }
    else if (IPv6TrapOutboundDHT(VA,Packet,Ether, srp)) {
        //
        // DHT: catches outbound UDP(DHT) and reroutes towards key in UDP payload.
        // In the case of DHT-generated packets the VRR dest may use the IEEE group
        // and dest bits even though the VRR addresses assigned to hosts avoid them. 
        //
        IsTransportPacket = FALSE;
        VrrTrace(VA,3,"MP:Tx=TrapOutDHT",NULL,NULL,Ether->Dest,NULL,0,NULL,0);
    }

    //
    // Mainline handling.
    //
    if (RtlEqualMemory(srp->Dest, DHTMagicL2, sizeof(PhysicalAddress))) {
        //
        // We never transmit to the magic DHT L2 address.
        //
        VrrTrace(VA,3,"MP:Tx=IsDHTMagicL2",NULL,NULL,Ether->Dest,NULL,0,NULL,0);
        goto ErrorFreeSRP;
    }
#if BROADCAST_SUPPORTED
    else if (IsBroadcastRelay(VA) == TRUE && 
             IsTransportPacket == TRUE && 
             IsIPv6NS == FALSE &&
             IEEE_802_ADDR_IS_BROADCAST(Ether->Dest)) {
        //
        // The packet was broadcast. Placing it on our
        // Broadcast list will filter duplicates and
        // set up for relay service if we provide one.
        //
        uint PacketLength;
        uint PayloadLength;
        char *Buffer;
        uint SizeofTwoEthAddr = sizeof(VirtualAddress) * 2;  // payload inc EThType but not Eth addrs.

        NdisQueryPacketLength(Packet, &PacketLength);
        Buffer = AllocFlatBuffer(Packet,PacketLength);
        PayloadLength = PacketLength - SizeofTwoEthAddr;

        UpdateBroadcastList(VA, VA->Address,       // tx path
                            srp->FrameSeqNo,0,
                            VA->Address, Ether->Dest, IsBroadcastRelay(VA),
                            //Buffer + sizeof(EtherHeader),PayloadLength);
                            Buffer + SizeofTwoEthAddr,PayloadLength);

        ExFreePool(Buffer);
        VrrTrace(VA,3,"MP:Tx=UpdtBcastList",NULL,NULL,Ether->Dest,"PktLen",PacketLength,"PayloadLen",PayloadLength);
        goto ErrorFreeSRP;
    }
    else if (IsBroadcastRelay(VA) == FALSE && 
             IsTransportPacket == TRUE && 
             IsIPv6NS == FALSE &&
             IEEE_802_ADDR_IS_BROADCAST(srp->Dest)) {
#else
    else if (IsTransportPacket && IEEE_802_ADDR_IS_BROADCAST(srp->Dest)) {
#endif
        //
        // VRR does not support multicast or broadcast by a transport protocol.
        //
        InterlockedIncrement((PLONG)&VA->CountXmitMulticast);
        VrrTrace(VA,3,"MP:Tx=drop user bcast/mcast packet",NULL,NULL,srp->Dest,NULL,0,NULL,0);
        goto ErrorFreeSRP;
    }
    else {
        //
        // Send transport packet towards FindNextHop(srp->Dest).
        // Similar to MaintBufSendPacket() direct (non-MB) transmission.
        //
        NDIS_PACKET *NewPacket = NULL;

        VrrTrace(VA,3,"MP:Tx=FNH path",NULL,NULL,Ether->Dest,NULL,0,NULL,0);
        
        //
        // Original unencrypted packet must be returned to NDIS on completion.
        //
        srp->TransmitComplete = MiniportSendComplete;
        
        //
        // In VRR we do not piggyback control messages on data packets.
        //

        //
        // SRPacketToPkt() performs FNH(srp->Dest,&srp->Tok) and
        // initializes the eth header in NewPacket.
        //
        Status = SRPacketToPkt(VA, srp, &NewPacket);
        if (Status != NDIS_STATUS_SUCCESS) {
            MiniportSendComplete(VA, srp, Status);
            return;
        }

        //
        // The additional packet clone ex SRPackettoPkt must be released
        // on completion.
        //
        PC(NewPacket)->srp = srp;
        PC(NewPacket)->TransmitComplete = MaintBufStaticSendComplete;

        if (PC(NewPacket)->PA == NULL) {
            //
            // This means the packet is trying to use a physical adapter that
            // no longer exists.
            //
            VrrKdPrint("MiniportTransmitPacket:  PC(NewPacket)->PA=NULL",NULL,srp->Dest);
            MaintBufStaticSendComplete(VA, NewPacket, NDIS_STATUS_FAILURE);
        }
        else {
            ProtocolTransmit(PC(NewPacket)->PA, NewPacket);
        }
    }

    return;

ErrorFreeSRP:
    SRPacketFree(srp);

ErrorReturn:
    NdisMSendComplete(VA->MiniportHandle, Packet, Status);
}

//* MiniportTransmitPackets
//
//  Called by NDIS to send packets via our virtual adapter.
//
void
MiniportTransmitPackets(
    IN NDIS_HANDLE MiniportAdapterContext,
    IN PPNDIS_PACKET PacketArray,
    IN UINT NumberOfPackets)
{
    MiniportAdapter *VA = (MiniportAdapter *) MiniportAdapterContext;
    uint i;

    for (i = 0; i < NumberOfPackets; i++)
        MiniportTransmitPacket(VA, PacketArray[i]);
}


//* MiniportReceiveLocally
//
//  Receives an SRPacket locally, using NdisMIndicateReceivePacket.
//  Decrypts the packet data for receiving it.
//
//  The ReceiveComplete handler is always called.
//
//  Does NOT directly consume srp or srp->Packet,
//  but the ReceiveComplete handler may do that.
//
void
MiniportReceiveLocally(
    MiniportAdapter *VA,
    SRPacket *srp,
    void (*Complete)(MiniportAdapter *VA, SRPacket *srp, NDIS_STATUS Status))
{
    NDIS_PACKET *Packet;
    NDIS_BUFFER *Buffer;
    void *Data;
    uint BufferLength;
    EtherHeader UNALIGNED *Ether;
    NDIS_STATUS Status;

    //
    // srp->Packet is NULL only in SRPackets that we generate ourself
    // (for example, for Acks, Route Requests, Route Replies)
    // and we should never try to receive such a packet locally.
    //
    VRRASSERT(srp->Packet != NULL);

    if (srp->PacketLength == srp->PayloadOffset) {
        //
        // This happens when we receive a packet which only contains
        // options, no payload.
        //
        InterlockedIncrement((PLONG)&VA->CountRecvEmpty);
        (*Complete)(VA, srp, NDIS_STATUS_SUCCESS);
        return;
    }

    //
    // The ethernet Type field is part of the encrypted data.
    //
    Status = CryptoDecryptPacket(VA, srp->Packet,
                                 srp->PayloadOffset,
                                 sizeof *Ether - sizeof Ether->Type,
                                 srp->IV, &Packet); 
    if (Status != NDIS_STATUS_SUCCESS) { 
        KdPrint(("VRR!MiniportReceiveLocally: CryptoDecryptPacket: %x\n", Status));
        InterlockedIncrement((PLONG)&VA->CountRecvDecryptFailure);
        (*Complete)(VA, srp, Status);
        return;
    }

    //
    // Get the ethernet header in the packet.
    //
    Buffer = NdisFirstBuffer(Packet);
    NdisQueryBuffer(Buffer, &Data, &BufferLength);
    if (BufferLength < sizeof *Ether) {
        InterlockedIncrement((PLONG)&VA->CountRecvSmall);
        NdisFreePacketClone(Packet);
        (*Complete)(VA, srp, NDIS_STATUS_INVALID_PACKET);
        return;
    }

    //
    // If the Type is ETYPE_MSFT, we do not receive the packet.
    //
    Ether = (EtherHeader UNALIGNED *) Data;
    if (Ether->Type == ETYPE_MSFT) {
        InterlockedIncrement((PLONG)&VA->CountRecvRecursive);
        NdisFreePacketClone(Packet);
        (*Complete)(VA, srp, NDIS_STATUS_SUCCESS);
        return;
    }

    InterlockedIncrement((PLONG)&VA->CountRecvLocally);

    //
    // Initialize the ethernet header.
    //
    RtlCopyMemory(Ether->Dest, VA->Address, SR_ADDR_LEN);
    RtlCopyMemory(Ether->Source, srp->Source, SR_ADDR_LEN);

    //
    // Prepare for MiniportReturnPacket.
    //
    PC(Packet)->srp = srp;
    PC(Packet)->ReceiveComplete = Complete;

    //
    // Indicate the packet up to any transports bound to us.
    // MiniportReturnPacket will be called asynchronously.
    //
    NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
    NDIS_SET_PACKET_HEADER_SIZE(Packet, sizeof *Ether);
    NdisMIndicateReceivePacket(VA->MiniportHandle, &Packet, 1);
}

//* MiniportReturnPacket
//
//  Called by NDIS to return a packet after the transports have
//  finished their receive processing.
//
void
MiniportReturnPacket(
    IN NDIS_HANDLE MiniportAdapterContext,
    IN PNDIS_PACKET Packet)
{
    MiniportAdapter *VA = (MiniportAdapter *) MiniportAdapterContext;
    SRPacket *srp = PC(Packet)->srp;
    void (*Complete)(MiniportAdapter *VA, SRPacket *srp, NDIS_STATUS Status) =
        PC(Packet)->ReceiveComplete;

    //
    // Free the clear-text packet that was created
    // in MiniportReceiveLocally.
    //
    NdisFreePacketClone(Packet);

    //
    // Indicate the completion of receive processing.
    //
    (*Complete)(VA, srp, NDIS_STATUS_SUCCESS);
}

//* MiniportReceiveComplete
//
//  Called after the completion of local receive processing
//  of an SRPacket.
//

⌨️ 快捷键说明

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