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

📄 ipfrag.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// IPFRAG.C
//
// Routines related to IP fragmentation
//
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "ip.h"

#define FRAG_LAST       0x80000000
#define FRAG_MIDDLE     0x40000000
#define FRAG_FIRST      0x20000000
#define FRAG_OFFSET     0x0000FFFF

REASM *_IPReasmPtr = 0;

//--------------------------------------------------------------------
// IPReasm() - Attempt to reassemble packet fragment
//
// Takes the supplied packet fragment, and attempts to reassable it
// into a complete packet. If the packet under reassembly is too large,
// the reassembly is aborted.
//--------------------------------------------------------------------
void IPReasm( HANDLE hPktIn, HANDLE hFrag, IPHDR *pIpHdr )
{
    HANDLE      hFragT,hFragB;
    REASM       *pr;
    uint        Offset,Valid,OffsetT;
    UINT8       *pb,*pbT;
    UINT16      Id;
    uint        tmp,hdrlen;
    UINT32      dwAux1 = 0;
    UINT32      dwAux2, dwTmp, dwOff, dwTmp2;

    ips.dwFragments++;

    // First, zap hPktIn - we just need the frag
    PktSetFrag( hPktIn, 0 );
    PktFree( hPktIn );

    // First, try and find a partially assembled packet with this ID
    Id = HNC16( pIpHdr->Id );
    pr = _IPReasmPtr;
    while( pr )
    {
        if( pr->Id == Id )
            goto ReasmContinue;
        pr = pr->pNext;
    }

    // We didn't find this Id in the list, so we'll create a new packet
    // to hold it.
    if( !(pr = mmAlloc( sizeof(REASM) )) )
    {
        ips.dwFragdropped++;
        FragFree( hFrag );
        return;
    }

    // Initialize new entry
    mmZeroInit( pr, sizeof(REASM) );
    pr->Type    = HTYPE_IPFRAG;
    pr->Id      = Id;
    pr->Timeout = llTimerGetTime(0) + IP_REASM_MAXTIME;

    // Insert into our list
    if( _IPReasmPtr )
    {
        pr->pNext = _IPReasmPtr;
        _IPReasmPtr->pPrev = pr;
    }
    _IPReasmPtr = pr;

ReasmContinue:
    // Now we have the packet under reassembly in "pr", and our
    // particular fragment in hFrag.

    // Now prepare the frag for insertion into the packet
    hdrlen = (uint)(pIpHdr->VerLen & 0xF) * 4;
    tmp    = (uint)(HNC16( pIpHdr->TotalLen ));

    dwAux2 = (UINT32)(tmp - hdrlen);    // Data length of frag
    FragSetAux2( hFrag, dwAux2 );       // Aux2 = Length

    tmp = HNC16( pIpHdr->FlagOff );

    // If DONT_FRAG is set, we should never have got here!
    if( tmp & IP_DF )
    {
        FragFree( hFrag );
        IPReasmFree( pr );
        return;
    }

    // Mark us as FIRST, MIDDLE, or LAST frag
    if( !(tmp & IP_MF) )
        dwAux1 |= FRAG_LAST;
    else
        dwAux1 |= FRAG_MIDDLE;

    // Set tmp = data offset
    tmp = (tmp & ~IP_MF) * 8;

    // If we're over our max, zap it
    if( (tmp+(uint)dwAux2) > IP_REASM_MAXSIZE )
    {
        FragFree( hFrag );
        IPReasmFree( pr );
        return;
    }

    // If we're the first frag, then Aux1 is our header size
    if( !tmp )
        dwAux1 = FRAG_FIRST | (UINT32)hdrlen;
    // Else Aux1 is of offset
    else
    {
        dwAux1 |= (UINT32)tmp;

        // We also need to remove the IP header from non-first frags
        FragGetBufParams( hFrag, 0, &Valid, &Offset );
        Offset += hdrlen;
        Valid  -= hdrlen;
        FragSetBufParams( hFrag, Valid, Offset );
    }
    FragSetAux1( hFrag, dwAux1 );

    // Insert hFrag into the correct place in the list
    if( !(hFragT = pr->hFrag) )
        pr->hFrag = hFrag;
    else
    {
        hFragB = 0;
        while( hFragT && FragGetAux1( hFragT ) < dwAux1 )
        {
            hFragB = hFragT;
            hFragT = FragGetNext( hFragB );
        }
        // We come after B, but before T
        FragSetNext( hFrag, hFragT );
        if( !hFragB )
            pr->hFrag = hFrag;
        else
            FragSetNext( hFragB, hFrag );
    }

    // Now see if we have a complete packet
    hFrag = pr->hFrag;

    // First we must have a "first frag"
    dwAux1 = FragGetAux1( hFrag );
    if( !(dwAux1 & FRAG_FIRST) )
        return;

    // dwTmp = Running length (not including IP header)
    dwTmp = 0;

    while( hFrag )
    {
        dwAux1 = FragGetAux1( hFrag );
        dwAux2 = FragGetAux2( hFrag );

        // If this is a "FIRST", then use the largest initial size
        if( dwAux1 & FRAG_FIRST )
        {
            if( dwAux2 > dwTmp )
                dwTmp = dwAux2;
        }
        else
        {
            // Verify the offset "reaches"
            if( (dwAux1&FRAG_OFFSET) > dwTmp )
                return;

            dwTmp2 = dwTmp - (dwAux1&FRAG_OFFSET);      // Data Overlap
            if( dwAux2 > dwTmp2 )
            {
                // Combine this frag into length
                dwTmp += dwAux2 - dwTmp2;
            }

            // If this is the last frag, we're done
            if( dwAux1 & FRAG_LAST )
                break;
        }
        hFrag = FragGetNext( hFrag );
    }

    if( hFrag )
    {
        // Here we have a completed packet!

        // Add in the original IP header size to length
        dwTmp += FragGetAux1(pr->hFrag) & FRAG_OFFSET;

        // Create the combined packet
        hPktIn = IFCreatePacket( (uint)dwTmp, 0, 0 );
        if( !hPktIn )
        {
            // Can't allocate final packet
            IPReasmFree( pr );
            return;
        }

        // Get the frag
        hFrag = PktGetFrag( hPktIn );

        // Get pointers to packet headers
        pb     = FragGetBufParams( hFrag, 0, 0, 0 );
        Offset = PktGetSizeLLC( hPktIn );

        // Fixup packet frag info
        FragSetBufParams( hFrag, (uint)dwTmp, Offset );

        // Now copy the fragments into our combined frag
        hFrag = pr->hFrag;

        // dwTmp = Running length (not including IP header)
        // dwOff = Running offset (length) (including IP header)
        dwTmp = 0;

        while( hFrag )
        {
            dwAux1 = FragGetAux1( hFrag );
            dwAux2 = FragGetAux2( hFrag );
            pbT    = FragGetBufParams( hFrag, 0, 0, &OffsetT );

            // If this is a "FIRST", then use the largest initial size
            if( dwAux1 & FRAG_FIRST )
            {
                if( dwAux2 > dwTmp )
                {
                    // Special for "first frag" - add in IP header
                    dwOff = dwAux2+(dwAux1&FRAG_OFFSET);
                    mmCopy( pb+Offset, pbT+OffsetT, (uint)dwOff );
                    dwTmp = dwAux2;
                }
            }
            else
            {
                dwTmp2 = dwTmp - (dwAux1&FRAG_OFFSET);      // Data Overlap
                if( dwAux2 > dwTmp2 )
                {
                    // Combine this frag into buffer
                    dwAux2 -= dwTmp2;
                    mmCopy( pb+Offset+dwOff, pbT+OffsetT+dwTmp2, (uint)dwAux2 );

                    // Combine this frag into length
                    dwTmp += dwAux2;
                    dwOff += dwAux2;
                }

                // If this is the last frag, we're done
                if( dwAux1 & FRAG_LAST )
                    break;
            }
            hFrag = FragGetNext( hFrag );
        }

        // Free the REASM struct and send the packet
        ips.dwFragdropped--;
        ips.dwReassembled++;
        IPReasmFree( pr );

        pIpHdr = (IPHDR *)(pb+Offset);
        pIpHdr->FlagOff  = 0;
        pIpHdr->TotalLen = HNC16(((uint)dwOff));

        IPChecksum( pIpHdr );
        IPRxPacket( hPktIn );
    }
    return;
}

//--------------------------------------------------------------------
// IPReasmTimeout() - Check reasm list for reassembly timeout
//
//--------------------------------------------------------------------
void IPReasmTimeout()
{
    REASM  *pr;
    REASM  *prNext;
    UINT32 TimeNow;

    TimeNow = llTimerGetTime(0);

    prNext = _IPReasmPtr;
    while( pr = prNext )
    {
        prNext = pr->pNext;
        if( pr->Timeout < TimeNow )
        {
            ips.dwFragtimeout++;
            IPReasmFree( pr );
        }
    }
}

//--------------------------------------------------------------------
// IPReasmFree() - Free a reasm entry and bump stats
//
//--------------------------------------------------------------------
void IPReasmFree( REASM *pr )
{
    // Remove from chain
    if( pr->pNext )
        pr->pNext->pPrev = pr->pPrev;

    if( !pr->pPrev )
        _IPReasmPtr = pr->pNext;
    else
        pr->pPrev->pNext = pr->pNext;

    // Free it
    FragFree( pr->hFrag );
    ips.dwFragdropped++;
    mmFree( pr );
    return;
}

⌨️ 快捷键说明

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