static eFrameProcessingResult_t prvAllowIPPacket()

in FreeRTOS_IP.c [1959:2140]


static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
                                                  const NetworkBufferDescriptor_t * const pxNetworkBuffer,
                                                  UBaseType_t uxHeaderLength )
{
    eFrameProcessingResult_t eReturn = eProcessBuffer;

    #if ( ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )
        const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
    #else

        /* or else, the parameter won't be used and the function will be optimised
         * away */
        ( void ) pxIPPacket;
    #endif

    #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 )
        {
            /* In systems with a very small amount of RAM, it might be advantageous
             * to have incoming messages checked earlier, by the network card driver.
             * This method may decrease the usage of sparse network buffers. */
            uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
            uint32_t ulSourceIPAddress = pxIPHeader->ulSourceIPAddress;

            /* Ensure that the incoming packet is not fragmented because the stack
             * doesn't not support IP fragmentation. All but the last fragment coming in will have their
             * "more fragments" flag set and the last fragment will have a non-zero offset.
             * We need to drop the packet in either of those cases. */
            if( ( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) || ( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_FLAGS_MORE_FRAGMENTS ) != 0U ) )
            {
                /* Can not handle, fragmented packet. */
                eReturn = eReleaseBuffer;
            }

            /* Test if the length of the IP-header is between 20 and 60 bytes,
             * and if the IP-version is 4. */
            else if( ( pxIPHeader->ucVersionHeaderLength < ipIPV4_VERSION_HEADER_LENGTH_MIN ) ||
                     ( pxIPHeader->ucVersionHeaderLength > ipIPV4_VERSION_HEADER_LENGTH_MAX ) )
            {
                /* Can not handle, unknown or invalid header version. */
                eReturn = eReleaseBuffer;
            }
            /* Is the packet for this IP address? */
            else if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&
                     /* Is it the global broadcast address 255.255.255.255 ? */
                     ( ulDestinationIPAddress != ipBROADCAST_IP_ADDRESS ) &&
                     /* Is it a specific broadcast address 192.168.1.255 ? */
                     ( ulDestinationIPAddress != xNetworkAddressing.ulBroadcastAddress ) &&
                     #if ( ipconfigUSE_LLMNR == 1 )
                         /* Is it the LLMNR multicast address? */
                         ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&
                     #endif
                     /* Or (during DHCP negotiation) we have no IP-address yet? */
                     ( *ipLOCAL_IP_ADDRESS_POINTER != 0U ) )
            {
                /* Packet is not for this node, release it */
                eReturn = eReleaseBuffer;
            }
            /* Is the source address correct? */
            else if( ( FreeRTOS_ntohl( ulSourceIPAddress ) & 0xffU ) == 0xffU )
            {
                /* The source address cannot be broadcast address. Replying to this
                 * packet may cause network storms. Drop the packet. */
                eReturn = eReleaseBuffer;
            }
            else if( ( memcmp( ( const void * ) xBroadcastMACAddress.ucBytes,
                               ( const void * ) ( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes ),
                               sizeof( MACAddress_t ) ) == 0 ) &&
                     ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xffU ) != 0xffU ) )
            {
                /* Ethernet address is a broadcast address, but the IP address is not a
                 * broadcast address. */
                eReturn = eReleaseBuffer;
            }
            else if( memcmp( ( void * ) &xBroadcastMACAddress,
                             ( void * ) &( pxIPPacket->xEthernetHeader.xSourceAddress ),
                             sizeof( MACAddress_t ) ) == 0 )
            {
                /* Ethernet source is a broadcast address. Drop the packet. */
                eReturn = eReleaseBuffer;
            }
            else if( xIsIPv4Multicast( ulSourceIPAddress ) == pdTRUE )
            {
                /* Source is a multicast IP address. Drop the packet in conformity with RFC 1112 section 7.2. */
                eReturn = eReleaseBuffer;
            }
            else
            {
                /* Packet is not fragmented, destination is this device, source IP and MAC
                 * addresses are correct. */
            }
        }
    #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */

    #if ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 )
        {
            /* Some drivers of NIC's with checksum-offloading will enable the above
             * define, so that the checksum won't be checked again here */
            if( eReturn == eProcessBuffer )
            {
                /* Is the IP header checksum correct?
                 *
                 * NOTE: When the checksum of IP header is calculated while not omitting
                 * the checksum field, the resulting value of the checksum always is 0xffff
                 * which is denoted by ipCORRECT_CRC. See this wiki for more information:
                 * https://en.wikipedia.org/wiki/IPv4_header_checksum#Verifying_the_IPv4_header_checksum
                 * and this RFC: https://tools.ietf.org/html/rfc1624#page-4
                 */
                if( usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC )
                {
                    /* Check sum in IP-header not correct. */
                    eReturn = eReleaseBuffer;
                }
                /* Is the upper-layer checksum (TCP/UDP/ICMP) correct? */
                else if( usGenerateProtocolChecksum( ( uint8_t * ) ( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength, pdFALSE ) != ipCORRECT_CRC )
                {
                    /* Protocol checksum not accepted. */
                    eReturn = eReleaseBuffer;
                }
                else
                {
                    /* The checksum of the received packet is OK. */
                }
            }
        }
    #else /* if ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) */
        {
            if( eReturn == eProcessBuffer )
            {
                if( xCheckSizeFields( ( uint8_t * ) ( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength ) != pdPASS )
                {
                    /* Some of the length checks were not successful. */
                    eReturn = eReleaseBuffer;
                }
            }

            #if ( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
                {
                    /* Check if this is a UDP packet without a checksum. */
                    if( eReturn == eProcessBuffer )
                    {
                        /* ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is defined as 0,
                         * and so UDP packets carrying a protocol checksum of 0, will
                         * be dropped. */

                        /* Identify the next protocol. */
                        if( pxIPPacket->xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
                        {
                            ProtocolPacket_t * pxProtPack;

                            /* pxProtPack will point to the offset were the protocols begin. */
                            pxProtPack = ipCAST_PTR_TO_TYPE_PTR( ProtocolPacket_t, &( pxNetworkBuffer->pucEthernetBuffer[ uxHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );

                            if( pxProtPack->xUDPPacket.xUDPHeader.usChecksum == ( uint16_t ) 0U )
                            {
                                #if ( ipconfigHAS_PRINTF != 0 )
                                    {
                                        static BaseType_t xCount = 0;

                                        if( xCount < 5 )
                                        {
                                            FreeRTOS_printf( ( "prvAllowIPPacket: UDP packet from %xip without CRC dropped\n",
                                                               FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) );
                                            xCount++;
                                        }
                                    }
                                #endif /* ( ipconfigHAS_PRINTF != 0 ) */

                                /* Protocol checksum not accepted. */
                                eReturn = eReleaseBuffer;
                            }
                        }
                    }
                }
            #endif /* ( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 ) */

            /* to avoid warning unused parameters */
            ( void ) uxHeaderLength;
        }
    #endif /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 */

    return eReturn;
}