Пример #1
0
/*********************************************************************
 * Function:        void ICMPProcess(void)
 *
 * PreCondition:    MAC buffer contains ICMP type packet.
 *
 * Input:           *remote: Pointer to a NODE_INFO structure of the
 *                  ping requester
 *                  len: Count of how many bytes the ping header and
 *                  payload are in this IP packet
 *
 * Output:          Generates an echo reply, if requested
 *                  Validates and sets ICMPFlags.bReplyValid if a
 *                  correct ping response to one of ours is received.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void ICMPProcess(NODE_INFO *remote, uint16_t len)
{
    TCPIP_UINT32_VAL dwVal;

    // Obtain the ICMP header Type, Code, and Checksum fields
    MACGetArray((uint8_t*)&dwVal, sizeof(dwVal));

    // See if this is an ICMP echo (ping) request
    if(dwVal.w[0] == 0x0008u)
    {
        // Validate the checksum using the Microchip MAC's DMA module
        // The checksum data includes the precomputed checksum in the
        // header, so a valid packet will always have a checksum of
        // 0x0000 if the packet is not disturbed.
        if(MACCalcRxChecksum(0+sizeof(IP_HEADER), len))
            return;

        // Calculate new Type, Code, and Checksum values
        dwVal.v[0] = 0x00;  // Type: 0 (ICMP echo/ping reply)
        dwVal.v[2] += 8;    // Subtract 0x0800 from the checksum
        if(dwVal.v[2] < 8u)
        {
            dwVal.v[3]++;
            if(dwVal.v[3] == 0u)
                dwVal.v[2]++;
        }

        // Wait for TX hardware to become available (finish transmitting
        // any previous packet)
        while(!IPIsTxReady());

        // Position the write pointer for the next IPPutHeader operation
        // NOTE: do not put this before the IPIsTxReady() call for WF compatbility
        MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));

        // Create IP header in TX memory
        IPPutHeader(remote, IP_PROT_ICMP, len);

        // Copy ICMP response into the TX memory
        MACPutArray((uint8_t*)&dwVal, sizeof(dwVal));
        MACMemCopyAsync(-1, -1, len-4);
        while(!MACIsMemCopyDone());

        // Transmit the echo reply packet
        MACFlush();
    }
#if defined(STACK_USE_ICMP_CLIENT)
    else if(dwVal.w[0] == 0x0000u)  // See if this an ICMP Echo reply to our request
    {
        // Get the sequence number and identifier fields
        MACGetArray((uint8_t*)&dwVal, sizeof(dwVal));

        // See if the identifier matches the one we sent
        if(dwVal.w[0] != 0xEFBE)
            return;

        if(dwVal.w[1] != wICMPSequenceNumber)
            return;

        // Validate the ICMP checksum field
        IPSetRxBuffer(0);
        if(CalcIPBufferChecksum(sizeof(ICMP_PACKET)))   // Two bytes of payload were sent in the echo request
            return;

        // Flag that we received the response and stop the timer ticking
        ICMPFlags.bReplyValid = 1;
        ICMPTimer = TickGet() - ICMPTimer;
    }
#endif
}
Пример #2
0
Файл: IP.c Проект: CEIT-UQ/RGB
/*********************************************************************
 * Function:        BOOL IPGetHeader( IP_ADDR    *localIP,
 *                                    NODE_INFO  *remote,
 *                                    BYTE        *Protocol,
 *                                    WORD        *len)
 *
 * PreCondition:    MACGetHeader() == TRUE
 *
 * Input:           localIP     - Local node IP Address as received
 *                                in current IP header.
 *                                If this information is not required
 *                                caller may pass NULL value.
 *                  remote      - Remote node info
 *                  Protocol    - Current packet protocol
 *                  len         - Current packet data length
 *
 * Output:          TRUE, if valid packet was received
 *                  FALSE otherwise
 *
 * Side Effects:    None
 *
 * Note:            Only one IP message can be received.
 *                  Caller may not transmit and receive a message
 *                  at the same time.
 *
 ********************************************************************/
BOOL IPGetHeader(IP_ADDR *localIP,
                 NODE_INFO *remote,
                 BYTE *protocol,
                 WORD *len)
{
    WORD_VAL    CalcChecksum;
    IP_HEADER   header;

#if defined(NON_MCHP_MAC)
    WORD_VAL    ReceivedChecksum;
    WORD        checksums[2];
    BYTE        optionsLen;
	#define MAX_OPTIONS_LEN     (40u)            // As per RFC 791.
    BYTE        options[MAX_OPTIONS_LEN];
#endif

    // Read IP header.
    MACGetArray((BYTE*)&header, sizeof(header));

    // Make sure that this is an IPv4 packet.
    if((header.VersionIHL & 0xf0) != IP_VERSION)
    	return FALSE;

	// Throw this packet away if it is a fragment.  
	// We don't have enough RAM for IP fragment reconstruction.
	if(header.FragmentInfo & 0xFF1F)
		return FALSE;

	IPHeaderLen = (header.VersionIHL & 0x0f) << 2;

#if !defined(NON_MCHP_MAC)
	// Validate the IP header.  If it is correct, the checksum 
	// will come out to 0x0000 (because the header contains a 
	// precomputed checksum).  A corrupt header will have a 
	// nonzero checksum.
	CalcChecksum.Val = MACCalcRxChecksum(0, IPHeaderLen);

	// Seek to the end of the IP header
	MACSetReadPtrInRx(IPHeaderLen);

    if(CalcChecksum.Val)
#else
    // Calculate options length in this header, if there is any.
    // IHL is in terms of numbers of 32-bit DWORDs; i.e. actual
    // length is 4 times IHL.
    optionsLen = IPHeaderLen - sizeof(header);

    // If there is any option(s), read it so that we can include them
    // in checksum calculation.
    if ( optionsLen > MAX_OPTIONS_LEN )
        return FALSE;

    if ( optionsLen > 0u )
        MACGetArray(options, optionsLen);

    // Save header checksum; clear it and recalculate it ourselves.
    ReceivedChecksum.Val = header.HeaderChecksum;
    header.HeaderChecksum = 0;

    // Calculate checksum of header including options bytes.
    checksums[0] = ~CalcIPChecksum((BYTE*)&header, sizeof(header));

    // Calculate Options checksum too, if they are present.
    if ( optionsLen > 0u )
        checksums[1] = ~CalcIPChecksum((BYTE*)options, optionsLen);
    else
        checksums[1] = 0;

    CalcChecksum.Val  = CalcIPChecksum((BYTE*)checksums,
                                            2 * sizeof(WORD));

    // Make sure that checksum is correct
    if ( ReceivedChecksum.Val != CalcChecksum.Val )
#endif
    {
        // Bad packet. The function caller will be notified by means of the FALSE 
        // return value and it should discard the packet.
        return FALSE;
    }

    // Network to host conversion.
    SwapIPHeader(&header);

    // If caller is intrested, return destination IP address
    // as seen in this IP header.
    if ( localIP )
        localIP->Val    = header.DestAddress.Val;

    remote->IPAddr.Val  = header.SourceAddress.Val;
    *protocol           = header.Protocol;
    *len 				= header.TotalLength - IPHeaderLen;

    return TRUE;
}