xref: /FreeRTOS-Plus-TCP-v3.1.0/source/include/FreeRTOS_DHCP.h (revision 37bdfe577f3b728058de714e2e747d3c78803f26)
1 /*
2  * FreeRTOS+TCP V3.1.0
3  * Copyright (C) 2022 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * http://aws.amazon.com/freertos
25  * http://www.FreeRTOS.org
26  */
27 
28 #ifndef FREERTOS_DHCP_H
29 #define FREERTOS_DHCP_H
30 
31 /* *INDENT-OFF* */
32 #ifdef __cplusplus
33     extern "C" {
34 #endif
35 /* *INDENT-ON* */
36 
37 /* Application level configuration options. */
38 #include "FreeRTOSIPConfig.h"
39 #include "IPTraceMacroDefaults.h"
40 
41 #include "FreeRTOS_Sockets.h"
42 
43 
44 #if ( ipconfigUSE_DHCP != 0 ) && ( ipconfigNETWORK_MTU < 586U )
45 
46 /* DHCP must be able to receive an options field of 312 bytes, the fixed
47  * part of the DHCP packet is 240 bytes, and the IP/UDP headers take 28 bytes. */
48     #error ipconfigNETWORK_MTU needs to be at least 586 to use DHCP
49 #endif
50 
51 /* Parameter widths in the DHCP packet. */
52 #define dhcpCLIENT_HARDWARE_ADDRESS_LENGTH    16      /**< Client hardware address length.*/
53 #define dhcpSERVER_HOST_NAME_LENGTH           64      /**< Server host name length. */
54 #define dhcpBOOT_FILE_NAME_LENGTH             128     /**< Boot file name length. */
55 
56 /* Timer parameters */
57 #ifndef dhcpINITIAL_TIMER_PERIOD
58     /** @brief The interval at which the DHCP state handler is called. */
59     #define dhcpINITIAL_TIMER_PERIOD    ( pdMS_TO_TICKS( 250U ) )
60 #endif
61 
62 #ifndef dhcpINITIAL_DHCP_TX_PERIOD
63 
64 /** @brief The initial amount of time to wait for a DHCP reply.  When repeating an
65  * unanswered request, this time-out shall be multiplied by 2. */
66     #define dhcpINITIAL_DHCP_TX_PERIOD    ( pdMS_TO_TICKS( 5000U ) )
67 #endif
68 
69 /* Codes of interest found in the DHCP options field. */
70 #define dhcpIPv4_ZERO_PAD_OPTION_CODE              ( 0U )      /**< Used to pad other options to make them aligned. See RFC 2132. */
71 #define dhcpIPv4_SUBNET_MASK_OPTION_CODE           ( 1U )      /**< Subnet mask. See RFC 2132. */
72 #define dhcpIPv4_GATEWAY_OPTION_CODE               ( 3U )      /**< Available routers. See RFC 2132. */
73 #define dhcpIPv4_DNS_SERVER_OPTIONS_CODE           ( 6U )      /**< Domain name server. See RFC 2132. */
74 #define dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE         ( 12U )     /**< Host name. See RFC 2132. */
75 #define dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE    ( 50U )     /**< Requested IP-address. See RFC 2132. */
76 #define dhcpIPv4_LEASE_TIME_OPTION_CODE            ( 51U )     /**< IP-address lease time. See RFC 2132. */
77 #define dhcpIPv4_MESSAGE_TYPE_OPTION_CODE          ( 53U )     /**< DHCP message type. See RFC 2132. */
78 #define dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE     ( 54U )     /**< Server Identifier. See RFC 2132. */
79 #define dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE     ( 55U )     /**< Parameter Request list. See RFC 2132. */
80 #define dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE     ( 61U )     /**<  Client Identifier. See RFC 2132. */
81 
82 /* The four DHCP message types of interest. */
83 #define dhcpMESSAGE_TYPE_DISCOVER                  ( 1 )     /**< DHCP discover message. */
84 #define dhcpMESSAGE_TYPE_OFFER                     ( 2 )     /**< DHCP offer message. */
85 #define dhcpMESSAGE_TYPE_REQUEST                   ( 3 )     /**< DHCP request message. */
86 #define dhcpMESSAGE_TYPE_ACK                       ( 5 )     /**< DHCP acknowledgement. */
87 #define dhcpMESSAGE_TYPE_NACK                      ( 6 )     /**< DHCP NACK. (Negative acknowledgement) */
88 
89 /* Offsets into the transmitted DHCP options fields at which various parameters
90  * are located. */
91 #define dhcpCLIENT_IDENTIFIER_OFFSET               ( 6U )      /**< Offset for the client ID option. */
92 #define dhcpREQUESTED_IP_ADDRESS_OFFSET            ( 14U )     /**< Offset for the requested IP-address option. */
93 #define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET          ( 20U )     /**< Offset for the server IP-address option. */
94 #define dhcpOPTION_50_OFFSET                       ( 12U )     /**< Offset of option-50. */
95 #define dhcpOPTION_50_SIZE                         ( 6U )      /**< Number of bytes included in option-50. */
96 
97 
98 /* Values used in the DHCP packets. */
99 #define dhcpREQUEST_OPCODE             ( 1U )                 /**< DHCP request opcode. */
100 #define dhcpREPLY_OPCODE               ( 2U )                 /**< DHCP reply opcode. */
101 #define dhcpADDRESS_TYPE_ETHERNET      ( 1U )                 /**< Address type: ethernet opcode. */
102 #define dhcpETHERNET_ADDRESS_LENGTH    ( 6U )                 /**< Ethernet address length opcode. */
103 
104 /* The following define is temporary and serves to make the /single source
105  * code more similar to the /multi version. */
106 
107 #define EP_DHCPData                     xDHCPData              /**< Temporary define to make /single source similar to /multi version. */
108 #define EP_IPv4_SETTINGS                xNetworkAddressing     /**< Temporary define to make /single source similar to /multi version. */
109 
110 /** @brief If a lease time is not received, use the default of two days (48 hours in ticks).
111  * Can not use pdMS_TO_TICKS() as integer overflow can occur. */
112 #define dhcpDEFAULT_LEASE_TIME          ( ( 48UL * 60UL * 60UL ) * configTICK_RATE_HZ )
113 
114 /** @brief Don't allow the lease time to be too short. */
115 #define dhcpMINIMUM_LEASE_TIME          ( pdMS_TO_TICKS( 60000UL ) )            /* 60 seconds in ticks. */
116 
117 /** @brief Marks the end of the variable length options field in the DHCP packet. */
118 #define dhcpOPTION_END_BYTE             0xffu
119 
120 /** @brief Offset into a DHCP message at which the first byte of the options is
121  * located. */
122 #define dhcpFIRST_OPTION_BYTE_OFFSET    ( 0xf0U )
123 
124 /* Standard DHCP port numbers and magic cookie value.
125  * DHCPv4 uses UDP port number 68 for clients and port number 67 for servers.
126  */
127 #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
128     #define dhcpCLIENT_PORT_IPv4    0x4400U          /**< Little endian representation of port 68. */
129     #define dhcpSERVER_PORT_IPv4    0x4300U          /**< Little endian representation of port 67. */
130     #define dhcpCOOKIE              0x63538263UL     /**< Little endian representation of magic cookie. */
131     #define dhcpBROADCAST           0x0080U          /**< Little endian representation of broadcast flag. */
132 #else
133     #define dhcpCLIENT_PORT_IPv4    0x0044U          /**< Big endian representation of port 68. */
134     #define dhcpSERVER_PORT_IPv4    0x0043U          /**< Big endian representation of port 68. */
135     #define dhcpCOOKIE              0x63825363UL     /**< Big endian representation of magic cookie. */
136     #define dhcpBROADCAST           0x8000U          /**< Big endian representation of broadcast flag. */
137 #endif /* ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) */
138 
139 #include "pack_struct_start.h"
140 struct xDHCPMessage_IPv4
141 {
142     uint8_t ucOpcode;                                                      /**< Operation Code: Specifies the general type of message. */
143     uint8_t ucAddressType;                                                 /**< Hardware type used on the local network. */
144     uint8_t ucAddressLength;                                               /**< Hardware Address Length: Specifies how long hardware
145                                                                             * addresses are in this message. */
146     uint8_t ucHops;                                                        /**< Hops. */
147     uint32_t ulTransactionID;                                              /**< A 32-bit identification field generated by the client,
148                                                                             * to allow it to match up the request with replies received
149                                                                             * from DHCP servers. */
150     uint16_t usElapsedTime;                                                /**< Number of seconds elapsed since a client began an attempt to acquire or renew a lease. */
151     uint16_t usFlags;                                                      /**< Just one bit used to indicate broadcast. */
152     uint32_t ulClientIPAddress_ciaddr;                                     /**< Client's IP address if it has one or 0 is put in this field. */
153     uint32_t ulYourIPAddress_yiaddr;                                       /**< The IP address that the server is assigning to the client. */
154     uint32_t ulServerIPAddress_siaddr;                                     /**< The DHCP server address that the client should use. */
155     uint32_t ulRelayAgentIPAddress_giaddr;                                 /**< Gateway IP address in case the server client are on different subnets. */
156     uint8_t ucClientHardwareAddress[ dhcpCLIENT_HARDWARE_ADDRESS_LENGTH ]; /**< The client hardware address. */
157     uint8_t ucServerHostName[ dhcpSERVER_HOST_NAME_LENGTH ];               /**< Server's hostname. */
158     uint8_t ucBootFileName[ dhcpBOOT_FILE_NAME_LENGTH ];                   /**< Boot file full directory path. */
159     uint32_t ulDHCPCookie;                                                 /**< Magic cookie option. */
160     /* Option bytes from here on. */
161 }
162 #include "pack_struct_end.h"
163 typedef struct xDHCPMessage_IPv4 DHCPMessage_IPv4_t;
164 
165 
166 #if ( ipconfigUSE_DHCP_HOOK != 0 )
167     /* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
168     typedef enum eDHCP_PHASE
169     {
170         eDHCPPhasePreDiscover, /**< Driver is about to send a DHCP discovery. */
171         eDHCPPhasePreRequest   /**< Driver is about to request DHCP an IP address. */
172     } eDHCPCallbackPhase_t;
173 
174 /** @brief Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
175     typedef enum eDHCP_ANSWERS
176     {
177         eDHCPContinue,      /**< Continue the DHCP process */
178         eDHCPUseDefaults,   /**< Stop DHCP and use the static defaults. */
179         eDHCPStopNoChanges, /**< Stop DHCP and continue with current settings. */
180     } eDHCPCallbackAnswer_t;
181 #endif /* #if( ipconfigUSE_DHCP_HOOK != 0 ) */
182 
183 /** @brief DHCP state machine states. */
184 typedef enum
185 {
186     eInitialWait = 0,          /**< Initial state: open a socket and wait a short time. */
187     eWaitingSendFirstDiscover, /**< Send a discover the first time it is called, and reset all timers. */
188     eWaitingOffer,             /**< Either resend the discover, or, if the offer is forthcoming, send a request. */
189     eWaitingAcknowledge,       /**< Either resend the request. */
190     eSendDHCPRequest,          /**< Sendto failed earlier, resend the request to lease the IP-address offered. */
191     #if ( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
192         eGetLinkLayerAddress,  /**< When DHCP didn't respond, try to obtain a LinkLayer address 168.254.x.x. */
193     #endif
194     eLeasedAddress,            /**< Resend the request at the appropriate time to renew the lease. */
195     eNotUsingLeasedAddress     /**< DHCP failed, and a default IP address is being used. */
196 } eDHCPState_t;
197 
198 /** @brief Hold information in between steps in the DHCP state machine. */
199 struct xDHCP_DATA
200 {
201     uint32_t ulTransactionId;      /**< The ID of the DHCP transaction */
202     uint32_t ulOfferedIPAddress;   /**< The IP address offered by the DHCP server */
203     uint32_t ulPreferredIPAddress; /**< A preferred IP address */
204     uint32_t ulDHCPServerAddress;  /**< The IP address of the DHCP server */
205     uint32_t ulLeaseTime;          /**< The time for which the current IP address is leased */
206     TickType_t xDHCPTxTime;        /**< The time at which a DHCP request was sent. */
207     TickType_t xDHCPTxPeriod;      /**< The maximum time that the client will wait for a reply. */
208     BaseType_t xUseBroadcast;      /**< Try both without and with the broadcast flag */
209     eDHCPState_t eDHCPState;       /**< Maintains the DHCP state machine state. */
210 };
211 
212 typedef struct xDHCP_DATA DHCPData_t;
213 
214 /* Returns the current state of a DHCP process. */
215 eDHCPState_t eGetDHCPState( void );
216 
217 /*
218  * NOT A PUBLIC API FUNCTION.
219  * It will be called when the DHCP timer expires, or when
220  * data has been received on the DHCP socket.
221  */
222 void vDHCPProcess( BaseType_t xReset,
223                    eDHCPState_t eExpectedState );
224 
225 /* Internal call: returns true if socket is the current DHCP socket */
226 BaseType_t xIsDHCPSocket( const ConstSocket_t xSocket );
227 
228 
229 /* The application can indicate a preferred IP address by calling this function
230  * before FreeRTOS_IPInit() is called. */
231 uint32_t vDHCPSetPreferredIPAddress( uint32_t ulIPAddress );
232 
233 #if ( ipconfigUSE_DHCP_HOOK != 0 )
234 
235 /* Prototype of the hook (or callback) function that must be provided by the
236  * application if ipconfigUSE_DHCP_HOOK is set to 1.  See the following URL for
237  * usage information:
238  * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK
239  */
240     eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase,
241                                                 uint32_t ulIPAddress );
242 #endif /* ( ipconfigUSE_DHCP_HOOK != 0 ) */
243 
244 /* *INDENT-OFF* */
245 #ifdef __cplusplus
246     } /* extern "C" */
247 #endif
248 /* *INDENT-ON* */
249 
250 #endif /* FREERTOS_DHCP_H */
251