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-2024 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.4.4
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  //Use default interface
60  settings->interface = netGetDefaultInterface();
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  //Save user settings
114  context->settings = *settings;
115 
116  //DHCP client is currently suspended
117  context->running = FALSE;
118  //Initialize state machine
119  context->state = DHCP_STATE_INIT;
120 
121  //Attach the DHCP client context to the network interface
122  interface->dhcpClientContext = context;
123 
124  //Successful initialization
125  return NO_ERROR;
126 }
127 
128 
129 /**
130  * @brief Start DHCP client
131  * @param[in] context Pointer to the DHCP client context
132  * @return Error code
133  **/
134 
136 {
137  error_t error;
138  NetInterface *interface;
139 
140  //Make sure the DHCP client context is valid
141  if(context == NULL)
143 
144  //Debug message
145  TRACE_INFO("Starting DHCP client...\r\n");
146 
147  //Get exclusive access
149 
150  //Point to the underlying network interface
151  interface = context->settings.interface;
152 
153  //Check the operational state of the DHCP client
154  if(!context->running)
155  {
156  //Reset DHCP configuration
157  dhcpClientResetConfig(context);
158 
159  //Initialize state machine
160  context->state = DHCP_STATE_INIT;
161 
162  //Register the callback function to be called whenever a UDP datagram
163  //is received on port 68
164  error = udpAttachRxCallback(interface, DHCP_CLIENT_PORT,
165  dhcpClientProcessMessage, context);
166 
167  //Check status code
168  if(!error)
169  {
170  //Start DHCP client
171  context->running = TRUE;
172  }
173  }
174  else
175  {
176  //The DHCP client is already running
177  error = ERROR_ALREADY_RUNNING;
178  }
179 
180  //Release exclusive access
182 
183  //Return status code
184  return error;
185 }
186 
187 
188 /**
189  * @brief Stop DHCP client
190  * @param[in] context Pointer to the DHCP client context
191  * @return Error code
192  **/
193 
195 {
196  NetInterface *interface;
197 
198  //Make sure the DHCP client context is valid
199  if(context == NULL)
201 
202  //Debug message
203  TRACE_INFO("Stopping DHCP client...\r\n");
204 
205  //Get exclusive access
207 
208  //Point to the underlying network interface
209  interface = context->settings.interface;
210 
211  //Check whether the DHCP client is running
212  if(context->running)
213  {
214  //Unregister callback function
216 
217  //Stop DHCP client
218  context->running = FALSE;
219  //Reinitialize state machine
220  context->state = DHCP_STATE_INIT;
221  }
222 
223  //Release exclusive access
225 
226  //Successful processing
227  return NO_ERROR;
228 }
229 
230 
231 /**
232  * @brief Release DHCP lease
233  * @param[in] context Pointer to the DHCP client context
234  * @return Error code
235  **/
236 
238 {
239  NetInterface *interface;
240 
241  //Check parameter
242  if(context == NULL)
244 
245  //Debug message
246  TRACE_INFO("Releasing DHCP lease...\r\n");
247 
248  //Get exclusive access
250 
251  //Point to the underlying network interface
252  interface = context->settings.interface;
253 
254  //Check whether the DHCP client is running
255  if(context->running)
256  {
257  //Check current state
258  if(context->state == DHCP_STATE_BOUND ||
259  context->state == DHCP_STATE_RENEWING ||
260  context->state == DHCP_STATE_REBINDING)
261  {
262  //Select a new transaction identifier
263  context->transactionId = netGenerateRand();
264 
265  //The client may choose to relinquish its lease on a network address
266  //by sending a DHCPRELEASE message to the server
267  dhcpClientSendRelease(context);
268 
269  //The host address is no longer valid
270  dhcpClientResetConfig(context);
271  }
272 
273  //Unregister callback function
275 
276  //Stop DHCP client
277  context->running = FALSE;
278  //Reinitialize state machine
279  context->state = DHCP_STATE_INIT;
280  }
281 
282  //Release exclusive access
284 
285  //Successful processing
286  return NO_ERROR;
287 }
288 
289 
290 /**
291  * @brief Retrieve current state
292  * @param[in] context Pointer to the DHCP client context
293  * @return Current DHCP client state
294  **/
295 
297 {
298  DhcpState state;
299 
300  //Get exclusive access
302  //Get current state
303  state = context->state;
304  //Release exclusive access
306 
307  //Return current state
308  return state;
309 }
310 
311 #endif
error_t dhcpClientRelease(DhcpClientContext *context)
Release DHCP lease.
Definition: dhcp_client.c:237
DHCP client (Dynamic Host Configuration Protocol)
error_t dhcpClientSendRelease(DhcpClientContext *context)
Send DHCPRELEASE message.
#define netMutex
Definition: net_legacy.h:195
DhcpClientLinkChangeCallback linkChangeEvent
Link state change event.
Definition: dhcp_client.h:224
error_t dhcpClientStop(DhcpClientContext *context)
Stop DHCP client.
Definition: dhcp_client.c:194
#define TRUE
Definition: os_port.h:50
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
uint32_t netGenerateRand(void)
Generate a random 32-bit value.
Definition: net_misc.c:922
error_t dhcpClientStart(DhcpClientContext *context)
Start DHCP client.
Definition: dhcp_client.c:135
#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
error_t udpDetachRxCallback(NetInterface *interface, uint16_t port)
Unregister user callback.
Definition: udp.c:1062
#define NetInterface
Definition: net.h:36
error_t udpAttachRxCallback(NetInterface *interface, uint16_t port, UdpRxCallback callback, void *param)
Register user callback.
Definition: udp.c:1021
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:467
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:95
@ 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:296
@ 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
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
bool_t manualDnsConfig
Force manual DNS configuration.
Definition: dhcp_client.h:221
DhcpClientParseOptionsCallback parseOptionsCallback
Parse DHCP options callback.
Definition: dhcp_client.h:227
DhcpClientAddOptionsCallback addOptionsCallback
Add DHCP options callback.
Definition: dhcp_client.h:226
@ DHCP_STATE_INIT
Definition: dhcp_client.h:159
#define osMemset(p, value, length)
Definition: os_port.h:135
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:293
void dhcpClientResetConfig(DhcpClientContext *context)
Reset DHCP configuration.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ DHCP_STATE_RENEWING
Definition: dhcp_client.h:167