mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-06-17 05:34:17 +08:00
Fix some build issues in older kernel demo projects.
Update to V2.0.7 of the TCP/IP stack: + Multiple security improvements and fixes in packet parsing routines, DNS caching, and TCP sequence number and ID generation. + Disable NBNS and LLMNR by default. + Add TCP hang protection by default. We thank Ori Karliner of Zimperium zLabs Team for reporting these issues.
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* FreeRTOS+TCP V2.0.7
|
||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
@ -61,7 +61,7 @@
|
||||
|
||||
/* This compile-time test was moved to here because some macro's
|
||||
were unknown within 'FreeRTOSIPConfigDefaults.h'. It tests whether
|
||||
the defined MTU size can contain at ;east a complete TCP packet. */
|
||||
the defined MTU size can contain at least a complete TCP packet. */
|
||||
|
||||
#if ( ( ipconfigTCP_MSS + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) > ipconfigNETWORK_MTU )
|
||||
#error The ipconfigTCP_MSS setting in FreeRTOSIPConfig.h is too large.
|
||||
@ -137,13 +137,6 @@ the defined MTU size can contain at ;east a complete TCP packet. */
|
||||
*/
|
||||
#define REDUCED_MSS_THROUGH_INTERNET ( 1400 )
|
||||
|
||||
/*
|
||||
* Each time a new TCP connection is being made, a new Initial Sequence Number shall be used.
|
||||
* The variable 'ulNextInitialSequenceNumber' will be incremented with a recommended value
|
||||
* of 0x102.
|
||||
*/
|
||||
#define INITIAL_SEQUENCE_NUMBER_INCREMENT ( 0x102UL )
|
||||
|
||||
/*
|
||||
* When there are no TCP options, the TCP offset equals 20 bytes, which is stored as
|
||||
* the number 5 (words) in the higher niblle of the TCP-offset byte.
|
||||
@ -269,10 +262,6 @@ static void prvTCPAddTxData( FreeRTOS_Socket_t *pxSocket );
|
||||
*/
|
||||
static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );
|
||||
|
||||
#if( ipconfigUSE_TCP_TIMESTAMPS == 1 )
|
||||
static UBaseType_t prvTCPSetTimeStamp( BaseType_t lOffset, FreeRTOS_Socket_t *pxSocket, TCPHeader_t *pxTCPHeader );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called from prvTCPHandleState(). Find the TCP payload data and check and
|
||||
* return its length.
|
||||
@ -360,12 +349,14 @@ static NetworkBufferDescriptor_t *prvTCPBufferResize( FreeRTOS_Socket_t *pxSocke
|
||||
static uint8_t prvWinScaleFactor( FreeRTOS_Socket_t *pxSocket );
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Initial Sequence Number, i.e. the next initial sequence number that will be
|
||||
used when a new connection is opened. The value should be randomized to prevent
|
||||
attacks from outside (spoofing). */
|
||||
uint32_t ulNextInitialSequenceNumber = 0ul;
|
||||
/*
|
||||
* Generate a randomized TCP Initial Sequence Number per RFC.
|
||||
*/
|
||||
extern uint32_t ulApplicationGetNextSequenceNumber(
|
||||
uint32_t ulSourceAddress,
|
||||
uint16_t usSourcePort,
|
||||
uint32_t ulDestinationAddress,
|
||||
uint16_t usDestinationPort );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@ -480,11 +471,11 @@ BaseType_t xReady = pdFALSE;
|
||||
if( ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) && ( pxSocket->u.xTCP.txStream != NULL ) )
|
||||
{
|
||||
/* The API FreeRTOS_send() might have added data to the TX stream. Add
|
||||
this data to the windowing system so it can be transmitted. */
|
||||
this data to the windowing system to it can be transmitted. */
|
||||
prvTCPAddTxData( pxSocket );
|
||||
}
|
||||
|
||||
#if( ipconfigUSE_TCP_WIN == 1 )
|
||||
#if ipconfigUSE_TCP_WIN == 1
|
||||
{
|
||||
if( pxSocket->u.xTCP.pxAckMessage != NULL )
|
||||
{
|
||||
@ -577,7 +568,7 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
|
||||
|
||||
if( pxSocket->u.xTCP.ucTCPState != eCONNECT_SYN )
|
||||
{
|
||||
/* The connection is in a state other than SYN. */
|
||||
/* The connection is in s state other than SYN. */
|
||||
pxNetworkBuffer = NULL;
|
||||
|
||||
/* prvTCPSendRepeated() will only create a network buffer if necessary,
|
||||
@ -609,18 +600,6 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
|
||||
the Ethernet address of the peer or the gateway is found. */
|
||||
pxTCPPacket = ( TCPPacket_t * )pxSocket->u.xTCP.xPacket.u.ucLastPacket;
|
||||
|
||||
#if( ipconfigUSE_TCP_TIMESTAMPS == 1 )
|
||||
{
|
||||
/* When TCP time stamps are enabled, but they will only be applied
|
||||
if the peer is outside the netmask, usually on the internet.
|
||||
Packages sent on a LAN are usually too big to carry time stamps. */
|
||||
if( ( ( pxSocket->u.xTCP.ulRemoteIP ^ FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) ) & xNetworkAddressing.ulNetMask ) != 0ul )
|
||||
{
|
||||
pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps = pdTRUE_UNSIGNED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* About to send a SYN packet. Call prvSetSynAckOptions() to set
|
||||
the proper options: The size of MSS and whether SACK's are
|
||||
allowed. */
|
||||
@ -707,12 +686,15 @@ NetworkBufferDescriptor_t xTempBuffer;
|
||||
|
||||
if( pxNetworkBuffer == NULL )
|
||||
{
|
||||
memset( &xTempBuffer, '\0', sizeof( xTempBuffer ) );
|
||||
pxNetworkBuffer = &xTempBuffer;
|
||||
|
||||
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
|
||||
{
|
||||
xTempBuffer.pxNextBuffer = NULL;
|
||||
}
|
||||
#endif
|
||||
xTempBuffer.pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;
|
||||
xTempBuffer.xDataLength = sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket );
|
||||
/* A pseudo network buffer can not be released. */
|
||||
xReleaseAfterSend = pdFALSE;
|
||||
}
|
||||
|
||||
@ -903,7 +885,7 @@ NetworkBufferDescriptor_t xTempBuffer;
|
||||
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
|
||||
|
||||
/* calculate the TCP checksum for an outgoing packet. */
|
||||
usGenerateProtocolChecksum( (uint8_t*)pxTCPPacket, pdTRUE );
|
||||
usGenerateProtocolChecksum( (uint8_t*)pxTCPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
|
||||
|
||||
/* A calculated checksum of 0 must be inverted as 0 means the checksum
|
||||
is disabled. */
|
||||
@ -914,11 +896,9 @@ NetworkBufferDescriptor_t xTempBuffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
|
||||
{
|
||||
pxNetworkBuffer->pxNextBuffer = NULL;
|
||||
}
|
||||
#endif
|
||||
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
|
||||
pxNetworkBuffer->pxNextBuffer = NULL;
|
||||
#endif
|
||||
|
||||
/* Important: tell NIC driver how many bytes must be sent. */
|
||||
pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER;
|
||||
@ -928,7 +908,7 @@ NetworkBufferDescriptor_t xTempBuffer;
|
||||
sizeof( pxEthernetHeader->xDestinationAddress ) );
|
||||
|
||||
/* The source MAC addresses is fixed to 'ipLOCAL_MAC_ADDRESS'. */
|
||||
memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress ), ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
|
||||
memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress) , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
|
||||
|
||||
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
|
||||
{
|
||||
@ -1002,6 +982,7 @@ eARPLookupResult_t eReturned;
|
||||
uint32_t ulRemoteIP;
|
||||
MACAddress_t xEthAddress;
|
||||
BaseType_t xReturn = pdTRUE;
|
||||
uint32_t ulInitialSequenceNumber = 0;
|
||||
|
||||
#if( ipconfigHAS_PRINTF != 0 )
|
||||
{
|
||||
@ -1017,32 +998,47 @@ BaseType_t xReturn = pdTRUE;
|
||||
|
||||
switch( eReturned )
|
||||
{
|
||||
case eARPCacheHit: /* An ARP table lookup found a valid entry. */
|
||||
break; /* We can now prepare the SYN packet. */
|
||||
case eARPCacheMiss: /* An ARP table lookup did not find a valid entry. */
|
||||
case eCantSendPacket: /* There is no IP address, or an ARP is still in progress. */
|
||||
default:
|
||||
/* Count the number of times it couldn't find the ARP address. */
|
||||
pxSocket->u.xTCP.ucRepCount++;
|
||||
case eARPCacheHit: /* An ARP table lookup found a valid entry. */
|
||||
break; /* We can now prepare the SYN packet. */
|
||||
case eARPCacheMiss: /* An ARP table lookup did not find a valid entry. */
|
||||
case eCantSendPacket: /* There is no IP address, or an ARP is still in progress. */
|
||||
default:
|
||||
/* Count the number of times it couldn't find the ARP address. */
|
||||
pxSocket->u.xTCP.ucRepCount++;
|
||||
|
||||
FreeRTOS_debug_printf( ( "ARP for %lxip (using %lxip): rc=%d %02X:%02X:%02X %02X:%02X:%02X\n",
|
||||
pxSocket->u.xTCP.ulRemoteIP,
|
||||
FreeRTOS_htonl( ulRemoteIP ),
|
||||
eReturned,
|
||||
xEthAddress.ucBytes[ 0 ],
|
||||
xEthAddress.ucBytes[ 1 ],
|
||||
xEthAddress.ucBytes[ 2 ],
|
||||
xEthAddress.ucBytes[ 3 ],
|
||||
xEthAddress.ucBytes[ 4 ],
|
||||
xEthAddress.ucBytes[ 5 ] ) );
|
||||
FreeRTOS_debug_printf( ( "ARP for %lxip (using %lxip): rc=%d %02X:%02X:%02X %02X:%02X:%02X\n",
|
||||
pxSocket->u.xTCP.ulRemoteIP,
|
||||
FreeRTOS_htonl( ulRemoteIP ),
|
||||
eReturned,
|
||||
xEthAddress.ucBytes[ 0 ],
|
||||
xEthAddress.ucBytes[ 1 ],
|
||||
xEthAddress.ucBytes[ 2 ],
|
||||
xEthAddress.ucBytes[ 3 ],
|
||||
xEthAddress.ucBytes[ 4 ],
|
||||
xEthAddress.ucBytes[ 5 ] ) );
|
||||
|
||||
/* And issue a (new) ARP request */
|
||||
FreeRTOS_OutputARPRequest( ulRemoteIP );
|
||||
/* And issue a (new) ARP request */
|
||||
FreeRTOS_OutputARPRequest( ulRemoteIP );
|
||||
|
||||
xReturn = pdFALSE;
|
||||
break;
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
if( xReturn != pdFALSE )
|
||||
{
|
||||
/* Get a difficult-to-predict initial sequence number for this 4-tuple. */
|
||||
ulInitialSequenceNumber = ulApplicationGetNextSequenceNumber(
|
||||
*ipLOCAL_IP_ADDRESS_POINTER,
|
||||
pxSocket->usLocalPort,
|
||||
pxSocket->u.xTCP.ulRemoteIP,
|
||||
pxSocket->u.xTCP.usRemotePort );
|
||||
|
||||
/* Check for a random number generation error. */
|
||||
if( 0 == ulInitialSequenceNumber )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if( xReturn != pdFALSE )
|
||||
{
|
||||
/* The MAC-address of the peer (or gateway) has been found,
|
||||
@ -1050,10 +1046,10 @@ BaseType_t xReturn = pdTRUE;
|
||||
pxTCPPacket = ( TCPPacket_t * )pxSocket->u.xTCP.xPacket.u.ucLastPacket;
|
||||
pxIPHeader = &pxTCPPacket->xIPHeader;
|
||||
|
||||
/* Reset the retry counter to zero... */
|
||||
/* reset the retry counter to zero. */
|
||||
pxSocket->u.xTCP.ucRepCount = 0u;
|
||||
|
||||
/* ...and remember that the connect/SYN data are prepared. */
|
||||
/* And remember that the connect/SYN data are prepared. */
|
||||
pxSocket->u.xTCP.bits.bConnPrepared = pdTRUE_UNSIGNED;
|
||||
|
||||
/* Now that the Ethernet address is known, the initial packet can be
|
||||
@ -1086,11 +1082,7 @@ BaseType_t xReturn = pdTRUE;
|
||||
pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = 0ul;
|
||||
|
||||
/* Start with ISN (Initial Sequence Number). */
|
||||
pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulNextInitialSequenceNumber;
|
||||
|
||||
/* And increment it with 268 for the next new connection, which is
|
||||
recommended value. */
|
||||
ulNextInitialSequenceNumber += 0x102UL;
|
||||
pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulInitialSequenceNumber;
|
||||
|
||||
/* The TCP header size is 20 bytes, divided by 4 equals 5, which is put in
|
||||
the high nibble of the TCP offset field. */
|
||||
@ -1160,38 +1152,73 @@ UBaseType_t uxNewMSS;
|
||||
pucLast = pucPtr + (((pxTCPHeader->ucTCPOffset >> 4) - 5) << 2);
|
||||
pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
|
||||
|
||||
/* Validate options size calculation. */
|
||||
if( pucLast > ( pxNetworkBuffer->pucEthernetBuffer + pxNetworkBuffer->xDataLength ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* The comparison with pucLast is only necessary in case the option data are
|
||||
corrupted, we don't like to run into invalid memory and crash. */
|
||||
while( pucPtr < pucLast )
|
||||
{
|
||||
UBaseType_t xRemainingOptionsBytes = pucLast - pucPtr;
|
||||
|
||||
if( pucPtr[ 0 ] == TCP_OPT_END )
|
||||
{
|
||||
/* End of options. */
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if( pucPtr[ 0 ] == TCP_OPT_NOOP)
|
||||
{
|
||||
pucPtr++;
|
||||
|
||||
/* NOP option, inserted to make the length a multiple of 4. */
|
||||
/* NOP option, inserted to make the length a multiple of 4. */
|
||||
pucPtr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Any other well-formed option must be at least two bytes: the option
|
||||
type byte followed by a length byte. */
|
||||
if( xRemainingOptionsBytes < 2 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
#if( ipconfigUSE_TCP_WIN != 0 )
|
||||
else if( ( pucPtr[ 0 ] == TCP_OPT_WSOPT ) && ( pucPtr[ 1 ] == TCP_OPT_WSOPT_LEN ) )
|
||||
else if( pucPtr[ 0 ] == TCP_OPT_WSOPT )
|
||||
{
|
||||
/* Confirm that the option fits in the remaining buffer space. */
|
||||
if( xRemainingOptionsBytes < TCP_OPT_WSOPT_LEN ||
|
||||
pucPtr[ 1 ] != TCP_OPT_WSOPT_LEN )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pxSocket->u.xTCP.ucPeerWinScaleFactor = pucPtr[ 2 ];
|
||||
pxSocket->u.xTCP.bits.bWinScaling = pdTRUE_UNSIGNED;
|
||||
pucPtr += TCP_OPT_WSOPT_LEN;
|
||||
}
|
||||
#endif /* ipconfigUSE_TCP_WIN */
|
||||
else if( ( pucPtr[ 0 ] == TCP_OPT_MSS ) && ( pucPtr[ 1 ] == TCP_OPT_MSS_LEN ) )
|
||||
else if( pucPtr[ 0 ] == TCP_OPT_MSS )
|
||||
{
|
||||
/* An MSS option with the correct option length. FreeRTOS_htons()
|
||||
/* Confirm that the option fits in the remaining buffer space. */
|
||||
if( xRemainingOptionsBytes < TCP_OPT_MSS_LEN ||
|
||||
pucPtr[ 1 ] != TCP_OPT_MSS_LEN )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* An MSS option with the correct option length. FreeRTOS_htons()
|
||||
is not needed here because usChar2u16() already returns a host
|
||||
endian number. */
|
||||
uxNewMSS = usChar2u16( pucPtr + 2 );
|
||||
|
||||
if( pxSocket->u.xTCP.usInitMSS != uxNewMSS )
|
||||
{
|
||||
/* Perform a basic check on the the new MSS. */
|
||||
if( uxNewMSS == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
FreeRTOS_debug_printf( ( "MSS change %u -> %lu\n", pxSocket->u.xTCP.usInitMSS, uxNewMSS ) );
|
||||
}
|
||||
|
||||
@ -1225,11 +1252,11 @@ UBaseType_t uxNewMSS;
|
||||
{
|
||||
/* All other options have a length field, so that we easily
|
||||
can skip past them. */
|
||||
int len = ( int )pucPtr[ 1 ];
|
||||
if( len == 0 )
|
||||
unsigned char len = pucPtr[ 1 ];
|
||||
if( len < 2 || len > xRemainingOptionsBytes )
|
||||
{
|
||||
/* If the length field is zero, the options are malformed
|
||||
and we don't process them further. */
|
||||
/* If the length field is too small or too big, the options are malformed.
|
||||
Don't process them further. */
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1284,16 +1311,6 @@ UBaseType_t uxNewMSS;
|
||||
}
|
||||
/* len should be 0 by now. */
|
||||
}
|
||||
#if ipconfigUSE_TCP_TIMESTAMPS == 1
|
||||
else if( pucPtr[0] == TCP_OPT_TIMESTAMP )
|
||||
{
|
||||
len -= 2; /* Skip option and length byte. */
|
||||
pucPtr += 2;
|
||||
pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps = pdTRUE_UNSIGNED;
|
||||
pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp = ulChar2u32( pucPtr );
|
||||
pxSocket->u.xTCP.xTCPWindow.tx.ulTimeStamp = ulChar2u32( pucPtr + 4 );
|
||||
}
|
||||
#endif /* ipconfigUSE_TCP_TIMESTAMPS == 1 */
|
||||
}
|
||||
#endif /* ipconfigUSE_TCP_WIN == 1 */
|
||||
|
||||
@ -1371,24 +1388,13 @@ UBaseType_t uxOptionsLength;
|
||||
}
|
||||
#else
|
||||
{
|
||||
#if( ipconfigUSE_TCP_TIMESTAMPS == 1 )
|
||||
if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )
|
||||
{
|
||||
uxOptionsLength += prvTCPSetTimeStamp( uxOptionsLength, pxSocket, &pxTCPPacket->xTCPHeader );
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = 2u;
|
||||
uxOptionsLength += 2u;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_NOOP;
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = TCP_OPT_NOOP;
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 2 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 3 ] = 2; /* 2: length of this option. */
|
||||
uxOptionsLength += 4u;
|
||||
}
|
||||
return uxOptionsLength; /* bytes, not words. */
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_NOOP;
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = TCP_OPT_NOOP;
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 2 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */
|
||||
pxTCPHeader->ucOptdata[ uxOptionsLength + 3 ] = 2; /* 2: length of this option. */
|
||||
uxOptionsLength += 4u;
|
||||
|
||||
return uxOptionsLength; /* bytes, not words. */
|
||||
}
|
||||
#endif /* ipconfigUSE_TCP_WIN == 0 */
|
||||
}
|
||||
@ -1566,7 +1572,7 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co
|
||||
/* Fill in the new state. */
|
||||
pxSocket->u.xTCP.ucTCPState = ( uint8_t ) eTCPState;
|
||||
|
||||
/* Touch the alive timers because moving to another state. */
|
||||
/* touch the alive timers because moving to another state. */
|
||||
prvTCPTouchSocket( pxSocket );
|
||||
|
||||
#if( ipconfigHAS_DEBUG_PRINTF == 1 )
|
||||
@ -1621,14 +1627,7 @@ BaseType_t xResize;
|
||||
( int32_t ) ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength ) + lDataLen );
|
||||
/* In case we were called from a TCP timer event, a buffer must be
|
||||
created. Otherwise, test 'xDataLength' of the provided buffer. */
|
||||
if( ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->xDataLength < (size_t)lNeeded ) )
|
||||
{
|
||||
xResize = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xResize = pdFALSE;
|
||||
}
|
||||
xResize = ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->xDataLength < (size_t)lNeeded );
|
||||
}
|
||||
|
||||
if( xResize != pdFALSE )
|
||||
@ -1640,6 +1639,9 @@ BaseType_t xResize;
|
||||
|
||||
if( pxReturn != NULL )
|
||||
{
|
||||
/* Set the actual packet size, in case the returned buffer is larger. */
|
||||
pxReturn->xDataLength = lNeeded;
|
||||
|
||||
/* Copy the existing data to the new created buffer. */
|
||||
if( pxNetworkBuffer )
|
||||
{
|
||||
@ -1695,8 +1697,8 @@ int32_t lStreamPos;
|
||||
pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;
|
||||
}
|
||||
|
||||
pxTCPPacket = ( TCPPacket_t * ) pucEthernetBuffer;
|
||||
pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
|
||||
pxTCPPacket = ( TCPPacket_t * ) ( pucEthernetBuffer );
|
||||
pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
|
||||
lDataLen = 0;
|
||||
lStreamPos = 0;
|
||||
pxTCPPacket->xTCPHeader.ucTCPFlags |= ipTCP_FLAG_ACK;
|
||||
@ -1848,19 +1850,6 @@ int32_t lStreamPos;
|
||||
pxTCPPacket->xTCPHeader.ucTCPFlags |= ( uint8_t ) ipTCP_FLAG_PSH;
|
||||
}
|
||||
|
||||
#if ipconfigUSE_TCP_TIMESTAMPS == 1
|
||||
{
|
||||
if( uxOptionsLength == 0u )
|
||||
{
|
||||
if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )
|
||||
{
|
||||
TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pucEthernetBuffer );
|
||||
uxOptionsLength = prvTCPSetTimeStamp( 0, pxSocket, &pxTCPPacket->xTCPHeader );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
lDataLen += ( int32_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
|
||||
}
|
||||
|
||||
@ -1941,9 +1930,9 @@ int32_t lCount, lLength;
|
||||
/* A txStream has been created already, see if the socket has new data for
|
||||
the sliding window.
|
||||
|
||||
uxStreamBufferMidSpace() returns the distance between rxHead and rxMid. It
|
||||
contains new Tx data which has not been passed to the sliding window yet.
|
||||
The oldest data not-yet-confirmed can be found at rxTail. */
|
||||
uxStreamBufferMidSpace() returns the distance between rxHead and rxMid. It contains new
|
||||
Tx data which has not been passed to the sliding window yet. The oldest
|
||||
data not-yet-confirmed can be found at rxTail. */
|
||||
lLength = ( int32_t ) uxStreamBufferMidSpace( pxSocket->u.xTCP.txStream );
|
||||
|
||||
if( lLength > 0 )
|
||||
@ -2064,29 +2053,6 @@ uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ipconfigUSE_TCP_TIMESTAMPS == 1
|
||||
|
||||
static UBaseType_t prvTCPSetTimeStamp( BaseType_t lOffset, FreeRTOS_Socket_t *pxSocket, TCPHeader_t *pxTCPHeader )
|
||||
{
|
||||
uint32_t ulTimes[2];
|
||||
uint8_t *ucOptdata = &( pxTCPHeader->ucOptdata[ lOffset ] );
|
||||
|
||||
ulTimes[0] = ( xTaskGetTickCount ( ) * 1000u ) / configTICK_RATE_HZ;
|
||||
ulTimes[0] = FreeRTOS_htonl( ulTimes[0] );
|
||||
ulTimes[1] = FreeRTOS_htonl( pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp );
|
||||
ucOptdata[0] = ( uint8_t ) TCP_OPT_TIMESTAMP;
|
||||
ucOptdata[1] = ( uint8_t ) TCP_OPT_TIMESTAMP_LEN;
|
||||
memcpy( &(ucOptdata[2] ), ulTimes, 8u );
|
||||
ucOptdata[10] = ( uint8_t ) TCP_OPT_NOOP;
|
||||
ucOptdata[11] = ( uint8_t ) TCP_OPT_NOOP;
|
||||
/* Do not return the same timestamps 2 times. */
|
||||
pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp = 0ul;
|
||||
return 12u;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* prvCheckRxData(): called from prvTCPHandleState()
|
||||
*
|
||||
@ -2279,15 +2245,6 @@ UBaseType_t uxOptionsLength = pxTCPWindow->ucOptionLength;
|
||||
pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
|
||||
}
|
||||
|
||||
#if( ipconfigUSE_TCP_TIMESTAMPS == 1 )
|
||||
{
|
||||
if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )
|
||||
{
|
||||
uxOptionsLength += prvTCPSetTimeStamp( uxOptionsLength, pxSocket, pxTCPHeader );
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigUSE_TCP_TIMESTAMPS == 1 */
|
||||
|
||||
return uxOptionsLength;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
@ -2941,16 +2898,31 @@ BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer
|
||||
{
|
||||
FreeRTOS_Socket_t *pxSocket;
|
||||
TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
|
||||
uint16_t ucTCPFlags = pxTCPPacket->xTCPHeader.ucTCPFlags;
|
||||
uint32_t ulLocalIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulDestinationIPAddress );
|
||||
uint16_t xLocalPort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usDestinationPort );
|
||||
uint32_t ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );
|
||||
uint16_t xRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );
|
||||
uint16_t ucTCPFlags;
|
||||
uint32_t ulLocalIP;
|
||||
uint16_t xLocalPort;
|
||||
uint32_t ulRemoteIP;
|
||||
uint16_t xRemotePort;
|
||||
BaseType_t xResult = pdPASS;
|
||||
|
||||
/* Find the destination socket, and if not found: return a socket listing to
|
||||
the destination PORT. */
|
||||
pxSocket = ( FreeRTOS_Socket_t * ) pxTCPSocketLookup( ulLocalIP, xLocalPort, ulRemoteIP, xRemotePort );
|
||||
/* Check for a minimum packet size. */
|
||||
if( pxNetworkBuffer->xDataLength >=
|
||||
ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER )
|
||||
{
|
||||
ucTCPFlags = pxTCPPacket->xTCPHeader.ucTCPFlags;
|
||||
ulLocalIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulDestinationIPAddress );
|
||||
xLocalPort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usDestinationPort );
|
||||
ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );
|
||||
xRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );
|
||||
|
||||
/* Find the destination socket, and if not found: return a socket listing to
|
||||
the destination PORT. */
|
||||
pxSocket = ( FreeRTOS_Socket_t * )pxTCPSocketLookup( ulLocalIP, xLocalPort, ulRemoteIP, xRemotePort );
|
||||
}
|
||||
else
|
||||
{
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
if( ( pxSocket == NULL ) || ( prvTCPSocketIsActive( ( UBaseType_t ) pxSocket->u.xTCP.ucTCPState ) == pdFALSE ) )
|
||||
{
|
||||
@ -3111,59 +3083,71 @@ BaseType_t xResult = pdPASS;
|
||||
static FreeRTOS_Socket_t *prvHandleListen( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
|
||||
{
|
||||
TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
|
||||
FreeRTOS_Socket_t *pxReturn;
|
||||
FreeRTOS_Socket_t *pxReturn = NULL;
|
||||
uint32_t ulInitialSequenceNumber;
|
||||
|
||||
/* Assume that a new Initial Sequence Number will be required. Request
|
||||
it now in order to fail out if necessary. */
|
||||
ulInitialSequenceNumber = ulApplicationGetNextSequenceNumber(
|
||||
*ipLOCAL_IP_ADDRESS_POINTER,
|
||||
pxSocket->usLocalPort,
|
||||
pxTCPPacket->xIPHeader.ulSourceIPAddress,
|
||||
pxTCPPacket->xTCPHeader.usSourcePort );
|
||||
|
||||
/* A pure SYN (without ACK) has come in, create a new socket to answer
|
||||
it. */
|
||||
if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )
|
||||
{
|
||||
/* The flag bReuseSocket indicates that the same instance of the
|
||||
listening socket should be used for the connection. */
|
||||
pxReturn = pxSocket;
|
||||
pxSocket->u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED;
|
||||
pxSocket->u.xTCP.pxPeerSocket = pxSocket;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The socket does not have the bReuseSocket flag set meaning create a
|
||||
new socket when a connection comes in. */
|
||||
pxReturn = NULL;
|
||||
if( 0 != ulInitialSequenceNumber )
|
||||
{
|
||||
if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )
|
||||
{
|
||||
/* The flag bReuseSocket indicates that the same instance of the
|
||||
listening socket should be used for the connection. */
|
||||
pxReturn = pxSocket;
|
||||
pxSocket->u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED;
|
||||
pxSocket->u.xTCP.pxPeerSocket = pxSocket;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The socket does not have the bReuseSocket flag set meaning create a
|
||||
new socket when a connection comes in. */
|
||||
pxReturn = NULL;
|
||||
|
||||
if( pxSocket->u.xTCP.usChildCount >= pxSocket->u.xTCP.usBacklog )
|
||||
{
|
||||
FreeRTOS_printf( ( "Check: Socket %u already has %u / %u child%s\n",
|
||||
pxSocket->usLocalPort,
|
||||
pxSocket->u.xTCP.usChildCount,
|
||||
pxSocket->u.xTCP.usBacklog,
|
||||
pxSocket->u.xTCP.usChildCount == 1 ? "" : "ren" ) );
|
||||
prvTCPSendReset( pxNetworkBuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeRTOS_Socket_t *pxNewSocket = (FreeRTOS_Socket_t *)
|
||||
FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
|
||||
if( pxSocket->u.xTCP.usChildCount >= pxSocket->u.xTCP.usBacklog )
|
||||
{
|
||||
FreeRTOS_printf( ( "Check: Socket %u already has %u / %u child%s\n",
|
||||
pxSocket->usLocalPort,
|
||||
pxSocket->u.xTCP.usChildCount,
|
||||
pxSocket->u.xTCP.usBacklog,
|
||||
pxSocket->u.xTCP.usChildCount == 1 ? "" : "ren" ) );
|
||||
prvTCPSendReset( pxNetworkBuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeRTOS_Socket_t *pxNewSocket = ( FreeRTOS_Socket_t * )
|
||||
FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
|
||||
|
||||
if( ( pxNewSocket == NULL ) || ( pxNewSocket == FREERTOS_INVALID_SOCKET ) )
|
||||
{
|
||||
FreeRTOS_debug_printf( ( "TCP: Listen: new socket failed\n" ) );
|
||||
prvTCPSendReset( pxNetworkBuffer );
|
||||
}
|
||||
else if( prvTCPSocketCopy( pxNewSocket, pxSocket ) != pdFALSE )
|
||||
{
|
||||
/* The socket will be connected immediately, no time for the
|
||||
owner to setsockopt's, therefore copy properties of the server
|
||||
socket to the new socket. Only the binding might fail (due to
|
||||
lack of resources). */
|
||||
pxReturn = pxNewSocket;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ( pxNewSocket == NULL ) || ( pxNewSocket == FREERTOS_INVALID_SOCKET ) )
|
||||
{
|
||||
FreeRTOS_debug_printf( ( "TCP: Listen: new socket failed\n" ) );
|
||||
prvTCPSendReset( pxNetworkBuffer );
|
||||
}
|
||||
else if( prvTCPSocketCopy( pxNewSocket, pxSocket ) != pdFALSE )
|
||||
{
|
||||
/* The socket will be connected immediately, no time for the
|
||||
owner to setsockopt's, therefore copy properties of the server
|
||||
socket to the new socket. Only the binding might fail (due to
|
||||
lack of resources). */
|
||||
pxReturn = pxNewSocket;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( pxReturn != NULL )
|
||||
if( 0 != ulInitialSequenceNumber && pxReturn != NULL )
|
||||
{
|
||||
pxReturn->u.xTCP.usRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );
|
||||
pxReturn->u.xTCP.ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );
|
||||
pxReturn->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulNextInitialSequenceNumber;
|
||||
pxReturn->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulInitialSequenceNumber;
|
||||
|
||||
/* Here is the SYN action. */
|
||||
pxReturn->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber );
|
||||
@ -3171,9 +3155,6 @@ FreeRTOS_Socket_t *pxReturn;
|
||||
|
||||
prvTCPCreateWindow( pxReturn );
|
||||
|
||||
/* It is recommended to increase the ISS for each new connection with a value of 0x102. */
|
||||
ulNextInitialSequenceNumber += INITIAL_SEQUENCE_NUMBER_INCREMENT;
|
||||
|
||||
vTCPStateChange( pxReturn, eSYN_FIRST );
|
||||
|
||||
/* Make a copy of the header up to the TCP header. It is needed later
|
||||
@ -3248,7 +3229,7 @@ struct freertos_sockaddr xAddress;
|
||||
/* A reference to the new socket may be stored and the socket is marked
|
||||
as 'passable'. */
|
||||
|
||||
/* When bPassAccept is true, this socket may be returned in a call to
|
||||
/* When bPassAccept is pdTRUE_UNSIGNED this socket may be returned in a call to
|
||||
accept(). */
|
||||
pxNewSocket->u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED;
|
||||
if(pxSocket->u.xTCP.pxPeerSocket == NULL )
|
||||
@ -3327,3 +3308,7 @@ BaseType_t xResult = pdFALSE;
|
||||
|
||||
#endif /* ipconfigUSE_TCP == 1 */
|
||||
|
||||
/* Provide access to private members for testing. */
|
||||
#ifdef AMAZON_FREERTOS_ENABLE_UNIT_TESTS
|
||||
#include "aws_freertos_tcp_test_access_tcp_define.h"
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user