dhcpv6_client.c
Go to the documentation of this file.
1 /**
2  * @file dhcpv6_client.c
3  * @brief DHCPv6 client (Dynamic Host Configuration Protocol for IPv6)
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 for IPv6 enables DHCP servers to
30  * pass configuration parameters such as IPv6 network addresses to IPv6
31  * nodes. This protocol is a stateful counterpart to IPv6 Stateless Address
32  * Autoconfiguration (RFC 2462), and can be used separately or concurrently
33  * with the latter to obtain configuration parameters. Refer to RFC 3315
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 DHCPV6_TRACE_LEVEL
41 
42 //Dependencies
43 #include "core/net.h"
44 #include "ipv6/ipv6.h"
45 #include "ipv6/ipv6_misc.h"
46 #include "dhcpv6/dhcpv6_client.h"
48 #include "debug.h"
49 
50 //Check TCP/IP stack configuration
51 #if (IPV6_SUPPORT == ENABLED && DHCPV6_CLIENT_SUPPORT == ENABLED)
52 
53 
54 /**
55  * @brief Initialize settings with default values
56  * @param[out] settings Structure that contains DHCPv6 client settings
57  **/
58 
60 {
61  //Use default interface
62  settings->interface = netGetDefaultInterface();
63 
64  //Support for quick configuration using rapid commit
65  settings->rapidCommit = FALSE;
66  //Use the DNS servers provided by the DHCPv6 server
67  settings->manualDnsConfig = FALSE;
68  //DHCPv6 configuration timeout
69  settings->timeout = 0;
70 
71  //DHCPv6 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 DHCPv6 options callback
79  settings->addOptionsCallback = NULL;
80  //Parse DHCPv6 options callback
81  settings->parseOptionsCallback = NULL;
82 }
83 
84 
85 /**
86  * @brief DHCPv6 client initialization
87  * @param[in] context Pointer to the DHCPv6 client context
88  * @param[in] settings DHCPv6 client specific settings
89  * @return Error code
90  **/
91 
93  const Dhcpv6ClientSettings *settings)
94 {
95  error_t error;
96  NetInterface *interface;
97 
98  //Debug message
99  TRACE_INFO("Initializing DHCPv6 client...\r\n");
100 
101  //Ensure the parameters are valid
102  if(context == NULL || settings == NULL)
104 
105  //The DHCPv6 client must be bound to a valid interface
106  if(settings->interface == NULL)
108 
109  //Point to the underlying network interface
110  interface = settings->interface;
111 
112  //Clear the DHCPv6 client context
113  osMemset(context, 0, sizeof(Dhcpv6ClientContext));
114  //Save user settings
115  context->settings = *settings;
116 
117  //Generate client's DUID
118  error = dhcpv6ClientGenerateDuid(context);
119  //any error to report?
120  if(error)
121  return error;
122 
123  //DHCPv6 client is currently suspended
124  context->running = FALSE;
125  //Initialize state machine
126  context->state = DHCPV6_STATE_INIT;
127 
128  //Attach the DHCPv6 client context to the network interface
129  interface->dhcpv6ClientContext = context;
130 
131  //Successful initialization
132  return NO_ERROR;
133 }
134 
135 
136 /**
137  * @brief Start DHCPv6 client
138  * @param[in] context Pointer to the DHCPv6 client context
139  * @return Error code
140  **/
141 
143 {
144  error_t error;
145  NetInterface *interface;
146 
147  //Make sure the DHCPv6 client context is valid
148  if(context == NULL)
150 
151  //Debug message
152  TRACE_INFO("Starting DHCPv6 client...\r\n");
153 
154  //Get exclusive access
156 
157  //Point to the underlying network interface
158  interface = context->settings.interface;
159 
160  //Check the operational state of the DHCPv6 client
161  if(!context->running)
162  {
163  //Flush the list of IPv6 addresses from the client's IA
164  dhcpv6ClientFlushAddrList(context);
165 
166  //Automatic DNS server configuration?
167  if(!context->settings.manualDnsConfig)
168  {
169  //Clear the list of DNS servers
170  ipv6FlushDnsServerList(interface);
171  }
172 
173  //Check if the link is up?
174  if(interface->linkState)
175  {
176  //A link-local address is formed by combining the well-known
177  //link-local prefix fe80::/10 with the interface identifier
179  }
180 
181  //Initialize state machine
182  context->state = DHCPV6_STATE_INIT;
183 
184  //Register the callback function to be called whenever a UDP datagram
185  //is received on port 546
186  error = udpAttachRxCallback(interface, DHCPV6_CLIENT_PORT,
187  dhcpv6ClientProcessMessage, context);
188 
189  //Check status code
190  if(!error)
191  {
192  //Start DHCPv6 client
193  context->running = TRUE;
194  }
195  }
196  else
197  {
198  //The DHCP client is already running
199  error = ERROR_ALREADY_RUNNING;
200  }
201 
202  //Release exclusive access
204 
205  //Return status code
206  return error;
207 }
208 
209 
210 /**
211  * @brief Stop DHCPv6 client
212  * @param[in] context Pointer to the DHCPv6 client context
213  * @return Error code
214  **/
215 
217 {
218  NetInterface *interface;
219 
220  //Make sure the DHCPv6 client context is valid
221  if(context == NULL)
223 
224  //Debug message
225  TRACE_INFO("Stopping DHCPv6 client...\r\n");
226 
227  //Get exclusive access
229 
230  //Point to the underlying network interface
231  interface = context->settings.interface;
232 
233  //Check whether the DHCPv6 client is running
234  if(context->running)
235  {
236  //Unregister callback function
238 
239  //Stop DHCPv6 client
240  context->running = FALSE;
241  //Reinitialize state machine
242  context->state = DHCPV6_STATE_INIT;
243  }
244 
245  //Release exclusive access
247 
248  //Successful processing
249  return NO_ERROR;
250 }
251 
252 
253 /**
254  * @brief Release DHCPv6 lease
255  * @param[in] context Pointer to the DHCPv6 client context
256  * @return Error code
257  **/
258 
260 {
261  uint_t i;
262  NetInterface *interface;
263  Dhcpv6ClientAddrEntry *entry;
264 
265  //Check parameter
266  if(context == NULL)
268 
269  //Debug message
270  TRACE_INFO("Releasing DHCPv6 lease...\r\n");
271 
272  //Get exclusive access
274 
275  //Point to the underlying network interface
276  interface = context->settings.interface;
277 
278  //Check whether the DHCPv6 client is running
279  if(context->running)
280  {
281  //BOUND state?
282  if(context->state == DHCPV6_STATE_BOUND)
283  {
284  //Loop through the IPv6 addresses recorded by the DHCPv6 client
285  for(i = 0; i < DHCPV6_CLIENT_ADDR_LIST_SIZE; i++)
286  {
287  //Point to the current entry
288  entry = &context->ia.addrList[i];
289 
290  //Valid IPv6 address?
291  if(entry->validLifetime > 0)
292  {
293  //The client must stop using the addresses being released as soon
294  //as the client begins the Release message exchange process
295  ipv6RemoveAddr(interface, &entry->addr);
296  }
297  }
298 
299  //Switch to the RELEASE state
301  }
302  else
303  {
304  //Stop DHCPv6 client
305  context->running = FALSE;
306  //Reinitialize state machine
307  context->state = DHCPV6_STATE_INIT;
308  }
309  }
310 
311  //Release exclusive access
313 
314  //Successful processing
315  return NO_ERROR;
316 }
317 
318 
319 /**
320  * @brief Retrieve current state
321  * @param[in] context Pointer to the DHCPv6 client context
322  * @return Current DHCPv6 client state
323  **/
324 
326 {
327  Dhcpv6State state;
328 
329  //Get exclusive access
331  //Get current state
332  state = context->state;
333  //Release exclusive access
335 
336  //Return current state
337  return state;
338 }
339 
340 #endif
IPv6 (Internet Protocol Version 6)
bool_t rapidCommit
Quick configuration using rapid commit.
Dhcpv6ParseOptionsCallback parseOptionsCallback
Parse DHCPv6 options callback.
#define netMutex
Definition: net_legacy.h:195
Dhcpv6StateChangeCallback stateChangeEvent
FSM state change event.
#define DHCPV6_CLIENT_PORT
Definition: dhcpv6_common.h:40
#define TRUE
Definition: os_port.h:50
void dhcpv6ClientFlushAddrList(Dhcpv6ClientContext *context)
Flush the list of IPv6 addresses from the IA.
@ DHCPV6_STATE_INIT
#define DHCPV6_CLIENT_ADDR_LIST_SIZE
Definition: dhcpv6_client.h:54
Helper functions for DHCPv6 client.
Ipv6Addr addr
IPv6 address.
bool_t manualDnsConfig
Force manual DNS configuration.
NetInterface * interface
Network interface to configure.
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
void ipv6FlushDnsServerList(NetInterface *interface)
Flush the list of DNS servers.
Definition: ipv6_misc.c:756
error_t
Error codes.
Definition: error.h:43
uint32_t validLifetime
Valid lifetime.
DHCPv6 client (Dynamic Host Configuration Protocol for IPv6)
error_t dhcpv6ClientStop(Dhcpv6ClientContext *context)
Stop DHCPv6 client.
error_t udpDetachRxCallback(NetInterface *interface, uint16_t port)
Unregister user callback.
Definition: udp.c:1062
IA address entry.
#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
Dhcpv6TimeoutCallback timeoutEvent
DHCPv6 configuration timeout event.
void dhcpv6ClientProcessMessage(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const UdpHeader *udpHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary, void *param)
Process incoming DHCPv6 message.
Helper functions for IPv6.
Dhcpv6State dhcpv6ClientGetState(Dhcpv6ClientContext *context)
Retrieve current state.
#define Dhcpv6ClientContext
DHCPv6 client settings.
systime_t timeout
DHCPv6 configuration timeout.
#define TRACE_INFO(...)
Definition: debug.h:95
void ipv6RemoveAddr(NetInterface *interface, const Ipv6Addr *addr)
Remove an entry from the list of IPv6 addresses.
Definition: ipv6_misc.c:339
Dhcpv6State
DHCPv6 client FSM states.
@ DHCPV6_STATE_BOUND
error_t dhcpv6ClientRelease(Dhcpv6ClientContext *context)
Release DHCPv6 lease.
error_t dhcpv6ClientInit(Dhcpv6ClientContext *context, const Dhcpv6ClientSettings *settings)
DHCPv6 client initialization.
Definition: dhcpv6_client.c:92
@ DHCPV6_STATE_RELEASE
error_t dhcpv6ClientGenerateDuid(Dhcpv6ClientContext *context)
Generate client's DUID.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
error_t dhcpv6ClientStart(Dhcpv6ClientContext *context)
Start DHCPv6 client.
Dhcpv6LinkChangeCallback linkChangeEvent
Link state change event.
void dhcpv6ClientGetDefaultSettings(Dhcpv6ClientSettings *settings)
Initialize settings with default values.
Definition: dhcpv6_client.c:59
error_t dhcpv6ClientGenerateLinkLocalAddr(Dhcpv6ClientContext *context)
Generate a link-local address.
Dhcpv6AddOptionsCallback addOptionsCallback
Add DHCPv6 options callback.
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
TCP/IP stack core.
void dhcpv6ClientChangeState(Dhcpv6ClientContext *context, Dhcpv6State newState, systime_t delay)
Update DHCPv6 FSM state.
@ ERROR_ALREADY_RUNNING
Definition: error.h:293
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.