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

📄 ipv6.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 3 页
字号:
        return TRUE;
    }

    return FALSE;
}

//* IPv6FakeDHTtxNA
//
//  Constructs an IPv6 Neighbor Advert for the magic
//  DHT transmit address and loops it back to the local
//  IPv6 stack. This because the neighbor cache of the
//  local IPv6 stack requires ND state for the DHT transmit
//  address before it will transmit packets towards that
//  address.
//
boolint
IPv6FakeDHTtxNA(
    MiniportAdapter *VA,
    IPv6Addr SolicitSource)
{
    NDIS_PACKET *AdvertPacket = NULL;
    NDIS_STATUS Status;
    uchar *Data;
    EtherHeader UNALIGNED *AdvertEther;
    VRRHeader UNALIGNED *AdvertVRR;
    ushort UNALIGNED *EthType;
    IPv6Header UNALIGNED *AdvertIPv6;
    IPv6NA UNALIGNED *AdvertICMPv6;
    u_long Flags = (ND_NA_FLAG_OVERRIDE | ND_NA_FLAG_SOLICITED);
    ushort PayloadLength = sizeof(IPv6NA);
    ushort Checksum;
    const AdvertSize = sizeof(EtherHeader)
                     + sizeof(IPv6Header)
                     + PayloadLength;

    //
    // Obtain NDIS packet, NDIS buffer and memory for IPv6 Neighbor Advert.
    //
    Status = MiniportMakeEmptyPacket(VA, AdvertSize, &AdvertPacket, &Data);
    if (Status != NDIS_STATUS_SUCCESS)
        goto ReleaseAndReturn;

    //
    // Initialize eth header.
    //
    AdvertEther = (EtherHeader UNALIGNED *)Data;
    RtlCopyMemory(AdvertEther->Dest, VA->Address, sizeof(VirtualAddress));
    RtlCopyMemory(AdvertEther->Source, DHTMagicL2, sizeof(VirtualAddress));
    AdvertEther->Type = RtlUshortByteSwap(ETYPE_IPv6);

    //
    // Initialize IPv6 header.
    //
    AdvertIPv6 = (IPv6Header UNALIGNED *)(AdvertEther + 1);
    AdvertIPv6->VersClassFlow = IP_VERSION6;
    AdvertIPv6->PayloadLength = RtlUshortByteSwap(PayloadLength);
    AdvertIPv6->NextHeader = IP_PROTOCOL_ICMPv6;
    AdvertIPv6->HopLimit = 255;
    RtlCopyMemory(&AdvertIPv6->Source, &DHTrxAddr, sizeof(in6_addr));
    RtlCopyMemory(&AdvertIPv6->Dest, &SolicitSource, sizeof(in6_addr));

    //
    // Initialize ICMPv6 header of type Neighbor Advert.
    //
    AdvertICMPv6 = (IPv6NA UNALIGNED *)(AdvertIPv6 + 1);
    AdvertICMPv6->ICMPHeader.Type = ICMPv6_NEIGHBOR_ADVERT;
    AdvertICMPv6->ICMPHeader.Code = 0;
    AdvertICMPv6->ICMPHeader.Checksum = 0;
    AdvertICMPv6->Flags = RtlUlongByteSwap(Flags);
    RtlCopyMemory(&AdvertICMPv6->TargetAddress, &DHTtxAddr, sizeof(in6_addr));
    AdvertICMPv6->TLLAType = 2;
    AdvertICMPv6->TLLALength = 1;
    RtlCopyMemory(&AdvertICMPv6->TLLAddress, DHTMagicL2, sizeof(PhysicalAddress));

    //
    // Initialize ICMPv6 checksum.
    //
    Checksum = ChecksumPacket(AdvertPacket,
                              (u_long)AdvertICMPv6 - (u_long)Data,
                              NULL,
                              sizeof *AdvertICMPv6,  // amount to checksum. aka PayloadLength
                              &AdvertIPv6->Source,
                              &AdvertIPv6->Dest,
                              IP_PROTOCOL_ICMPv6);
    AdvertICMPv6->ICMPHeader.Checksum = Checksum;    // Note: no byte-swap.

    //
    // Send the NA to our local IPv6 protocol driver.
    // The receive completion handling will free our NDIS packet.
    //
    PC(AdvertPacket)->srp = NULL; 
    PC(AdvertPacket)->ReceiveComplete = MiniportReceiveComplete;
    NDIS_SET_PACKET_STATUS(AdvertPacket, NDIS_STATUS_SUCCESS);
    NDIS_SET_PACKET_HEADER_SIZE(AdvertPacket, sizeof(EtherHeader));
    NdisMIndicateReceivePacket(VA->MiniportHandle, &AdvertPacket, 1);

    return TRUE;

ReleaseAndReturn:

    if (AdvertPacket != NULL)
        NdisFreePacketClone(AdvertPacket);

    return FALSE;
}

//* SetVSetChanged
//
//  Sets a flag so that an unsolicited DHT message
//  of type DHT_QUERY_VSET will be generated and
//  sent to the local IPv6 stack. This is used to
//  signal changes of driver state to DHT apps.
//
void
SetVSetChanged (
    MiniportAdapter *VA)
{
    InterlockedExchange(&VA->NT.DHTQueryVSet, TRUE);
}

//* TestVSetChanged
//
//  Indicates whether an unsolicited DHT message of type
//  DHT_QUERY_VSET is pending, clearing the indicator.
//
//  Returns non-zero iff DHT_QUERY_VSET is pending.
//
boolint
TestVSetChanged (
    MiniportAdapter *VA)
{
    return InterlockedCompareExchange(&VA->NT.DHTQueryVSet, FALSE, TRUE);
}


//* DHTDriverRequest
//
//  DHT applications may send requests to their local
//  VRR driver by constructing a UDP packet addressed to
//  a well-known destination. The driver intercepts these
//  packets and replies using a looped back UDP packet or,
//  as a special case, by delivering the request up to a
//  higher-level driver as a packet.
//
//  The caller must guarantee that *RequestDHT is contiguous
//  in memory for RequestLength bytes.
//
void
DHTDriverRequest (
    MiniportAdapter *VA,
    uchar MsgType,
    DHTHeader UNALIGNED *RequestDHT,
    ushort RequestLength,
    ushort Port)
{
    NDIS_PACKET *Packet = NULL;
    NDIS_STATUS Status;
    uchar *Data;
    EtherHeader UNALIGNED *Ether;
    IPv6Header UNALIGNED *IPv6;
    ICMPv6Header UNALIGNED *ICMPv6;
    UDPHeader UNALIGNED *UDP;
    DHTHeader UNALIGNED *DHT;
    uint PacketLength;
    ushort IPv6Length;

    //
    // Validate message type and length. Calculate
    // reply length.
    //
    IPv6Length = sizeof(UDPHeader) 
               + sizeof(DHTHeader);

    if (MsgType == DHT_QUERY_VSET) {
        IPv6Length += sizeof(DHTQueryVSet);
        PacketLength = sizeof(EtherHeader)
                     + sizeof(IPv6Header)
                     + IPv6Length;
    }
    else if (MsgType == DHT_QUERY_NEXT_HOP &&
             RequestLength >= sizeof(DHTHeader) &&
             RequestDHT != NULL) {
        IPv6Length += sizeof(DHTReplyNextHop);
        PacketLength = sizeof(EtherHeader)
                     + sizeof(IPv6Header)
                     + IPv6Length;
    }
    else if (MsgType == DHT_ERROR_NEXT_HOP &&
             RequestLength >= sizeof(DHTHeader) &&
             RequestDHT != NULL) {
        IPv6Length += RequestLength;
        PacketLength = sizeof(EtherHeader)
                     + sizeof(IPv6Header)
                     + IPv6Length;
    }
    else if (MsgType == DHT_TRAP_PACKET) {
    
        if (RequestLength > DHTTrapPacketMaxSize()) {
            KdPrint(("VrrKdPrint: (%u) DHTDriverRequest(TRAP): pkt (%i) too large for DHT payload (%i)\n",
                     TIMESTAMP, RequestLength, DHTTrapPacketMaxSize()));
            goto ReleaseAndReturn;
        }
        IPv6Length += RequestLength;
        PacketLength = sizeof(EtherHeader)
                     + sizeof(IPv6Header)
                     + IPv6Length;
    }
    else if (MsgType == DHT_LOOPBACK) {
        PacketLength = RequestLength - sizeof(DHTHeader);
    }
    else if (MsgType == DHT_COMMAND &&
             RequestLength >= (sizeof(DHTHeader) + sizeof(DHTCommand)) &&
             RequestDHT != NULL) {
        IPv6Length += sizeof(DHTCommand);
        PacketLength = sizeof(EtherHeader)
                     + sizeof(IPv6Header)
                     + IPv6Length;
    }
    else {
        KdPrint(("VrrKdPrint: (%u) DHTDriverReply: invalid Msg Type(%u) Len(%u)\n",
                 TIMESTAMP, MsgType, RequestLength));
        goto ReleaseAndReturn;
    }

    //
    // Obtain NDIS packet, NDIS buffer and memory.
    //
    Status = MiniportMakeEmptyPacket(VA, PacketLength, &Packet, &Data);
    if (Status != NDIS_STATUS_SUCCESS)
        goto ReleaseAndReturn;
    RtlZeroMemory(Data,PacketLength);

    //
    // Loopback: caller must supply all headers. We treat
    // as an opaque payload - whatever our caller supplied
    // after the DHTHeader gets looped back.
    //
    if (MsgType == DHT_LOOPBACK) {
        uchar *SrcBuff = (uchar UNALIGNED *)RequestDHT;

        SrcBuff += sizeof(DHTHeader);
        RtlCopyMemory(Data, SrcBuff, PacketLength);
        VrrKdPrint("DHTDriverRequest(TRAP) looping back packet",NULL,NULL);

        goto ReceivePacket;
    }

    //
    // Initialize eth header.
    //
    Ether = (EtherHeader UNALIGNED *)Data;
    RtlCopyMemory(Ether->Dest, VA->Address, sizeof(VirtualAddress));
    RtlCopyMemory(Ether->Source, VA->Address, sizeof(VirtualAddress));
    Ether->Type = RtlUshortByteSwap(ETYPE_IPv6);

    //
    // Initialize IPv6 header.
    //
    IPv6 = (IPv6Header UNALIGNED *)(Ether + 1);
    IPv6->VersClassFlow = IP_VERSION6;
    IPv6->PayloadLength = RtlUshortByteSwap(IPv6Length);
    IPv6->NextHeader = IP_PROTOCOL_UDP;
    IPv6->HopLimit = 255;
    RtlCopyMemory(&IPv6->Source, &DHTtxAddr, sizeof(in6_addr));
    RtlCopyMemory(&IPv6->Dest, &DHTrxAddr, sizeof(in6_addr));

    //
    // Initialize UDP header.
    //
    UDP = (UDPHeader UNALIGNED *)(IPv6 + 1);
    Port = (Port == 0) ? DHT_DEFAULT_UDP_PORT : Port;
    UDP->Source = RtlUshortByteSwap(Port);
    UDP->Dest = RtlUshortByteSwap(Port);
    UDP->Checksum = 0;

    //
    // Initialize DHTHeader.
    //
    DHT = (DHTHeader UNALIGNED *)(UDP + 1);
    RtlCopyMemory(&DHT->Dest,VA->Address,sizeof(VirtualAddress));

    //
    // Initialize reply.
    //
    switch (MsgType) {

        case DHT_QUERY_VSET: {
            //
            // Reply enumerates our VSet.
            //
            DHTQueryVSet UNALIGNED *Reply;
            KIRQL OldIrql;
            NodeTableEntry *NTE;
            VirtualAddress *self;
            uint i;
#if DHT_QUERY_VSET_NEW
            AddressList *ALE = NULL;
#else
            uchar CountLeft = 0;
            uchar CountRight = 0;
#endif
            VirtualAddress *VSet;

            DHT->Type.Type = DHT_QUERY_VSET;
            Reply = (DHTQueryVSet UNALIGNED *)(DHT + 1);
            Reply->MaxVSetSize = VRR_MAX_VSET_SIZE;

            //
            // Initialize state bits.
            //
            if (IsDriverActive(VA))
                Reply->State.DriverActive = 1;
            if (InterlockedCompareExchange(&VA->VrrAPIJoined,0,0))
                Reply->State.VrrAPIJoined = 1;
            if (IsJoiningOnHold(VA))
                Reply->State.JoiningOnHold = 1;

            UDP->Length = RtlUshortByteSwap(sizeof(DHTHeader)
                                          + sizeof(DHTQueryVSet));

            KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);

            //
            // Initialize entry for self.
            //
            self = (VirtualAddress *)Reply->VSet[VRR_WING_SIZE];
            RtlCopyMemory(self,VA->NT.Self->Address,sizeof(VirtualAddress));
#if DHT_QUERY_VSET_NEW
            //
            // Initialize entries for LHS neighbours.
            //
            VRRASSERT(AddressListCount(VA->NT.VSetLeft) <= VRR_WING_SIZE);
            VSet = self;
            Reply->CountLeft = (uchar)AddressListCount(VA->NT.VSetLeft);
            for (ALE = VA->NT.VSetLeft; ALE != NULL; ALE = ALE->Next)
                RtlCopyMemory(*(--VSet), ALE->Address, sizeof(VirtualAddress));

            //
            // Initialize entries for RHS neighbours.
            //
            VRRASSERT(AddressListCount(VA->NT.VSetRight) <= VRR_WING_SIZE);
            VSet = self;
            Reply->CountRight = (uchar)AddressListCount(VA->NT.VSetRight);
            for (ALE = VA->NT.VSetRight; ALE != NULL; ALE = ALE->Next)
                RtlCopyMemory(*(++VSet), ALE->Address, sizeof(VirtualAddress));

#else
            //
            // Initialize entries for LHS neighbours.
            //
            NTE = VA->NT.Self;
            VRRASSERT(VA->NT.CountLeft <= 0xff);
            VSet = self;
            for (i = 0; i < VA->NT.CountLeft; i++) {
                NTE = NTE->Prev;
                CountLeft++;
                RtlCopyMemory(*(--VSet), NTE->Address, sizeof(VirtualAddress));
            }
            Reply->CountLeft = CountLeft;

            //
            // Initialize entries for RHS neighbours.
            //
            NTE = VA->NT.Self;
            VRRASSERT(VA->NT.CountRight <= 0xff);
            VSet = self;
            for (i = 0; i < VA->NT.CountRight; i++) {
                NTE = NTE->Next;
                CountRight++;
                RtlCopyMemory(*(++VSet), NTE->Address, sizeof(VirtualAddress));
            }
            Reply->CountRight = CountRight;
#endif
            KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
            break;
        }
        
        case DHT_QUERY_NEXT_HOP: {
            //
            // Reply indicates next hop towards given destination.
            //
            DHTReplyNextHop UNALIGNED *Reply;
            TxToken Token;
            FindNextHopResult Result;

            DHT->Type.Type = DHT_QUERY_NEXT_HOP;
            Reply = (DHTReplyNextHop UNALIGNED *)(DHT + 1);

            UDP->Length = RtlUshortByteSwap(sizeof(DHTHeader)
                                          + sizeof(DHTReplyNextHop));

            RtlCopyMemory(Reply->Dest, RequestDHT->Dest, sizeof(VirtualAddress));

            //
            // Find next hop.
            //
            Result = FindNextHop(VA, 
                                 RequestDHT->Dest,
                                 VRR_IFID_UNSPECIFIED,
                                 VRR_IFID_UNSPECIFIED,
                                 &Token,
                                 NULL,
                                 NULL_SR_FLAGS);

            if (Result == SuccessFwd) {
                //
                // Next hop is to a neighboring node.
                //
                Reply->Success = TRUE;
                RtlCopyMemory(Reply->NextHop, Token.NextVAddress, sizeof(VirtualAddress));
            }
            else if (Result == SuccessRcvSelf || Result == SuccessRcvNearest) {

⌨️ 快捷键说明

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