Skip to content
83 changes: 63 additions & 20 deletions source/FreeRTOS_ARP.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,6 @@ eFrameProcessingResult_t eARPProcessPacket( const NetworkBufferDescriptor_t * px
void * pvCopyDest;
NetworkEndPoint_t * pxTargetEndPoint = pxNetworkBuffer->pxEndPoint;

#if ( ipconfigARP_USE_CLASH_DETECTION != 0 )
NetworkEndPoint_t * pxSourceEndPoint;
#endif

/* Next defensive request must not be sent for arpIP_CLASH_RESET_TIMEOUT_MS
* period. */
static TickType_t uxARPClashTimeoutPeriod = pdMS_TO_TICKS( arpIP_CLASH_RESET_TIMEOUT_MS );
Expand Down Expand Up @@ -241,7 +237,7 @@ eFrameProcessingResult_t eARPProcessPacket( const NetworkBufferDescriptor_t * px
/* Process received ARP frame to see if there is a clash. */
#if ( ipconfigARP_USE_CLASH_DETECTION != 0 )
{
pxSourceEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( ulSenderProtocolAddress, 2 );
NetworkEndPoint_t * pxSourceEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( ulSenderProtocolAddress, 2 );

if( ( pxSourceEndPoint != NULL ) && ( pxSourceEndPoint->ipv4_settings.ulIPAddress == ulSenderProtocolAddress ) )
{
Expand Down Expand Up @@ -419,7 +415,8 @@ static void vARPProcessPacketReply( const ARPPacket_t * pxARPFrame,
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress, pxTargetEndPoint );
}

if( pxARPWaitingNetworkBuffer != NULL )
if( ( pxARPWaitingNetworkBuffer != NULL ) &&
( uxIPHeaderSizePacket( pxARPWaitingNetworkBuffer ) == ipSIZE_OF_IPv4_HEADER ) )
{
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
Expand Down Expand Up @@ -499,24 +496,70 @@ BaseType_t xCheckRequiresARPResolution( const NetworkBufferDescriptor_t * pxNetw
{
BaseType_t xNeedsARPResolution = pdFALSE;

/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
const IPPacket_t * pxIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer );
const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
IPV4Parameters_t * pxIPv4Settings = &( pxNetworkBuffer->pxEndPoint->ipv4_settings );
if( uxIPHeaderSizePacket( pxNetworkBuffer ) == ipSIZE_OF_IPv6_HEADER )
{
const IPPacket_IPv6_t * pxIPPacket = ( ( IPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer );
const IPHeader_IPv6_t * pxIPHeader = &( pxIPPacket->xIPHeader );
IPv6_Address_t * pxIPAddress = &( pxIPHeader->xSourceAddress );
uint8_t ucNextHeader = pxIPHeader->ucNextHeader;

if( ( ucNextHeader == ipPROTOCOL_TCP ) ||
( ucNextHeader == ipPROTOCOL_UDP ) )
{
IPv6_Type_t eType = xIPv6_GetIPType( pxIPAddress );
FreeRTOS_printf( ( "xCheckRequiresARPResolution: %pip type %s\n", pxIPAddress->ucBytes, ( eType == eIPv6_Global ) ? "Global" : ( eType == eIPv6_LinkLocal ) ? "LinkLocal" : "other" ) );

if( eType == eIPv6_LinkLocal )
{
MACAddress_t xMACAddress;
NetworkEndPoint_t * pxEndPoint;
eARPLookupResult_t eResult;
char pcName[ 80 ];

eResult = eNDGetCacheEntry( pxIPAddress, &xMACAddress, &pxEndPoint );
FreeRTOS_printf( ( "xCheckRequiresARPResolution: eResult %s with EP %s\n", ( eResult == eARPCacheMiss ) ? "Miss" : ( eResult == eARPCacheHit ) ? "Hit" : "Error", pcEndpointName( pxEndPoint, pcName, sizeof pcName ) ) );

if( eResult == eARPCacheMiss )
{
NetworkBufferDescriptor_t * pxTempBuffer;
size_t uxNeededSize;

uxNeededSize = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER + sizeof( ICMPRouterSolicitation_IPv6_t );
pxTempBuffer = pxGetNetworkBufferWithDescriptor( BUFFER_FROM_WHERE_CALL( 199 ) uxNeededSize, 0U );

if( ( pxIPHeader->ulSourceIPAddress & pxIPv4Settings->ulNetMask ) == ( pxIPv4Settings->ulIPAddress & pxIPv4Settings->ulNetMask ) )
if( pxTempBuffer != NULL )
{
pxTempBuffer->pxEndPoint = pxNetworkBuffer->pxEndPoint;
pxTempBuffer->pxInterface = pxNetworkBuffer->pxInterface;
vNDSendNeighbourSolicitation( pxNetworkBuffer, pxIPAddress );
}

xNeedsARPResolution = pdTRUE;
}
}
}
}
else
{
/* If the IP is on the same subnet and we do not have an ARP entry already,
* then we should send out ARP for finding the MAC address. */
if( xIsIPInARPCache( pxIPHeader->ulSourceIPAddress ) == pdFALSE )
/* MISRA Ref 11.3.1 [Misaligned access] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
/* coverity[misra_c_2012_rule_11_3_violation] */
const IPPacket_t * pxIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer );
const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
IPV4Parameters_t * pxIPv4Settings = &( pxNetworkBuffer->pxEndPoint->ipv4_settings );

if( ( pxIPHeader->ulSourceIPAddress & pxIPv4Settings->ulNetMask ) == ( pxIPv4Settings->ulIPAddress & pxIPv4Settings->ulNetMask ) )
{
FreeRTOS_OutputARPRequest( pxIPHeader->ulSourceIPAddress );
/* If the IP is on the same subnet and we do not have an ARP entry already,
* then we should send out ARP for finding the MAC address. */
if( xIsIPInARPCache( pxIPHeader->ulSourceIPAddress ) == pdFALSE )
{
FreeRTOS_OutputARPRequest( pxIPHeader->ulSourceIPAddress );

/* This packet needs resolution since this is on the same subnet
* but not in the ARP cache. */
xNeedsARPResolution = pdTRUE;
/* This packet needs resolution since this is on the same subnet
* but not in the ARP cache. */
xNeedsARPResolution = pdTRUE;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion source/FreeRTOS_DNS_Networking.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@
if( xReturn <= 0 )
{
/* 'pdFREERTOS_ERRNO_EWOULDBLOCK' is returned in case of a timeout. */
FreeRTOS_printf( ( "DNS_ReadReply returns %d\n", xReturn ) );
FreeRTOS_printf( ( "DNS_ReadReply returns %d\n", ( int ) xReturn ) );
}

return xReturn;
Expand Down
21 changes: 13 additions & 8 deletions source/FreeRTOS_DNS_Parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@
{
NetworkBufferDescriptor_t * pxNetworkBuffer;
NetworkEndPoint_t * pxEndPoint, xEndPoint;
size_t uxUDPOffset;

pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );

Expand All @@ -450,6 +451,9 @@
break;
}

uxUDPOffset = ( size_t ) ( pucUDPPayloadBuffer - pxNetworkBuffer->pucEthernetBuffer );
configASSERT( ( uxUDPOffset == ipUDP_PAYLOAD_OFFSET_IPv4 ) || ( uxUDPOffset == ipUDP_PAYLOAD_OFFSET_IPv6 ) );

if( pxNetworkBuffer->pxEndPoint == NULL )
{
/* NetworkInterface is obliged to set 'pxEndPoint' in every received packet,
Expand Down Expand Up @@ -480,8 +484,8 @@
}
#endif /* ( ipconfigUSE_IPv6 != 0 ) */

/* If this is not a reply to our DNS request, it might an LLMNR
* request. */
/* If this is not a reply to our DNS request, it might be an mDNS or an LLMNR
* request. Ask the application if it uses the name. */
if( xApplicationDNSQueryHook( &xEndPoint, xSet.pcName ) )
{
int16_t usLength;
Expand Down Expand Up @@ -524,7 +528,7 @@
xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) xSet.pcRequestedName ) - pucUDPPayloadBuffer );

pxNetworkBuffer = pxNewBuffer;
pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ uxUDPOffset ] );

xSet.pucByte = &( pucNewBuffer[ xOffset1 ] );
xSet.pcRequestedName = ( char * ) &( pucNewBuffer[ xOffset2 ] );
Expand All @@ -538,7 +542,7 @@
}
else
{
pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ uxUDPOffset ] );
}
}

Expand Down Expand Up @@ -575,11 +579,11 @@
}
else
{
/*logging*/
FreeRTOS_printf( ( "LLMNR return IPv4 %lxip\n", FreeRTOS_ntohl( xEndPoint.ipv4_settings.ulIPAddress ) ) );
size_t uxDistance;
vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, ( uint16_t ) sizeof( pxAnswer->ulIPAddress ) );
vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( xEndPoint.ipv4_settings.ulIPAddress ) );
usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( xSet.pucByte - pucNewBuffer ) );
uxDistance = ( size_t ) ( xSet.pucByte - pucNewBuffer );
usLength = ( int16_t ) ( sizeof( *pxAnswer ) + uxDistance );
}

prepareReplyDNSMessage( pxNetworkBuffer, usLength );
Expand Down Expand Up @@ -956,14 +960,15 @@
if( pxIPHeader->ulDestinationIPAddress == ipMDNS_IP_ADDRESS )
{
pxIPHeader->ulDestinationIPAddress = ipMDNS_IP_ADDRESS;
pxIPHeader->ucTimeToLive = ipMDNS_TIME_TO_LIVE;
}
else
{
pxIPHeader->ulDestinationIPAddress = pxIPHeader->ulSourceIPAddress;
pxIPHeader->ucTimeToLive = ipconfigUDP_TIME_TO_LIVE;
}

pxIPHeader->ulSourceIPAddress = ( pxEndPoint != NULL ) ? pxEndPoint->ipv4_settings.ulIPAddress : 0U;
pxIPHeader->ucTimeToLive = ipconfigUDP_TIME_TO_LIVE;
pxIPHeader->usIdentification = FreeRTOS_htons( usPacketIdentifier );

/* The stack doesn't support fragments, so the fragment offset field must always be zero.
Expand Down
39 changes: 21 additions & 18 deletions source/FreeRTOS_IP.c
Original file line number Diff line number Diff line change
Expand Up @@ -1772,31 +1772,32 @@ static eFrameProcessingResult_t prvProcessIPPacket( const IPPacket_t * pxIPPacke
* entry. */
if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
{
/* Refresh the ARP cache with the IP/MAC-address of the received
* packet. For UDP packets, this will be done later in
* xProcessReceivedUDPPacket(), as soon as it's know that the message
* will be handled. This will prevent the ARP cache getting
* overwritten with the IP address of useless broadcast packets. */
if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE )
{
vNDRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), &( pxIPHeader_IPv6->xSourceAddress ), pxNetworkBuffer->pxEndPoint );
}
else

if( xCheckRequiresARPResolution( pxNetworkBuffer ) == pdTRUE )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is ARP resolution needed here for IPv6?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes maybe we should give that function a different name like: xCheckRequiresAddressResolution(). In this PR I added code to handle both IPv4 and IPv6 packets.

{
eReturn = eWaitingARPResolution;
}
else
{
/* IP address is not on the same subnet, ARP table can be updated.
* Refresh the ARP cache with the IP/MAC-address of the received
* packet. For UDP packets, this will be done later in
/* Refresh the ARP cache with the IP/MAC-address of the received
* packet. For UDP packets, this will be done later in
* xProcessReceivedUDPPacket(), as soon as it's know that the message
* will be handled. This will prevent the ARP cache getting
* overwritten with the IP address of useless broadcast packets.
*/
vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress, pxNetworkBuffer->pxEndPoint );
* overwritten with the IP address of useless broadcast packets. */
if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE )
{
vNDRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), &( pxIPHeader_IPv6->xSourceAddress ), pxNetworkBuffer->pxEndPoint );
}
else
{
/* IP address is not on the same subnet, ARP table can be updated.
* Refresh the ARP cache with the IP/MAC-address of the received
* packet. For UDP packets, this will be done later in
* xProcessReceivedUDPPacket(), as soon as it's know that the message
* will be handled. This will prevent the ARP cache getting
* overwritten with the IP address of useless broadcast packets.
*/
vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress, pxNetworkBuffer->pxEndPoint );
}
}
}

Expand All @@ -1812,7 +1813,9 @@ static eFrameProcessingResult_t prvProcessIPPacket( const IPPacket_t * pxIPPacke
* went wrong because it will not be able to validate what it
* receives. */
#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
eReturn = ProcessICMPPacket( pxNetworkBuffer );
{
eReturn = ProcessICMPPacket( pxNetworkBuffer );
}
#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
break;

Expand Down
2 changes: 1 addition & 1 deletion source/FreeRTOS_IPv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ eFrameProcessingResult_t prvAllowIPPacketIPv6( const IPHeader_IPv6_t * const pxI
const IPv6_Address_t * pxDestinationIPAddress = &( pxIPv6Header->xDestinationAddress );

/* Is the packet for this IP address? */
if( ( FreeRTOS_FindEndPointOnIP_IPv6( pxDestinationIPAddress ) != NULL ) ||
if( ( pxNetworkBuffer->pxEndPoint != NULL ) ||
/* Is it the multicast address FF00::/8 ? */
( xIsIPv6Multicast( pxDestinationIPAddress ) != pdFALSE ) ||
/* Or (during DHCP negotiation) we have no IP-address yet? */
Expand Down
Loading