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

📄 sr.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 3 页
字号:
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// (c) Microsoft Corporation. All rights reserved. 
//
// This file is part of the Microsoft Virtual Ring Routing distribution.
// You should have received a copy of the Microsoft Research Shared Source
// license agreement (MSR-SSLA) for this software; see the file "license.txt".
// If not, please see http://research.microsoft.com/vrr/license.htm,
// or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
//
// This file is derived from the Microsoft Research Mesh Connectivity Layer,
// available under the MSR-SSLA license, and downloadable from
// http://research.microsoft.com/mesh/.
//

#include "headers.h"

//
// Prototypes for internal helper functions.
//
static SRPacket *FillSRPacket(SRPacket *SRP, VRRHeader *VRR);
static uint SROptionLength(const SRPacket *SRP);

//* SRFreeOptionList
//
//  Helper function for SRPacketFree.
//  Frees a list of options.
//
void
SRFreeOptionList(InternalOption *List)
{
    InternalOption *Opt;

    while ((Opt = List) != NULL) {
        List = Opt->Next;
        ExFreePool(Opt);
    }
}

//* SRPacketFree
//
//  Deallocate a SRPacket and all its sub-allocations.
//
void
SRPacketFree(SRPacket *SRP)
{
    SRFreeOptionList((InternalOption *)SRP->ackreq);
    SRFreeOptionList((InternalOption *)SRP->ack);
    SRFreeOptionList((InternalOption *)SRP->Probe);
    SRFreeOptionList((InternalOption *)SRP->ProbeReply);
    SRFreeOptionList((InternalOption *)SRP->VrrHello);
    SRFreeOptionList((InternalOption *)SRP->VrrSetup);
    SRFreeOptionList((InternalOption *)SRP->VrrTearDown);
    SRFreeOptionList((InternalOption *)SRP->VrrSetupReq);

    if (SRP->Packet != NULL) {
        VRRASSERT(SRP->FreePacket != NULL);
        (*SRP->FreePacket)(SRP->PA, SRP->Packet);
    }

    ExFreePool(SRP);
}

//* SRPacketMAC
//
//  Calculates the MAC value for an VRR packet.
//
static void
SRPacketMAC(
    MiniportAdapter *VA,
    uchar *MAC,
    NDIS_PACKET *Packet)
{
    if (VA->Crypto) {
        //
        // The normal case - real security.
        // We truncate the HMAC-SHA1 output to VRR_MAC_LENGTH bytes.
        //
#if BUILD_CRYPTO // DDK
        CryptoMAC(VA->CryptoKeyMAC, MAC, VRR_MAC_LENGTH, 
                  Packet, sizeof(EtherHeader) + VRR_MAC_SKIP);
#endif
    }
    else {
        //
        // Security is disabled, but we still want version checking.
        // We just send the per-adapter key (which is not a strong secret).
        //
#if BUILD_CRYPTO
        VRRASSERT(CRYPTO_KEY_MAC_LENGTH == VRR_MAC_LENGTH);
#endif
        RtlCopyMemory(MAC, VA->CryptoKeyMAC, VRR_MAC_LENGTH);
    }
}

//* SRPacketFromPkt
//
//  Parses an NDIS packet into an SRPacket.
//
NDIS_STATUS
SRPacketFromPkt(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet,
    SRPacket **pSRP)
{
    uchar MAC[VRR_MAC_LENGTH];
    SRPacket *SRP;
    void *OrigHeader;
    EtherHeader *OrigEther;
    VRRHeader *OrigVRR;
    NDIS_BUFFER *OrigBuffer;
    uint OrigBufferLength;
    uint HeaderLength;
    uint OrigPacketLength;
    InternalAcknowledgementRequest *AckReq;
    InternalAcknowledgement *Ack;
    InternalProbe *Pro;
    InternalProbeReply *ProRep;
    InternalVrrHello *VrrH; 
    InternalVrrSetup *VrrS; 
    InternalVrrTearDown *VrrT; 
    InternalVrrSetupReq *VrrSR; 

    //
    // NB: Below code assumes the entire VRR header is contiguous.
    //

    NdisGetFirstBufferFromPacket(Packet, &OrigBuffer, &OrigHeader,
                                 &OrigBufferLength, &OrigPacketLength);
    VRRASSERT(OrigBufferLength <= OrigPacketLength);
    if (OrigBufferLength < sizeof(EtherHeader) + sizeof(VRRHeader))
        return NDIS_STATUS_BUFFER_TOO_SHORT;

    OrigEther = (EtherHeader *) OrigHeader;
    OrigVRR = (VRRHeader *) (OrigEther + 1);

    HeaderLength = (sizeof(EtherHeader) +
                    sizeof(VRRHeader) +
                    OrigVRR->HeaderLength);

    if (OrigBufferLength < HeaderLength)
        return NDIS_STATUS_BUFFER_TOO_SHORT;

    if (OrigVRR->HopCount >= VRR_MAX_HOPCOUNT) {
        VrrKdPrint("SRPacketFromPkt: drop pkt(s,d) HopCount exceeded",
                 OrigVRR->Source, OrigVRR->Dest);
        InterlockedIncrement(&VA->CountHopCountExceeded);
        return NDIS_STATUS_INVALID_PACKET;
    }

    //
    // Verify the MAC.
    //
    SRPacketMAC(VA, MAC, Packet);
    if (! RtlEqualMemory(MAC, OrigVRR->MAC, VRR_MAC_LENGTH)) {
        InterlockedIncrement((PLONG)&VA->CountRecvBadMAC); 
        return NDIS_STATUS_INVALID_PACKET; 
    }

    SRP = ExAllocatePool(NonPagedPool, sizeof *SRP);
    if (SRP == NULL)
        return NDIS_STATUS_RESOURCES;
    RtlZeroMemory(SRP, sizeof *SRP);

    //
    // Parse the VRR header options.
    //
    SRP = FillSRPacket(SRP, OrigVRR);
    if (SRP == NULL) {
        //
        // Illegal packet format. FillSRPacket freed SRP.
        //
        return NDIS_STATUS_INVALID_PACKET;
    }

    //
    // Extract fields from from the VRR header.
    //
    RtlCopyMemory(SRP->Source, OrigVRR->Source, sizeof(VirtualAddress));
    RtlCopyMemory(SRP->Dest, OrigVRR->Dest, sizeof(VirtualAddress));
    RtlCopyMemory(SRP->Origin, OrigVRR->Origin, sizeof(VirtualAddress));
    SRP->FrameSeqNo = RtlUlongByteSwap(OrigVRR->FrameSeqNo);
    SRP->HopCount = OrigVRR->HopCount;

    //
    // Save information about the original packet.
    // NB: Calling SRPacketFree after doing this
    // and before our caller initializes SRP->FreePacket
    // will cause a bugcheck.
    //
    SRP->Packet = Packet;
    SRP->PacketLength = OrigPacketLength;
    SRP->PayloadOffset = HeaderLength;

    //
    // Save some info for later.
    //
    RtlCopyMemory(SRP->EtherDest, OrigEther->Dest, SR_ADDR_LEN);
    RtlCopyMemory(SRP->EtherSource, OrigEther->Source, SR_ADDR_LEN);
    RtlCopyMemory(SRP->IV, OrigVRR->IV, VRR_IV_LENGTH);

    //
    // Increment our counters.
    //
    for (AckReq = SRP->ackreq; AckReq != NULL; AckReq = AckReq->next)
        InterlockedIncrement((PLONG)&VA->CountRecvAckRequest);
    for (Ack = SRP->ack; Ack != NULL; Ack = Ack->next)
        InterlockedIncrement((PLONG)&VA->CountRecvAck);
    for (Pro = SRP->Probe; Pro != NULL; Pro = Pro->Next)
        InterlockedIncrement((PLONG)&VA->CountRecvProbe);
    for (ProRep = SRP->ProbeReply; ProRep != NULL; ProRep = ProRep->Next)
        InterlockedIncrement((PLONG)&VA->CountRecvProbeReply);
    for (VrrH = SRP->VrrHello; VrrH != NULL; VrrH = VrrH->Next)
        InterlockedIncrement((PLONG)&VA->CountRecvHello);
    for (VrrS = SRP->VrrSetup; VrrS != NULL; VrrS = VrrS->Next)
        InterlockedIncrement((PLONG)&VA->CountRecvSetup);
    for (VrrT = SRP->VrrTearDown; VrrT != NULL; VrrT = VrrT->Next)
        InterlockedIncrement((PLONG)&VA->CountRecvTearDown);
    for (VrrSR = SRP->VrrSetupReq; VrrSR != NULL; VrrSR = VrrSR->Next) {
        InterlockedIncrement((PLONG)&VA->CountRecvSetupReq);
        if (SR_DIRECTION_BITS(VrrSR->Opt.Type) == VRR_SR_DIRECT_LHS)
            InterlockedIncrement((PLONG)&VA->CountRecvSRleft);
        if (SR_DIRECTION_BITS(VrrSR->Opt.Type) == VRR_SR_DIRECT_RHS)
            InterlockedIncrement((PLONG)&VA->CountRecvSRright);

    }

    *pSRP = SRP;
    return NDIS_STATUS_SUCCESS;
}

//* CheckPacket
//
//  This is a combination of SRPacketFromPkt and FillSRPacket
//  that just sanity-checks the packet, for debugging purposes.
//
NDIS_STATUS
CheckPacket(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet)
{
    uchar MAC[VRR_MAC_LENGTH];
    void *OrigHeader;
    EtherHeader *OrigEther;
    VRRHeader *OrigVRR;
    NDIS_BUFFER *OrigBuffer;
    uint OrigBufferLength;
    uint HeaderLength;
    uint OrigPacketLength;

    VRROption *Walk;
    uint Left;

    //
    // NB: Below code assumes the entire VRR header is contiguous.
    //

    NdisGetFirstBufferFromPacket(Packet, &OrigBuffer, &OrigHeader,
                                 &OrigBufferLength, &OrigPacketLength);
    VRRASSERT(OrigBufferLength <= OrigPacketLength);
    if (OrigBufferLength < sizeof(EtherHeader) + sizeof(VRRHeader)) {
        KdPrint(("VRR!CheckPacket: header truncated\n"));
        return NDIS_STATUS_BUFFER_TOO_SHORT;
    }

    OrigEther = (EtherHeader *) OrigHeader;
    OrigVRR = (VRRHeader *) (OrigEther + 1);

    HeaderLength = (sizeof(EtherHeader) +
                    sizeof(VRRHeader) +
                    OrigVRR->HeaderLength);

    if (OrigBufferLength < HeaderLength) {
        KdPrint(("VRR!CheckPacket: options truncated\n"));
        return NDIS_STATUS_BUFFER_TOO_SHORT;
    }

    //
    // Verify the MAC.
    //
    SRPacketMAC(VA, MAC, Packet);
    if (! RtlEqualMemory(MAC, OrigVRR->MAC, VRR_MAC_LENGTH)) {
        KdPrint(("VRR!CheckPacket: bad MAC\n"));
        return NDIS_STATUS_INVALID_PACKET;
    }

    //
    // Walk the options and verify them.
    //

    Walk = (VRROption *)(OrigVRR + 1);
    Left = OrigVRR->HeaderLength;

    while (Left != 0) {
        //
        // Verify that we have enough data to match what the option
        // itself claims is present.
        //
        if ((Left < sizeof *Walk) ||
            (Left < sizeof *Walk + Walk->optDataLen)) {
            KdPrint(("VRR!CheckPacket: bad option length\n"));
            return NDIS_STATUS_INVALID_PACKET;
        }

        switch (Walk->optionType) {

        case VRR_OPTION_TYPE_ACKREQ:
            if (Walk->optDataLen != ACK_REQUEST_LEN) {
                KdPrint(("VRR!CheckPacket: bad ack req\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case VRR_OPTION_TYPE_ACK:
            if (Walk->optDataLen != ACKNOWLEDGEMENT_LEN) {
                KdPrint(("VRR!CheckPacket: bad ack\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case VRR_OPTION_TYPE_PROBE:
            //
            // First, make sure that we have enough
            // data left to read ProbeType correctly. 
            //
            if (Walk->optDataLen < PROBE_LEN) {
                KdPrint(("VRR!CheckPacket: bad probe\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }

            switch (((Probe *)Walk)->ProbeType) {
            case METRIC_TYPE_PKTPAIR:
                if (Walk->optDataLen != PROBE_LEN) {
                    KdPrint(("VRR!CheckPacket: bad pktpair\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
                break;
            default:
                KdPrint(("VRR!CheckPacket: bad probe type\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case VRR_OPTION_TYPE_PROBEREPLY:
            //
            // First, make sure that we have enough
            // data left to read ProbeType correctly. 
            //
            if (Walk->optDataLen < PROBE_REPLY_LEN) {
                KdPrint(("VRR!CheckPacket: bad probe reply\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }

            switch (((Probe *)Walk)->ProbeType) {
            case METRIC_TYPE_PKTPAIR:
                if (Walk->optDataLen != PROBE_REPLY_LEN + sizeof(PRPktPair)) {
                    KdPrint(("VRR!CheckPacket: bad pktpair reply\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
                break;
            default:
                KdPrint(("VRR!CheckPacket: bad probe reply type\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            break;

        case VRR_OPTION_TYPE_HELLO:
            //
            // VrrHello options must be large enough to hold Hello preamble.
            //
            if (Walk->optDataLen < VRRHELLO_LEN(0)) {
                KdPrint(("VRR!CheckPacket: VrrHello length < sizeof(Hello preamble)\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            //
            // VrrHello NCEList length must be an integral multiple of NCEList * n.
            //
            if (Walk->optDataLen > VRRHELLO_LEN(0)) {
                uint NCEBuff = Walk->optDataLen - (sizeof(VrrHello) - sizeof(VRROption));
                if (0 != NCEBuff % sizeof(VrrHelloNCE)) {
                    KdPrint(("VRR!CheckPacket: VrrHello trailer not multiple of NCE info\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
            }
            

⌨️ 快捷键说明

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