From 1803d907dddc36083c4821fd883177a424e86677 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Wed, 6 Sep 2023 15:16:59 +0800 Subject: [PATCH] Preparing library to use loopback device --- source/FreeRTOS_ARP.c | 7 +++- source/FreeRTOS_IP.c | 3 +- source/FreeRTOS_IPv4.c | 52 ++++++++++++++++++++++++++++ source/FreeRTOS_IPv6.c | 57 ++++++++++++++++++++----------- source/FreeRTOS_ND.c | 3 +- source/FreeRTOS_Routing.c | 19 ++++++----- source/include/FreeRTOS_IPv4.h | 10 ++++++ source/include/FreeRTOS_IPv6.h | 17 +++++++++ source/include/FreeRTOS_Routing.h | 1 + 9 files changed, 137 insertions(+), 32 deletions(-) diff --git a/source/FreeRTOS_ARP.c b/source/FreeRTOS_ARP.c index 509e927ad..20de92a92 100644 --- a/source/FreeRTOS_ARP.c +++ b/source/FreeRTOS_ARP.c @@ -565,7 +565,12 @@ BaseType_t xCheckRequiresARPResolution( const NetworkBufferDescriptor_t * pxNetw ( ucNextHeader == ipPROTOCOL_UDP ) ) { IPv6_Type_t eType = xIPv6_GetIPType( ( const IPv6_Address_t * ) pxIPAddress ); - FreeRTOS_printf( ( "xCheckRequiresARPResolution: %pip type %s\n", ( void * ) pxIPAddress->ucBytes, ( eType == eIPv6_Global ) ? "Global" : ( eType == eIPv6_LinkLocal ) ? "LinkLocal" : "other" ) ); + FreeRTOS_debug_printf( ( "xCheckRequiresARPResolution: %pip type %s\n", + ( void * ) pxIPAddress->ucBytes, + ( eType == eIPv6_Global ) ? "Global" : + ( eType == eIPv6_LinkLocal ) ? "LinkLocal" : + ( eType == eIPv6_Loopback ) ? "Loopback" : + "other" ) ); if( eType == eIPv6_LinkLocal ) { diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index 7366e8f89..2a2a22dfa 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -1716,8 +1716,7 @@ static eFrameProcessingResult_t prvProcessUDPPacket( NetworkBufferDescriptor_t * eReturn = eReleaseBuffer; } else if( ( pxUDPPacket->xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) && - ( ipFIRST_LOOPBACK_IPv4 <= ( FreeRTOS_ntohl( pxUDPPacket->xIPHeader.ulDestinationIPAddress ) ) ) && - ( ( FreeRTOS_ntohl( pxUDPPacket->xIPHeader.ulDestinationIPAddress ) ) < ipLAST_LOOPBACK_IPv4 ) ) + ( xBadIPv4Loopback( &( pxUDPPacket->xIPHeader ) ) != pdFALSE ) ) { /* The local loopback addresses must never appear outside a host. See RFC 1122 * section 3.2.1.3. */ diff --git a/source/FreeRTOS_IPv4.c b/source/FreeRTOS_IPv4.c index a4cd45e6d..7b4b189cb 100644 --- a/source/FreeRTOS_IPv4.c +++ b/source/FreeRTOS_IPv4.c @@ -210,6 +210,58 @@ BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress ) } /*-----------------------------------------------------------*/ +/** + * @brief Check if the packet is an illegal loopback packet. + * + * @param[in] pxIPHeader The IP-header being checked. + * + * @return Returns pdTRUE if the packet should be stopped, because either the source + * or the target address is a loopback address. + */ +BaseType_t xBadIPv4Loopback( const IPHeader_t * const pxIPHeader ) +{ + BaseType_t xReturn = pdFALSE; + const NetworkEndPoint_t * pxEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( pxIPHeader->ulSourceIPAddress, 3 ); + + /* Allow loopback packets from this node itself only. */ + if( pxEndPoint != NULL ) + { + BaseType_t x1 = ( xIsIPv4Loopback( pxIPHeader->ulDestinationIPAddress ) != 0 ) ? pdTRUE : pdFALSE; + BaseType_t x2 = ( xIsIPv4Loopback( pxIPHeader->ulSourceIPAddress ) != 0 ) ? pdTRUE : pdFALSE; + + if( x1 != x2 ) + { + /* Either the source or the destination address is an IPv4 loopback address. */ + xReturn = pdTRUE; + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Is the IP address an IPv4 loopback address. + * + * @param[in] ulIPAddress The IP address being checked. + * + * @return pdTRUE if the IP address is a loopback address or else, pdFALSE. + */ +BaseType_t xIsIPv4Loopback( uint32_t ulAddress ) +{ + BaseType_t xReturn = pdFALSE; + uint32_t ulIP = FreeRTOS_ntohl( ulAddress ); + + if( ( ulIP >= ipFIRST_LOOPBACK_IPv4 ) && + ( ulIP < ipLAST_LOOPBACK_IPv4 ) ) + { + xReturn = pdTRUE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + /** * @brief Check whether this IPv4 packet is to be allowed or to be dropped. * diff --git a/source/FreeRTOS_IPv6.c b/source/FreeRTOS_IPv6.c index 6050e5ca1..744351106 100644 --- a/source/FreeRTOS_IPv6.c +++ b/source/FreeRTOS_IPv6.c @@ -62,7 +62,7 @@ const struct xIPv6_Address FreeRTOS_in6addr_any = { 0 }; /** * This variable is initialized by the system to contain the loopback IPv6 address. */ -const struct xIPv6_Address FreeRTOS_in6addr_loopback = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } }; +const struct xIPv6_Address FreeRTOS_in6addr_loopback = { { 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U } }; #if ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 ) /* Check IPv6 packet length. */ @@ -242,14 +242,6 @@ const struct xIPv6_Address FreeRTOS_in6addr_loopback = { { 0, 0, 0, 0, 0, 0, 0, */ static const struct xIPv6_Address xIPv6UnspecifiedAddress = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; -#if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) - -/* - * Check if the packet is a loopback packet. - */ - static BaseType_t xIsIPv6Loopback( const IPHeader_IPv6_t * const pxIPv6Header ); -#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 */ - /** * @brief Get the group ID and stored into IPv6_Address_t. * @@ -270,34 +262,60 @@ static void xGetIPv6MulticastGroupID( const IPv6_Address_t * pxIPv6Address, /*-----------------------------------------------------------*/ +/** + * @brief Check if the IP-address is an IPv6 loopback address. + * + * @param[in] ulIPAddress The IP-address being checked. + * + * @return pdTRUE if the IP-address is a loopback address or else, pdFALSE. + */ +BaseType_t xIsIPv6Loopback( const IPv6_Address_t * pxAddress ) +{ + BaseType_t xReturn = pdFALSE; + + if( memcmp( pxAddress->ucBytes, FreeRTOS_in6addr_loopback.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 ) + { + xReturn = pdTRUE; + } + + return xReturn; +} + #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) /** - * @brief Check if the packet is a loopback packet. + * @brief Check if the packet is an illegal loopback packet. * - * @param[in] pxIPv6Header The IP packet in pxNetworkBuffer. + * @param[in] pxIPv6Header The IP-header of the packet. * - * @return Returns pdTRUE if it's a legal loopback packet, pdFALSE if not . + * @return Returns pdTRUE if the packet should be stopped, because either the source + * or the target address is a loopback address. */ /* MISRA Ref 8.9.1 [File scoped variables] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */ /* coverity[misra_c_2012_rule_8_9_violation] */ /* coverity[single_use] */ - static BaseType_t xIsIPv6Loopback( const IPHeader_IPv6_t * const pxIPv6Header ) + BaseType_t xBadIPv6Loopback( const IPHeader_IPv6_t * const pxIPv6Header ) { BaseType_t xReturn = pdFALSE; const NetworkEndPoint_t * pxEndPoint = FreeRTOS_FindEndPointOnIP_IPv6( &( pxIPv6Header->xSourceAddress ) ); /* Allow loopback packets from this node itself only. */ - if( ( pxEndPoint != NULL ) && - ( memcmp( pxIPv6Header->xDestinationAddress.ucBytes, FreeRTOS_in6addr_loopback.ucBytes, sizeof( IPv6_Address_t ) ) == 0 ) && - ( memcmp( pxIPv6Header->xSourceAddress.ucBytes, pxEndPoint->ipv6_settings.xIPAddress.ucBytes, sizeof( IPv6_Address_t ) ) == 0 ) ) + if( pxEndPoint != NULL ) { - xReturn = pdTRUE; + BaseType_t x1 = ( xIsIPv6Loopback( &( pxIPv6Header->xDestinationAddress ) ) != 0 ) ? pdTRUE : pdFALSE; + BaseType_t x2 = ( xIsIPv6Loopback( &( pxIPv6Header->xSourceAddress ) ) != 0 ) ? pdTRUE : pdFALSE; + + if( x1 != x2 ) + { + /* Either source or the destination address is a loopback address. */ + xReturn = pdTRUE; + } } return xReturn; } + #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 */ @@ -476,10 +494,9 @@ eFrameProcessingResult_t prvAllowIPPacketIPv6( const IPHeader_IPv6_t * const pxI eReturn = eProcessBuffer; } /* Is it the legal multicast address? */ - else if( ( xHasUnspecifiedAddress == pdFALSE ) && + else if( ( ( xHasUnspecifiedAddress == pdFALSE ) && + ( xBadIPv6Loopback( pxIPv6Header ) == pdFALSE ) ) && ( ( xIsIPv6AllowedMulticast( pxDestinationIPAddress ) != pdFALSE ) || - /* Is it loopback address sent from this node? */ - ( xIsIPv6Loopback( pxIPv6Header ) != pdFALSE ) || /* Or (during DHCP negotiation) we have no IP-address yet? */ ( FreeRTOS_IsNetworkUp() == 0 ) ) ) { diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index ea64f8cb4..26e07341d 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -1254,7 +1254,8 @@ if( xResult == pdPASS ) { - configASSERT( ( uxPrefixLength > 0U ) && ( uxPrefixLength < ( 8U * ipSIZE_OF_IPv6_ADDRESS ) ) ); + /* A loopback IP-address has a prefix of 128. */ + configASSERT( ( uxPrefixLength > 0U ) && ( uxPrefixLength <= ( 8U * ipSIZE_OF_IPv6_ADDRESS ) ) ); if( uxPrefixLength >= 8U ) { diff --git a/source/FreeRTOS_Routing.c b/source/FreeRTOS_Routing.c index f2babf08b..49ff57813 100644 --- a/source/FreeRTOS_Routing.c +++ b/source/FreeRTOS_Routing.c @@ -155,14 +155,6 @@ struct xIPv6_Couple if( pxInterface != NULL ) { - /* This interface will be added to the end of the list of interfaces, so - * there is no pxNext yet. */ - pxInterface->pxNext = NULL; - - /* The end point for this interface has not yet been set. */ - /*_RB_ As per other comments, why not set the end point at the same time? */ - pxInterface->pxEndPoint = NULL; - if( pxNetworkInterfaces == NULL ) { /* No other interfaces are set yet, so this is the first in the list. */ @@ -189,6 +181,7 @@ struct xIPv6_Couple if( pxIterator->pxNext == NULL ) { pxIterator->pxNext = pxInterface; + pxInterface->pxNext = NULL; break; } @@ -1452,6 +1445,7 @@ IPv6_Type_t xIPv6_GetIPType( const IPv6_Address_t * pxAddress ) { eIPv6_LinkLocal, 0xFFC0U, 0xFE80U }, /* 1111 1110 10 */ { eIPv6_SiteLocal, 0xFFC0U, 0xFEC0U }, /* 1111 1110 11 */ { eIPv6_Multicast, 0xFF00U, 0xFF00U }, /* 1111 1111 */ + { eIPv6_Loopback, 0xFFFFU, 0x0000U }, /* 0000 0000 ::1 */ }; if( pxAddress != NULL ) @@ -1462,6 +1456,15 @@ IPv6_Type_t xIPv6_GetIPType( const IPv6_Address_t * pxAddress ) ( uint16_t ) ( ( ( ( uint16_t ) pxAddress->ucBytes[ 0 ] ) << 8 ) | ( ( uint16_t ) pxAddress->ucBytes[ 1 ] ) ); + if( xIPCouples[ xIndex ].eType == eIPv6_Loopback ) + { + if( xIsIPv6Loopback( &pxAddress ) != pdFALSE ) + { + eResult = eIPv6_Loopback; + break; + } + } + if( ( usAddress & xIPCouples[ xIndex ].usMask ) == xIPCouples[ xIndex ].usExpected ) { eResult = xIPCouples[ xIndex ].eType; diff --git a/source/include/FreeRTOS_IPv4.h b/source/include/FreeRTOS_IPv4.h index eef778e29..c7d15af90 100644 --- a/source/include/FreeRTOS_IPv4.h +++ b/source/include/FreeRTOS_IPv4.h @@ -88,6 +88,16 @@ uint32_t FreeRTOS_GetIPAddress( void ); /* Return pdTRUE if the IPv4 address is a multicast address. */ BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress ); +/* Return pdTRUE if the IPv4 address is a loopback address. */ +BaseType_t xIsIPv4Loopback( uint32_t ulAddress ); + +/* + * Return pdTRUE if either source or destination is a loopback address. + * A loopback IP-address may only communicate internally with another + * loopback IP-address. + */ +BaseType_t xBadIPv4Loopback( const IPHeader_t * const pxIPHeader ); + /* The function 'prvAllowIPPacket()' checks if a packets should be processed. */ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * const pxIPPacket, const struct xNETWORK_BUFFER * const pxNetworkBuffer, diff --git a/source/include/FreeRTOS_IPv6.h b/source/include/FreeRTOS_IPv6.h index 66755b2d1..214498a53 100644 --- a/source/include/FreeRTOS_IPv6.h +++ b/source/include/FreeRTOS_IPv6.h @@ -88,6 +88,23 @@ eFrameProcessingResult_t prvAllowIPPacketIPv6( const IPHeader_IPv6_t * const pxI const NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength ); +#if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) + +/* + * Return pdTRUE if either source or destination is a loopback address. + * A loopback IP-address may only communicate internally with another + * loopback IP-address. + */ + BaseType_t xBadIPv6Loopback( const IPHeader_IPv6_t * const pxIPv6Header ); +#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 */ + +#if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) + /* + * Check if the address is a loopback IP-address. + */ + BaseType_t xIsIPv6Loopback( const IPv6_Address_t* pxAddress ); +#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 */ + /** @brief Handle the IPv6 extension headers. */ eFrameProcessingResult_t eHandleIPv6ExtensionHeaders( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xDoRemove ); diff --git a/source/include/FreeRTOS_Routing.h b/source/include/FreeRTOS_Routing.h index 7d143b9b7..24dd4a5f3 100644 --- a/source/include/FreeRTOS_Routing.h +++ b/source/include/FreeRTOS_Routing.h @@ -332,6 +332,7 @@ eIPv6_LinkLocal, /* 1111 1110 10 */ eIPv6_SiteLocal, /* 1111 1110 11 */ eIPv6_Multicast, /* 1111 1111 */ + eIPv6_Loopback, /* 1111 (::1) */ eIPv6_Unknown, /* Not implemented. */ } IPv6_Type_t;