/*\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
/* Standard includes. */\r
#endif\r
\r
/* Codes of interest found in the DHCP options field. */\r
-#define dhcpIPv4_ZERO_PAD_OPTION_CODE ( 0u )\r
-#define dhcpIPv4_SUBNET_MASK_OPTION_CODE ( 1u )\r
-#define dhcpIPv4_GATEWAY_OPTION_CODE ( 3u )\r
-#define dhcpIPv4_DNS_SERVER_OPTIONS_CODE ( 6u )\r
-#define dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE ( 12u )\r
-#define dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE ( 50u )\r
-#define dhcpIPv4_LEASE_TIME_OPTION_CODE ( 51u )\r
-#define dhcpIPv4_MESSAGE_TYPE_OPTION_CODE ( 53u )\r
-#define dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE ( 54u )\r
-#define dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE ( 55u )\r
-#define dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE ( 61u )\r
+#define dhcpZERO_PAD_OPTION_CODE ( 0u )\r
+#define dhcpSUBNET_MASK_OPTION_CODE ( 1u )\r
+#define dhcpGATEWAY_OPTION_CODE ( 3u )\r
+#define dhcpDNS_SERVER_OPTIONS_CODE ( 6u )\r
+#define dhcpDNS_HOSTNAME_OPTIONS_CODE ( 12u )\r
+#define dhcpREQUEST_IP_ADDRESS_OPTION_CODE ( 50u )\r
+#define dhcpLEASE_TIME_OPTION_CODE ( 51u )\r
+#define dhcpMESSAGE_TYPE_OPTION_CODE ( 53u )\r
+#define dhcpSERVER_IP_ADDRESS_OPTION_CODE ( 54u )\r
+#define dhcpPARAMETER_REQUEST_OPTION_CODE ( 55u )\r
+#define dhcpCLIENT_IDENTIFIER_OPTION_CODE ( 61u )\r
\r
/* The four DHCP message types of interest. */\r
#define dhcpMESSAGE_TYPE_DISCOVER ( 1 )\r
made up of the length byte, and minimum one byte value. */\r
#define dhcpMAX_OPTION_LENGTH_OF_INTEREST ( 2L )\r
\r
-/* Standard DHCP port numbers and magic cookie value.\r
-DHCPv4 uses UDP port number 68 for clients and port number 67 for servers.\r
-*/\r
+/* Standard DHCP port numbers and magic cookie value. */\r
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )\r
#define dhcpCLIENT_PORT 0x4400u\r
#define dhcpSERVER_PORT 0x4300u\r
\r
if( xDHCPData.xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )\r
{\r
- xDHCPData.ulTransactionId++;\r
- xDHCPData.xDHCPTxTime = xTaskGetTickCount();\r
- xDHCPData.xUseBroadcast = !xDHCPData.xUseBroadcast;\r
- prvSendDHCPDiscover( );\r
- FreeRTOS_debug_printf( ( "vDHCPProcess: timeout %lu ticks\n", xDHCPData.xDHCPTxPeriod ) );\r
+ xDHCPData.ulTransactionId = ipconfigRAND32( );\r
+\r
+ if( 0 != xDHCPData.ulTransactionId )\r
+ {\r
+ xDHCPData.xDHCPTxTime = xTaskGetTickCount( );\r
+ xDHCPData.xUseBroadcast = !xDHCPData.xUseBroadcast;\r
+ prvSendDHCPDiscover( );\r
+ FreeRTOS_debug_printf( ( "vDHCPProcess: timeout %lu ticks\n", xDHCPData.xDHCPTxPeriod ) );\r
+ }\r
+ else\r
+ {\r
+ FreeRTOS_debug_printf( ( "vDHCPProcess: failed to generate a random Transaction ID\n" ) );\r
+ }\r
}\r
else\r
{\r
{\r
/* xGivingUp became true either because of a time-out, or because\r
xApplicationDHCPHook() returned another value than 'eDHCPContinue',\r
- meaning that the conversion is cancelled from here. */\r
+ meaning that the conversion is canceled from here. */\r
\r
/* Revert to static IP address. */\r
taskENTER_CRITICAL();\r
\r
static void prvInitialiseDHCP( void )\r
{\r
- /* Initialise the parameters that will be set by the DHCP process. */\r
- if( xDHCPData.ulTransactionId == 0ul )\r
- {\r
- xDHCPData.ulTransactionId = ipconfigRAND32();\r
- }\r
- else\r
+ /* Initialise the parameters that will be set by the DHCP process. Per\r
+ https://www.ietf.org/rfc/rfc2131.txt, Transaction ID should be a random\r
+ value chosen by the client. */\r
+ xDHCPData.ulTransactionId = ipconfigRAND32();\r
+\r
+ /* Check for random number generator API failure. */\r
+ if( 0 != xDHCPData.ulTransactionId )\r
{\r
- xDHCPData.ulTransactionId++;\r
+ xDHCPData.xUseBroadcast = 0;\r
+ xDHCPData.ulOfferedIPAddress = 0UL;\r
+ xDHCPData.ulDHCPServerAddress = 0UL;\r
+ xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;\r
+\r
+ /* Create the DHCP socket if it has not already been created. */\r
+ prvCreateDHCPSocket();\r
+ FreeRTOS_debug_printf( ( "prvInitialiseDHCP: start after %lu ticks\n", dhcpINITIAL_TIMER_PERIOD ) );\r
+ vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );\r
}\r
-\r
- xDHCPData.xUseBroadcast = 0;\r
- xDHCPData.ulOfferedIPAddress = 0UL;\r
- xDHCPData.ulDHCPServerAddress = 0UL;\r
- xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;\r
-\r
- /* Create the DHCP socket if it has not already been created. */\r
- prvCreateDHCPSocket();\r
- FreeRTOS_debug_printf( ( "prvInitialiseDHCP: start after %lu ticks\n", dhcpINITIAL_TIMER_PERIOD ) );\r
- vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );\r
}\r
/*-----------------------------------------------------------*/\r
\r
pxDHCPMessage = ( DHCPMessage_t * ) ( pucUDPPayload );\r
\r
/* Sanity check. */\r
- if( ( pxDHCPMessage->ulDHCPCookie == ( uint32_t ) dhcpCOOKIE ) &&\r
+ if( ( lBytes >= sizeof( DHCPMessage_t ) ) &&\r
+ ( pxDHCPMessage->ulDHCPCookie == ( uint32_t ) dhcpCOOKIE ) &&\r
( pxDHCPMessage->ucOpcode == ( uint8_t ) dhcpREPLY_OPCODE ) &&\r
( pxDHCPMessage->ulTransactionID == FreeRTOS_htonl( xDHCPData.ulTransactionId ) ) )\r
{\r
- if( memcmp( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress ), ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ) == 0 )\r
+ if( memcmp( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress ),\r
+ ( void * ) ipLOCAL_MAC_ADDRESS,\r
+ sizeof( MACAddress_t ) ) == 0 )\r
{\r
/* None of the essential options have been processed yet. */\r
ulProcessed = 0ul;\r
while( pucByte < pucLastByte )\r
{\r
ucOptionCode = pucByte[ 0 ];\r
- if( ucOptionCode == ( uint8_t ) dhcpOPTION_END_BYTE )\r
+ if( ucOptionCode == dhcpOPTION_END_BYTE )\r
{\r
/* Ready, the last byte has been seen. */\r
break;\r
}\r
- if( ucOptionCode == ( uint8_t ) dhcpIPv4_ZERO_PAD_OPTION_CODE )\r
+ if( ucOptionCode == dhcpZERO_PAD_OPTION_CODE )\r
{\r
/* The value zero is used as a pad byte,\r
it is not followed by a length byte. */\r
pucByte += 1;\r
continue;\r
}\r
- ucLength = pucByte[ 1 ];\r
- pucByte += 2;\r
+\r
+ /* Stop if the response is malformed. */\r
+ if( pucByte < pucLastByte - 1 )\r
+ {\r
+ ucLength = pucByte[ 1 ];\r
+ pucByte += 2;\r
+\r
+ if( pucByte >= pucLastByte - ucLength )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ break;\r
+ }\r
\r
/* In most cases, a 4-byte network-endian parameter follows,\r
- just get it once here and use later */\r
- memcpy( ( void * ) &( ulParameter ), ( void * ) pucByte, ( size_t ) sizeof( ulParameter ) );\r
+ just get it once here and use later. */\r
+ if( ucLength >= sizeof( ulParameter ) )\r
+ {\r
+ memcpy( ( void * ) &( ulParameter ),\r
+ ( void * ) pucByte,\r
+ ( size_t ) sizeof( ulParameter ) );\r
+ }\r
+ else\r
+ {\r
+ ulParameter = 0;\r
+ }\r
\r
+ /* Option-specific handling. */\r
switch( ucOptionCode )\r
{\r
- case dhcpIPv4_MESSAGE_TYPE_OPTION_CODE :\r
+ case dhcpMESSAGE_TYPE_OPTION_CODE :\r
\r
if( *pucByte == ( uint8_t ) xExpectedMessageType )\r
{\r
state machine is expecting. */\r
ulProcessed++;\r
}\r
- else\r
+ else if( *pucByte == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )\r
{\r
- if( *pucByte == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )\r
+ if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_ACK )\r
{\r
- if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_ACK )\r
- {\r
- /* Start again. */\r
- xDHCPData.eDHCPState = eWaitingSendFirstDiscover;\r
- }\r
+ /* Start again. */\r
+ xDHCPData.eDHCPState = eWaitingSendFirstDiscover;\r
}\r
- /* Stop processing further options. */\r
- ucLength = 0;\r
+ }\r
+ else\r
+ {\r
+ /* Don't process other message types. */\r
}\r
break;\r
\r
- case dhcpIPv4_SUBNET_MASK_OPTION_CODE :\r
+ case dhcpSUBNET_MASK_OPTION_CODE :\r
\r
if( ucLength == sizeof( uint32_t ) )\r
{\r
}\r
break;\r
\r
- case dhcpIPv4_GATEWAY_OPTION_CODE :\r
- /* The DHCP server may send more than 1 gateway addresses. */\r
- if( ucLength >= sizeof( uint32_t ) )\r
+ case dhcpGATEWAY_OPTION_CODE :\r
+\r
+ if( ucLength == sizeof( uint32_t ) )\r
{\r
/* ulProcessed is not incremented in this case\r
because the gateway is not essential. */\r
}\r
break;\r
\r
- case dhcpIPv4_DNS_SERVER_OPTIONS_CODE :\r
+ case dhcpDNS_SERVER_OPTIONS_CODE :\r
\r
/* ulProcessed is not incremented in this case\r
because the DNS server is not essential. Only the\r
xNetworkAddressing.ulDNSServerAddress = ulParameter;\r
break;\r
\r
- case dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE :\r
+ case dhcpSERVER_IP_ADDRESS_OPTION_CODE :\r
\r
if( ucLength == sizeof( uint32_t ) )\r
{\r
}\r
break;\r
\r
- case dhcpIPv4_LEASE_TIME_OPTION_CODE :\r
+ case dhcpLEASE_TIME_OPTION_CODE :\r
\r
if( ucLength == sizeof( xDHCPData.ulLeaseTime ) )\r
{\r
}\r
\r
FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayload );\r
- } /* if( lBytes > 0 ) */\r
+ }\r
\r
return xReturn;\r
}\r
pxDHCPMessage->ucOpcode = ( uint8_t ) xOpcode;\r
pxDHCPMessage->ucAddressType = ( uint8_t ) dhcpADDRESS_TYPE_ETHERNET;\r
pxDHCPMessage->ucAddressLength = ( uint8_t ) dhcpETHERNET_ADDRESS_LENGTH;\r
-\r
- /* ulTransactionID doesn't really need a htonl() translation, but when DHCP\r
- times out, it is nicer to see an increasing number in this ID field */\r
pxDHCPMessage->ulTransactionID = FreeRTOS_htonl( xDHCPData.ulTransactionId );\r
pxDHCPMessage->ulDHCPCookie = ( uint32_t ) dhcpCOOKIE;\r
if( xDHCPData.xUseBroadcast != pdFALSE )\r
\r
/* Point to where the OPTION_END was stored to add data. */\r
pucPtr = &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + ( *pxOptionsArraySize - 1 ) ] );\r
- pucPtr[ 0 ] = dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE;\r
+ pucPtr[ 0 ] = dhcpDNS_HOSTNAME_OPTIONS_CODE;\r
pucPtr[ 1 ] = ( uint8_t ) xNameLength;\r
memcpy( ( void *) ( pucPtr + 2 ), pucHostName, xNameLength );\r
pucPtr[ 2 + xNameLength ] = dhcpOPTION_END_BYTE;\r
/* Do not change the ordering without also changing\r
dhcpCLIENT_IDENTIFIER_OFFSET, dhcpREQUESTED_IP_ADDRESS_OFFSET and\r
dhcpDHCP_SERVER_IP_ADDRESS_OFFSET. */\r
- dhcpIPv4_MESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_REQUEST, /* Message type option. */\r
- dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0, /* Client identifier. */\r
- dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address being requested. */\r
- dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address of the DHCP server. */\r
+ dhcpMESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_REQUEST, /* Message type option. */\r
+ dhcpCLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0, /* Client identifier. */\r
+ dhcpREQUEST_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address being requested. */\r
+ dhcpSERVER_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address of the DHCP server. */\r
dhcpOPTION_END_BYTE\r
};\r
size_t xOptionsLength = sizeof( ucDHCPRequestOptions );\r
\r
- pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, ( uint8_t ) dhcpREQUEST_OPCODE, ucDHCPRequestOptions, &xOptionsLength );\r
+ pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, dhcpREQUEST_OPCODE, ucDHCPRequestOptions, &xOptionsLength );\r
\r
/* Copy in the IP address being requested. */\r
memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpREQUESTED_IP_ADDRESS_OFFSET ] ),\r
static const uint8_t ucDHCPDiscoverOptions[] =\r
{\r
/* Do not change the ordering without also changing dhcpCLIENT_IDENTIFIER_OFFSET. */\r
- dhcpIPv4_MESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_DISCOVER, /* Message type option. */\r
- dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0, /* Client identifier. */\r
- dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE, 3, dhcpIPv4_SUBNET_MASK_OPTION_CODE, dhcpIPv4_GATEWAY_OPTION_CODE, dhcpIPv4_DNS_SERVER_OPTIONS_CODE, /* Parameter request option. */\r
+ dhcpMESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_DISCOVER, /* Message type option. */\r
+ dhcpCLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0, /* Client identifier. */\r
+ dhcpPARAMETER_REQUEST_OPTION_CODE, 3, dhcpSUBNET_MASK_OPTION_CODE, dhcpGATEWAY_OPTION_CODE, dhcpDNS_SERVER_OPTIONS_CODE, /* Parameter request option. */\r
dhcpOPTION_END_BYTE\r
};\r
size_t xOptionsLength = sizeof( ucDHCPDiscoverOptions );\r
\r
- pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, ( uint8_t ) dhcpREQUEST_OPCODE, ucDHCPDiscoverOptions, &xOptionsLength );\r
+ pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, dhcpREQUEST_OPCODE, ucDHCPDiscoverOptions, &xOptionsLength );\r
\r
FreeRTOS_debug_printf( ( "vDHCPProcess: discover\n" ) );\r
iptraceSENDING_DHCP_DISCOVER();\r