dhcp_client.c
Go to the documentation of this file.
1 /**
2  * @file dhcp_client.c
3  * @brief DHCP client (Dynamic Host Configuration Protocol)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * The Dynamic Host Configuration Protocol is used to provide configuration
30  * parameters to hosts. Refer to the following RFCs for complete details:
31  * - RFC 2131: Dynamic Host Configuration Protocol
32  * - RFC 2132: DHCP Options and BOOTP Vendor Extensions
33  * - RFC 4039: Rapid Commit Option for the DHCP version 4
34  *
35  * @author Oryx Embedded SARL (www.oryx-embedded.com)
36  * @version 2.6.0
37  **/
38 
39 //Switch to the appropriate trace level
40 #define TRACE_LEVEL DHCP_TRACE_LEVEL
41 
42 //Dependencies
43 #include "core/net.h"
44 #include "dhcp/dhcp_client.h"
45 #include "dhcp/dhcp_client_misc.h"
46 #include "debug.h"
47 
48 //Check TCP/IP stack configuration
49 #if (IPV4_SUPPORT == ENABLED && DHCP_CLIENT_SUPPORT == ENABLED)
50 
51 
52 /**
53  * @brief Initialize settings with default values
54  * @param[out] settings Structure that contains DHCP client settings
55  **/
56 
58 {
59  //Network interface to configure
60  settings->interface = NULL;
61  //Index of the IP address to be configured
62  settings->ipAddrIndex = 0;
63 
64  //Support for quick configuration using rapid commit
65  settings->rapidCommit = FALSE;
66  //Use the DNS servers provided by the DHCP server
67  settings->manualDnsConfig = FALSE;
68  //DHCP configuration timeout
69  settings->timeout = 0;
70 
71  //DHCP configuration timeout event
72  settings->timeoutEvent = NULL;
73  //Link state change event
74  settings->linkChangeEvent = NULL;
75  //FSM state change event
76  settings->stateChangeEvent = NULL;
77 
78  //Add DHCP options callback
79  settings->addOptionsCallback = NULL;
80  //Parse DHCP options callback
81  settings->parseOptionsCallback = NULL;
82 }
83 
84 
85 /**
86  * @brief DHCP client initialization
87  * @param[in] context Pointer to the DHCP client context
88  * @param[in] settings DHCP client specific settings
89  * @return Error code
90  **/
91 
93  const DhcpClientSettings *settings)
94 {
95  NetInterface *interface;
96 
97  //Debug message
98  TRACE_INFO("Initializing DHCP client...\r\n");
99 
100  //Ensure the parameters are valid
101  if(context == NULL || settings == NULL)
103 
104  //The DHCP client must be bound to a valid interface
105  if(settings->interface == NULL)
107 
108  //Point to the underlying network interface
109  interface = settings->interface;
110 
111  //Clear the DHCP client context
112  osMemset(context, 0, sizeof(DhcpClientContext));
113 
114  //Attach TCP/IP stack context
115  context->netContext = settings->interface->netContext;
116 
117  //Save user settings
118  context->interface = settings->interface;
119  context->ipAddrIndex = settings->ipAddrIndex;
120  context->rapidCommit = settings->rapidCommit;
121  context->manualDnsConfig = settings->manualDnsConfig;
122  context->configTimeout = settings->timeout;
123  context->timeoutEvent = settings->timeoutEvent;
124  context->linkChangeEvent = settings->linkChangeEvent;
125  context->stateChangeEvent = settings->stateChangeEvent;
126  context->addOptionsCallback = settings->addOptionsCallback;
127  context->parseOptionsCallback = settings->parseOptionsCallback;
128 
129  //DHCP client is currently suspended
130  context->running = FALSE;
131  //Initialize state machine
132  context->state = DHCP_STATE_INIT;
133 
134  //Get exclusive access
135  netLock(context->netContext);
136  //Attach the DHCP client context to the network interface
137  interface->dhcpClientContext = context;
138  //Release exclusive access
139  netUnlock(context->netContext);
140 
141  //Successful initialization
142  return NO_ERROR;
143 }
144 
145 
146 /**
147  * @brief Start DHCP client
148  * @param[in] context Pointer to the DHCP client context
149  * @return Error code
150  **/
151 
153 {
154  error_t error;
155 
156  //Make sure the DHCP client context is valid
157  if(context == NULL)
159 
160  //Debug message
161  TRACE_INFO("Starting DHCP client...\r\n");
162 
163  //Get exclusive access
164  netLock(context->netContext);
165 
166  //Check the operational state of the DHCP client
167  if(!context->running)
168  {
169  //Reset DHCP configuration
170  dhcpClientResetConfig(context);
171 
172  //Initialize state machine
173  context->state = DHCP_STATE_INIT;
174 
175  //Register the callback function to be called whenever a UDP datagram
176  //is received on port 68
177  error = udpRegisterRxCallback(context->interface, DHCP_CLIENT_PORT,
178  dhcpClientProcessMessage, context);
179 
180  //Check status code
181  if(!error)
182  {
183  //Start DHCP client
184  context->running = TRUE;
185  }
186  }
187  else
188  {
189  //The DHCP client is already running
190  error = ERROR_ALREADY_RUNNING;
191  }
192 
193  //Release exclusive access
194  netUnlock(context->netContext);
195 
196  //Return status code
197  return error;
198 }
199 
200 
201 /**
202  * @brief Stop DHCP client
203  * @param[in] context Pointer to the DHCP client context
204  * @return Error code
205  **/
206 
208 {
209  //Make sure the DHCP client context is valid
210  if(context == NULL)
212 
213  //Debug message
214  TRACE_INFO("Stopping DHCP client...\r\n");
215 
216  //Get exclusive access
217  netLock(context->netContext);
218 
219  //Check whether the DHCP client is running
220  if(context->running)
221  {
222  //Unregister callback function
223  udpUnregisterRxCallback(context->interface, DHCP_CLIENT_PORT);
224 
225  //Stop DHCP client
226  context->running = FALSE;
227  //Reinitialize state machine
228  context->state = DHCP_STATE_INIT;
229  }
230 
231  //Release exclusive access
232  netUnlock(context->netContext);
233 
234  //Successful processing
235  return NO_ERROR;
236 }
237 
238 
239 /**
240  * @brief Release DHCP lease
241  * @param[in] context Pointer to the DHCP client context
242  * @return Error code
243  **/
244 
246 {
247  //Check parameter
248  if(context == NULL)
250 
251  //Debug message
252  TRACE_INFO("Releasing DHCP lease...\r\n");
253 
254  //Get exclusive access
255  netLock(context->netContext);
256 
257  //Check whether the DHCP client is running
258  if(context->running)
259  {
260  //Check current state
261  if(context->state == DHCP_STATE_BOUND ||
262  context->state == DHCP_STATE_RENEWING ||
263  context->state == DHCP_STATE_REBINDING)
264  {
265  //Select a new transaction identifier
266  context->transactionId = netGenerateRand(context->netContext);
267 
268  //The client may choose to relinquish its lease on a network address
269  //by sending a DHCPRELEASE message to the server
270  dhcpClientSendRelease(context);
271 
272  //The host address is no longer valid
273  dhcpClientResetConfig(context);
274  }
275 
276  //Unregister callback function
277  udpUnregisterRxCallback(context->interface, DHCP_CLIENT_PORT);
278 
279  //Stop DHCP client
280  context->running = FALSE;
281  //Reinitialize state machine
282  context->state = DHCP_STATE_INIT;
283  }
284 
285  //Release exclusive access
286  netUnlock(context->netContext);
287 
288  //Successful processing
289  return NO_ERROR;
290 }
291 
292 
293 /**
294  * @brief Retrieve current state
295  * @param[in] context Pointer to the DHCP client context
296  * @return Current DHCP client state
297  **/
298 
300 {
301  DhcpState state;
302 
303  //Get exclusive access
304  netLock(context->netContext);
305  //Get current state
306  state = context->state;
307  //Release exclusive access
308  netUnlock(context->netContext);
309 
310  //Return current state
311  return state;
312 }
313 
314 
315 /**
316  * @brief Release DHCP client context
317  * @param[in] context Pointer to the DHCP client context
318  **/
319 
321 {
322  NetInterface *interface;
323 
324  //Make sure the DHCP client context is valid
325  if(context != NULL)
326  {
327  //Get exclusive access
328  netLock(context->netContext);
329 
330  //Point to the underlying network interface
331  interface = context->interface;
332  //Detach the DHCP client context from the network interface
333  interface->dhcpClientContext = NULL;
334 
335  //Release exclusive access
336  netUnlock(context->netContext);
337 
338  //Clear DHCP client context
339  osMemset(context, 0, sizeof(DhcpClientContext));
340  }
341 }
342 
343 #endif
error_t dhcpClientRelease(DhcpClientContext *context)
Release DHCP lease.
Definition: dhcp_client.c:245
void netUnlock(NetContext *context)
Release exclusive access to the core of the TCP/IP stack.
Definition: net.c:319
error_t udpUnregisterRxCallback(NetInterface *interface, uint16_t port)
Unregister user callback.
Definition: udp.c:1062
DHCP client (Dynamic Host Configuration Protocol)
error_t dhcpClientSendRelease(DhcpClientContext *context)
Send DHCPRELEASE message.
DhcpClientLinkChangeCallback linkChangeEvent
Link state change event.
Definition: dhcp_client.h:224
error_t dhcpClientStop(DhcpClientContext *context)
Stop DHCP client.
Definition: dhcp_client.c:207
#define TRUE
Definition: os_port.h:50
uint32_t netGenerateRand(NetContext *context)
Generate a random 32-bit value.
Definition: net_misc.c:956
bool_t rapidCommit
Quick configuration using rapid commit.
Definition: dhcp_client.h:220
DhcpClientStateChangeCallback stateChangeEvent
FSM state change event.
Definition: dhcp_client.h:225
Helper functions for DHCP client.
#define DhcpClientContext
Definition: dhcp_client.h:145
error_t dhcpClientStart(DhcpClientContext *context)
Start DHCP client.
Definition: dhcp_client.c:152
void dhcpClientDeinit(DhcpClientContext *context)
Release DHCP client context.
Definition: dhcp_client.c:320
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint_t ipAddrIndex
Index of the IP address to be configured.
Definition: dhcp_client.h:219
error_t
Error codes.
Definition: error.h:43
DhcpClientTimeoutCallback timeoutEvent
DHCP configuration timeout event.
Definition: dhcp_client.h:223
#define NetInterface
Definition: net.h:40
error_t dhcpClientInit(DhcpClientContext *context, const DhcpClientSettings *settings)
DHCP client initialization.
Definition: dhcp_client.c:92
DHCP client settings.
Definition: dhcp_client.h:217
#define TRACE_INFO(...)
Definition: debug.h:105
@ DHCP_STATE_REBINDING
Definition: dhcp_client.h:168
systime_t timeout
DHCP configuration timeout.
Definition: dhcp_client.h:222
DhcpState dhcpClientGetState(DhcpClientContext *context)
Retrieve current state.
Definition: dhcp_client.c:299
@ DHCP_STATE_BOUND
Definition: dhcp_client.h:166
void dhcpClientProcessMessage(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const UdpHeader *udpHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary, void *param)
Process incoming DHCP message.
NetInterface * interface
Network interface to configure.
Definition: dhcp_client.h:218
DhcpState
DHCP FSM states.
Definition: dhcp_client.h:158
bool_t manualDnsConfig
Force manual DNS configuration.
Definition: dhcp_client.h:221
DhcpClientParseOptionsCallback parseOptionsCallback
Parse DHCP options callback.
Definition: dhcp_client.h:227
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
DhcpClientAddOptionsCallback addOptionsCallback
Add DHCP options callback.
Definition: dhcp_client.h:226
@ DHCP_STATE_INIT
Definition: dhcp_client.h:159
error_t udpRegisterRxCallback(NetInterface *interface, uint16_t port, UdpRxCallback callback, void *param)
Register user callback.
Definition: udp.c:1021
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
#define DHCP_CLIENT_PORT
Definition: dhcp_common.h:41
void dhcpClientGetDefaultSettings(DhcpClientSettings *settings)
Initialize settings with default values.
Definition: dhcp_client.c:57
@ ERROR_ALREADY_RUNNING
Definition: error.h:294
void dhcpClientResetConfig(DhcpClientContext *context)
Reset DHCP configuration.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ DHCP_STATE_RENEWING
Definition: dhcp_client.h:167