]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
Update version number in +TCP code.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / FreeRTOS_TCP_IP.c
index 1f306b01d6a56556eaec100ecbd86262dd795ed6..7ec07336c2976f61f5317325aa3cea5c1e8adc4f 100644 (file)
@@ -1,58 +1,26 @@
 /*\r
- * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
- * Authors include Hein Tibosch and Richard Barry\r
+ * FreeRTOS+TCP V2.0.11\r
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
  *\r
- *******************************************************************************\r
- ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
- ***                                                                         ***\r
- ***                                                                         ***\r
- ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
- ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
- ***   download):                                                            ***\r
- ***                                                                         ***\r
- ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
- ***   for some time.  Be aware however that we are still refining its       ***\r
- ***   design, the source code does not yet quite conform to the strict      ***\r
- ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
- ***   the documentation and testing is not necessarily complete.            ***\r
- ***                                                                         ***\r
- ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
- ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
- ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
- ***   under a license other than that described below.                      ***\r
- ***                                                                         ***\r
- ***                                                                         ***\r
- ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
- *******************************************************************************\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
  *\r
- * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
- * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
- * executed, as follows:\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
  *\r
- * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
- * License Arrangements heading of the FreeRTOS+TCP license information web\r
- * page, then it can be used under the terms of the FreeRTOS Open Source\r
- * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
- * under the terms of the GNU General Public License V2.  Links to the relevant\r
- * licenses follow:\r
- *\r
- * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
- * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
- * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
- *\r
- * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
- * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
- * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
- * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
- * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
- * implied, expressed, or statutory.\r
- *\r
- * 1 tab == 4 spaces!\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
  *\r
+ * http://aws.amazon.com/freertos\r
  * http://www.FreeRTOS.org\r
- * http://www.FreeRTOS.org/plus\r
- * http://www.FreeRTOS.org/labs\r
- *\r
  */\r
 \r
 /*\r
@@ -93,7 +61,7 @@
 \r
 /* This compile-time test was moved to here because some macro's\r
 were unknown within 'FreeRTOSIPConfigDefaults.h'.  It tests whether\r
-the defined MTU size can contain at ;east a complete TCP packet. */\r
+the defined MTU size can contain at least a complete TCP packet. */\r
 \r
 #if ( ( ipconfigTCP_MSS + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) > ipconfigNETWORK_MTU )\r
        #error The ipconfigTCP_MSS setting in FreeRTOSIPConfig.h is too large.\r
@@ -169,13 +137,6 @@ the defined MTU size can contain at ;east a complete TCP packet. */
  */\r
 #define REDUCED_MSS_THROUGH_INTERNET           ( 1400 )\r
 \r
-/*\r
- * Each time a new TCP connection is being made, a new Initial Sequence Number shall be used.\r
- * The variable 'ulNextInitialSequenceNumber' will be incremented with a recommended value\r
- * of 0x102.\r
- */\r
-#define INITIAL_SEQUENCE_NUMBER_INCREMENT              ( 0x102UL )\r
-\r
 /*\r
  * When there are no TCP options, the TCP offset equals 20 bytes, which is stored as\r
  * the number 5 (words) in the higher niblle of the TCP-offset byte.\r
@@ -301,10 +262,6 @@ static void prvTCPAddTxData( FreeRTOS_Socket_t *pxSocket );
  */\r
 static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );\r
 \r
-#if(   ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
-       static UBaseType_t prvTCPSetTimeStamp( BaseType_t lOffset, FreeRTOS_Socket_t *pxSocket, TCPHeader_t *pxTCPHeader );\r
-#endif\r
-\r
 /*\r
  * Called from prvTCPHandleState().  Find the TCP payload data and check and\r
  * return its length.\r
@@ -392,12 +349,13 @@ static NetworkBufferDescriptor_t *prvTCPBufferResize( FreeRTOS_Socket_t *pxSocke
        static uint8_t prvWinScaleFactor( FreeRTOS_Socket_t *pxSocket );\r
 #endif\r
 \r
-/*-----------------------------------------------------------*/\r
-\r
-/* Initial Sequence Number, i.e. the next initial sequence number that will be\r
-used when a new connection is opened.  The value should be randomized to prevent\r
-attacks from outside (spoofing). */\r
-uint32_t ulNextInitialSequenceNumber = 0ul;\r
+/*\r
+ * Generate a randomized TCP Initial Sequence Number per RFC.\r
+ */\r
+extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,\r
+                                                                                                       uint16_t usSourcePort,\r
+                                                                                                       uint32_t ulDestinationAddress,\r
+                                                                                                       uint16_t usDestinationPort );\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -512,11 +470,11 @@ BaseType_t xReady = pdFALSE;
        if( ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) && ( pxSocket->u.xTCP.txStream != NULL ) )\r
        {\r
                /* The API FreeRTOS_send() might have added data to the TX stream.  Add\r
-               this data to the windowing system so it can be transmitted. */\r
+               this data to the windowing system to it can be transmitted. */\r
                prvTCPAddTxData( pxSocket );\r
        }\r
 \r
-       #if( ipconfigUSE_TCP_WIN == 1 )\r
+       #if ipconfigUSE_TCP_WIN == 1\r
        {\r
                if( pxSocket->u.xTCP.pxAckMessage != NULL )\r
                {\r
@@ -609,7 +567,7 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
 \r
        if( pxSocket->u.xTCP.ucTCPState != eCONNECT_SYN )\r
        {\r
-               /* The connection is in a state other than SYN. */\r
+               /* The connection is in s state other than SYN. */\r
                pxNetworkBuffer = NULL;\r
 \r
                /* prvTCPSendRepeated() will only create a network buffer if necessary,\r
@@ -641,18 +599,6 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
                        the Ethernet address of the peer or the gateway is found. */\r
                        pxTCPPacket = ( TCPPacket_t * )pxSocket->u.xTCP.xPacket.u.ucLastPacket;\r
 \r
-                       #if( ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
-                       {\r
-                               /* When TCP time stamps are enabled, but they will only be applied\r
-                               if the peer is outside the netmask, usually on the internet.\r
-                               Packages sent on a LAN are usually too big to carry time stamps. */\r
-                               if( ( ( pxSocket->u.xTCP.ulRemoteIP ^ FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) ) & xNetworkAddressing.ulNetMask ) != 0ul )\r
-                               {\r
-                                       pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps = pdTRUE_UNSIGNED;\r
-                               }\r
-                       }\r
-                       #endif\r
-\r
                        /* About to send a SYN packet.  Call prvSetSynAckOptions() to set\r
                        the proper options: The size of MSS and whether SACK's are\r
                        allowed. */\r
@@ -739,12 +685,15 @@ NetworkBufferDescriptor_t xTempBuffer;
 \r
        if( pxNetworkBuffer == NULL )\r
        {\r
-               memset( &xTempBuffer, '\0', sizeof( xTempBuffer ) );\r
                pxNetworkBuffer = &xTempBuffer;\r
 \r
+               #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+               {\r
+                       xTempBuffer.pxNextBuffer = NULL;\r
+               }\r
+               #endif\r
                xTempBuffer.pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;\r
                xTempBuffer.xDataLength = sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket );\r
-               /* A pseudo network buffer can not be released. */\r
                xReleaseAfterSend = pdFALSE;\r
        }\r
 \r
@@ -904,8 +853,8 @@ NetworkBufferDescriptor_t xTempBuffer;
                        vFlip_32( pxTCPPacket->xTCPHeader.ulSequenceNumber, pxTCPPacket->xTCPHeader.ulAckNr );\r
                }\r
 \r
-               pxIPHeader->ucTimeToLive           = ( uint8_t ) ipconfigTCP_TIME_TO_LIVE;\r
-               pxIPHeader->usLength               = FreeRTOS_htons( ulLen );\r
+               pxIPHeader->ucTimeToLive                   = ( uint8_t ) ipconfigTCP_TIME_TO_LIVE;\r
+               pxIPHeader->usLength                       = FreeRTOS_htons( ulLen );\r
                if( ( pxSocket == NULL ) || ( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ) )\r
                {\r
                        /* When pxSocket is NULL, this function is called by prvTCPSendReset()\r
@@ -931,11 +880,11 @@ NetworkBufferDescriptor_t xTempBuffer;
                {\r
                        /* calculate the IP header checksum, in case the driver won't do that. */\r
                        pxIPHeader->usHeaderChecksum = 0x00u;\r
-                       pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0u, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );\r
+                       pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );\r
                        pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );\r
 \r
                        /* calculate the TCP checksum for an outgoing packet. */\r
-                       usGenerateProtocolChecksum( (uint8_t*)pxTCPPacket, pdTRUE );\r
+                       usGenerateProtocolChecksum( (uint8_t*)pxTCPPacket, pxNetworkBuffer->xDataLength, pdTRUE );\r
 \r
                        /* A calculated checksum of 0 must be inverted as 0 means the checksum\r
                        is disabled. */\r
@@ -946,11 +895,9 @@ NetworkBufferDescriptor_t xTempBuffer;
                }\r
                #endif\r
 \r
-               #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
-               {\r
-                       pxNetworkBuffer->pxNextBuffer = NULL;\r
-               }\r
-               #endif\r
+       #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+               pxNetworkBuffer->pxNextBuffer = NULL;\r
+       #endif\r
 \r
                /* Important: tell NIC driver how many bytes must be sent. */\r
                pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER;\r
@@ -960,7 +907,7 @@ NetworkBufferDescriptor_t xTempBuffer;
                        sizeof( pxEthernetHeader->xDestinationAddress ) );\r
 \r
                /* The source MAC addresses is fixed to 'ipLOCAL_MAC_ADDRESS'. */\r
-               memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress ), ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );\r
+               memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress, ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );\r
 \r
                #if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
                {\r
@@ -1034,6 +981,7 @@ eARPLookupResult_t eReturned;
 uint32_t ulRemoteIP;\r
 MACAddress_t xEthAddress;\r
 BaseType_t xReturn = pdTRUE;\r
+uint32_t ulInitialSequenceNumber = 0;\r
 \r
        #if( ipconfigHAS_PRINTF != 0 )\r
        {\r
@@ -1049,30 +997,44 @@ BaseType_t xReturn = pdTRUE;
 \r
        switch( eReturned )\r
        {\r
-               case eARPCacheHit:              /* An ARP table lookup found a valid entry. */\r
-                       break;                          /* We can now prepare the SYN packet. */\r
-               case eARPCacheMiss:             /* An ARP table lookup did not find a valid entry. */\r
-               case eCantSendPacket:   /* There is no IP address, or an ARP is still in progress. */\r
-               default:\r
-                       /* Count the number of times it couldn't find the ARP address. */\r
-                       pxSocket->u.xTCP.ucRepCount++;\r
-       \r
-                       FreeRTOS_debug_printf( ( "ARP for %lxip (using %lxip): rc=%d %02X:%02X:%02X %02X:%02X:%02X\n",\r
-                               pxSocket->u.xTCP.ulRemoteIP,\r
-                               FreeRTOS_htonl( ulRemoteIP ),\r
-                               eReturned,\r
-                               xEthAddress.ucBytes[ 0 ],\r
-                               xEthAddress.ucBytes[ 1 ],\r
-                               xEthAddress.ucBytes[ 2 ],\r
-                               xEthAddress.ucBytes[ 3 ],\r
-                               xEthAddress.ucBytes[ 4 ],\r
-                               xEthAddress.ucBytes[ 5 ] ) );\r
-       \r
-                       /* And issue a (new) ARP request */\r
-                       FreeRTOS_OutputARPRequest( ulRemoteIP );\r
-       \r
+       case eARPCacheHit:              /* An ARP table lookup found a valid entry. */\r
+               break;                          /* We can now prepare the SYN packet. */\r
+       case eARPCacheMiss:             /* An ARP table lookup did not find a valid entry. */\r
+       case eCantSendPacket:   /* There is no IP address, or an ARP is still in progress. */\r
+       default:\r
+               /* Count the number of times it couldn't find the ARP address. */\r
+               pxSocket->u.xTCP.ucRepCount++;\r
+\r
+               FreeRTOS_debug_printf( ( "ARP for %lxip (using %lxip): rc=%d %02X:%02X:%02X %02X:%02X:%02X\n",\r
+                       pxSocket->u.xTCP.ulRemoteIP,\r
+                       FreeRTOS_htonl( ulRemoteIP ),\r
+                       eReturned,\r
+                       xEthAddress.ucBytes[ 0 ],\r
+                       xEthAddress.ucBytes[ 1 ],\r
+                       xEthAddress.ucBytes[ 2 ],\r
+                       xEthAddress.ucBytes[ 3 ],\r
+                       xEthAddress.ucBytes[ 4 ],\r
+                       xEthAddress.ucBytes[ 5 ] ) );\r
+\r
+               /* And issue a (new) ARP request */\r
+               FreeRTOS_OutputARPRequest( ulRemoteIP );\r
+\r
+               xReturn = pdFALSE;\r
+       }\r
+\r
+       if( xReturn != pdFALSE )\r
+       {\r
+               /* Get a difficult-to-predict initial sequence number for this 4-tuple. */\r
+               ulInitialSequenceNumber = ulApplicationGetNextSequenceNumber( *ipLOCAL_IP_ADDRESS_POINTER,\r
+                                                                                                                                         pxSocket->usLocalPort,\r
+                                                                                                                                         pxSocket->u.xTCP.ulRemoteIP,\r
+                                                                                                                                         pxSocket->u.xTCP.usRemotePort );\r
+\r
+               /* Check for a random number generation error. */\r
+               if( 0 == ulInitialSequenceNumber )\r
+               {\r
                        xReturn = pdFALSE;\r
-                       break;\r
+               }\r
        }\r
 \r
        if( xReturn != pdFALSE )\r
@@ -1082,10 +1044,10 @@ BaseType_t xReturn = pdTRUE;
                pxTCPPacket = ( TCPPacket_t * )pxSocket->u.xTCP.xPacket.u.ucLastPacket;\r
                pxIPHeader = &pxTCPPacket->xIPHeader;\r
 \r
-               /* Reset the retry counter to zero... */\r
+               /* reset the retry counter to zero. */\r
                pxSocket->u.xTCP.ucRepCount = 0u;\r
 \r
-               /* ...and remember that the connect/SYN data are prepared. */\r
+               /* And remember that the connect/SYN data are prepared. */\r
                pxSocket->u.xTCP.bits.bConnPrepared = pdTRUE_UNSIGNED;\r
 \r
                /* Now that the Ethernet address is known, the initial packet can be\r
@@ -1118,11 +1080,7 @@ BaseType_t xReturn = pdTRUE;
                pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = 0ul;\r
 \r
                /* Start with ISN (Initial Sequence Number). */\r
-               pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulNextInitialSequenceNumber;\r
-\r
-               /* And increment it with 268 for the next new connection, which is\r
-               recommended value. */\r
-               ulNextInitialSequenceNumber += 0x102UL;\r
+               pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulInitialSequenceNumber;\r
 \r
                /* The TCP header size is 20 bytes, divided by 4 equals 5, which is put in\r
                the high nibble of the TCP offset field. */\r
@@ -1192,31 +1150,58 @@ UBaseType_t uxNewMSS;
        pucLast = pucPtr + (((pxTCPHeader->ucTCPOffset >> 4) - 5) << 2);\r
        pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
 \r
+       /* Validate options size calculation. */\r
+       if( pucLast > ( pxNetworkBuffer->pucEthernetBuffer + pxNetworkBuffer->xDataLength ) )\r
+       {\r
+               return;\r
+       }\r
+\r
        /* The comparison with pucLast is only necessary in case the option data are\r
        corrupted, we don't like to run into invalid memory and crash. */\r
        while( pucPtr < pucLast )\r
        {\r
+               UBaseType_t xRemainingOptionsBytes = pucLast - pucPtr;\r
+\r
                if( pucPtr[ 0 ] == TCP_OPT_END )\r
                {\r
                        /* End of options. */\r
-                       return;\r
+                       break;\r
                }\r
                if( pucPtr[ 0 ] == TCP_OPT_NOOP)\r
                {\r
+                       /* NOP option, inserted to make the length a multiple of 4. */\r
                        pucPtr++;\r
+                       continue;\r
+               }\r
 \r
-                       /* NOP option, inserted to make the length a multiple of 4. */\r
+               /* Any other well-formed option must be at least two bytes: the option\r
+               type byte followed by a length byte. */\r
+               if( xRemainingOptionsBytes < 2 )\r
+               {\r
+                       break;\r
                }\r
 #if( ipconfigUSE_TCP_WIN != 0 )\r
-               else if( ( pucPtr[ 0 ] == TCP_OPT_WSOPT ) && ( pucPtr[ 1 ] == TCP_OPT_WSOPT_LEN ) )\r
+               else if( pucPtr[ 0 ] == TCP_OPT_WSOPT )\r
                {\r
+                       /* Confirm that the option fits in the remaining buffer space. */\r
+                       if( ( xRemainingOptionsBytes < TCP_OPT_WSOPT_LEN ) || ( pucPtr[ 1 ] != TCP_OPT_WSOPT_LEN ) )\r
+                       {\r
+                               break;\r
+                       }\r
+\r
                        pxSocket->u.xTCP.ucPeerWinScaleFactor = pucPtr[ 2 ];\r
                        pxSocket->u.xTCP.bits.bWinScaling = pdTRUE_UNSIGNED;\r
                        pucPtr += TCP_OPT_WSOPT_LEN;\r
                }\r
 #endif /* ipconfigUSE_TCP_WIN */\r
-               else if( ( pucPtr[ 0 ] == TCP_OPT_MSS ) && ( pucPtr[ 1 ] == TCP_OPT_MSS_LEN ) )\r
+               else if( pucPtr[ 0 ] == TCP_OPT_MSS )\r
                {\r
+                       /* Confirm that the option fits in the remaining buffer space. */\r
+                       if( ( xRemainingOptionsBytes < TCP_OPT_MSS_LEN )|| ( pucPtr[ 1 ] != TCP_OPT_MSS_LEN ) )\r
+                       {\r
+                               break;\r
+                       }\r
+\r
                        /* An MSS option with the correct option length.  FreeRTOS_htons()\r
                        is not needed here because usChar2u16() already returns a host\r
                        endian number. */\r
@@ -1224,6 +1209,12 @@ UBaseType_t uxNewMSS;
 \r
                        if( pxSocket->u.xTCP.usInitMSS != uxNewMSS )\r
                        {\r
+                               /* Perform a basic check on the the new MSS. */\r
+                               if( uxNewMSS == 0 )\r
+                               {\r
+                                       break;\r
+                               }\r
+\r
                                FreeRTOS_debug_printf( ( "MSS change %u -> %lu\n", pxSocket->u.xTCP.usInitMSS, uxNewMSS ) );\r
                        }\r
 \r
@@ -1257,11 +1248,11 @@ UBaseType_t uxNewMSS;
                {\r
                        /* All other options have a length field, so that we easily\r
                        can skip past them. */\r
-                       int len = ( int )pucPtr[ 1 ];\r
-                       if( len == 0 )\r
+                       unsigned char len = pucPtr[ 1 ];\r
+                       if( ( len < 2 ) || ( len > xRemainingOptionsBytes ) )\r
                        {\r
-                               /* If the length field is zero, the options are malformed\r
-                               and we don't process them further. */\r
+                               /* If the length field is too small or too big, the options are malformed.\r
+                               Don't process them further. */\r
                                break;\r
                        }\r
 \r
@@ -1316,16 +1307,6 @@ UBaseType_t uxNewMSS;
                                        }\r
                                        /* len should be 0 by now. */\r
                                }\r
-                               #if     ipconfigUSE_TCP_TIMESTAMPS == 1\r
-                                       else if( pucPtr[0] == TCP_OPT_TIMESTAMP )\r
-                                       {\r
-                                               len -= 2;       /* Skip option and length byte. */\r
-                                               pucPtr += 2;\r
-                                               pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps = pdTRUE_UNSIGNED;\r
-                                               pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp = ulChar2u32( pucPtr );\r
-                                               pxSocket->u.xTCP.xTCPWindow.tx.ulTimeStamp = ulChar2u32( pucPtr + 4 );\r
-                                       }\r
-                               #endif  /* ipconfigUSE_TCP_TIMESTAMPS == 1 */\r
                        }\r
                        #endif  /* ipconfigUSE_TCP_WIN == 1 */\r
 \r
@@ -1403,23 +1384,12 @@ UBaseType_t uxOptionsLength;
        }\r
        #else\r
        {\r
-               #if( ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
-                       if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )\r
-                       {\r
-                               uxOptionsLength += prvTCPSetTimeStamp( uxOptionsLength, pxSocket, &pxTCPPacket->xTCPHeader );\r
-                               pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */\r
-                               pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = 2u;\r
-                               uxOptionsLength += 2u;\r
-                       }\r
-                       else\r
-               #endif\r
-               {\r
-                       pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_NOOP;\r
-                       pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = TCP_OPT_NOOP;\r
-                       pxTCPHeader->ucOptdata[ uxOptionsLength + 2 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */\r
-                       pxTCPHeader->ucOptdata[ uxOptionsLength + 3 ] = 2;      /* 2: length of this option. */\r
-                       uxOptionsLength += 4u;\r
-               }\r
+               pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_NOOP;\r
+               pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = TCP_OPT_NOOP;\r
+               pxTCPHeader->ucOptdata[ uxOptionsLength + 2 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */\r
+               pxTCPHeader->ucOptdata[ uxOptionsLength + 3 ] = 2;      /* 2: length of this option. */\r
+               uxOptionsLength += 4u;\r
+\r
                return uxOptionsLength; /* bytes, not words. */\r
        }\r
        #endif  /* ipconfigUSE_TCP_WIN == 0 */\r
@@ -1598,7 +1568,7 @@ BaseType_t bAfter  = ( BaseType_t ) NOW_CONNECTED( eTCPState );                                           /* Is it co
        /* Fill in the new state. */\r
        pxSocket->u.xTCP.ucTCPState = ( uint8_t ) eTCPState;\r
 \r
-       /* Touch the alive timers because moving to another state. */\r
+       /* touch the alive timers because moving to another state. */\r
        prvTCPTouchSocket( pxSocket );\r
 \r
        #if( ipconfigHAS_DEBUG_PRINTF == 1 )\r
@@ -1653,14 +1623,7 @@ BaseType_t xResize;
                        ( int32_t ) ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength ) + lDataLen );\r
                /* In case we were called from a TCP timer event, a buffer must be\r
                created.  Otherwise, test 'xDataLength' of the provided buffer. */\r
-               if( ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->xDataLength < (size_t)lNeeded ) )\r
-               {\r
-                       xResize = pdTRUE;\r
-               }\r
-               else\r
-               {\r
-                       xResize = pdFALSE;\r
-               }\r
+               xResize = ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->xDataLength < (size_t)lNeeded );\r
        }\r
 \r
        if( xResize != pdFALSE )\r
@@ -1672,6 +1635,9 @@ BaseType_t xResize;
 \r
                if( pxReturn != NULL )\r
                {\r
+                       /* Set the actual packet size, in case the returned buffer is larger. */\r
+                       pxReturn->xDataLength = lNeeded;\r
+\r
                        /* Copy the existing data to the new created buffer. */\r
                        if( pxNetworkBuffer )\r
                        {\r
@@ -1727,8 +1693,8 @@ int32_t lStreamPos;
                pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;\r
        }\r
 \r
-       pxTCPPacket = ( TCPPacket_t * ) pucEthernetBuffer;\r
-       pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );\r
+       pxTCPPacket = ( TCPPacket_t * ) ( pucEthernetBuffer );\r
+       pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
        lDataLen = 0;\r
        lStreamPos = 0;\r
        pxTCPPacket->xTCPHeader.ucTCPFlags |= ipTCP_FLAG_ACK;\r
@@ -1880,19 +1846,6 @@ int32_t lStreamPos;
                        pxTCPPacket->xTCPHeader.ucTCPFlags |= ( uint8_t ) ipTCP_FLAG_PSH;\r
                }\r
 \r
-               #if     ipconfigUSE_TCP_TIMESTAMPS == 1\r
-               {\r
-                       if( uxOptionsLength == 0u )\r
-                       {\r
-                               if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )\r
-                               {\r
-                                       TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pucEthernetBuffer );\r
-                                       uxOptionsLength = prvTCPSetTimeStamp( 0, pxSocket, &pxTCPPacket->xTCPHeader );\r
-                               }\r
-                       }\r
-               }\r
-               #endif\r
-\r
                lDataLen += ( int32_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );\r
        }\r
 \r
@@ -1973,9 +1926,9 @@ int32_t lCount, lLength;
        /* A txStream has been created already, see if the socket has new data for\r
        the sliding window.\r
 \r
-       uxStreamBufferMidSpace() returns the distance between rxHead and rxMid.  It\r
-       contains new Tx data which has not been passed to the sliding window yet.\r
-       The oldest data not-yet-confirmed can be found at rxTail. */\r
+       uxStreamBufferMidSpace() returns the distance between rxHead and rxMid.  It contains new\r
+       Tx data which has not been passed to the sliding window yet.  The oldest\r
+       data not-yet-confirmed can be found at rxTail. */\r
        lLength = ( int32_t ) uxStreamBufferMidSpace( pxSocket->u.xTCP.txStream );\r
 \r
        if( lLength > 0 )\r
@@ -2096,29 +2049,6 @@ uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-#if    ipconfigUSE_TCP_TIMESTAMPS == 1\r
-\r
-       static UBaseType_t prvTCPSetTimeStamp( BaseType_t lOffset, FreeRTOS_Socket_t *pxSocket, TCPHeader_t *pxTCPHeader )\r
-       {\r
-       uint32_t ulTimes[2];\r
-       uint8_t *ucOptdata = &( pxTCPHeader->ucOptdata[ lOffset ] );\r
-\r
-               ulTimes[0]   = ( xTaskGetTickCount ( ) * 1000u ) / configTICK_RATE_HZ;\r
-               ulTimes[0]   = FreeRTOS_htonl( ulTimes[0] );\r
-               ulTimes[1]   = FreeRTOS_htonl( pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp );\r
-               ucOptdata[0] = ( uint8_t ) TCP_OPT_TIMESTAMP;\r
-               ucOptdata[1] = ( uint8_t ) TCP_OPT_TIMESTAMP_LEN;\r
-               memcpy( &(ucOptdata[2] ), ulTimes, 8u );\r
-               ucOptdata[10] = ( uint8_t ) TCP_OPT_NOOP;\r
-               ucOptdata[11] = ( uint8_t ) TCP_OPT_NOOP;\r
-               /* Do not return the same timestamps 2 times. */\r
-               pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp = 0ul;\r
-               return 12u;\r
-       }\r
-\r
-#endif\r
-/*-----------------------------------------------------------*/\r
-\r
 /*\r
  * prvCheckRxData(): called from prvTCPHandleState()\r
  *\r
@@ -2137,7 +2067,7 @@ int32_t lLength, lTCPHeaderLength, lReceiveLength, lUrgentLength;
        The size of the TCP header is given in a multiple of 4-byte words (single\r
        byte, needs no ntoh() translation).  A shift-right 2: is the same as\r
        (offset >> 4) * 4. */\r
-    lTCPHeaderLength = ( BaseType_t ) ( ( pxTCPHeader->ucTCPOffset & VALID_BITS_IN_TCP_OFFSET_BYTE ) >> 2 );\r
+       lTCPHeaderLength = ( BaseType_t ) ( ( pxTCPHeader->ucTCPOffset & VALID_BITS_IN_TCP_OFFSET_BYTE ) >> 2 );\r
 \r
        /* Let pucRecvData point to the first byte received. */\r
        *ppucRecvData = pxNetworkBuffer->pucEthernetBuffer + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + lTCPHeaderLength;\r
@@ -2311,15 +2241,6 @@ UBaseType_t uxOptionsLength = pxTCPWindow->ucOptionLength;
                pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
        }\r
 \r
-       #if(    ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
-       {\r
-               if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )\r
-               {\r
-                       uxOptionsLength += prvTCPSetTimeStamp( uxOptionsLength, pxSocket, pxTCPHeader );\r
-               }\r
-       }\r
-       #endif  /* ipconfigUSE_TCP_TIMESTAMPS == 1 */\r
-\r
        return uxOptionsLength;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -2511,7 +2432,7 @@ int32_t lDistance, lSendResult;
                {\r
                        /* xTCPWindowTxDone returns true when all Tx queues are empty. */\r
                        bRxComplete = xTCPWindowRxEmpty( pxTCPWindow );\r
-                       bTxDone     = xTCPWindowTxDone( pxTCPWindow );\r
+                       bTxDone  = xTCPWindowTxDone( pxTCPWindow );\r
 \r
                        if( ( bRxComplete == 0 ) || ( bTxDone == 0 ) )\r
                        {\r
@@ -2973,16 +2894,30 @@ BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer
 {\r
 FreeRTOS_Socket_t *pxSocket;\r
 TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
-uint16_t ucTCPFlags = pxTCPPacket->xTCPHeader.ucTCPFlags;\r
-uint32_t ulLocalIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulDestinationIPAddress );\r
-uint16_t xLocalPort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usDestinationPort );\r
-uint32_t ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );\r
-uint16_t xRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );\r
+uint16_t ucTCPFlags;\r
+uint32_t ulLocalIP;\r
+uint16_t xLocalPort;\r
+uint32_t ulRemoteIP;\r
+uint16_t xRemotePort;\r
 BaseType_t xResult = pdPASS;\r
 \r
-       /* Find the destination socket, and if not found: return a socket listing to\r
-       the destination PORT. */\r
-       pxSocket = ( FreeRTOS_Socket_t * ) pxTCPSocketLookup( ulLocalIP, xLocalPort, ulRemoteIP, xRemotePort );\r
+       /* Check for a minimum packet size. */\r
+       if( pxNetworkBuffer->xDataLength >= ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) )\r
+       {\r
+               ucTCPFlags = pxTCPPacket->xTCPHeader.ucTCPFlags;\r
+               ulLocalIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulDestinationIPAddress );\r
+               xLocalPort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usDestinationPort );\r
+               ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );\r
+               xRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );\r
+\r
+               /* Find the destination socket, and if not found: return a socket listing to\r
+               the destination PORT. */\r
+               pxSocket = ( FreeRTOS_Socket_t * )pxTCPSocketLookup( ulLocalIP, xLocalPort, ulRemoteIP, xRemotePort );\r
+       }\r
+       else\r
+       {\r
+               return pdFAIL;\r
+       }\r
 \r
        if( ( pxSocket == NULL ) || ( prvTCPSocketIsActive( ( UBaseType_t ) pxSocket->u.xTCP.ucTCPState ) == pdFALSE ) )\r
        {\r
@@ -3143,59 +3078,70 @@ BaseType_t xResult = pdPASS;
 static FreeRTOS_Socket_t *prvHandleListen( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )\r
 {\r
 TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
-FreeRTOS_Socket_t *pxReturn;\r
+FreeRTOS_Socket_t *pxReturn = NULL;\r
+uint32_t ulInitialSequenceNumber;\r
+\r
+       /* Assume that a new Initial Sequence Number will be required. Request\r
+       it now in order to fail out if necessary. */\r
+       ulInitialSequenceNumber = ulApplicationGetNextSequenceNumber( *ipLOCAL_IP_ADDRESS_POINTER,\r
+                                                                                                                                 pxSocket->usLocalPort,\r
+                                                                                                                                 pxTCPPacket->xIPHeader.ulSourceIPAddress,\r
+                                                                                                                                 pxTCPPacket->xTCPHeader.usSourcePort );\r
 \r
        /* A pure SYN (without ACK) has come in, create a new socket to answer\r
        it. */\r
-       if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )\r
-       {\r
-               /* The flag bReuseSocket indicates that the same instance of the\r
-               listening socket should be used for the connection. */\r
-               pxReturn = pxSocket;\r
-               pxSocket->u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED;\r
-               pxSocket->u.xTCP.pxPeerSocket = pxSocket;\r
-       }\r
-       else\r
+       if( 0 != ulInitialSequenceNumber )\r
        {\r
-               /* The socket does not have the bReuseSocket flag set meaning create a\r
-               new socket when a connection comes in. */\r
-               pxReturn = NULL;\r
-\r
-               if( pxSocket->u.xTCP.usChildCount >= pxSocket->u.xTCP.usBacklog )\r
+               if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )\r
                {\r
-                       FreeRTOS_printf( ( "Check: Socket %u already has %u / %u child%s\n",\r
-                               pxSocket->usLocalPort,\r
-                               pxSocket->u.xTCP.usChildCount,\r
-                               pxSocket->u.xTCP.usBacklog,\r
-                               pxSocket->u.xTCP.usChildCount == 1 ? "" : "ren" ) );\r
-                       prvTCPSendReset( pxNetworkBuffer );\r
+                       /* The flag bReuseSocket indicates that the same instance of the\r
+                       listening socket should be used for the connection. */\r
+                       pxReturn = pxSocket;\r
+                       pxSocket->u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED;\r
+                       pxSocket->u.xTCP.pxPeerSocket = pxSocket;\r
                }\r
                else\r
                {\r
-                       FreeRTOS_Socket_t *pxNewSocket = (FreeRTOS_Socket_t *)\r
-                               FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );\r
+                       /* The socket does not have the bReuseSocket flag set meaning create a\r
+                       new socket when a connection comes in. */\r
+                       pxReturn = NULL;\r
 \r
-                       if( ( pxNewSocket == NULL ) || ( pxNewSocket == FREERTOS_INVALID_SOCKET ) )\r
+                       if( pxSocket->u.xTCP.usChildCount >= pxSocket->u.xTCP.usBacklog )\r
                        {\r
-                               FreeRTOS_debug_printf( ( "TCP: Listen: new socket failed\n" ) );\r
+                               FreeRTOS_printf( ( "Check: Socket %u already has %u / %u child%s\n",\r
+                                       pxSocket->usLocalPort,\r
+                                       pxSocket->u.xTCP.usChildCount,\r
+                                       pxSocket->u.xTCP.usBacklog,\r
+                                       pxSocket->u.xTCP.usChildCount == 1 ? "" : "ren" ) );\r
                                prvTCPSendReset( pxNetworkBuffer );\r
                        }\r
-                       else if( prvTCPSocketCopy( pxNewSocket, pxSocket ) != pdFALSE )\r
+                       else\r
                        {\r
-                               /* The socket will be connected immediately, no time for the\r
-                               owner to setsockopt's, therefore copy properties of the server\r
-                               socket to the new socket.  Only the binding might fail (due to\r
-                               lack of resources). */\r
-                               pxReturn = pxNewSocket;\r
+                               FreeRTOS_Socket_t *pxNewSocket = ( FreeRTOS_Socket_t * )\r
+                                       FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );\r
+\r
+                               if( ( pxNewSocket == NULL ) || ( pxNewSocket == FREERTOS_INVALID_SOCKET ) )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "TCP: Listen: new socket failed\n" ) );\r
+                                       prvTCPSendReset( pxNetworkBuffer );\r
+                               }\r
+                               else if( prvTCPSocketCopy( pxNewSocket, pxSocket ) != pdFALSE )\r
+                               {\r
+                                       /* The socket will be connected immediately, no time for the\r
+                                       owner to setsockopt's, therefore copy properties of the server\r
+                                       socket to the new socket.  Only the binding might fail (due to\r
+                                       lack of resources). */\r
+                                       pxReturn = pxNewSocket;\r
+                               }\r
                        }\r
                }\r
        }\r
 \r
-       if( pxReturn != NULL )\r
+       if( ( 0 != ulInitialSequenceNumber ) && ( pxReturn != NULL ) )\r
        {\r
                pxReturn->u.xTCP.usRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );\r
                pxReturn->u.xTCP.ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );\r
-               pxReturn->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulNextInitialSequenceNumber;\r
+               pxReturn->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulInitialSequenceNumber;\r
 \r
                /* Here is the SYN action. */\r
                pxReturn->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber );\r
@@ -3203,9 +3149,6 @@ FreeRTOS_Socket_t *pxReturn;
 \r
                prvTCPCreateWindow( pxReturn );\r
 \r
-               /* It is recommended to increase the ISS for each new connection with a value of 0x102. */\r
-               ulNextInitialSequenceNumber += INITIAL_SEQUENCE_NUMBER_INCREMENT;\r
-\r
                vTCPStateChange( pxReturn, eSYN_FIRST );\r
 \r
                /* Make a copy of the header up to the TCP header.  It is needed later\r
@@ -3280,7 +3223,7 @@ struct freertos_sockaddr xAddress;
                /* A reference to the new socket may be stored and the socket is marked\r
                as 'passable'. */\r
 \r
-               /* When bPassAccept is true, this socket may be returned in a call to\r
+               /* When bPassAccept is pdTRUE_UNSIGNED this socket may be returned in a call to\r
                accept(). */\r
                pxNewSocket->u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED;\r
                if(pxSocket->u.xTCP.pxPeerSocket == NULL )\r
@@ -3359,3 +3302,8 @@ BaseType_t xResult = pdFALSE;
 \r
 #endif /* ipconfigUSE_TCP == 1 */\r
 \r
+/* Provide access to private members for testing. */\r
+#ifdef AMAZON_FREERTOS_ENABLE_UNIT_TESTS\r
+       #include "aws_freertos_tcp_test_access_tcp_define.h"\r
+#endif\r
+\r