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

📄 icmpin.c

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

static void ICMPRevSrcRoute( uint IPHdrLen, IPHDR *pbHdrIP );

//--------------------------------------------------------------------
// ICMPInput()
//
// Rx ICMP Packet
//--------------------------------------------------------------------
void ICMPInput( HANDLE hPkt )
{
    HANDLE     hFrag;
    uint       w,Offset,Valid,IPHdrLen,ICMPLen;
    IPN        IPSrc,IPDst;
    uint       Type,Code;
    UINT8      *pb;
    IPHDR      *pIpHdr;
    ICMPHDR    *pIcHdr;

    if( !(hFrag = PktGetFrag( hPkt )) )
    {
        DbgPrintf(DBG_ERROR,"ICMPRxPacket: No packet");
        PktFree( hPkt );
        return;
    }

    // Get the size of the IP Header and pointer to our data
    w = PktGetFlags( hPkt );
    if( !(w & FLG_PKT_IP_VALID) || (w & FLG_PKT_LLC_VALID) )
    {
        DbgPrintf(DBG_ERROR,"ICMPRxPacket: Bad packet");
        PktFree( hPkt );
        return;
    }

    // Get the IP header len
    IPHdrLen = PktGetSizeNet( hPkt );

    // Get the buffer parameters
    pb = FragGetBufParams( hFrag, 0, &Valid, &Offset );

    // Assign an IP header pointer
    pIpHdr = (IPHDR *)(pb + Offset);

    // Assign a ICMP header pointer
    pIcHdr = (ICMPHDR *)(pb + Offset + IPHdrLen);

    // Get the total length of the ICMP message
    ICMPLen = (uint)(HNC16( pIpHdr->TotalLen )) - IPHdrLen;

    // Check for packet too small
    if( ICMPLen < ICMPHDR_SIZE )
    {
        _dwICMPInErrors++;
        PktFree( hPkt );
        return;
    }

    // Check checksum
    w = (uint)pIcHdr->Checksum;
    ICMPChecksum( pIcHdr, ICMPLen );
    if( w != (uint)pIcHdr->Checksum )
    {
        _dwICMPInErrors++;
        PktFree( hPkt );
        return;
    }

    // Check for bad type
    Type = (uint)pIcHdr->Type;
    Code = (uint)pIcHdr->Code;
    if( Type > ICMP_MAXTYPE )
    {
        _dwICMPInErrors++;
        PktFree( hPkt );
        return;
    }

    // Record the Transport Header Size
    PktSetSizeTP( hPkt, ICMPLen );
    PktSetFlagsSet( hPkt, FLG_PKT_TP_VALID );

    // Bump the stats
    _dwICMPIn[ Type ]++;

    // Get source and destination
    IPSrc = RdNet32(&pIpHdr->dwIPSrc);
    IPDst = RdNet32(&pIpHdr->dwIPDst);

    // Process the Message
    switch( Type )
    {
    case ICMP_UNREACH:
        switch (Code)
        {
        case ICMP_UNREACH_NET:
        case ICMP_UNREACH_HOST:
        case ICMP_UNREACH_PROTOCOL:
        case ICMP_UNREACH_PORT:
        case ICMP_UNREACH_SRCFAIL:
            Code += PRC_UNREACH_NET;
            break;

        case ICMP_UNREACH_NEEDFRAG:
            Code = PRC_MSGSIZE;
            break;

        case ICMP_UNREACH_NET_UNKNOWN:
        case ICMP_UNREACH_NET_PROHIB:
        case ICMP_UNREACH_TOSNET:
            Code = PRC_UNREACH_NET;
            break;

        case ICMP_UNREACH_HOST_UNKNOWN:
        case ICMP_UNREACH_ISOLATED:
        case ICMP_UNREACH_HOST_PROHIB:
        case ICMP_UNREACH_TOSHOST:
            Code = PRC_UNREACH_HOST;
            break;

        case ICMP_UNREACH_FILTER_PROHIB:
        case ICMP_UNREACH_HOST_PRECEDENCE:
        case ICMP_UNREACH_PRECEDENCE_CUTOFF:
            Code = PRC_UNREACH_PORT;
            break;

        default:
            goto bad_code;
        }
        goto deliver;

    case ICMP_TIMXCEED:
        if( Code > 1 )
            goto bad_code;
        Code += PRC_TIMXCEED_INTRANS;
        goto deliver;

    case ICMP_PARAMPROB:
        if( Code > 1 )
            goto bad_code;
        Code = PRC_PARAMPROB;
            goto deliver;

    case ICMP_SOURCEQUENCH:
        if( Code )
            goto bad_code;
        Code = PRC_QUENCH;

    deliver:
        SockPcbCtlError( Code, (IPHDR *)(pIcHdr->Data + 4) );
        break;

    bad_code:
        break;

    case ICMP_REDIRECT:
        if( Code > 3 )
            goto bad_code;

        // Handle Route Change Immediately
        pIpHdr = (IPHDR *)(pIcHdr->Data + 4);

        // IPSrc is the route we're trying to get to
        IPSrc = RdNet32(&pIpHdr->dwIPDst);

        // IPDst is the gatway we should be uisng
        IPDst = RdNet32(((IPN *)(pIcHdr->Data)));

        // Redirect route if option is set
        if( ICMP_DO_REDIRECT )
        {
            RtRedirect( IPSrc, IPDst );
            SockPcbCtlError(PRC_REDIRECT_NET+Code, (IPHDR *)(pIcHdr->Data+4));
        }

        // Lastly, send a report
        RTCReport( MSG_RTC_REDIRECT, IPSrc, IPDst );
        break;

    // Echo Request
    case ICMP_ECHO:
        // If this packet is for us, reflect it
        if( BindFindByHost( 0, IPDst ) )
	    goto ICMP_REFLECT;

    // The following are just sent to Raw
    case ICMP_ECHOREPLY:
    case ICMP_ROUTERADVERT:
    case ICMP_ROUTERSOLICIT:
    case ICMP_TSTAMPREPLY:
    case ICMP_IREQREPLY:
    case ICMP_MASKREPLY:
    default:
        break;
    }

    // Give most packets to Raw
    RawInput( hPkt );
    return;

ICMP_REFLECT:
    // Don't forward back to bad address
    if( IPSrc == INADDR_ANY || IPSrc == INADDR_BROADCAST ||
            IN_EXPERIMENTAL(IPSrc) || IN_MULTICAST(IPSrc) ||
            IN_LOOPBACK(IPSrc) )
    {
        PktFree( hPkt );
        return;
    }

    // Fix the TTL
    pIpHdr->Ttl = ICMP_TTL_ECHO;

    // Change the type to reply
    pIcHdr->Type = ICMP_ECHOREPLY;

    // Bump the stats
    _dwICMPOut[ ICMP_ECHOREPLY ]++;

    // Swap Src and Dst
    // The Old Src is now the Dst
    WrNet32( &pIpHdr->dwIPSrc, IPDst );
    WrNet32( &pIpHdr->dwIPDst, IPSrc );

    // Checksum the reply
    ICMPChecksum( pIcHdr, ICMPLen );

    // Now we must reverse the source route (if any)
    if( IPHdrLen > IPHDR_SIZE )
        ICMPRevSrcRoute( IPHdrLen, pIpHdr );

    // Send the packet
    IPTxPacket( hPkt, FLG_IPTX_RAW );

    return;
}

//--------------------------------------------------------------------
// ICMPRevSrcRoute()
//
// Reverse the source route of a packet
//--------------------------------------------------------------------
static void ICMPRevSrcRoute( uint IPHdrLen, IPHDR *pIpHdr )
{
    uint   OptIdx,OptBytes,OptSize;
    UINT8  Opt;
    int    OffFirst,OffLast;
    IPN    IPTmp;

    // Byte count of options
    OptBytes = IPHdrLen - IPHDR_SIZE;

    // Process option bytes
    for( OptIdx = 0; OptIdx < OptBytes; OptIdx += OptSize )
    {
        Opt = pIpHdr->Options[OptIdx];

        // Validate Option and Get Size
        if( Opt == IPOPT_EOL )
            break;
        else if( Opt == IPOPT_NOP )
            OptSize = 1;
        else
        {
            OptSize = pIpHdr->Options[OptIdx+1];
            if( OptSize <= 0 || OptSize > OptBytes )
                return;
        }

        // Check for source routing
        if( Opt == IPOPT_SSRR || Opt == IPOPT_LSRR )
        {
            // Source route in use. We must reverse it.

            // First, set Offset to 4
            pIpHdr->Options[OptIdx+2] = 4;

            // Now reverse the route
            OffFirst = OptIdx+3;
            OffLast  = OptIdx+OptSize-4;

            // We know the DestIP is now the last thing in the source
            // route, and what was last in the source route is now
            // DestIP
            mmCopy( &IPTmp, pIpHdr->Options+OffLast, 4 );
            mmCopy( pIpHdr->Options+OffLast, &pIpHdr->dwIPDst, 4 );
            mmCopy( &pIpHdr->dwIPDst, &IPTmp, 4 );

            // We've used OffLast, so bump it down
            OffLast -= 4;

            // Now, while OffFirst < OffLast, do SWAPS.
            while( OffFirst < OffLast )
            {
                mmCopy( &IPTmp, pIpHdr->Options+OffLast, 4 );
                mmCopy( pIpHdr->Options+OffLast, pIpHdr->Options+OffFirst, 4 );
                mmCopy( pIpHdr->Options+OffFirst, &IPTmp, 4 );
                OffFirst += 4;
                OffLast  -= 4;
            }
        }
    }
}

⌨️ 快捷键说明

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