예제 #1
0
파일: icmp.c 프로젝트: ctapang/v0_70_01b
// Processes an ICMP packet and generates an echo reply, if requested
// Note: the srcAdd parameter could be detected from the pNetIf
// However, when support for multiple IP addresses per interface is implemented
// passing the source address explicitely is better
void TCPIP_ICMP_Process(TCPIP_NET_IF* pNetIf, TCPIP_MAC_PACKET* pRxPkt, uint32_t destAdd, uint32_t srcAdd)
{
    ICMP_HEADER            *pRxHdr;
    TCPIP_MAC_DATA_SEGMENT *pSeg;
    TCPIP_UINT16_VAL        checksum;
    TCPIP_MAC_PKT_ACK_RES   ackRes;

    pRxHdr = (ICMP_HEADER*)pRxPkt->pTransportLayer;
    ackRes = TCPIP_MAC_PKT_ACK_RX_OK;

    while(true)
    {

        if(pRxPkt->totTransportLen < sizeof(*pRxHdr))
        {
            ackRes = TCPIP_MAC_PKT_ACK_STRUCT_ERR;
            break;
        }

        // Validate the checksum
        // The checksum data includes the precomputed checksum in the header
        // so a valid packet will always have a checksum of 0x0000
        // 1st segment
        checksum.Val = ~TCPIP_Helper_CalcIPChecksum(pRxPkt->pTransportLayer, pRxPkt->pDSeg->segLen, 0);
        // add the other possible data segments
        for(pSeg = pRxPkt->pDSeg->next; pSeg != 0; pSeg = pSeg->next)
        {
            checksum.Val = ~TCPIP_Helper_CalcIPChecksum(pSeg->segLoad, pSeg->segLen, checksum.Val);
        }

        if((uint16_t)~checksum.Val != 0)
        {
            ackRes = TCPIP_MAC_PKT_ACK_CHKSUM_ERR;
            break;
        }

        if(pRxHdr->vType == ICMP_TYPE_ECHO_REQUEST && pRxHdr->vCode == ICMP_CODE_ECHO_REQUEST)
        {   // echo request
            ackRes = _ICMPProcessEchoRequest(pNetIf, pRxPkt, destAdd, srcAdd);
            break;
        }

#if defined(TCPIP_STACK_USE_ICMP_CLIENT)
        if(pRxHdr->vType == ICMP_TYPE_ECHO_REPLY && pRxHdr->vCode == ICMP_CODE_ECHO_REPLY)
        {   // echo reply; check if our own
            // Get the sequence number and identifier fields
            TCPIP_UINT32_VAL userData;
            IPV4_ADDR remoteIPAddr;

            userData.w[0] = pRxHdr->wIdentifier;
            userData.w[1] = pRxHdr->wSequenceNumber;
            remoteIPAddr.Val = srcAdd;

            // Send a message to the application-level Ping driver that we've received an Echo Reply
            _ICMPNotifyClients(pNetIf, &remoteIPAddr, (void *)userData.v);
            ackRes = TCPIP_MAC_PKT_ACK_RX_OK;
        }
#endif

        break;
    }


    TCPIP_PKT_PacketAcknowledge(pRxPkt, ackRes); 
    return;
}
예제 #2
0
// Processes an ICMP packet and generates an echo reply, if requested
static void  TCPIP_ICMP_Process(void)
{
    TCPIP_NET_IF*           pNetIf;
    TCPIP_MAC_PACKET*       pRxPkt;
    IPV4_HEADER*            pIpv4Header;
    uint32_t                destAdd;
    uint32_t                srcAdd;
    ICMP_HEADER*            pRxHdr;
    uint16_t                icmpTotLength;
    uint16_t                checksum;
    TCPIP_MAC_PKT_ACK_RES   ackRes;



    // extract queued ICMP packets
    while((pRxPkt = _TCPIPStackModuleRxExtract(TCPIP_THIS_MODULE_ID)) != 0)
    {
        pNetIf = (TCPIP_NET_IF*)pRxPkt->pktIf;

        pRxHdr = (ICMP_HEADER*)pRxPkt->pTransportLayer;
        ackRes = TCPIP_MAC_PKT_ACK_RX_OK;

        pIpv4Header = (IPV4_HEADER*)pRxPkt->pNetLayer;
        destAdd = pIpv4Header->DestAddress.Val;
        srcAdd =  pIpv4Header->SourceAddress.Val;


        while(true)
        {
            icmpTotLength = pRxPkt->totTransportLen;

            if(icmpTotLength < sizeof(*pRxHdr))
            {
                ackRes = TCPIP_MAC_PKT_ACK_STRUCT_ERR;
                break;
            }

            // Validate the checksum
            // The checksum data includes the precomputed checksum in the header
            // so a valid packet will always have a checksum of 0x0000
            // 1st segment
            if((pRxPkt->pktFlags & TCPIP_MAC_PKT_FLAG_SPLIT) != 0)
            {
                checksum = TCPIP_Helper_PacketChecksum(pRxPkt, (uint8_t*)pRxHdr, icmpTotLength, 0);
            }
            else
            {
                checksum = TCPIP_Helper_CalcIPChecksum((uint8_t*)pRxHdr, icmpTotLength, 0);
            }

            if(checksum != 0)
            {
                ackRes = TCPIP_MAC_PKT_ACK_CHKSUM_ERR;
                break;
            }

            if(pRxHdr->vType == ICMP_TYPE_ECHO_REQUEST && pRxHdr->vCode == ICMP_CODE_ECHO_REQUEST)
            {   // echo request
                ackRes = _ICMPProcessEchoRequest(pNetIf, pRxPkt, destAdd, srcAdd);
                break;
            }

#if defined(TCPIP_STACK_USE_ICMP_CLIENT)
            if(pRxHdr->vType == ICMP_TYPE_ECHO_REPLY && pRxHdr->vCode == ICMP_CODE_ECHO_REPLY)
            {   // echo reply; check if our own
                // Get the sequence number and identifier fields
#if (TCPIP_ICMP_CLIENT_USER_NOTIFICATION != 0)
                TCPIP_UINT32_VAL userData;
                IPV4_ADDR remoteIPAddr;

                userData.w[0] = pRxHdr->wIdentifier;
                userData.w[1] = pRxHdr->wSequenceNumber;
                remoteIPAddr.Val = srcAdd;

                // Send a message to the application-level Ping driver that we've received an Echo Reply
                _ICMPNotifyClients(pNetIf, &remoteIPAddr, (void *)userData.v);
#endif  // (TCPIP_ICMP_CLIENT_USER_NOTIFICATION != 0)
                ackRes = TCPIP_MAC_PKT_ACK_RX_OK;
                break;
            }
#endif

            // unknown type
            ackRes = TCPIP_MAC_PKT_ACK_TYPE_ERR;
            break;
        }


        TCPIP_PKT_FlightLog(pRxPkt, TCPIP_THIS_MODULE_ID, ackRes, 0);
        TCPIP_PKT_PacketAcknowledge(pRxPkt, ackRes); 
    }
}