diff --git a/source/FreeRTOS_TCP_IP.c b/source/FreeRTOS_TCP_IP.c index 6ba71a33f2..12a2c4c0c4 100644 --- a/source/FreeRTOS_TCP_IP.c +++ b/source/FreeRTOS_TCP_IP.c @@ -882,7 +882,8 @@ pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength ) != pdFALSE ) ) { /* Send a challenge ACK. */ - ( void ) prvTCPSendChallengeAck( pxNetworkBuffer ); + ( void ) prvTCPSendChallengeAck( pxNetworkBuffer, pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber, + pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber ); } else { diff --git a/source/FreeRTOS_TCP_Transmission.c b/source/FreeRTOS_TCP_Transmission.c index 3b0abe63f7..1e25476e5b 100644 --- a/source/FreeRTOS_TCP_Transmission.c +++ b/source/FreeRTOS_TCP_Transmission.c @@ -1352,11 +1352,28 @@ * unexpected but still within the window. * * @param[in] pxNetworkBuffer The network buffer descriptor with the packet. + * @param[in] ulCurrentSequenceNumber The current expected sequence value by the connection. + * @param[in] ulOurSequenceNumber The SEQ number to send out. * * @return Returns the value back from #prvTCPSendSpecialPacketHelper. */ - BaseType_t prvTCPSendChallengeAck( NetworkBufferDescriptor_t * pxNetworkBuffer ) + BaseType_t prvTCPSendChallengeAck( NetworkBufferDescriptor_t * pxNetworkBuffer, + uint32_t ulCurrentSequenceNumber, + uint32_t ulOurSequenceNumber ) { + ProtocolHeaders_t * pxProtocolHeaders = ( ( ProtocolHeaders_t * ) + &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizePacket( pxNetworkBuffer ) ] ) ); + + /* In https://tools.ietf.org/html/rfc5961#section-3.2 the field values are defined as follows: + * + * + * + * The prvTCPSendSpecialPacketHelper function uses the sequence number of the packet as the + * ACK number and the ACK number as the sequence number, therefore the values are set swapped + * here to match the RFC. */ + pxProtocolHeaders->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( ulCurrentSequenceNumber ); + pxProtocolHeaders->xTCPHeader.ulAckNr = FreeRTOS_htonl( ulOurSequenceNumber ); + return prvTCPSendSpecialPacketHelper( pxNetworkBuffer, tcpTCP_FLAG_ACK ); } /*-----------------------------------------------------------*/ diff --git a/source/include/FreeRTOS_TCP_Transmission.h b/source/include/FreeRTOS_TCP_Transmission.h index 1e48fbc30a..8b030f4caa 100644 --- a/source/include/FreeRTOS_TCP_Transmission.h +++ b/source/include/FreeRTOS_TCP_Transmission.h @@ -149,7 +149,9 @@ BaseType_t prvSendData( FreeRTOS_Socket_t * pxSocket, * case #3. In summary, an RST was received with a sequence number that is * unexpected but still within the window. */ -BaseType_t prvTCPSendChallengeAck( NetworkBufferDescriptor_t * pxNetworkBuffer ); +BaseType_t prvTCPSendChallengeAck( NetworkBufferDescriptor_t * pxNetworkBuffer, + uint32_t ulCurrentSequenceNumber, + uint32_t ulOurSequenceNumber ); /* * Reply to a peer with the RST flag on, in case a packet can not be handled. diff --git a/test/unit-test/FreeRTOS_TCP_Transmission/FreeRTOS_TCP_Transmission_utest.c b/test/unit-test/FreeRTOS_TCP_Transmission/FreeRTOS_TCP_Transmission_utest.c index bdfae76934..6dc8bc64de 100644 --- a/test/unit-test/FreeRTOS_TCP_Transmission/FreeRTOS_TCP_Transmission_utest.c +++ b/test/unit-test/FreeRTOS_TCP_Transmission/FreeRTOS_TCP_Transmission_utest.c @@ -2610,11 +2610,13 @@ void test_prvTCPSendChallengeAck( void ) eARPGetCacheEntry_ExpectAnyArgsAndReturn( eResolutionCacheHit ); eARPGetCacheEntry_ReturnThruPtr_ppxEndPoint( &pxEndPoint ); - Return = prvTCPSendChallengeAck( pxNetworkBuffer ); + Return = prvTCPSendChallengeAck( pxNetworkBuffer, 0x3333, 0x4444 ); TEST_ASSERT_EQUAL( pdFALSE, Return ); TEST_ASSERT_EQUAL( 1, NetworkInterfaceOutputFunction_Stub_Called ); TEST_ASSERT_EQUAL( tcpTCP_FLAG_ACK, pxTCPPacket->xTCPHeader.ucTCPFlags ); TEST_ASSERT_EQUAL( 0x50, pxTCPPacket->xTCPHeader.ucTCPOffset ); + TEST_ASSERT_EQUAL( 0x3333, FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulAckNr ) ); + TEST_ASSERT_EQUAL( 0x4444, FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber ) ); } /* test prvTCPSendReset function */