/*\r
- * FreeRTOS+TCP V2.0.0\r
+ * FreeRTOS+TCP V2.0.11\r
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
*\r
* Permission is hereby granted, free of charge, to any person obtaining a copy of\r
* subject to the following conditions:\r
*\r
* The above copyright notice and this permission notice shall be included in all\r
- * copies or substantial portions of the Software. If you wish to use our Amazon\r
- * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
+ * copies or substantial portions of the Software.\r
*\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
* 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://www.FreeRTOS.org\r
* http://aws.amazon.com/freertos\r
- *\r
- * 1 tab == 4 spaces!\r
+ * http://www.FreeRTOS.org\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