1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Component */
17 /** */
18 /** Dynamic Host Configuration Protocol over IPv6 (DHCPv6 Client) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_DHCPV6_SOURCE_CODE
24
25
26 /* Force error checking to be disabled in this module */
27
28 #ifndef NX_DISABLE_ERROR_CHECKING
29 #define NX_DISABLE_ERROR_CHECKING
30 #endif
31
32 /* Include necessary system files. */
33
34 #include <stdio.h>
35 #include "nx_api.h"
36 #include "nx_system.h"
37 #include "nx_ip.h"
38 #include "nx_ipv6.h"
39 #include "nx_udp.h"
40 #include "nxd_dhcpv6_client.h"
41 #include "tx_timer.h"
42
43 #ifdef FEATURE_NX_IPV6
44
45 /* Bring in externs for caller checking code. */
46
47 NX_CALLER_CHECKING_EXTERNS
48
49
50 /* Define the address of All DHCP Relay Agents and Servers as per RFC3315. */
51 static NXD_ADDRESS All_DHCPv6_Relay_Servers_Address;
52
53 /* Keep the DHCPv6 instance for DAD callback notify. */
54 static NX_DHCPV6 *_nx_dhcpv6_DAD_ptr;
55
56
57 /**************************************************************************/
58 /* */
59 /* FUNCTION RELEASE */
60 /* */
61 /* _nx_dhcpv6_add_client_duid PORTABLE C */
62 /* 6.1 */
63 /* AUTHOR */
64 /* */
65 /* Yuxin Zhou, Microsoft Corporation */
66 /* */
67 /* DESCRIPTION */
68 /* */
69 /* This function adds the client DUID to the Client request packet */
70 /* based on the Client DUID on record, checking to make sure it does */
71 /* not go past the end of the packet payload. */
72 /* */
73 /* INPUT */
74 /* */
75 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
76 /* received_buffer Pointer to server reply */
77 /* length Size of server reply buffer */
78 /* */
79 /* OUTPUT */
80 /* */
81 /* NX_SUCCESS Successful completion status */
82 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
83 /* Not enough room for the Client */
84 /* DUID in the packet payload */
85 /* CALLS */
86 /* */
87 /* memset Clears specified area of memory */
88 /* memcpy Copies specified area of memory */
89 /* */
90 /* CALLED BY */
91 /* */
92 /* _nx_dhcpv6_send_request Compiles and sends the Client */
93 /* DHCPv6 request */
94 /* */
95 /* RELEASE HISTORY */
96 /* */
97 /* DATE NAME DESCRIPTION */
98 /* */
99 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
100 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
101 /* verified memcpy use cases, */
102 /* resulting in version 6.1 */
103 /* */
104 /**************************************************************************/
_nx_dhcpv6_add_client_duid(NX_DHCPV6 * dhcpv6_ptr,UCHAR * buffer_ptr,UINT * index)105 UINT _nx_dhcpv6_add_client_duid(NX_DHCPV6 *dhcpv6_ptr, UCHAR *buffer_ptr, UINT *index)
106 {
107
108 ULONG message_word;
109 ULONG available_payload;
110 UCHAR mac[8];
111 UINT i = 0;
112
113
114 /* Compute the available payload in the packet buffer. */
115 available_payload = dhcpv6_ptr -> nx_dhcpv6_pool_ptr -> nx_packet_pool_payload_size -
116 (ULONG)sizeof(NX_IPV6_HEADER) - (ULONG)sizeof(NX_UDP_HEADER) - *index;
117
118 /* Check if the largest possible client DUID will fit in the packet buffer. */
119 if ((available_payload - 4) < ((ULONG)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_option_length)))
120 {
121
122 /* Hmmm... not enough! Can't do it. */
123 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
124 }
125
126 /* Build the header from the client DUID. */
127 message_word = (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_op_code)) << 16);
128 message_word |= (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_option_length);
129
130 /* Adjust for endianness. */
131 NX_CHANGE_ULONG_ENDIAN(message_word);
132
133 /* Copy first half of the Client DUID option to packet buffer. */
134 memcpy((buffer_ptr + (*index)), &message_word, sizeof(UINT)); /* Use case of memcpy is verified. */
135 (*index) += (ULONG)sizeof(UINT);
136
137 /* Build the DUID type and hardware type. */
138 message_word = (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_type)) << 16);
139 message_word |= dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_hardware_type;
140
141 /* Adjust for endianness. */
142 NX_CHANGE_ULONG_ENDIAN(message_word);
143
144 /* Set up the DUID type and hardware type. */
145 memcpy((buffer_ptr + (*index)), &message_word, sizeof(UINT)); /* Use case of memcpy is verified. */
146 (*index) += (ULONG)sizeof(UINT);
147
148 /* Include the 'time' field if this is a Link layer time DUID type. */
149 if (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_type == NX_DHCPV6_DUID_TYPE_LINK_TIME)
150 {
151
152 /* Build the time. */
153 message_word = dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_time;
154
155 /* Adjust for endianness. */
156 NX_CHANGE_ULONG_ENDIAN(message_word);
157
158 /* Set up the time. */
159 memcpy((buffer_ptr + (*index)), &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
160 (*index) += (ULONG)sizeof(ULONG);
161 }
162
163 /* Build the link layer address. */
164 if (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_ETHERNET)
165 {
166
167 /* The length of link layer address is 48 bit. */
168
169 /* Build the MSW. */
170 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw >> 8);
171 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw);
172 }
173 else if(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_EUI_64)
174 {
175
176 /* The length of link layer address is 64 bits. */
177
178 /* Build the MSW. */
179 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw >> 24);
180 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw >> 16);
181 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw >> 8);
182 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw);
183 }
184
185 /* Build the LSW. */
186 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw >> 24);
187 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw >> 16);
188 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw >> 8);
189 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw);
190
191 /* Set up the link layer address. */
192 memcpy((buffer_ptr + (*index)), mac, i); /* Use case of memcpy is verified. */
193 (*index) += i;
194
195 return NX_SUCCESS;
196 }
197
198
199 /**************************************************************************/
200 /* */
201 /* FUNCTION RELEASE */
202 /* */
203 /* _nx_dhcpv6_add_elapsed_time PORTABLE C */
204 /* 6.1 */
205 /* AUTHOR */
206 /* */
207 /* Yuxin Zhou, Microsoft Corporation */
208 /* */
209 /* DESCRIPTION */
210 /* */
211 /* This function adds the elapsed time option to the Client request */
212 /* packet using the session duration time tracked by the DHCPv6 Client */
213 /* thread, and checks to make sure it does not go past the end of the */
214 /* packet payload. */
215 /* */
216 /* Note that the elapsed time is the time from which the Client */
217 /* initiates the request to the time the it gets and processes a valid */
218 /* server reply. Its accuracy depends on the resolution of the session*/
219 /* timer. */
220 /* */
221 /* INPUT */
222 /* */
223 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
224 /* buffer_ptr Pointer to request packet buffer */
225 /* index Location into buffer to write data*/
226 /* */
227 /* OUTPUT */
228 /* */
229 /* NX_SUCCESS Successful completion status */
230 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
231 /* Not enough room for the elapsed */
232 /* time option in the packet payload*/
233 /* CALLS */
234 /* */
235 /* memset Clears specified area of memory */
236 /* memcpy Copies specified area of memory */
237 /* */
238 /* CALLED BY */
239 /* */
240 /* _nx_dhcpv6_send_request Compiles and sends the Client */
241 /* DHCPv6 request */
242 /* */
243 /* RELEASE HISTORY */
244 /* */
245 /* DATE NAME DESCRIPTION */
246 /* */
247 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
248 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
249 /* verified memcpy use cases, */
250 /* resulting in version 6.1 */
251 /* */
252 /**************************************************************************/
_nx_dhcpv6_add_elapsed_time(NX_DHCPV6 * dhcpv6_ptr,UCHAR * buffer_ptr,UINT * index)253 UINT _nx_dhcpv6_add_elapsed_time(NX_DHCPV6 *dhcpv6_ptr, UCHAR *buffer_ptr, UINT *index)
254 {
255
256 ULONG available_payload;
257
258
259 /* Compute the available payload for DHCP data in the packet buffer. */
260 available_payload = (dhcpv6_ptr -> nx_dhcpv6_pool_ptr -> nx_packet_pool_payload_size -
261 (ULONG)sizeof(NX_IPV6_HEADER) - (ULONG)sizeof(NX_UDP_HEADER) - *index);
262
263 /* Check if the data will fit in the packet buffer. */
264 if (available_payload < sizeof(NX_DHCPV6_ELAPSED_TIME))
265 {
266
267 /* Hmmm... not enough! Can't do it. */
268 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
269 }
270
271 /* Adjust for endianness. */
272 NX_CHANGE_USHORT_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_op_code);
273 NX_CHANGE_USHORT_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_op_length);
274 NX_CHANGE_USHORT_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time);
275
276 /* Set up the elapsed time option, in hundredths of seconds. */
277 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_elapsed_time), sizeof(NX_DHCPV6_ELAPSED_TIME)); /* Use case of memcpy is verified. */
278 *index += (ULONG)sizeof(NX_DHCPV6_ELAPSED_TIME);
279
280 /* Swap bytes back. */
281 NX_CHANGE_USHORT_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_op_code);
282 NX_CHANGE_USHORT_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_op_length);
283 NX_CHANGE_USHORT_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time);
284
285 return NX_SUCCESS;
286 }
287
288
289 /**************************************************************************/
290 /* */
291 /* FUNCTION RELEASE */
292 /* */
293 /* _nx_dhcpv6_add_ia_address PORTABLE C */
294 /* 6.1 */
295 /* AUTHOR */
296 /* */
297 /* Yuxin Zhou, Microsoft Corporation */
298 /* */
299 /* DESCRIPTION */
300 /* */
301 /* This function adds the IA address option to the Client request */
302 /* packet using the Client IA on record. Also checks to make sure */
303 /* adding the IA option does not go past the end of the packet payload.*/
304 /* */
305 /* INPUT */
306 /* */
307 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
308 /* buffer_ptr Pointer to request packet buffer */
309 /* index Location into buffer to write data*/
310 /* ia_index The index of IA address */
311 /* */
312 /* OUTPUT */
313 /* */
314 /* NX_SUCCESS Successful completion status */
315 /* NX_DHCPV6_INVALID_IA_ADDRESS IA address on record is NULL */
316 /* NX_DHCPV6_OPTION_NO_DATA No IA option in client record */
317 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
318 /* Not enough room for the IA address*/
319 /* option in the packet payload */
320 /* CALLS */
321 /* */
322 /* memset Clears specified area of memory */
323 /* memcpy Copies specified area of memory */
324 /* */
325 /* CALLED BY */
326 /* */
327 /* _nx_dhcpv6_add_iana Adds the IANA and optionally the */
328 /* IA option to Client request */
329 /* */
330 /* RELEASE HISTORY */
331 /* */
332 /* DATE NAME DESCRIPTION */
333 /* */
334 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
335 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
336 /* verified memcpy use cases, */
337 /* resulting in version 6.1 */
338 /* */
339 /**************************************************************************/
_nx_dhcpv6_add_ia_address(NX_DHCPV6 * dhcpv6_ptr,UCHAR * buffer_ptr,UINT * index,UINT ia_index)340 UINT _nx_dhcpv6_add_ia_address(NX_DHCPV6 *dhcpv6_ptr, UCHAR *buffer_ptr, UINT *index, UINT ia_index)
341 {
342
343 ULONG message_word;
344 ULONG available_payload;
345
346 /* Set the IA option length. */
347 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_option_length = (6 * sizeof(ULONG));
348
349 /* Compute the available payload for DHCP data in the packet buffer. */
350 available_payload = (dhcpv6_ptr -> nx_dhcpv6_pool_ptr -> nx_packet_pool_payload_size -
351 (ULONG)sizeof(NX_IPV6_HEADER) - (ULONG)sizeof(NX_UDP_HEADER) - *index);
352
353 /* Check if the client IA address option will fit in the packet buffer. */
354 if (available_payload < (((ULONG)dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_option_length) + 4))
355 {
356
357 /* Hmmm... not enough! Can't do it. */
358 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
359 }
360
361 /* Check that the IA address option has been created. */
362 if (dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_op_code != NX_DHCPV6_OP_IA_ADDRESS)
363 {
364
365 /* Missing or invalid IA option and/or data. */
366 return NX_DHCPV6_INVALID_IA_DATA;
367 }
368
369 /* Make sure the IA address block has a non zero IP address. */
370 if ((dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0] == 0) &&
371 (dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[1] == 0) &&
372 (dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[2] == 0) &&
373 (dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[3] == 0))
374 {
375
376 return NX_DHCPV6_INVALID_IA_ADDRESS;
377 }
378
379 /* If the client has created an address option, apply it to the message. */
380
381 /* Clear memory to make the first word of the IA option header. */
382 memset(&message_word, 0, sizeof(ULONG));
383
384 /* Extract the IA data from the client record. */
385 message_word = (((ULONG)dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_op_code) << 16);
386 message_word |= dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_option_length;
387
388 /* Adjust for endianness. */
389 NX_CHANGE_ULONG_ENDIAN(message_word);
390
391 /* Copy IA data into the packet and update the index into the buffer. */
392 memcpy((buffer_ptr + (*index)), &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
393 (*index) += (ULONG)sizeof(ULONG);
394
395 /* Add the IPv6 address. */
396 /* Adjust for endianness. */
397 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0]);
398 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[1]);
399 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[2]);
400 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[3]);
401
402 /* Copy the Client preferred IPv6 address to the packet. */
403 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0]), sizeof(ULONG)); /* Use case of memcpy is verified. */
404 (*index) += (ULONG)sizeof(ULONG);
405 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[1]), sizeof(ULONG)); /* Use case of memcpy is verified. */
406 (*index) += (ULONG)sizeof(ULONG);
407 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[2]), sizeof(ULONG)); /* Use case of memcpy is verified. */
408 (*index) += (ULONG)sizeof(ULONG);
409 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[3]), sizeof(ULONG)); /* Use case of memcpy is verified. */
410 (*index) += (ULONG)sizeof(ULONG);
411
412 /* Swap bytes back. */
413 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0]);
414 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[1]);
415 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[2]);
416 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[3]);
417
418 /* Add the preferred lifetime and valid lifetime option. */
419 if((dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT) ||
420 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_CONFIRM) ||
421 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE) ||
422 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE))
423 {
424
425 /* When sending a confirm request, DHCPv6 Client should set its T1,T2,preferred-lifetime and
426 valid-lifetime to zero, as the server will ignore these fields, RFC3315,page41. */
427 memset((buffer_ptr + (*index)), 0, sizeof(ULONG));
428 (*index) += (ULONG)sizeof(ULONG);
429 memset((buffer_ptr + (*index)), 0, sizeof(ULONG));
430 (*index) += (ULONG)sizeof(ULONG);
431 }
432 else
433 {
434
435 /* Adjust for endianness. */
436 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_preferred_lifetime);
437 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime);
438
439 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_preferred_lifetime), sizeof(ULONG)); /* Use case of memcpy is verified. */
440 (*index) += (ULONG)sizeof(ULONG);
441 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime), sizeof(ULONG)); /* Use case of memcpy is verified. */
442 (*index) += (ULONG)sizeof(ULONG);
443
444 /* Swap bytes back. */
445 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_preferred_lifetime);
446 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime);
447
448 }
449
450 return NX_SUCCESS;
451 }
452
453
454 /**************************************************************************/
455 /* */
456 /* FUNCTION RELEASE */
457 /* */
458 /* _nx_dhcpv6_add_iana PORTABLE C */
459 /* 6.1 */
460 /* AUTHOR */
461 /* */
462 /* Yuxin Zhou, Microsoft Corporation */
463 /* */
464 /* DESCRIPTION */
465 /* */
466 /* This function adds the IANA option to the Client request packet */
467 /* using the Client IANA on record. Also checks to make sure adding */
468 /* the IANA option does not go past the end of the packet payload. If */
469 /* exist IA options, it will call the service to add the IA option */
470 /* within the IANA option data. It then updates the IANA length field */
471 /* for the embedded IA option. */
472 /* */
473 /* INPUT */
474 /* */
475 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
476 /* buffer_ptr Pointer to request packet buffer */
477 /* index Location into buffer to write data*/
478 /* */
479 /* OUTPUT */
480 /* */
481 /* status Actual completion status */
482 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
483 /* Not enough room for the IANA */
484 /* option in the packet payload */
485 /* CALLS */
486 /* */
487 /* _nx_dhcpv6_add_ia_address Adds the IA option to buffer */
488 /* memset Clears specified area of memory */
489 /* memcpy Copies specified area of memory */
490 /* */
491 /* CALLED BY */
492 /* */
493 /* _nx_dhcpv6_send_request Compiles and sends the Client */
494 /* DHCPv6 request */
495 /* */
496 /* RELEASE HISTORY */
497 /* */
498 /* DATE NAME DESCRIPTION */
499 /* */
500 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
501 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
502 /* verified memcpy use cases, */
503 /* resulting in version 6.1 */
504 /* */
505 /**************************************************************************/
_nx_dhcpv6_add_iana(NX_DHCPV6 * dhcpv6_ptr,UCHAR * buffer_ptr,UINT * index)506 UINT _nx_dhcpv6_add_iana(NX_DHCPV6 *dhcpv6_ptr, UCHAR *buffer_ptr, UINT *index)
507 {
508
509 UINT status;
510 UINT temp_index;
511 UINT ia_index;
512 UINT ia_length;
513 ULONG message_word;
514 ULONG available_payload;
515
516
517 /* Initialize the completion status variable. */
518 status = NX_SUCCESS;
519 ia_length = 0;
520
521 /* Compute the available payload in the packet buffer. */
522 available_payload = dhcpv6_ptr -> nx_dhcpv6_pool_ptr -> nx_packet_pool_payload_size -
523 (ULONG)sizeof(NX_IPV6_HEADER) - (ULONG)sizeof(NX_UDP_HEADER) - *index;
524
525 /* Check if the client IANA will fit in the packet buffer. */
526 if (available_payload < (((ULONG)dhcpv6_ptr -> nx_dhcpv6_iana.nx_option_length) + 4))
527 {
528
529 /* Hmmm... not enough! Can't do it. */
530 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
531 }
532
533 /* Save this location in the buffer. */
534 temp_index = *index;
535
536 /* Skip the option code and option lenght of IA_NA, write these option after padding the all IA option. */
537 (*index) += (ULONG)sizeof(ULONG);
538
539 /* Add the IA_NA ID. */
540 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_iana.nx_IA_NA_id);
541 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_iana.nx_IA_NA_id), sizeof(ULONG)); /* Use case of memcpy is verified. */
542 (*index) += (ULONG)sizeof(ULONG);
543 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_iana.nx_IA_NA_id);
544
545 /* Add the T1 and T2 option. */
546 if((dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT) ||
547 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_CONFIRM) ||
548 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE) ||
549 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE))
550 {
551
552 /* When sending a confirm request, DHCPv6 Client should set its T1,T2,preferred-lifetime and
553 valid-lifetime to zero, as the server will ignore these fields, RFC3315,page41. */
554 memset((buffer_ptr + (*index)), 0, sizeof(ULONG)); /* Use case of memcpy is verified. */
555 (*index) += (ULONG)sizeof(ULONG);
556 memset((buffer_ptr + (*index)), 0, sizeof(ULONG)); /* Use case of memcpy is verified. */
557 (*index) += (ULONG)sizeof(ULONG);
558 }
559 else
560 {
561
562 /* Adjust the data. */
563 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1);
564 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2);
565
566 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1), sizeof(ULONG)); /* Use case of memcpy is verified. */
567 (*index) += (ULONG)sizeof(ULONG);
568 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2), sizeof(ULONG)); /* Use case of memcpy is verified. */
569 (*index) += (ULONG)sizeof(ULONG);
570
571 /* Swap bytes back. */
572 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1);
573 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2);
574 }
575
576 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
577 {
578
579 /* Check the IA address status. */
580 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status)
581 {
582
583 /* Yes, so add one...*/
584 status = _nx_dhcpv6_add_ia_address(dhcpv6_ptr, buffer_ptr, index, ia_index);
585
586 /* Was the IA address option get appended successfully? */
587 if (status == NX_SUCCESS)
588 {
589
590 /* Update the IA address to record the IANA option length. */
591 ia_length = (UINT)(ia_length + dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_option_length + 4);
592 }
593 }
594 }
595
596 /* Clear memory to make the first word of the IA-NA header. */
597 memset(&message_word, 0, sizeof(ULONG));
598
599 /* Set the IA_NA option code and option length. */
600 dhcpv6_ptr -> nx_dhcpv6_iana.nx_op_code = NX_DHCPV6_OP_IA_NA;
601 dhcpv6_ptr -> nx_dhcpv6_iana.nx_option_length = (USHORT)(ia_length + 12);
602
603 /* Write the IANA opcode and data length into one word. */
604 message_word = (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_iana.nx_op_code)) << 16);
605 message_word |= dhcpv6_ptr -> nx_dhcpv6_iana.nx_option_length;
606
607 /* Adjust for endianness. */
608 NX_CHANGE_ULONG_ENDIAN(message_word);
609
610 /* Copy the word into the packet buffer going to the server. */
611 memcpy((buffer_ptr + temp_index), &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
612
613 return NX_SUCCESS;
614 }
615
616
617 /**************************************************************************/
618 /* */
619 /* FUNCTION RELEASE */
620 /* */
621 /* _nx_dhcpv6_add_option_request PORTABLE C */
622 /* 6.1 */
623 /* AUTHOR */
624 /* */
625 /* Yuxin Zhou, Microsoft Corporation */
626 /* */
627 /* DESCRIPTION */
628 /* */
629 /* This function adds the option request option to the Client request */
630 /* packet using the internal 'register' in the DHCPv6 Client instance */
631 /* for what DHCPv6 options have been set or cleared. Also checks to */
632 /* make sure it does not go past the end of the packet payload. */
633 /* */
634 /* INPUT */
635 /* */
636 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
637 /* buffer_ptr Pointer to request packet buffer */
638 /* index Location into buffer to write data*/
639 /* */
640 /* OUTPUT */
641 /* */
642 /* NX_SUCCESS Successful completion status */
643 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
644 /* Not enough room for the option */
645 /* request in the packet payload */
646 /* CALLS */
647 /* */
648 /* memset Clears specified area of memory */
649 /* memcpy Copies specified area of memory */
650 /* */
651 /* CALLED BY */
652 /* */
653 /* _nx_dhcpv6_send_request Compiles and sends the Client */
654 /* DHCPv6 request */
655 /* */
656 /* RELEASE HISTORY */
657 /* */
658 /* DATE NAME DESCRIPTION */
659 /* */
660 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
661 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
662 /* verified memcpy use cases, */
663 /* resulting in version 6.1 */
664 /* */
665 /**************************************************************************/
_nx_dhcpv6_add_option_request(NX_DHCPV6 * dhcpv6_ptr,UCHAR * buffer_ptr,UINT * index)666 UINT _nx_dhcpv6_add_option_request(NX_DHCPV6 *dhcpv6_ptr, UCHAR *buffer_ptr, UINT *index)
667 {
668
669 USHORT message_word;
670 USHORT option_list;
671 USHORT option_length = 0;
672 UCHAR *option_length_ptr;
673 ULONG available_payload;
674
675
676 /* Compute the available payload for DHCP data in the packet buffer. */
677 available_payload = (dhcpv6_ptr -> nx_dhcpv6_pool_ptr -> nx_packet_pool_payload_size -
678 (ULONG)sizeof(NX_IPV6_HEADER) - (ULONG)sizeof(NX_UDP_HEADER) - *index);
679
680 /* Check if the option request option will fit in the packet buffer. */
681 if (available_payload < (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_option_request.nx_option_length)) + 4))
682 {
683
684 /* Hmmm... not enough! Can't do it. */
685 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
686 }
687
688 /* Set a local variable for convenience. */
689 option_list = dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request;
690
691 /* Update the option code.
692 Adjust for endianness. */
693 NX_CHANGE_USHORT_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_code);
694
695 /* Copy the option code to the packet. */
696 memcpy((buffer_ptr + (*index)), &(dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_code), sizeof(USHORT)); /* Use case of memcpy is verified. */
697 *index += (ULONG)sizeof(USHORT);
698
699 /* Swap bytes back. */
700 NX_CHANGE_USHORT_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_code);
701
702 /* Record the option length pointer and skip it, update the option length after fill the option data. */
703 option_length_ptr = buffer_ptr + (*index);
704 *index += (ULONG)sizeof(USHORT);
705
706 /* Now check to see which options we add as option data: */
707
708 /* Is the DNS server option requested? */
709 if(option_list & NX_DHCPV6_DNS_SERVER_OPTION)
710 {
711
712 /* Yes, add this option code into the option request data. */
713 message_word = NX_DHCPV6_OP_DNS_SERVER;
714
715 /* Adjust for endianness. */
716 NX_CHANGE_USHORT_ENDIAN(message_word);
717
718 memcpy((buffer_ptr + (*index)), &message_word, sizeof(SHORT)); /* Use case of memcpy is verified. */
719
720 /* Update the location of the buffer write pointer. */
721 *index += (ULONG)sizeof(SHORT);
722 option_length = (USHORT)(option_length + sizeof(SHORT));
723 }
724
725 /* Is the timeS server option requested? */
726 if(option_list & NX_DHCPV6_SNTP_SERVER_OPTION)
727 {
728
729 /* Yes, add this option code into the option request data. */
730 message_word = NX_DHCPV6_OP_SNTP_SERVER;
731
732 /* Adjust for endianness. */
733 NX_CHANGE_USHORT_ENDIAN(message_word);
734
735 memcpy((buffer_ptr + (*index)), &message_word, sizeof(SHORT)); /* Use case of memcpy is verified. */
736
737 /* Update the location of the buffer write pointer. */
738 *index += (ULONG)sizeof(SHORT);
739 option_length = (USHORT)(option_length + sizeof(SHORT));
740 }
741
742 /* Is the time zone option requested? */
743 if(option_list & NX_DHCPV6_NEW_POSIX_TIMEZONE_OPTION)
744 {
745
746 /* Yes, add this option code into the option request data. */
747 message_word = NX_DHCPV6_OP_NEW_POSIX_TIMEZONE;
748
749 /* Adjust for endianness. */
750 NX_CHANGE_USHORT_ENDIAN(message_word);
751
752 memcpy((buffer_ptr + (*index)), &message_word, sizeof(SHORT)); /* Use case of memcpy is verified. */
753
754 /* Update the location of the buffer write pointer. */
755 *index += (ULONG)sizeof(SHORT);
756 option_length = (USHORT)(option_length + sizeof(SHORT));
757 }
758
759 /* Is the domain name option requested? */
760 if(option_list & NX_DHCPV6_DOMAIN_NAME_OPTION)
761 {
762
763 /* Yes, add this option code into the option request data. */
764 message_word = NX_DHCPV6_OP_DOMAIN_NAME;
765
766 /* Adjust for endianness. */
767 NX_CHANGE_USHORT_ENDIAN(message_word);
768
769 memcpy((buffer_ptr + (*index)), &message_word, sizeof(SHORT)); /* Use case of memcpy is verified. */
770
771 /* Update the location of the buffer write pointer. */
772 *index += (ULONG)sizeof(SHORT);
773 option_length = (USHORT)(option_length + sizeof(SHORT));
774 }
775
776 /* Is the fully qualified domain name option requested?
777 A client MUST only include the Client FQDN option in SOLICIT, REQUEST, RENEW, or REBIND message.
778 A client that sends the Client FQDN option MUST also include the option in the Option Requst option
779 if it expects the server to include the Client FQDN option in any responses. RFC4704, Section5, Page7. */
780 if(((dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT) ||
781 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST) ||
782 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_RENEW) ||
783 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_REBIND)) &&
784 (option_list & NX_DHCPV6_CLIENT_FQDN_OPTION))
785 {
786
787 /* Yes, add this option code into the option request data. */
788 message_word = NX_DHCPV6_OP_CLIENT_FQDN;
789
790 /* Adjust for endianness. */
791 NX_CHANGE_USHORT_ENDIAN(message_word);
792
793 memcpy((buffer_ptr + (*index)), &message_word, sizeof(SHORT)); /* Use case of memcpy is verified. */
794
795 /* Update the location of the buffer write pointer. */
796 *index += (ULONG)sizeof(SHORT);
797 option_length = (USHORT)(option_length + sizeof(SHORT));
798 }
799
800 /* Now record and update the option lenght. */
801 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_option_length = option_length;
802 NX_CHANGE_USHORT_ENDIAN(option_length);
803 memcpy(option_length_ptr, &option_length, sizeof(SHORT)); /* Use case of memcpy is verified. */
804
805 return NX_SUCCESS;
806 }
807
808
809 /**************************************************************************/
810 /* */
811 /* FUNCTION RELEASE */
812 /* */
813 /* _nx_dhcpv6_add_server_duid PORTABLE C */
814 /* 6.1 */
815 /* AUTHOR */
816 /* */
817 /* Yuxin Zhou, Microsoft Corporation */
818 /* */
819 /* DESCRIPTION */
820 /* */
821 /* This function adds the server DUID to the Client request packet */
822 /* based on the server DUID on record, checking to make sure it does */
823 /* not go past the end of the packet payload. */
824 /* */
825 /* INPUT */
826 /* */
827 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
828 /* received_buffer Pointer to server reply */
829 /* length Size of server reply buffer */
830 /* */
831 /* OUTPUT */
832 /* */
833 /* NX_SUCCESS Successful completion status */
834 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
835 /* Not enough room for the server */
836 /* DUID in the packet payload */
837 /* CALLS */
838 /* */
839 /* memset Clears specified area of memory */
840 /* memcpy Copies specified area of memory */
841 /* */
842 /* CALLED BY */
843 /* */
844 /* _nx_dhcpv6_send_request Compiles and sends the Client */
845 /* DHCPv6 request */
846 /* */
847 /* RELEASE HISTORY */
848 /* */
849 /* DATE NAME DESCRIPTION */
850 /* */
851 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
852 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
853 /* verified memcpy use cases, */
854 /* resulting in version 6.1 */
855 /* */
856 /**************************************************************************/
_nx_dhcpv6_add_server_duid(NX_DHCPV6 * dhcpv6_ptr,UCHAR * buffer_ptr,UINT * index)857 UINT _nx_dhcpv6_add_server_duid(NX_DHCPV6 *dhcpv6_ptr, UCHAR *buffer_ptr, UINT *index)
858 {
859
860 ULONG message_word;
861 ULONG available_payload;
862 UCHAR mac[8];
863 UINT i = 0;
864
865
866 /* Compute the available payload for DHCP data in the packet buffer. */
867 available_payload = (dhcpv6_ptr -> nx_dhcpv6_pool_ptr -> nx_packet_pool_payload_size -
868 (ULONG)sizeof(NX_IPV6_HEADER) - (ULONG)sizeof(NX_UDP_HEADER) - *index);
869
870 /* Check if the largest possible server DUID will fit in the packet buffer. */
871 if (available_payload < (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_option_length)) + 4))
872 {
873
874 /* Hmmm... not enough! Can't do it. */
875 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
876 }
877
878 /* Make sure the Client has a valid Server DUID. */
879 if (dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_op_code != NX_DHCPV6_OP_SERVER_ID)
880 {
881
882 /* Missing or invalid option data. */
883 return NX_DHCPV6_INVALID_SERVER_DUID;
884 }
885
886 /* Build the header from the client's record of its DHCPv6 Server DUID. */
887 message_word = (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_op_code)) << 16);
888 message_word |= (dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_option_length);
889
890 /* Adjust for endianness. */
891 NX_CHANGE_ULONG_ENDIAN(message_word);
892
893 /* Copy first half of the Server DUID option to packet buffer. */
894 memcpy((buffer_ptr + (*index)), &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
895 *index += (ULONG)sizeof(ULONG);
896
897 /* Build the DUID type and hardware type. */
898 message_word = (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_duid_type)) << 16);
899 message_word |= dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_hardware_type;
900
901 /* Adjust for endianness. */
902 NX_CHANGE_ULONG_ENDIAN(message_word);
903
904 /* Set up the DUID type and hardware type. */
905 memcpy((buffer_ptr + (*index)), &message_word, sizeof(UINT)); /* Use case of memcpy is verified. */
906 *index += (ULONG)sizeof(UINT);
907
908 /* Include the 'time' field if this is a Link layer time DUID type. */
909 if (dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_duid_type == NX_DHCPV6_DUID_TYPE_LINK_TIME)
910 {
911
912 /* Build the time. */
913 message_word = dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_duid_time;
914
915 /* Adjust for endianness. */
916 NX_CHANGE_ULONG_ENDIAN(message_word);
917
918 /* Set up the time. */
919 memcpy((buffer_ptr + (*index)), &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
920 (*index) += (ULONG)sizeof(ULONG);
921 }
922
923 /* Build the link layer address. */
924 if (dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_ETHERNET)
925 {
926
927 /* The length of link layer address is 48 bit. */
928
929 /* Build the MSW. */
930 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw >> 8);
931 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw);
932 }
933 else if(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_EUI_64)
934 {
935
936 /* The length of link layer address is 64 bits. */
937
938 /* Build the MSW. */
939 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw >> 24);
940 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw >> 16);
941 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw >> 8);
942 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw);
943 }
944
945 /* Build the LSW. */
946 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_lsw >> 24);
947 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_lsw >> 16);
948 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_lsw >> 8);
949 mac[i++] = (UCHAR)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_lsw);
950
951 /* Set up the link layer address. */
952 memcpy((buffer_ptr + (*index)), mac, i); /* Use case of memcpy is verified. */
953 (*index) += i;
954
955 return NX_SUCCESS;
956 }
957
958
959 /**************************************************************************/
960 /* */
961 /* FUNCTION RELEASE */
962 /* */
963 /* _nx_dhcpv6_add_client_FQDN PORTABLE C */
964 /* 6.1 */
965 /* AUTHOR */
966 /* */
967 /* Yuxin Zhou, Microsoft Corporation */
968 /* */
969 /* DESCRIPTION */
970 /* */
971 /* This function adds the DHCPv6 Client FQDN Option to the Client */
972 /* request packet , checking to make sure it does not go past the end */
973 /* of the packet payload. */
974 /* */
975 /* INPUT */
976 /* */
977 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
978 /* received_buffer Pointer to server reply */
979 /* length Size of server reply buffer */
980 /* */
981 /* OUTPUT */
982 /* */
983 /* NX_SUCCESS Successful completion status */
984 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
985 /* Not enough room for the server */
986 /* DUID in the packet payload */
987 /* CALLS */
988 /* */
989 /* memset Clears specified area of memory */
990 /* memcpy Copies specified area of memory */
991 /* */
992 /* CALLED BY */
993 /* */
994 /* _nx_dhcpv6_send_request Compiles and sends the Client */
995 /* DHCPv6 request */
996 /* */
997 /* RELEASE HISTORY */
998 /* */
999 /* DATE NAME DESCRIPTION */
1000 /* */
1001 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1002 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
1003 /* verified memcpy use cases, */
1004 /* resulting in version 6.1 */
1005 /* */
1006 /**************************************************************************/
_nx_dhcpv6_add_client_FQDN(NX_DHCPV6 * dhcpv6_ptr,UCHAR * buffer_ptr,UINT * index)1007 UINT _nx_dhcpv6_add_client_FQDN(NX_DHCPV6 *dhcpv6_ptr, UCHAR *buffer_ptr, UINT *index)
1008 {
1009
1010 ULONG message_word;
1011 ULONG available_payload;
1012 UINT domain_name_length;
1013
1014
1015 /* Compute the available payload for DHCP data in the packet buffer. */
1016 available_payload = (dhcpv6_ptr -> nx_dhcpv6_pool_ptr -> nx_packet_pool_payload_size -
1017 (ULONG)sizeof(NX_IPV6_HEADER) - (ULONG)sizeof(NX_UDP_HEADER) - *index);
1018
1019 /* Check if the largest possible server DUID will fit in the packet buffer. */
1020 if (available_payload < (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_option_length)) + 4))
1021 {
1022
1023 /* Hmmm... not enough! Can't do it. */
1024 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
1025 }
1026
1027 memset(&message_word, 0, sizeof(ULONG));
1028
1029 /* Set the option code and option length. */
1030 message_word = (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_op_code)) << 16);
1031 message_word |= (dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_op_length);
1032
1033 /* Adjust for endianness. */
1034 NX_CHANGE_ULONG_ENDIAN(message_word);
1035
1036 /* Add the option code and option length into packet buffer. */
1037 memcpy((buffer_ptr + (*index)), &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
1038 *index += (ULONG)sizeof(ULONG);
1039
1040 /* Add the flags into packet buffer. */
1041 *(buffer_ptr + (*index)) = dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_flags;
1042 *index += 1;
1043
1044 /* Encode the domain name into the packet buffer. */
1045 domain_name_length = _nx_dhcpv6_name_string_encode(buffer_ptr + (*index), (UCHAR *)dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_domain_name);
1046 *index += domain_name_length;
1047
1048 return NX_SUCCESS;
1049 }
1050
1051
1052 /**************************************************************************/
1053 /* */
1054 /* FUNCTION RELEASE */
1055 /* */
1056 /* _nxe_dhcpv6_client_create PORTABLE C */
1057 /* 6.1 */
1058 /* AUTHOR */
1059 /* */
1060 /* Yuxin Zhou, Microsoft Corporation */
1061 /* */
1062 /* DESCRIPTION */
1063 /* */
1064 /* This function performs error checking on the NetX create dhcpv6 */
1065 /* client service. */
1066 /* */
1067 /* INPUT */
1068 /* */
1069 /* dhcpv6_ptr Pointer to DHCPV6 Client */
1070 /* ip_ptr Pointer to Client IP instance */
1071 /* name_ptr DHCPV6 name pointer */
1072 /* packet_pool_ptr Pointer to Client packet pool */
1073 /* stack_ptr Pointer to free memory */
1074 /* stack_size Size of client stack memory */
1075 /* dhcpv6_state_change_notify Client state change handler */
1076 /* dhcpv6_server_error_handler Server error status handler */
1077 /* */
1078 /* OUTPUT */
1079 /* */
1080 /* status Completion status */
1081 /* NX_PTR_ERROR Invalid pointer input */
1082 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
1083 /* */
1084 /* CALLS */
1085 /* */
1086 /* _nx_dhcpv6_client_create Actual Client create function */
1087 /* */
1088 /* CALLED BY */
1089 /* */
1090 /* Application Code */
1091 /* */
1092 /* RELEASE HISTORY */
1093 /* */
1094 /* DATE NAME DESCRIPTION */
1095 /* */
1096 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1097 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1098 /* resulting in version 6.1 */
1099 /* */
1100 /**************************************************************************/
_nxe_dhcpv6_client_create(NX_DHCPV6 * dhcpv6_ptr,NX_IP * ip_ptr,CHAR * name_ptr,NX_PACKET_POOL * packet_pool_ptr,VOID * stack_ptr,ULONG stack_size,VOID (* dhcpv6_state_change_notify)(struct NX_DHCPV6_STRUCT * dhcpv6_ptr,UINT old_state,UINT new_state),VOID (* dhcpv6_server_error_handler)(struct NX_DHCPV6_STRUCT * dhcpv6_ptr,UINT op_code,UINT status_code,UINT message_type))1101 UINT _nxe_dhcpv6_client_create(NX_DHCPV6 *dhcpv6_ptr, NX_IP *ip_ptr, CHAR *name_ptr,
1102 NX_PACKET_POOL *packet_pool_ptr, VOID *stack_ptr, ULONG stack_size,
1103 VOID (*dhcpv6_state_change_notify)(struct NX_DHCPV6_STRUCT *dhcpv6_ptr, UINT old_state, UINT new_state),
1104 VOID (*dhcpv6_server_error_handler)(struct NX_DHCPV6_STRUCT *dhcpv6_ptr, UINT op_code, UINT status_code, UINT message_type))
1105 {
1106
1107 UINT status;
1108
1109
1110 /* Check for invalid pointer input. */
1111 if (!dhcpv6_ptr ||!ip_ptr || !packet_pool_ptr || !stack_ptr)
1112 {
1113
1114 return NX_PTR_ERROR;
1115 }
1116
1117 /* Check for invalid non pointer input. */
1118 if ((ip_ptr -> nx_ip_id != NX_IP_ID) || (stack_size < TX_MINIMUM_STACK))
1119 {
1120
1121 return NX_DHCPV6_PARAM_ERROR;
1122 }
1123
1124 /* Call actual DHCPV6 create service. */
1125 status = _nx_dhcpv6_client_create(dhcpv6_ptr, ip_ptr, name_ptr, packet_pool_ptr, stack_ptr, stack_size,
1126 dhcpv6_state_change_notify, dhcpv6_server_error_handler);
1127
1128 /* Return status. */
1129 return(status);
1130 }
1131
1132
1133 /**************************************************************************/
1134 /* */
1135 /* FUNCTION RELEASE */
1136 /* */
1137 /* _nx_dhcpv6_client_create PORTABLE C */
1138 /* 6.1 */
1139 /* AUTHOR */
1140 /* */
1141 /* Yuxin Zhou, Microsoft Corporation */
1142 /* */
1143 /* DESCRIPTION */
1144 /* */
1145 /* This function creates the DHCPv6 Client instance with a Netx packet */
1146 /* pool, processing thread, and various flag event queues, timers and */
1147 /* mutexes necessary for DHCPv6 Client operations. Reocrd the DHCPv6 */
1148 /* pointer for DAD callback function process. */
1149 /* */
1150 /* INPUT */
1151 /* */
1152 /* dhcpv6_ptr Pointer to DHCPV6 Client */
1153 /* ip_ptr Pointer to Client IP instance */
1154 /* name_ptr DHCPV6 name pointer */
1155 /* packet_pool_ptr Pointer to Client packet pool */
1156 /* stack_ptr Pointer to free memory */
1157 /* stack_size Size of Client stack memory */
1158 /* dhcpv6_state_change_notify Client state change handler */
1159 /* dhcpv6_server_error_handler Server error status handler */
1160 /* */
1161 /* OUTPUT */
1162 /* */
1163 /* status Actual completion status */
1164 /* NX_SUCCESS Successful completion status */
1165 /* */
1166 /* CALLS */
1167 /* */
1168 /* tx_event_flags_create Create ThreadX flag event queue*/
1169 /* tx_mutex_create Create mutex lock on resource */
1170 /* nx_packet_pool_delete Delete the DHCPV6 packet pool */
1171 /* nx_udp_socket_create Create the DHCPV6 UDP socket */
1172 /* nx_udp_socket_delete Delete the DHCPV6 UDP socket */
1173 /* tx_mutex_create Create DHCPV6 mutex */
1174 /* tx_mutex_delete Delete DHCPV6 mutex */
1175 /* tx_thread_create Create DHCPV6 thread */
1176 /* tx_timer_create Create DHCPV6 timer */
1177 /* tx_timer_delete Delete DHCPV6 timer */
1178 /* nxd_ipv6_address_change_notify Set the DAD callback function */
1179 /* */
1180 /* CALLED BY */
1181 /* */
1182 /* Application Code */
1183 /* */
1184 /* RELEASE HISTORY */
1185 /* */
1186 /* DATE NAME DESCRIPTION */
1187 /* */
1188 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1189 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1190 /* resulting in version 6.1 */
1191 /* */
1192 /**************************************************************************/
_nx_dhcpv6_client_create(NX_DHCPV6 * dhcpv6_ptr,NX_IP * ip_ptr,CHAR * name_ptr,NX_PACKET_POOL * packet_pool_ptr,VOID * stack_ptr,ULONG stack_size,VOID (* dhcpv6_state_change_notify)(struct NX_DHCPV6_STRUCT * dhcpv6_ptr,UINT old_state,UINT new_state),VOID (* dhcpv6_server_error_handler)(struct NX_DHCPV6_STRUCT * dhcpv6_ptr,UINT op_code,UINT status_code,UINT message_type))1193 UINT _nx_dhcpv6_client_create(NX_DHCPV6 *dhcpv6_ptr, NX_IP *ip_ptr, CHAR *name_ptr,
1194 NX_PACKET_POOL *packet_pool_ptr, VOID *stack_ptr, ULONG stack_size,
1195 VOID (*dhcpv6_state_change_notify)(struct NX_DHCPV6_STRUCT *dhcpv6_ptr, UINT old_state, UINT new_state),
1196 VOID (*dhcpv6_server_error_handler)(struct NX_DHCPV6_STRUCT *dhcpv6_ptr, UINT op_code, UINT status_code, UINT message_type))
1197
1198 {
1199
1200 UINT status;
1201
1202
1203 /* Initialize the DHCPV6 control block to zero. */
1204 memset((void *) dhcpv6_ptr, 0, sizeof(NX_DHCPV6));
1205
1206 /* Initialize the DHCPV6 Server and Relay multicast address. */
1207 memset(&All_DHCPv6_Relay_Servers_Address, 0, sizeof(NXD_ADDRESS));
1208 All_DHCPv6_Relay_Servers_Address.nxd_ip_version = NX_IP_VERSION_V6;
1209 All_DHCPv6_Relay_Servers_Address.nxd_ip_address.v6[0] = 0xff020000;
1210 All_DHCPv6_Relay_Servers_Address.nxd_ip_address.v6[1] = 0x00000000;
1211 All_DHCPv6_Relay_Servers_Address.nxd_ip_address.v6[2] = 0x00000000;
1212 All_DHCPv6_Relay_Servers_Address.nxd_ip_address.v6[3] = 0x00010002;
1213
1214 /* Set the destination address. */
1215 COPY_NXD_ADDRESS(&All_DHCPv6_Relay_Servers_Address, &(dhcpv6_ptr -> nx_dhcpv6_client_destination_address));
1216
1217 /* Set the DHCPv6 IP pointer. */
1218 dhcpv6_ptr -> nx_dhcpv6_ip_ptr = ip_ptr;
1219
1220 /* Set the DHCPV6 name. */
1221 dhcpv6_ptr -> nx_dhcpv6_name = name_ptr;
1222
1223 /* If multihome support is available, default the client DHCP network to the primary interface. */
1224 dhcpv6_ptr -> nx_dhcpv6_client_interface_index = 0;
1225
1226 /* Set the Client packet pool for sending messages to the Server. */
1227 dhcpv6_ptr -> nx_dhcpv6_pool_ptr = packet_pool_ptr;
1228
1229 /* Create the IP timer event flag instance. */
1230 status = tx_event_flags_create(&(dhcpv6_ptr -> nx_dhcpv6_events), "DHCPv6 Client Timer Events Queue");
1231
1232 /* Check for error. */
1233 if (status != TX_SUCCESS)
1234 {
1235
1236 return status;
1237 }
1238
1239 /* Create the DHCPV6 client mutex. */
1240 status = tx_mutex_create(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), "DHCPV6 Client Process State", TX_NO_INHERIT);
1241
1242 /* Determine if the mutexes creation was successful. */
1243 if (status)
1244 {
1245
1246 /* Delete the flag queue. */
1247 tx_event_flags_delete(&dhcpv6_ptr -> nx_dhcpv6_events);
1248
1249 /* No, return error status. */
1250 return status;
1251 }
1252
1253 /* Create the DHCPV6 timer for keeping track of the IP lease's time remaining before expiration. */
1254 status = tx_timer_create(&(dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer), "NetX DHCPV6 Client IP Lease timer",
1255 _nx_dhcpv6_IP_lifetime_timeout_entry, (ULONG)(ALIGN_TYPE)dhcpv6_ptr,
1256 (NX_DHCPV6_IP_LIFETIME_TIMER_INTERVAL * NX_DHCPV6_TICKS_PER_SECOND),
1257 (NX_DHCPV6_IP_LIFETIME_TIMER_INTERVAL * NX_DHCPV6_TICKS_PER_SECOND),
1258 TX_NO_ACTIVATE);
1259
1260 NX_TIMER_EXTENSION_PTR_SET(&(dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer), dhcpv6_ptr)
1261
1262 /* Determine if the timer creation was successful. */
1263 if (status)
1264 {
1265
1266 /* Delete the mutex. */
1267 tx_mutex_delete(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
1268
1269 /* Delete all the timers, since we don't know which create call fails. */
1270 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
1271
1272 /* Delete the UDP socket. */
1273 nx_udp_socket_delete(&(dhcpv6_ptr -> nx_dhcpv6_socket));
1274
1275 /* Delete the packet pool. */
1276 /* Delete the flag queue. */
1277 tx_event_flags_delete(&dhcpv6_ptr -> nx_dhcpv6_events);
1278
1279 /* No, return error status. */
1280 return status;
1281 }
1282
1283 /* Create the DHCPV6 timer for keeping track of the DHCPv6 Client session time. */
1284 status = tx_timer_create(&(dhcpv6_ptr -> nx_dhcpv6_session_timer), "NetX DHCPV6 Client Session Duration timer",
1285 _nx_dhcpv6_session_timeout_entry, (ULONG)(ALIGN_TYPE)dhcpv6_ptr,
1286 (NX_DHCPV6_SESSION_TIMER_INTERVAL * NX_DHCPV6_TICKS_PER_SECOND),
1287 (NX_DHCPV6_SESSION_TIMER_INTERVAL * NX_DHCPV6_TICKS_PER_SECOND),
1288 TX_NO_ACTIVATE);
1289
1290 NX_TIMER_EXTENSION_PTR_SET(&(dhcpv6_ptr -> nx_dhcpv6_session_timer), dhcpv6_ptr)
1291
1292 /* Determine if the timers creation was successful. */
1293 if (status)
1294 {
1295
1296 /* Delete the mutex. */
1297 tx_mutex_delete(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
1298
1299 /* Delete all the timers, since we don't know which create call fails. */
1300 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
1301 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer));
1302
1303 /* Delete the UDP socket. */
1304 nx_udp_socket_delete(&(dhcpv6_ptr -> nx_dhcpv6_socket));
1305
1306 /* Delete the packet pool. */
1307 /* Delete the flag queue. */
1308 tx_event_flags_delete(&dhcpv6_ptr -> nx_dhcpv6_events);
1309
1310 /* No, return error status. */
1311 return status;
1312 }
1313
1314 /* Create the DHCPV6 processing thread. */
1315 status = tx_thread_create(&(dhcpv6_ptr -> nx_dhcpv6_thread), "NetX DHCPV6 Client", _nx_dhcpv6_thread_entry,
1316 (ULONG)(ALIGN_TYPE)dhcpv6_ptr, stack_ptr, stack_size,
1317 NX_DHCPV6_THREAD_PRIORITY, NX_DHCPV6_THREAD_PRIORITY, 1, TX_DONT_START);
1318
1319 NX_THREAD_EXTENSION_PTR_SET(&(dhcpv6_ptr -> nx_dhcpv6_thread), dhcpv6_ptr)
1320
1321 /* Determine if the thread creation was successful. */
1322 if (status)
1323 {
1324
1325 /* Delete the timers. */
1326 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer));
1327 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
1328
1329 /* Delete the mutex. */
1330 tx_mutex_delete(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
1331
1332 /* Delete the flag queue. */
1333 tx_event_flags_delete(&dhcpv6_ptr -> nx_dhcpv6_events);
1334
1335 /* No, return error status. */
1336 return status;
1337 }
1338
1339 /* Create the DHCP socket. */
1340 status = nx_udp_socket_create(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, &(dhcpv6_ptr -> nx_dhcpv6_socket), "NetX DHCPV6 Client",
1341 NX_DHCPV6_TYPE_OF_SERVICE, NX_DONT_FRAGMENT,
1342 NX_DHCPV6_TIME_TO_LIVE, NX_DHCPV6_QUEUE_DEPTH);
1343
1344 /* Was the socket creation successful? */
1345 if (status != NX_SUCCESS)
1346 {
1347
1348 /* Delete the timers. */
1349 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer));
1350 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
1351
1352 /* Delete the mutex. */
1353 tx_mutex_delete(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
1354
1355 /* Delete the flag queue. */
1356 tx_event_flags_delete(&dhcpv6_ptr -> nx_dhcpv6_events);
1357
1358 tx_thread_delete(&dhcpv6_ptr -> nx_dhcpv6_thread);
1359
1360 /* No, return error status. */
1361 return status;
1362 }
1363
1364 /* Set the Client in the initial state. */
1365 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
1366
1367 /* Set the 'time accrued' on the Client global IP address at zero seconds. */
1368 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = 0;
1369
1370 /* Update the DHCPv6 Client ID. */
1371 dhcpv6_ptr -> nx_dhcpv6_id = NX_DHCPV6_ID;
1372
1373 /* Save the DHCPV6 instance pointer in the socket. */
1374 dhcpv6_ptr -> nx_dhcpv6_socket.nx_udp_socket_reserved_ptr = (void *) dhcpv6_ptr;
1375
1376 /* Set up the elapsed time for the anticipated message exchange with the DHCPv6 Server. */
1377 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_op_code = NX_DHCPV6_OP_ELAPSED_TIME;
1378 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
1379
1380 /* Set the elapsed time option data length, minus the option header. */
1381 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_op_length = sizeof(NX_DHCPV6_ELAPSED_TIME) - 4;
1382
1383 /* Set the option request option code. Cannot set the data length as yet. */
1384 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_code = NX_DHCPV6_OP_OPTION_REQUEST;
1385
1386 /* Assign the various handlers (server error messages and state change). */
1387 dhcpv6_ptr -> nx_dhcpv6_state_change_callback = dhcpv6_state_change_notify;
1388 dhcpv6_ptr -> nx_dhcpv6_server_error_handler = dhcpv6_server_error_handler;
1389
1390 #if !defined (NX_DISABLE_IPV6_DAD) && defined (NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY)
1391 /* Set the callback function to detect DAD process.
1392 If DAD failure, automatically set event to send DHCP decline meessage.
1393 Notice: other modules should not set the address change notify function again. */
1394 status = nxd_ipv6_address_change_notify(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, _nx_dhcpv6_ipv6_address_DAD_notify);
1395
1396 /* Was the callback notify fucntion creation successful? */
1397 if (status != NX_SUCCESS)
1398 {
1399
1400 /* Delete the timers. */
1401 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer));
1402 tx_timer_delete(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
1403
1404 /* Delete the mutex. */
1405 tx_mutex_delete(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
1406
1407 /* Delete the flag queue. */
1408 tx_event_flags_delete(&dhcpv6_ptr -> nx_dhcpv6_events);
1409
1410 /* Delete the thread. */
1411 tx_thread_delete(&dhcpv6_ptr -> nx_dhcpv6_thread);
1412
1413 /* Delete the thread. */
1414 nx_udp_socket_delete(&(dhcpv6_ptr -> nx_dhcpv6_socket));
1415
1416 /* No, return error status. */
1417 return status;
1418 }
1419 #endif
1420
1421 /* Keep the DHCPv6 instance for DAD callback notify. */
1422 _nx_dhcpv6_DAD_ptr = dhcpv6_ptr;
1423
1424 /* Return a successful status. */
1425 return(NX_SUCCESS);
1426 }
1427
1428
1429 /**************************************************************************/
1430 /* */
1431 /* FUNCTION RELEASE */
1432 /* */
1433 /* _nxe_dhcpv6_client_delete PORTABLE C */
1434 /* 6.1 */
1435 /* AUTHOR */
1436 /* */
1437 /* Yuxin Zhou, Microsoft Corporation */
1438 /* */
1439 /* DESCRIPTION */
1440 /* */
1441 /* This function performs error checking on the NetX delete dhcpv6 */
1442 /* client service. */
1443 /* */
1444 /* INPUT */
1445 /* */
1446 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
1447 /* */
1448 /* OUTPUT */
1449 /* */
1450 /* OUTPUT */
1451 /* */
1452 /* status Completion status */
1453 /* NX_PTR_ERROR Invalid pointer input */
1454 /* */
1455 /* */
1456 /* CALLS */
1457 /* */
1458 /* _nx_dhcpv6_client_delete Actual DHCPV6 delete function */
1459 /* */
1460 /* CALLED BY */
1461 /* */
1462 /* Application Code */
1463 /* */
1464 /* RELEASE HISTORY */
1465 /* */
1466 /* DATE NAME DESCRIPTION */
1467 /* */
1468 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1469 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1470 /* resulting in version 6.1 */
1471 /* */
1472 /**************************************************************************/
_nxe_dhcpv6_client_delete(NX_DHCPV6 * dhcpv6_ptr)1473 UINT _nxe_dhcpv6_client_delete(NX_DHCPV6 *dhcpv6_ptr)
1474 {
1475
1476 UINT status;
1477
1478
1479 /* Check for invalid input pointers. */
1480 if ((dhcpv6_ptr == NX_NULL) || (dhcpv6_ptr -> nx_dhcpv6_id != NX_DHCPV6_ID))
1481 {
1482 return(NX_PTR_ERROR);
1483 }
1484
1485 /* Check for appropriate caller. */
1486 NX_THREADS_ONLY_CALLER_CHECKING
1487
1488 /* Call actual DHCPV6 delete service. */
1489 status = _nx_dhcpv6_client_delete(dhcpv6_ptr);
1490
1491 /* Return commpletion status. */
1492 return(status);
1493 }
1494
1495
1496 /**************************************************************************/
1497 /* */
1498 /* FUNCTION RELEASE */
1499 /* */
1500 /* _nx_dhcpv6_client_delete PORTABLE C */
1501 /* 6.1 */
1502 /* AUTHOR */
1503 /* */
1504 /* Yuxin Zhou, Microsoft Corporation */
1505 /* */
1506 /* DESCRIPTION */
1507 /* */
1508 /* This function deletes the DHCPV6 Client instance and releases all */
1509 /* NetX Duo and ThreadX resources. */
1510 /* */
1511 /* INPUT */
1512 /* */
1513 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
1514 /* */
1515 /* OUTPUT */
1516 /* */
1517 /* NX_SUCCESS Successful Completion status */
1518 /* */
1519 /* CALLS */
1520 /* */
1521 /* nx_udp_socket_unbind Release DHCPV6 UDP socket port*/
1522 /* nx_udp_socket_delete Delete the DHCPV6 UDP socket */
1523 /* tx_thread_terminate Terminate DHCPV6 thread */
1524 /* tx_thread_delete Delete DHCPV6 thread */
1525 /* tx_timer_delete Delete DHCPV6 timers */
1526 /* tx_mutex_delete Delete DHCPV6 mutexes */
1527 /* tx_event_flags_delete Delete DHCPV6 flag queue */
1528 /* */
1529 /* CALLED BY */
1530 /* */
1531 /* Application Code */
1532 /* */
1533 /* RELEASE HISTORY */
1534 /* */
1535 /* DATE NAME DESCRIPTION */
1536 /* */
1537 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1538 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1539 /* resulting in version 6.1 */
1540 /* */
1541 /**************************************************************************/
_nx_dhcpv6_client_delete(NX_DHCPV6 * dhcpv6_ptr)1542 UINT _nx_dhcpv6_client_delete(NX_DHCPV6 *dhcpv6_ptr)
1543 {
1544
1545
1546 /* Terminate the DHCPV6 processing thread. */
1547 tx_thread_terminate(&(dhcpv6_ptr -> nx_dhcpv6_thread));
1548
1549 /* Delete the DHCPV6 processing thread. */
1550 tx_thread_delete(&(dhcpv6_ptr -> nx_dhcpv6_thread));
1551
1552 /* Delete the flag event queue. */
1553 tx_event_flags_delete(&dhcpv6_ptr -> nx_dhcpv6_events);
1554
1555 /* Delete the timers */
1556 tx_timer_delete(&(dhcpv6_ptr->nx_dhcpv6_IP_lifetime_timer));
1557 tx_timer_delete(&(dhcpv6_ptr->nx_dhcpv6_session_timer));
1558
1559 /* Delete the mutex. */
1560 tx_mutex_delete(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
1561
1562 /* Release the UDP socket port. */
1563 nx_udp_socket_unbind(&(dhcpv6_ptr -> nx_dhcpv6_socket));
1564
1565 /* Delete the UDP socket. */
1566 nx_udp_socket_delete(&(dhcpv6_ptr -> nx_dhcpv6_socket));
1567
1568 /* Clear the dhcpv6 structure ID. */
1569 dhcpv6_ptr -> nx_dhcpv6_id = 0;
1570
1571 /* Return a successful status. */
1572 return(NX_SUCCESS);
1573 }
1574
1575
1576 /**************************************************************************/
1577 /* */
1578 /* FUNCTION RELEASE */
1579 /* */
1580 /* _nxe_dhcpv6_create_client_duid PORTABLE C */
1581 /* 6.1 */
1582 /* AUTHOR */
1583 /* */
1584 /* Yuxin Zhou, Microsoft Corporation */
1585 /* */
1586 /* DESCRIPTION */
1587 /* */
1588 /* This function performs error checking on the create Client DUID */
1589 /* service. */
1590 /* */
1591 /* INPUT */
1592 /* */
1593 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
1594 /* duid_type Type of DUID (link layer +/- time)*/
1595 /* hardware_type Network hardware type e.g IEEE 802*/
1596 /* time Time stamp unique DUID identifier */
1597 /* */
1598 /* OUTPUT */
1599 /* */
1600 /* status Actual completion status */
1601 /* NX_PTR_ERROR Invalid pointer input */
1602 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
1603 /* NX_DHCPV6_UNSUPPORTED_DUID_TYPE Unsupported DUID type */
1604 /* NX_DHCPV6_UNSUPPORTED_DUID_HW_TYPE Unsupported DUID hardware type */
1605 /* */
1606 /* CALLS */
1607 /* */
1608 /* _nx_dhcpv6_create_client_duid Actual create client DUID service */
1609 /* */
1610 /* CALLED BY */
1611 /* */
1612 /* Application Code */
1613 /* */
1614 /* RELEASE HISTORY */
1615 /* */
1616 /* DATE NAME DESCRIPTION */
1617 /* */
1618 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1619 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1620 /* resulting in version 6.1 */
1621 /* */
1622 /**************************************************************************/
_nxe_dhcpv6_create_client_duid(NX_DHCPV6 * dhcpv6_ptr,UINT duid_type,UINT hardware_type,ULONG time)1623 UINT _nxe_dhcpv6_create_client_duid(NX_DHCPV6 *dhcpv6_ptr, UINT duid_type, UINT hardware_type, ULONG time)
1624 {
1625
1626 UINT status;
1627
1628
1629 /* Check for invalid pointer input. */
1630 if (!dhcpv6_ptr)
1631 {
1632
1633 return NX_PTR_ERROR;
1634 }
1635
1636 /* Check for valid non pointer input. */
1637 if ((duid_type < NX_DHCPV6_DUID_TYPE_LINK_TIME) || (duid_type > NX_DHCPV6_DUID_TYPE_LINK_ONLY))
1638 {
1639 return NX_DHCPV6_PARAM_ERROR;
1640 }
1641
1642 /* Ethernet is the only a hardware type supported by this API. */
1643 if ((hardware_type != NX_DHCPV6_CLIENT_HARDWARE_TYPE_ETHERNET) && (hardware_type != NX_DHCPV6_CLIENT_HARDWARE_TYPE_EUI_64))
1644 {
1645
1646 /* Return any other type as an error status. */
1647 return NX_DHCPV6_UNSUPPORTED_DUID_HW_TYPE;
1648 }
1649
1650 /* This DUID type is not supported by this API. */
1651 if (duid_type == NX_DHCPV6_DUID_TYPE_VENDOR_ASSIGNED)
1652 {
1653
1654 /* Return as an error status. */
1655 return NX_DHCPV6_UNSUPPORTED_DUID_TYPE;
1656 }
1657
1658 /* Call the actual service. */
1659 status = _nx_dhcpv6_create_client_duid(dhcpv6_ptr, duid_type, hardware_type, time);
1660
1661 return status;
1662 }
1663
1664
1665 /**************************************************************************/
1666 /* */
1667 /* FUNCTION RELEASE */
1668 /* */
1669 /* _nx_dhcpv6_create_client_duid PORTABLE C */
1670 /* 6.1 */
1671 /* AUTHOR */
1672 /* */
1673 /* Yuxin Zhou, Microsoft Corporation */
1674 /* */
1675 /* DESCRIPTION */
1676 /* */
1677 /* This function updates the DHCPv6 client DHCP Unique Identifier */
1678 /* (DUID) with the input values, sets the linklocal address while the */
1679 /* Client does not have an assigned global IP address, after waiting */
1680 /* for the IPv6 thread task to read its MAC address. If the caller */
1681 /* does not supply a time ID, it will generate one in place for Link */
1682 /* Layer Plus Time DUIDs. */
1683 /* */
1684 /* INPUT */
1685 /* */
1686 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
1687 /* duid_type Type of DUID (link layer +/- time)*/
1688 /* hardware_type Network hardware type e.g IEEE 802*/
1689 /* time Time stamp unique DUID identifier */
1690 /* */
1691 /* OUTPUT */
1692 /* */
1693 /* NX_SUCCESS Successful completion status */
1694 /* */
1695 /* CALLS */
1696 /* */
1697 /* memset Clear specified area of memory */
1698 /* rand Generate random number for time ID*/
1699 /* tx_thread_sleep Relinquish thread control (sleep) */
1700 /* nxd_ipv6_linklocal_address_set Use MAC address as temporary IP */
1701 /* source address */
1702 /* */
1703 /* CALLED BY */
1704 /* */
1705 /* Application Code */
1706 /* */
1707 /* RELEASE HISTORY */
1708 /* */
1709 /* DATE NAME DESCRIPTION */
1710 /* */
1711 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1712 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1713 /* resulting in version 6.1 */
1714 /* */
1715 /**************************************************************************/
_nx_dhcpv6_create_client_duid(NX_DHCPV6 * dhcpv6_ptr,UINT duid_type,UINT hardware_type,ULONG time)1716 UINT _nx_dhcpv6_create_client_duid(NX_DHCPV6 *dhcpv6_ptr, UINT duid_type, UINT hardware_type, ULONG time)
1717 {
1718
1719 NX_INTERFACE *interface_ptr;
1720 USHORT option_length;
1721
1722
1723 /* Set the interface pointer. */
1724 interface_ptr = &(dhcpv6_ptr -> nx_dhcpv6_ip_ptr -> nx_ip_interface[dhcpv6_ptr -> nx_dhcpv6_client_interface_index]);
1725
1726 /* Initialize the DUID to null. */
1727 memset(&(dhcpv6_ptr -> nx_dhcpv6_client_duid), 0, sizeof(NX_DHCPV6_DUID));
1728
1729 /* Assign the DUID op code. */
1730 dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_op_code = NX_DHCPV6_OP_CLIENT_ID;
1731
1732 /* Assign field attributes depending on the DUID type. */
1733 if ((duid_type == NX_DHCPV6_DUID_TYPE_LINK_TIME) || (duid_type == NX_DHCPV6_DUID_TYPE_LINK_ONLY))
1734 {
1735
1736 /* Set the option data length minus the option header and size of the time field. */
1737 dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_type = (USHORT)duid_type;
1738 dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_hardware_type = (USHORT)hardware_type;
1739 option_length = 4;
1740
1741 /* Is the Link Layer Time DUID type? */
1742 if (duid_type == NX_DHCPV6_DUID_TYPE_LINK_TIME)
1743 {
1744
1745 /* Yes; add the size of the time field to the data length. */
1746 option_length = (USHORT)(option_length + 4);
1747
1748 /* Did the caller supplied a time? */
1749 if (!time)
1750 {
1751 /* No, create a time field using the defined time constant plus a randomizing factor.*/
1752 dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_time = (SECONDS_SINCE_JAN_1_2000_MOD_32 + (ULONG)(NX_RAND())) & 0xFFFFFFFF;
1753 }
1754 else
1755 {
1756 /* Apply the input time. */
1757 dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_time = time;
1758 }
1759 }
1760
1761 /* Set the globally unique link layer address. */
1762 dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw = interface_ptr -> nx_interface_physical_address_msw;
1763 dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw = interface_ptr -> nx_interface_physical_address_lsw;
1764
1765 /* Check the hardware type. */
1766 if (hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_ETHERNET)
1767 {
1768
1769 /* The length of link layer address is 48 bits. */
1770 option_length = (USHORT)(option_length + 6);
1771 }
1772 else if (hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_EUI_64)
1773 {
1774
1775 /* The length of link layer address is 64 bits. */
1776 option_length = (USHORT)(option_length + 8);
1777 }
1778
1779 /* Set the option length. */
1780 dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_option_length = option_length;
1781 }
1782
1783 return NX_SUCCESS;
1784 }
1785
1786
1787 /**************************************************************************/
1788 /* */
1789 /* FUNCTION RELEASE */
1790 /* */
1791 /* _nxe_dhcpv6_add_client_ia PORTABLE C */
1792 /* 6.1 */
1793 /* AUTHOR */
1794 /* */
1795 /* Yuxin Zhou, Microsoft Corporation */
1796 /* */
1797 /* DESCRIPTION */
1798 /* */
1799 /* This function performs error checking on the add Client IA */
1800 /* (Identity Association) option service, including checking for invalid*/
1801 /* preferred and valid lifetimes. */
1802 /* */
1803 /* INPUT */
1804 /* */
1805 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
1806 /* ipv6_address Requested IPv6 address */
1807 /* preferred_lifetime Requested IP lease time before */
1808 /* address is deprecated */
1809 /* valid_lifetime Requested IP lease time before */
1810 /* address is expired */
1811 /* */
1812 /* OUTPUT */
1813 /* */
1814 /* status Actual completion status */
1815 /* NX_PTR_ERROR Invalid pointer input */
1816 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
1817 /* */
1818 /* CALLS */
1819 /* */
1820 /* _nx_dhcpv6_add_client_ia Actual add client IA service */
1821 /* */
1822 /* CALLED BY */
1823 /* */
1824 /* Application Code */
1825 /* */
1826 /* RELEASE HISTORY */
1827 /* */
1828 /* DATE NAME DESCRIPTION */
1829 /* */
1830 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1831 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1832 /* resulting in version 6.1 */
1833 /* */
1834 /**************************************************************************/
_nxe_dhcpv6_add_client_ia(NX_DHCPV6 * dhcpv6_ptr,NXD_ADDRESS * ipv6_address,ULONG preferred_lifetime,ULONG valid_lifetime)1835 UINT _nxe_dhcpv6_add_client_ia(NX_DHCPV6 *dhcpv6_ptr, NXD_ADDRESS *ipv6_address,
1836 ULONG preferred_lifetime, ULONG valid_lifetime)
1837 {
1838
1839 UINT status;
1840
1841
1842 /* Check for invalid pointer input. */
1843 if (!dhcpv6_ptr || !ipv6_address)
1844 {
1845
1846 return NX_PTR_ERROR;
1847 }
1848
1849 /* Make sure the IPv6 address valid. */
1850 if ((ipv6_address -> nxd_ip_address.v6[0] == 0) &&
1851 (ipv6_address -> nxd_ip_address.v6[1] == 0) &&
1852 (ipv6_address -> nxd_ip_address.v6[2] == 0) &&
1853 (ipv6_address -> nxd_ip_address.v6[3] == 0))
1854 {
1855
1856 return NX_DHCPV6_INVALID_IA_ADDRESS;
1857 }
1858
1859 /* Check for valid non pointer input. */
1860 if (preferred_lifetime > valid_lifetime)
1861 {
1862
1863 /* Client preferred time must be less than valid time or
1864 server will reject it. */
1865 return NX_DHCPV6_PARAM_ERROR;
1866 }
1867
1868 /* Check for an empty IANA instance. */
1869 if (!dhcpv6_ptr -> nx_dhcpv6_iana.nx_op_code)
1870 {
1871
1872 return NX_DHCPV6_PARAM_ERROR;
1873 }
1874
1875 /* Call the actual service. */
1876 status = _nx_dhcpv6_add_client_ia(dhcpv6_ptr, ipv6_address, preferred_lifetime, valid_lifetime);
1877
1878 /* Return completion status. */
1879 return status;
1880 }
1881
1882
1883 /**************************************************************************/
1884 /* */
1885 /* FUNCTION RELEASE */
1886 /* */
1887 /* _nx_dhcpv6_add_client_ia PORTABLE C */
1888 /* 6.1 */
1889 /* AUTHOR */
1890 /* */
1891 /* Yuxin Zhou, Microsoft Corporation */
1892 /* */
1893 /* DESCRIPTION */
1894 /* */
1895 /* This function adds the Client Identity Association address with */
1896 /* the input values. */
1897 /* */
1898 /* INPUT */
1899 /* */
1900 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
1901 /* ipv6_address Requested IPv6 address */
1902 /* preferred_lifetime Requested IP lease time before */
1903 /* address is deprecated */
1904 /* valid_lifetime Requested IP lease time before */
1905 /* address is expired */
1906 /* */
1907 /* OUTPUT */
1908 /* */
1909 /* NX_SUCCESS Successful completion status */
1910 /* NX_DHCPV6_REACHED_MAX_IA_ADDRESS No space to record IA address */
1911 /* */
1912 /* CALLS */
1913 /* */
1914 /* memset Clear specified area of memory */
1915 /* */
1916 /* CALLED BY */
1917 /* */
1918 /* Application Code */
1919 /* */
1920 /* RELEASE HISTORY */
1921 /* */
1922 /* DATE NAME DESCRIPTION */
1923 /* */
1924 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1925 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1926 /* resulting in version 6.1 */
1927 /* */
1928 /**************************************************************************/
_nx_dhcpv6_add_client_ia(NX_DHCPV6 * dhcpv6_ptr,NXD_ADDRESS * ipv6_address,ULONG preferred_lifetime,ULONG valid_lifetime)1929 UINT _nx_dhcpv6_add_client_ia(NX_DHCPV6 *dhcpv6_ptr, NXD_ADDRESS *ipv6_address,
1930 ULONG preferred_lifetime, ULONG valid_lifetime)
1931 {
1932 UINT ia_index;
1933
1934
1935 /* Perform duplicate address detection. */
1936 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
1937 {
1938 if((dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0] == ipv6_address->nxd_ip_address.v6[0]) &&
1939 (dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[1] == ipv6_address->nxd_ip_address.v6[1]) &&
1940 (dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[2] == ipv6_address->nxd_ip_address.v6[2]) &&
1941 (dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[3] == ipv6_address->nxd_ip_address.v6[3]))
1942 {
1943
1944 /* The IA address has already exists. */
1945 return (NX_DHCPV6_IA_ADDRESS_ALREADY_EXIST);
1946 }
1947 }
1948
1949 /* Find one valid space to set the IA address. */
1950 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
1951 {
1952
1953 if(!dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status)
1954 {
1955
1956 /* Yes, got it. */
1957 break;
1958 }
1959 }
1960
1961 if(ia_index < NX_DHCPV6_MAX_IA_ADDRESS)
1962 {
1963
1964 /* Yes, get it, set the IA address. */
1965
1966 /* Initialize the IA-Address to null. */
1967 memset(&(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index]), 0, sizeof(NX_DHCPV6_IA_ADDRESS));
1968
1969 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_op_code = NX_DHCPV6_OP_IA_ADDRESS;
1970
1971 /* Set the IA option length - minus the option header. */
1972 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_option_length = (7 * sizeof(ULONG)) - 4;
1973
1974 /* Set the IP address parameters as a hint to the server. */
1975 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_version = NX_IP_VERSION_V6;
1976 COPY_IPV6_ADDRESS(&(ipv6_address -> nxd_ip_address.v6[0]), &(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0]));
1977
1978 /* Set the life time parameters as a hint to the server. */
1979 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_preferred_lifetime = preferred_lifetime;
1980 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime = valid_lifetime;
1981 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status = NX_DHCPV6_IA_ADDRESS_STATE_INITIAL;
1982
1983 return NX_SUCCESS;
1984 }
1985 else
1986 {
1987 return NX_DHCPV6_REACHED_MAX_IA_ADDRESS;
1988 }
1989 }
1990
1991
1992 /**************************************************************************/
1993 /* */
1994 /* FUNCTION RELEASE */
1995 /* */
1996 /* _nxe_dhcpv6_create_client_iana PORTABLE C */
1997 /* 6.1 */
1998 /* AUTHOR */
1999 /* */
2000 /* Yuxin Zhou, Microsoft Corporation */
2001 /* */
2002 /* DESCRIPTION */
2003 /* */
2004 /* This function performs error checking on the create Client IA-NA */
2005 /* option service, including checking for invalid T1 and T2 times. */
2006 /* */
2007 /* INPUT */
2008 /* */
2009 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
2010 /* IA_ident Interface Association ID */
2011 /* T1 Requested lease time with server */
2012 /* assigning IP (renew) */
2013 /* T2 Requested lease time with any */
2014 /* other server (rebind) */
2015 /* */
2016 /* OUTPUT */
2017 /* */
2018 /* status Actual completion status */
2019 /* NX_PTR_ERROR Invalid pointer input */
2020 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
2021 /* */
2022 /* CALLS */
2023 /* */
2024 /* _nx_dhcpv6_create_client_iana Actual create client IANA service */
2025 /* */
2026 /* CALLED BY */
2027 /* */
2028 /* Application Code */
2029 /* */
2030 /* RELEASE HISTORY */
2031 /* */
2032 /* DATE NAME DESCRIPTION */
2033 /* */
2034 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2035 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2036 /* resulting in version 6.1 */
2037 /* */
2038 /**************************************************************************/
_nxe_dhcpv6_create_client_iana(NX_DHCPV6 * dhcpv6_ptr,UINT IA_ident,ULONG T1,ULONG T2)2039 UINT _nxe_dhcpv6_create_client_iana(NX_DHCPV6 *dhcpv6_ptr, UINT IA_ident, ULONG T1, ULONG T2)
2040 {
2041
2042 UINT status;
2043
2044
2045 /* Check for invalid pointer input. */
2046 if (!dhcpv6_ptr || !IA_ident)
2047 {
2048
2049 return NX_PTR_ERROR;
2050 }
2051
2052 /* Check for valid non pointer input. */
2053 if (T1 > T2)
2054 {
2055
2056 /* Client preferred time must be less than valid time or server will reject it. */
2057 return NX_DHCPV6_PARAM_ERROR;
2058 }
2059
2060
2061 /* Call the actual service. */
2062 status = _nx_dhcpv6_create_client_iana(dhcpv6_ptr, IA_ident, T1, T2);
2063
2064 /* Return completion status. */
2065 return status;
2066 }
2067
2068
2069 /**************************************************************************/
2070 /* */
2071 /* FUNCTION RELEASE */
2072 /* */
2073 /* _nx_dhcpv6_create_client_iana PORTABLE C */
2074 /* 6.1 */
2075 /* AUTHOR */
2076 /* */
2077 /* Yuxin Zhou, Microsoft Corporation */
2078 /* */
2079 /* DESCRIPTION */
2080 /* */
2081 /* This function updates the Client's Identity Association for Non */
2082 /* Temporary Address (IANA) with the input values. */
2083 /* */
2084 /* INPUT */
2085 /* */
2086 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
2087 /* IA_ident Interface Association ID */
2088 /* T1 Requested lease time with server */
2089 /* assigning IP (renew) */
2090 /* T2 Requested lease time with any */
2091 /* other server (rebind) */
2092 /* */
2093 /* OUTPUT */
2094 /* */
2095 /* NX_SUCCESS Successful completion status */
2096 /* */
2097 /* CALLS */
2098 /* */
2099 /* memset Clear specified area of memory */
2100 /* */
2101 /* CALLED BY */
2102 /* */
2103 /* Application Code */
2104 /* */
2105 /* RELEASE HISTORY */
2106 /* */
2107 /* DATE NAME DESCRIPTION */
2108 /* */
2109 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2110 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2111 /* resulting in version 6.1 */
2112 /* */
2113 /**************************************************************************/
_nx_dhcpv6_create_client_iana(NX_DHCPV6 * dhcpv6_ptr,UINT IA_ident,ULONG T1,ULONG T2)2114 UINT _nx_dhcpv6_create_client_iana(NX_DHCPV6 *dhcpv6_ptr, UINT IA_ident, ULONG T1, ULONG T2)
2115 {
2116
2117 /* Initialize the IANA to null. */
2118 memset(&(dhcpv6_ptr -> nx_dhcpv6_iana), 0, sizeof(NX_DHCPV6_IA_NA));
2119
2120 /* Assign the IANA attributes. */
2121 dhcpv6_ptr -> nx_dhcpv6_iana.nx_op_code = NX_DHCPV6_OP_IA_NA;
2122 dhcpv6_ptr -> nx_dhcpv6_iana.nx_IA_NA_id = IA_ident;
2123
2124 /* Set the IANA option data length, minus the option header. */
2125 dhcpv6_ptr -> nx_dhcpv6_iana.nx_option_length = 3 * sizeof(ULONG);
2126
2127 /* Apply the Client's preference for IP renew/rebind times. */
2128 dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1 = T1;
2129 dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2 = T2;
2130
2131 return NX_SUCCESS;
2132 }
2133
2134
2135 /**************************************************************************/
2136 /* */
2137 /* FUNCTION RELEASE */
2138 /* */
2139 /* _nxe_dhcpv6_get_client_duid_time_id PORTABLE C */
2140 /* 6.1 */
2141 /* AUTHOR */
2142 /* */
2143 /* Yuxin Zhou, Microsoft Corporation */
2144 /* */
2145 /* DESCRIPTION */
2146 /* */
2147 /* This function performs error checking on the get Client DUID time ID*/
2148 /* service. */
2149 /* */
2150 /* INPUT */
2151 /* */
2152 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2153 /* time_id Pointer to DUID time field */
2154 /* */
2155 /* OUTPUT */
2156 /* */
2157 /* status Actual completion status */
2158 /* NX_PTR_ERROR Invalid pointer input */
2159 /* */
2160 /* CALLS */
2161 /* */
2162 /* _nx_dhcpv6_get_client_duid_time_id Actual get Client DUID time ID */
2163 /* service */
2164 /* */
2165 /* CALLED BY */
2166 /* */
2167 /* Application Code */
2168 /* */
2169 /* RELEASE HISTORY */
2170 /* */
2171 /* DATE NAME DESCRIPTION */
2172 /* */
2173 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2174 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2175 /* resulting in version 6.1 */
2176 /* */
2177 /**************************************************************************/
_nxe_dhcpv6_get_client_duid_time_id(NX_DHCPV6 * dhcpv6_ptr,ULONG * time_id)2178 UINT _nxe_dhcpv6_get_client_duid_time_id(NX_DHCPV6 *dhcpv6_ptr, ULONG *time_id)
2179 {
2180
2181 UINT status;
2182
2183
2184 /* Check for valid pointer input. */
2185 if (!dhcpv6_ptr || !time_id)
2186 {
2187
2188 return NX_PTR_ERROR;
2189 }
2190
2191 /* Check for appropriate caller. */
2192 NX_THREADS_ONLY_CALLER_CHECKING
2193
2194 /* Call the actual service. */
2195 status = _nx_dhcpv6_get_client_duid_time_id(dhcpv6_ptr, time_id);
2196
2197 /* Return completion status. */
2198 return status;
2199 }
2200
2201
2202 /**************************************************************************/
2203 /* */
2204 /* FUNCTION RELEASE */
2205 /* */
2206 /* _nx_dhcpv6_get_client_duid_time_id PORTABLE C */
2207 /* 6.1 */
2208 /* AUTHOR */
2209 /* */
2210 /* Yuxin Zhou, Microsoft Corporation */
2211 /* */
2212 /* DESCRIPTION */
2213 /* */
2214 /* This function retrieves the Client DUID time ID saved to the client */
2215 /* record. It does not check if the DUID is properly filled out. It is*/
2216 /* up to the caller to check for a zero value (invalid) time ID. */
2217 /* */
2218 /* INPUT */
2219 /* */
2220 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2221 /* time_id Pointer to DUID time field */
2222 /* */
2223 /* OUTPUT */
2224 /* */
2225 /* status Actual completion status */
2226 /* NX_PTR_ERROR Invalid pointer input */
2227 /* */
2228 /* CALLS */
2229 /* */
2230 /* _nx_dhcpv6_get_client_duid_time_id Actual get Client DUID time ID */
2231 /* service */
2232 /* */
2233 /* CALLED BY */
2234 /* */
2235 /* Application Code */
2236 /* */
2237 /* RELEASE HISTORY */
2238 /* */
2239 /* DATE NAME DESCRIPTION */
2240 /* */
2241 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2242 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2243 /* resulting in version 6.1 */
2244 /* */
2245 /**************************************************************************/
_nx_dhcpv6_get_client_duid_time_id(NX_DHCPV6 * dhcpv6_ptr,ULONG * time_id)2246 UINT _nx_dhcpv6_get_client_duid_time_id(NX_DHCPV6 *dhcpv6_ptr, ULONG *time_id)
2247 {
2248
2249 /* The Time field is part of the NX_DHCPV6_DUID struct in the Client record. */
2250 *time_id = dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_time;
2251
2252 /* Return successful completion. */
2253 return NX_SUCCESS;
2254 }
2255
2256
2257 /**************************************************************************/
2258 /* */
2259 /* FUNCTION RELEASE */
2260 /* */
2261 /* _nx_dhcpv6_register_IP_address PORTABLE C */
2262 /* 6.1 */
2263 /* AUTHOR */
2264 /* */
2265 /* Yuxin Zhou, Microsoft Corporation */
2266 /* */
2267 /* DESCRIPTION */
2268 /* */
2269 /* This function registers the assigned IP address to the IP task, */
2270 /* which adds the input address to the IP address table.In either case,*/
2271 /* the address index in the IP address table is recorded to the Client */
2272 /* record.It will require it if the DHCPv6 Client wants to clear the */
2273 /* IPv6 address. */
2274 /* */
2275 /* Note: the host application should perform address verification */
2276 /* e.g. Duplicate Address Detection to verify uniqueness of the input */
2277 /* address. If duplicate address detection is enabled in NetX Duo this */
2278 /* is done automatically. */
2279 /* */
2280 /* INPUT */
2281 /* */
2282 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2283 /* */
2284 /* OUTPUT */
2285 /* */
2286 /* status Actual completion status */
2287 /* */
2288 /* CALLS */
2289 /* */
2290 /* _nxd_ipv6_address_set Add global address to IP */
2291 /* tx_mutex_get Get the DHCPv6 mutex */
2292 /* tx_mutex_put Put the DHCPv6 mutex */
2293 /* */
2294 /* CALLED BY */
2295 /* */
2296 /* nx_dhcpv6_process Process received packets */
2297 /* */
2298 /* RELEASE HISTORY */
2299 /* */
2300 /* DATE NAME DESCRIPTION */
2301 /* */
2302 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2303 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2304 /* resulting in version 6.1 */
2305 /* */
2306 /**************************************************************************/
_nx_dhcpv6_register_IP_address(NX_DHCPV6 * dhcpv6_ptr)2307 UINT _nx_dhcpv6_register_IP_address(NX_DHCPV6 *dhcpv6_ptr)
2308 {
2309
2310 UINT status;
2311 UINT address_index;
2312 UINT ia_index;
2313
2314 /* Set the DHCPv6 Client IPv6 addresses. */
2315 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
2316 {
2317
2318 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_INITIAL)
2319 {
2320
2321 /* Add the address to the IP instance address table. */
2322 status = nxd_ipv6_address_set(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, dhcpv6_ptr -> nx_dhcpv6_client_interface_index,
2323 &dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address, 64, &address_index);
2324
2325 /* Check for successful result. */
2326 if (status == NX_SUCCESS)
2327 {
2328
2329 /* Get the mutex protection for DHCP client. */
2330 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
2331
2332 #if !defined (NX_DISABLE_IPV6_DAD) && defined (NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY)
2333
2334 /* Set the IPv6 address status as DAD tentative, the status will be updated in _nx_dhcpv6_ipv6_address_DAD_notify. */
2335 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status = NX_DHCPV6_IA_ADDRESS_STATE_DAD_TENTATIVE;
2336 #else
2337
2338 /* Set the IPv6 address status as valid. */
2339 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status = NX_DHCPV6_IA_ADDRESS_STATE_VALID;
2340 #endif
2341
2342 /* Record the address index in the Client record. */
2343 dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index] = address_index;
2344
2345 /* All done! Release the mutex.*/
2346 tx_mutex_put(&dhcpv6_ptr -> nx_dhcpv6_client_mutex);
2347 }
2348
2349 }
2350 }
2351
2352 /* Add the default router. */
2353 nxd_ipv6_default_router_add(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, &(dhcpv6_ptr-> nx_dhcpv6_server_address),
2354 NX_WAIT_FOREVER, dhcpv6_ptr -> nx_dhcpv6_client_interface_index);
2355
2356 return NX_SUCCESS;
2357 }
2358
2359 /**************************************************************************/
2360 /* */
2361 /* FUNCTION RELEASE */
2362 /* */
2363 /* _nxe_dhcpv6_get_IP_address PORTABLE C */
2364 /* 6.1 */
2365 /* AUTHOR */
2366 /* */
2367 /* Yuxin Zhou, Microsoft Corporation */
2368 /* */
2369 /* DESCRIPTION */
2370 /* */
2371 /* This function performs error checking on the get Client global IP */
2372 /* address service. */
2373 /* */
2374 /* INPUT */
2375 /* */
2376 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2377 /* ip_address Pointer to global IP address */
2378 /* */
2379 /* OUTPUT */
2380 /* */
2381 /* status Actual completion status */
2382 /* NX_PTR_ERROR Invalid pointer input */
2383 /* */
2384 /* CALLS */
2385 /* */
2386 /* _nx_dhcpv6_get_IP_address Actual get Client global IP */
2387 /* address service */
2388 /* */
2389 /* CALLED BY */
2390 /* */
2391 /* Application Code */
2392 /* */
2393 /* RELEASE HISTORY */
2394 /* */
2395 /* DATE NAME DESCRIPTION */
2396 /* */
2397 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2398 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2399 /* resulting in version 6.1 */
2400 /* */
2401 /**************************************************************************/
_nxe_dhcpv6_get_IP_address(NX_DHCPV6 * dhcpv6_ptr,NXD_ADDRESS * ip_address)2402 UINT _nxe_dhcpv6_get_IP_address(NX_DHCPV6 *dhcpv6_ptr, NXD_ADDRESS *ip_address)
2403 {
2404
2405 UINT status;
2406
2407
2408 /* Check for valid pointer input. */
2409 if (!dhcpv6_ptr || !ip_address)
2410 {
2411
2412 return NX_PTR_ERROR;
2413 }
2414
2415 /* Check for appropriate caller. */
2416 NX_THREADS_ONLY_CALLER_CHECKING
2417
2418 /* Call the actual service. */
2419 status = _nx_dhcpv6_get_IP_address(dhcpv6_ptr, ip_address);
2420
2421 /* Return completion status. */
2422 return status;
2423 }
2424
2425
2426 /**************************************************************************/
2427 /* */
2428 /* FUNCTION RELEASE */
2429 /* */
2430 /* _nx_dhcpv6_get_IP_address PORTABLE C */
2431 /* 6.1 */
2432 /* AUTHOR */
2433 /* */
2434 /* Yuxin Zhou, Microsoft Corporation */
2435 /* */
2436 /* DESCRIPTION */
2437 /* */
2438 /* This function retrieves the IP address from the DHCPv6 */
2439 /* Client record. If the client address is not valid, a null IP */
2440 /* address is returned and an error status is set. */
2441 /* */
2442 /* Note that if the Client has received an IP address from the DHCPv6 */
2443 /* server the host must register that ddress with NetX Duo by calling */
2444 /* address with NetX Duo by calling the service nxd_ipv6_address_set. */
2445 /* Once the address is registered, the host can confirm its address by */
2446 /* calling nxd_ipv6_address_get. */
2447 /* */
2448 /* INPUT */
2449 /* */
2450 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2451 /* ip_address Pointer to NetX Duo address */
2452 /* */
2453 /* OUTPUT */
2454 /* */
2455 /* NX_SUCCESS Returned non zero IP address */
2456 /* NX_DHCPV6_IA_ADDRESS_NOT_VALID Client not assigned an address */
2457 /* */
2458 /* CALLS */
2459 /* */
2460 /* None */
2461 /* */
2462 /* CALLED BY */
2463 /* */
2464 /* Application */
2465 /* */
2466 /* RELEASE HISTORY */
2467 /* */
2468 /* DATE NAME DESCRIPTION */
2469 /* */
2470 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2471 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2472 /* resulting in version 6.1 */
2473 /* */
2474 /**************************************************************************/
_nx_dhcpv6_get_IP_address(NX_DHCPV6 * dhcpv6_ptr,NXD_ADDRESS * ip_address)2475 UINT _nx_dhcpv6_get_IP_address(NX_DHCPV6 *dhcpv6_ptr, NXD_ADDRESS *ip_address)
2476 {
2477
2478 UINT status;
2479
2480
2481 /* Clear the address buffer. */
2482 SET_UNSPECIFIED_ADDRESS(&ip_address -> nxd_ip_address.v6[0]);
2483
2484 /* Initialize the outcome as no address assigned. */
2485 status = NX_DHCPV6_IA_ADDRESS_NOT_VALID;
2486
2487 /* Is the client assigned a valid address? */
2488 if (dhcpv6_ptr -> nx_dhcpv6_ia[0].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID)
2489 {
2490 /* Yes; return the assigned IP address from the DHCPv6 Client record. */
2491 COPY_IPV6_ADDRESS(&(dhcpv6_ptr -> nx_dhcpv6_ia[0].nx_global_address.nxd_ip_address.v6[0]),
2492 &(ip_address -> nxd_ip_address.v6[0]));
2493
2494 status = NX_SUCCESS;
2495 }
2496
2497 return status;
2498 }
2499
2500
2501 /**************************************************************************/
2502 /* */
2503 /* FUNCTION RELEASE */
2504 /* */
2505 /* _nxe_dhcpv6_get_lease_time_data PORTABLE C */
2506 /* 6.1 */
2507 /* AUTHOR */
2508 /* */
2509 /* Yuxin Zhou, Microsoft Corporation */
2510 /* */
2511 /* DESCRIPTION */
2512 /* */
2513 /* This function performs error checking on the get Client IP lease */
2514 /* time service. */
2515 /* */
2516 /* INPUT */
2517 /* */
2518 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2519 /* T1 Pointer to T1 time */
2520 /* T2 Pointer to T2 time */
2521 /* preferred_lifetime Pointer to preferred lifetime */
2522 /* valid_lifetime Pointer to valid lifetime */
2523 /* */
2524 /* OUTPUT */
2525 /* */
2526 /* status Actual completion status */
2527 /* NX_PTR_ERROR Invalid pointer input */
2528 /* */
2529 /* CALLS */
2530 /* */
2531 /* _nx_dhcpv6_get_lease_time_data Actual get Client IP lease time */
2532 /* service */
2533 /* */
2534 /* CALLED BY */
2535 /* */
2536 /* Application Code */
2537 /* */
2538 /* RELEASE HISTORY */
2539 /* */
2540 /* DATE NAME DESCRIPTION */
2541 /* */
2542 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2543 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2544 /* resulting in version 6.1 */
2545 /* */
2546 /**************************************************************************/
_nxe_dhcpv6_get_lease_time_data(NX_DHCPV6 * dhcpv6_ptr,ULONG * T1,ULONG * T2,ULONG * preferred_lifetime,ULONG * valid_lifetime)2547 UINT _nxe_dhcpv6_get_lease_time_data(NX_DHCPV6 *dhcpv6_ptr, ULONG *T1, ULONG *T2, ULONG *preferred_lifetime,
2548 ULONG *valid_lifetime)
2549 {
2550
2551 UINT status;
2552
2553
2554 /* Check for valid pointer input. */
2555 if (!dhcpv6_ptr || !T1 || !T2 || !preferred_lifetime || !valid_lifetime )
2556 {
2557 return NX_PTR_ERROR;
2558 }
2559
2560 /* Check for appropriate caller. */
2561 NX_THREADS_ONLY_CALLER_CHECKING
2562
2563 /* Call the actual service. */
2564 status = _nx_dhcpv6_get_lease_time_data(dhcpv6_ptr, T1, T2, preferred_lifetime, valid_lifetime);
2565
2566 /* Return completion status. */
2567 return status;
2568 }
2569
2570
2571 /**************************************************************************/
2572 /* */
2573 /* FUNCTION RELEASE */
2574 /* */
2575 /* _nx_dhcpv6_get_lease_time_data PORTABLE C */
2576 /* 6.1 */
2577 /* AUTHOR */
2578 /* */
2579 /* Yuxin Zhou, Microsoft Corporation */
2580 /* */
2581 /* DESCRIPTION */
2582 /* */
2583 /* This function retrieves the Client's global IP lease times T1 and T2*/
2584 /* and valid and preferred lifetimes. The address_status input field */
2585 /* indicates if the IP address on the Client record is valid and */
2586 /* registered. If so the lease and valid lifetimes are also registered */
2587 /* with the server (not merely Client preference or left over from an */
2588 /* expired IP address). */
2589 /* */
2590 /* INPUT */
2591 /* */
2592 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2593 /* T1 Pointer to T1 time */
2594 /* T2 Pointer to T2 time */
2595 /* preferred_lifetime Pointer to preferred lifetime */
2596 /* valid_lifetime Pointer to valid lifetime */
2597 /* */
2598 /* OUTPUT */
2599 /* */
2600 /* NX_SUCCESS Successful completion status */
2601 /* */
2602 /* CALLS */
2603 /* */
2604 /* None */
2605 /* */
2606 /* CALLED BY */
2607 /* */
2608 /* Application */
2609 /* */
2610 /* RELEASE HISTORY */
2611 /* */
2612 /* DATE NAME DESCRIPTION */
2613 /* */
2614 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2615 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2616 /* resulting in version 6.1 */
2617 /* */
2618 /**************************************************************************/
_nx_dhcpv6_get_lease_time_data(NX_DHCPV6 * dhcpv6_ptr,ULONG * T1,ULONG * T2,ULONG * preferred_lifetime,ULONG * valid_lifetime)2619 UINT _nx_dhcpv6_get_lease_time_data(NX_DHCPV6 *dhcpv6_ptr, ULONG *T1, ULONG *T2, ULONG *preferred_lifetime,
2620 ULONG *valid_lifetime)
2621 {
2622
2623 /* Initialize data to zero. */
2624 *T1 = 0;
2625 *T2 = 0;
2626 *valid_lifetime = 0;
2627 *preferred_lifetime = 0;
2628
2629 /* If the client has a valid IP address status, return the actual lease time data. */
2630 if (dhcpv6_ptr -> nx_dhcpv6_ia[0].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID)
2631 {
2632 /* Get the time data from the Client record IA. */
2633 *T1 = dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1;
2634 *T2 = dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2;
2635 *preferred_lifetime = dhcpv6_ptr -> nx_dhcpv6_ia[0].nx_preferred_lifetime;
2636 *valid_lifetime = dhcpv6_ptr -> nx_dhcpv6_ia[0].nx_valid_lifetime;
2637 }
2638
2639 /* Return successful completion. */
2640 return NX_SUCCESS;
2641 }
2642
2643 /**************************************************************************/
2644 /* */
2645 /* FUNCTION RELEASE */
2646 /* */
2647 /* _nxe_dhcpv6_get_DNS_server_address PORTABLE C */
2648 /* 6.1 */
2649 /* AUTHOR */
2650 /* */
2651 /* Yuxin Zhou, Microsoft Corporation */
2652 /* */
2653 /* DESCRIPTION */
2654 /* */
2655 /* */
2656 /* INPUT */
2657 /* */
2658 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2659 /* index Index into DNS server list */
2660 /* server_address Pointer to copy address to */
2661 /* */
2662 /* OUTPUT */
2663 /* */
2664 /* NX_SUCCESS Successful completion status */
2665 /* NX_PTR_ERROR Invalid pointer input */
2666 /* */
2667 /* CALLS */
2668 /* _nx_dhcpv6_get_DNS_server_address Actual get DNS server address */
2669 /* service */
2670 /* */
2671 /* CALLED BY */
2672 /* */
2673 /* Application */
2674 /* */
2675 /* RELEASE HISTORY */
2676 /* */
2677 /* DATE NAME DESCRIPTION */
2678 /* */
2679 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2680 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2681 /* resulting in version 6.1 */
2682 /* */
2683 /**************************************************************************/
_nxe_dhcpv6_get_DNS_server_address(NX_DHCPV6 * dhcpv6_ptr,UINT index,NXD_ADDRESS * server_address)2684 UINT _nxe_dhcpv6_get_DNS_server_address(NX_DHCPV6 *dhcpv6_ptr, UINT index, NXD_ADDRESS *server_address)
2685 {
2686
2687 UINT status;
2688
2689
2690 /* Check for valid pointer input. */
2691 if (dhcpv6_ptr == NX_NULL)
2692 {
2693 return NX_PTR_ERROR;
2694 }
2695
2696 /* Check for appropriate caller. */
2697 NX_THREADS_ONLY_CALLER_CHECKING
2698
2699 /* Call the actual service. */
2700 status = _nx_dhcpv6_get_DNS_server_address(dhcpv6_ptr, index, server_address);
2701
2702 /* Return completion status. */
2703 return status;
2704 }
2705
2706
2707 /**************************************************************************/
2708 /* */
2709 /* FUNCTION RELEASE */
2710 /* */
2711 /* _nx_dhcpv6_get_DNS_server_address PORTABLE C */
2712 /* 6.1 */
2713 /* AUTHOR */
2714 /* */
2715 /* Yuxin Zhou, Microsoft Corporation */
2716 /* */
2717 /* DESCRIPTION */
2718 /* */
2719 /* This function retrieves the DNS server address at the specified */
2720 /* index in the DHCP Client DNS list. The Client DNS server list is */
2721 /* compiled from DHCP Server messages supplying DNS server address */
2722 /* data. */
2723 /* */
2724 /* Note: the DHCPv6 Client is configured to store up to */
2725 /* NX_DHCPV6_NUM_DNS_SERVERS DNS server addresses. It is up to the */
2726 /* caller to supply the index to get each server in the list if there */
2727 /* is more than one stored. */
2728 /* */
2729 /* INPUT */
2730 /* */
2731 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2732 /* index Index into DNS server list */
2733 /* server_address Pointer to copy address to */
2734 /* */
2735 /* OUTPUT */
2736 /* */
2737 /* NX_SUCCESS Successful completion status */
2738 /* NX_DHCPV6_PARAM_ERROR Invalid index supplied */
2739 /* */
2740 /* CALLS */
2741 /* */
2742 /* _nx_dhcpv6_get_DNS_server_address Actual get DNS server address */
2743 /* service */
2744 /* */
2745 /* CALLED BY */
2746 /* */
2747 /* Application */
2748 /* */
2749 /* RELEASE HISTORY */
2750 /* */
2751 /* DATE NAME DESCRIPTION */
2752 /* */
2753 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2754 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2755 /* resulting in version 6.1 */
2756 /* */
2757 /**************************************************************************/
2758
_nx_dhcpv6_get_DNS_server_address(NX_DHCPV6 * dhcpv6_ptr,UINT index,NXD_ADDRESS * server_address)2759 UINT _nx_dhcpv6_get_DNS_server_address(NX_DHCPV6 *dhcpv6_ptr, UINT index, NXD_ADDRESS *server_address)
2760 {
2761
2762
2763 /* Check for a valid input. */
2764 if (index >= NX_DHCPV6_NUM_DNS_SERVERS)
2765 {
2766
2767 return NX_DHCPV6_PARAM_ERROR;
2768 }
2769
2770 /* Store the specified DNS server addresses in the DHCPv6 Client list. */
2771 COPY_NXD_ADDRESS(&(dhcpv6_ptr -> nx_dhcpv6_DNS_name_server_address[index]), server_address);
2772
2773 return NX_SUCCESS;
2774 }
2775
2776
2777 /**************************************************************************/
2778 /* */
2779 /* FUNCTION RELEASE */
2780 /* */
2781 /* _nxe_dhcpv6_get_time_server_address PORTABLE C */
2782 /* 6.1 */
2783 /* AUTHOR */
2784 /* */
2785 /* Yuxin Zhou, Microsoft Corporation */
2786 /* */
2787 /* DESCRIPTION */
2788 /* */
2789 /* */
2790 /* INPUT */
2791 /* */
2792 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2793 /* index Index into time server list */
2794 /* server_address Pointer to copy address to */
2795 /* */
2796 /* OUTPUT */
2797 /* */
2798 /* NX_SUCCESS Successful completion status */
2799 /* NX_PTR_ERROR Invalid pointer input */
2800 /* */
2801 /* CALLS */
2802 /* _nx_dhcpv6_get_time_server_address Actual get time server address */
2803 /* service */
2804 /* */
2805 /* CALLED BY */
2806 /* */
2807 /* Application */
2808 /* */
2809 /* RELEASE HISTORY */
2810 /* */
2811 /* DATE NAME DESCRIPTION */
2812 /* */
2813 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2814 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2815 /* resulting in version 6.1 */
2816 /* */
2817 /**************************************************************************/
_nxe_dhcpv6_get_time_server_address(NX_DHCPV6 * dhcpv6_ptr,UINT index,NXD_ADDRESS * server_address)2818 UINT _nxe_dhcpv6_get_time_server_address(NX_DHCPV6 *dhcpv6_ptr, UINT index, NXD_ADDRESS *server_address)
2819 {
2820
2821 UINT status;
2822
2823
2824 /* Check for valid pointer input. */
2825 if (dhcpv6_ptr == NX_NULL)
2826 {
2827 return NX_PTR_ERROR;
2828 }
2829
2830 /* Check for appropriate caller. */
2831 NX_THREADS_ONLY_CALLER_CHECKING
2832
2833 /* Call the actual service. */
2834 status = _nx_dhcpv6_get_time_server_address(dhcpv6_ptr, index, server_address);
2835
2836 /* Return completion status. */
2837 return status;
2838 }
2839
2840
2841 /**************************************************************************/
2842 /* */
2843 /* FUNCTION RELEASE */
2844 /* */
2845 /* _nx_dhcpv6_get_time_server_address PORTABLE C */
2846 /* 6.1 */
2847 /* AUTHOR */
2848 /* */
2849 /* Yuxin Zhou, Microsoft Corporation */
2850 /* */
2851 /* DESCRIPTION */
2852 /* */
2853 /* This function retrieves the time server address at the specified */
2854 /* index in the DHCP Client time list. The Client time server list is */
2855 /* compiled from DHCP Server messages supplying time server address */
2856 /* data. */
2857 /* */
2858 /* Note: the DHCPv6 Client is configured to store up to */
2859 /* NX_DHCPV6_NUM_TIME_SERVERS TIME server addresses. It is up to the */
2860 /* caller to supply the index to get each server in the list if there */
2861 /* is more than one stored. */
2862 /* */
2863 /* INPUT */
2864 /* */
2865 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2866 /* index Index into time server list */
2867 /* server_address Pointer to copy address to */
2868 /* */
2869 /* OUTPUT */
2870 /* */
2871 /* NX_SUCCESS Successful completion status */
2872 /* NX_DHCPV6_PARAM_ERROR Invalid index supplied */
2873 /* */
2874 /* CALLS */
2875 /* */
2876 /* _nx_dhcpv6_get_time_server_address Actual get time server address */
2877 /* service */
2878 /* */
2879 /* CALLED BY */
2880 /* */
2881 /* Application */
2882 /* */
2883 /* RELEASE HISTORY */
2884 /* */
2885 /* DATE NAME DESCRIPTION */
2886 /* */
2887 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2888 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2889 /* resulting in version 6.1 */
2890 /* */
2891 /**************************************************************************/
_nx_dhcpv6_get_time_server_address(NX_DHCPV6 * dhcpv6_ptr,UINT index,NXD_ADDRESS * server_address)2892 UINT _nx_dhcpv6_get_time_server_address(NX_DHCPV6 *dhcpv6_ptr, UINT index, NXD_ADDRESS *server_address)
2893 {
2894
2895
2896 /* Check for a valid input. */
2897 if (index >= NX_DHCPV6_NUM_TIME_SERVERS)
2898 {
2899
2900 return NX_DHCPV6_PARAM_ERROR;
2901 }
2902
2903 /* Store the specified time server addresses in the DHCPv6 Client list. */
2904 COPY_NXD_ADDRESS(&(dhcpv6_ptr -> nx_dhcpv6_time_server_address[index]), server_address);
2905
2906 return NX_SUCCESS;
2907 }
2908
2909
2910 /**************************************************************************/
2911 /* */
2912 /* FUNCTION RELEASE */
2913 /* */
2914 /* _nxe_dhcpv6_get_other_option_data PORTABLE C */
2915 /* 6.1 */
2916 /* AUTHOR */
2917 /* */
2918 /* Yuxin Zhou, Microsoft Corporation */
2919 /* */
2920 /* DESCRIPTION */
2921 /* */
2922 /* */
2923 /* INPUT */
2924 /* */
2925 /* dhcpv6_ptr Pointer to DHCPv6 Client */
2926 /* option_code Option code of requested data */
2927 /* buffer Buffer to copy data to */
2928 /* buffer_length Size of buffer to copy to */
2929 /* */
2930 /* OUTPUT */
2931 /* */
2932 /* status Completion status */
2933 /* NX_PTR_ERROR Invalid pointer input */
2934 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
2935 /* */
2936 /* CALLS */
2937 /* _nx_dhcpv6_get_other_option_data Actual get other option data */
2938 /* service */
2939 /* */
2940 /* CALLED BY */
2941 /* */
2942 /* Application */
2943 /* */
2944 /* RELEASE HISTORY */
2945 /* */
2946 /* DATE NAME DESCRIPTION */
2947 /* */
2948 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2949 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2950 /* resulting in version 6.1 */
2951 /* */
2952 /**************************************************************************/
_nxe_dhcpv6_get_other_option_data(NX_DHCPV6 * dhcpv6_ptr,UINT option_code,UCHAR * buffer,UINT buffer_length)2953 UINT _nxe_dhcpv6_get_other_option_data(NX_DHCPV6 *dhcpv6_ptr, UINT option_code, UCHAR *buffer,UINT buffer_length)
2954 {
2955
2956 UINT status;
2957
2958
2959 /* Check for valid pointer input. */
2960 if (!dhcpv6_ptr || !buffer)
2961 {
2962 return NX_PTR_ERROR;
2963 }
2964
2965 /* Check for invalid non pointer input. */
2966 if (!option_code || !buffer_length)
2967 {
2968
2969 return NX_DHCPV6_PARAM_ERROR;
2970 }
2971
2972 /* Check for appropriate caller. */
2973 NX_THREADS_ONLY_CALLER_CHECKING
2974
2975 /* Call the actual service. */
2976 status = _nx_dhcpv6_get_other_option_data(dhcpv6_ptr, option_code, buffer, buffer_length);
2977
2978 /* Return completion status. */
2979 return status;
2980 }
2981
2982
2983 /**************************************************************************/
2984 /* */
2985 /* FUNCTION RELEASE */
2986 /* */
2987 /* _nx_dhcpv6_get_other_option_data PORTABLE C */
2988 /* 6.1 */
2989 /* AUTHOR */
2990 /* */
2991 /* Yuxin Zhou, Microsoft Corporation */
2992 /* */
2993 /* DESCRIPTION */
2994 /* */
2995 /* This function retrieves the option information requested in the */
2996 /* input parameter. Note that there are only 2 options which the */
2997 /* NetX DHCPv6 client supports. Some options have their own specific */
2998 /* API such as _nx_dhcpv6_get_DNS_server_address. The complete list */
2999 /* of options is not supported by the NetX Duo DHCPv6 Client. */
3000 /* */
3001 /* INPUT */
3002 /* */
3003 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3004 /* option_code Option code of requested data */
3005 /* buffer Buffer to copy data to */
3006 /* buffer_length Size of buffer to copy to */
3007 /* */
3008 /* OUTPUT */
3009 /* */
3010 /* status Completion status */
3011 /* NX_DHCPV6_UNKNOWN_OPTION Unknown option specified */
3012 /* */
3013 /* CALLS */
3014 /* */
3015 /* memcpy Copy specified area of memory */
3016 /* */
3017 /* CALLED BY */
3018 /* */
3019 /* Application */
3020 /* */
3021 /* RELEASE HISTORY */
3022 /* */
3023 /* DATE NAME DESCRIPTION */
3024 /* */
3025 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3026 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
3027 /* verified memcpy use cases, */
3028 /* resulting in version 6.1 */
3029 /* */
3030 /**************************************************************************/
_nx_dhcpv6_get_other_option_data(NX_DHCPV6 * dhcpv6_ptr,UINT option_code,UCHAR * buffer,UINT buffer_length)3031 UINT _nx_dhcpv6_get_other_option_data(NX_DHCPV6 *dhcpv6_ptr, UINT option_code, UCHAR *buffer, UINT buffer_length)
3032 {
3033
3034
3035 UINT length = 0;
3036
3037 /* Check to see which option data is requested: */
3038 switch (option_code)
3039 {
3040
3041 case NX_DHCPV6_NEW_POSIX_TIMEZONE_OPTION:
3042
3043 /* Update the amount of data we are copying into the buffer. */
3044 length += NX_DHCPV6_TIME_ZONE_BUFFER_SIZE;
3045
3046 /* Check that we don't overrun the buffer. */
3047 if (length > buffer_length)
3048 {
3049 return NX_DHCPV6_INVALID_DATA_SIZE;
3050 }
3051
3052 /* Copy the time zone data to the supplied buffer. */
3053 memcpy(buffer, dhcpv6_ptr -> nx_dhcpv6_time_zone, NX_DHCPV6_TIME_ZONE_BUFFER_SIZE); /* Use case of memcpy is verified. */
3054
3055 break;
3056
3057
3058 case NX_DHCPV6_DOMAIN_NAME_OPTION:
3059
3060 /* Update the amount of data we are copying into the buffer. */
3061 length += NX_DHCPV6_DOMAIN_NAME_BUFFER_SIZE;
3062
3063 /* Check that we don't overrun the buffer. */
3064 if (length > buffer_length)
3065 {
3066 return NX_DHCPV6_INVALID_DATA_SIZE;
3067 }
3068
3069 /* Copy the domain name data to the supplied buffer. */
3070 memcpy(buffer, dhcpv6_ptr -> nx_dhcpv6_domain_name, NX_DHCPV6_DOMAIN_NAME_BUFFER_SIZE); /* Use case of memcpy is verified. */
3071 break;
3072
3073 /* Unknown or unsupported option*/
3074 default:
3075
3076 return NX_DHCPV6_UNKNOWN_OPTION;
3077 }
3078
3079 return NX_SUCCESS;
3080 }
3081
3082
3083 /**************************************************************************/
3084 /* */
3085 /* FUNCTION RELEASE */
3086 /* */
3087 /* _nxe_dhcpv6_get_time_accrued PORTABLE C */
3088 /* 6.1 */
3089 /* AUTHOR */
3090 /* */
3091 /* Yuxin Zhou, Microsoft Corporation */
3092 /* */
3093 /* DESCRIPTION */
3094 /* */
3095 /* This function performs error checking on the get time accrued on */
3096 /* Client IP lease service. */
3097 /* */
3098 /* INPUT */
3099 /* */
3100 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3101 /* time_accrued Pointer to time since IP lease */
3102 /* assigned (secs) */
3103 /* */
3104 /* OUTPUT */
3105 /* */
3106 /* status Actual completion status */
3107 /* NX_PTR_ERROR Invalid pointer input */
3108 /* */
3109 /* CALLS */
3110 /* */
3111 /* _nx_dhcpv6_get_time_accrued Actual get time accrued on Client */
3112 /* IP address lease service */
3113 /* */
3114 /* CALLED BY */
3115 /* */
3116 /* Application Code */
3117 /* */
3118 /* RELEASE HISTORY */
3119 /* */
3120 /* DATE NAME DESCRIPTION */
3121 /* */
3122 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3123 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3124 /* resulting in version 6.1 */
3125 /* */
3126 /**************************************************************************/
_nxe_dhcpv6_get_time_accrued(NX_DHCPV6 * dhcpv6_ptr,ULONG * time_accrued)3127 UINT _nxe_dhcpv6_get_time_accrued(NX_DHCPV6 *dhcpv6_ptr, ULONG *time_accrued)
3128 {
3129
3130 UINT status;
3131
3132
3133 /* Check for valid pointer input. */
3134 if (!dhcpv6_ptr || !time_accrued)
3135 {
3136 return NX_PTR_ERROR;
3137 }
3138
3139 /* Check for appropriate caller. */
3140 NX_THREADS_ONLY_CALLER_CHECKING
3141
3142 /* Call the actual service. */
3143 status = _nx_dhcpv6_get_time_accrued(dhcpv6_ptr, time_accrued);
3144
3145 /* Return completion status. */
3146 return status;
3147 }
3148
3149
3150 /**************************************************************************/
3151 /* */
3152 /* FUNCTION RELEASE */
3153 /* */
3154 /* _nx_dhcpv6_get_time_accrued PORTABLE C */
3155 /* 6.1 */
3156 /* AUTHOR */
3157 /* */
3158 /* Yuxin Zhou, Microsoft Corporation */
3159 /* */
3160 /* DESCRIPTION */
3161 /* */
3162 /* This function retrieves the time accrued on the assigned global IP */
3163 /* address lease. IP address to verify the address is still valid. */
3164 /* */
3165 /* INPUT */
3166 /* */
3167 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3168 /* time_accrued Pointer to time since IP lease */
3169 /* assigned (secs) */
3170 /* */
3171 /* OUTPUT */
3172 /* */
3173 /* NX_SUCCESS Successful completion status */
3174 /* */
3175 /* CALLS */
3176 /* */
3177 /* tx_mutex_get Obtain exclusive lock on Client */
3178 /* time accrued variable */
3179 /* tx_mutex_put Release exclusive lock in Client */
3180 /* time variable */
3181 /* */
3182 /* CALLED BY */
3183 /* */
3184 /* Application */
3185 /* */
3186 /* RELEASE HISTORY */
3187 /* */
3188 /* DATE NAME DESCRIPTION */
3189 /* */
3190 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3191 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3192 /* resulting in version 6.1 */
3193 /* */
3194 /**************************************************************************/
_nx_dhcpv6_get_time_accrued(NX_DHCPV6 * dhcpv6_ptr,ULONG * time_accrued)3195 UINT _nx_dhcpv6_get_time_accrued(NX_DHCPV6 *dhcpv6_ptr, ULONG *time_accrued)
3196 {
3197 UINT ia_index;
3198 UINT found_ia = 0;
3199
3200 /* Initialize the time accrued to zero. */
3201 *time_accrued = 0;
3202
3203 /* Check if the client currently has a valid IP address assigned. */
3204 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
3205 {
3206
3207 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID)
3208 {
3209
3210 /* Yes, got it. */
3211 found_ia= 1;
3212 break;
3213 }
3214 }
3215
3216 if(found_ia == 1)
3217 {
3218
3219 /* Get the time accrued on the IP address lease. */
3220 *time_accrued = dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued;
3221 }
3222
3223 /* Return successful completion. */
3224 return NX_SUCCESS;
3225 }
3226
3227
3228 /**************************************************************************/
3229 /* */
3230 /* FUNCTION RELEASE */
3231 /* */
3232 /* _nxe_dhcpv6_get_iana_lease_time PORTABLE C */
3233 /* 6.1 */
3234 /* AUTHOR */
3235 /* */
3236 /* Yuxin Zhou, Microsoft Corporation */
3237 /* */
3238 /* DESCRIPTION */
3239 /* */
3240 /* This function performs error checking on the get T1 and T2 value */
3241 /* of IANA option. */
3242 /* */
3243 /* INPUT */
3244 /* */
3245 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3246 /* T1 Pointer to T1 time */
3247 /* T2 Pointer to T2 time */
3248 /* */
3249 /* OUTPUT */
3250 /* */
3251 /* status Actual completion status */
3252 /* NX_PTR_ERROR Invalid pointer input */
3253 /* */
3254 /* CALLS */
3255 /* */
3256 /* _nx_dhcpv6_get_iana_lease_time Actual get Client IP T1/T2 time */
3257 /* */
3258 /* CALLED BY */
3259 /* */
3260 /* Application Code */
3261 /* */
3262 /* RELEASE HISTORY */
3263 /* */
3264 /* DATE NAME DESCRIPTION */
3265 /* */
3266 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3267 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3268 /* resulting in version 6.1 */
3269 /* */
3270 /**************************************************************************/
_nxe_dhcpv6_get_iana_lease_time(NX_DHCPV6 * dhcpv6_ptr,ULONG * T1,ULONG * T2)3271 UINT _nxe_dhcpv6_get_iana_lease_time(NX_DHCPV6 *dhcpv6_ptr, ULONG *T1, ULONG *T2)
3272 {
3273
3274 UINT status;
3275
3276
3277 /* Check for valid pointer input. */
3278 if (!dhcpv6_ptr || !T1 || !T2)
3279 {
3280 return NX_PTR_ERROR;
3281 }
3282
3283 /* Check for appropriate caller. */
3284 NX_THREADS_ONLY_CALLER_CHECKING
3285
3286 /* Call the actual service. */
3287 status = _nx_dhcpv6_get_iana_lease_time(dhcpv6_ptr, T1, T2);
3288
3289 /* Return completion status. */
3290 return status;
3291 }
3292
3293
3294 /**************************************************************************/
3295 /* */
3296 /* FUNCTION RELEASE */
3297 /* */
3298 /* _nx_dhcpv6_get_iana_lease_time PORTABLE C */
3299 /* 6.1 */
3300 /* AUTHOR */
3301 /* */
3302 /* Yuxin Zhou, Microsoft Corporation */
3303 /* */
3304 /* DESCRIPTION */
3305 /* */
3306 /* This function retrieves the T1 and T2 of Client's global IP. */
3307 /* */
3308 /* INPUT */
3309 /* */
3310 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3311 /* T1 Pointer to T1 time */
3312 /* T2 Pointer to T2 time */
3313 /* */
3314 /* OUTPUT */
3315 /* */
3316 /* NX_SUCCESS Successful completion status */
3317 /* */
3318 /* CALLS */
3319 /* */
3320 /* None */
3321 /* */
3322 /* CALLED BY */
3323 /* */
3324 /* Application */
3325 /* */
3326 /* RELEASE HISTORY */
3327 /* */
3328 /* DATE NAME DESCRIPTION */
3329 /* */
3330 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3331 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3332 /* resulting in version 6.1 */
3333 /* */
3334 /**************************************************************************/
_nx_dhcpv6_get_iana_lease_time(NX_DHCPV6 * dhcpv6_ptr,ULONG * T1,ULONG * T2)3335 UINT _nx_dhcpv6_get_iana_lease_time(NX_DHCPV6 *dhcpv6_ptr, ULONG *T1, ULONG *T2)
3336 {
3337 UINT ia_index;
3338 UINT found_ia = 0;
3339
3340 /* Initialize data to zero. */
3341 *T1 = 0;
3342 *T2 = 0;
3343
3344 /* Check if the client currently has a valid IP address assigned. */
3345 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
3346 {
3347
3348 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID)
3349 {
3350
3351 /* Yes, got it. */
3352 found_ia= 1;
3353 break;
3354 }
3355 }
3356
3357 if(found_ia == 1)
3358 {
3359
3360 /* Get the time data from the Client record IA. */
3361 *T1 = dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1;
3362 *T2 = dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2;
3363 }
3364
3365 /* Return successful completion. */
3366 return NX_SUCCESS;
3367 }
3368
3369
3370 /**************************************************************************/
3371 /* */
3372 /* FUNCTION RELEASE */
3373 /* */
3374 /* _nxe_dhcpv6_get_valid_ip_address_count PORTABLE C */
3375 /* 6.1 */
3376 /* AUTHOR */
3377 /* */
3378 /* Yuxin Zhou, Microsoft Corporation */
3379 /* */
3380 /* DESCRIPTION */
3381 /* */
3382 /* This function performs error checking on the get valid IP address */
3383 /* count. */
3384 /* */
3385 /* INPUT */
3386 /* */
3387 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3388 /* address_count The count of valid IP address */
3389 /* */
3390 /* OUTPUT */
3391 /* */
3392 /* status Actual completion status */
3393 /* NX_PTR_ERROR Invalid pointer input */
3394 /* */
3395 /* CALLS */
3396 /* */
3397 /* _nx_dhcpv6_get_valid_ip_address_count */
3398 /* Actual get the valid IP count */
3399 /* */
3400 /* CALLED BY */
3401 /* */
3402 /* Application Code */
3403 /* */
3404 /* RELEASE HISTORY */
3405 /* */
3406 /* DATE NAME DESCRIPTION */
3407 /* */
3408 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3409 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3410 /* resulting in version 6.1 */
3411 /* */
3412 /**************************************************************************/
_nxe_dhcpv6_get_valid_ip_address_count(NX_DHCPV6 * dhcpv6_ptr,UINT * address_count)3413 UINT _nxe_dhcpv6_get_valid_ip_address_count(NX_DHCPV6 *dhcpv6_ptr, UINT *address_count)
3414 {
3415
3416 UINT status;
3417
3418
3419 /* Check for valid pointer input. */
3420 if (!dhcpv6_ptr || !address_count)
3421 {
3422 return NX_PTR_ERROR;
3423 }
3424
3425 /* Check for appropriate caller. */
3426 NX_THREADS_ONLY_CALLER_CHECKING
3427
3428 /* Call the actual service. */
3429 status = _nx_dhcpv6_get_valid_ip_address_count(dhcpv6_ptr, address_count);
3430
3431 /* Return completion status. */
3432 return status;
3433 }
3434
3435
3436 /**************************************************************************/
3437 /* */
3438 /* FUNCTION RELEASE */
3439 /* */
3440 /* _nx_dhcpv6_get_valid_ip_address_count PORTABLE C */
3441 /* 6.1 */
3442 /* AUTHOR */
3443 /* */
3444 /* Yuxin Zhou, Microsoft Corporation */
3445 /* */
3446 /* DESCRIPTION */
3447 /* */
3448 /* This function retrieves the Client's global IP, then record the */
3449 /* count of valid IP address */
3450 /* */
3451 /* INPUT */
3452 /* */
3453 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3454 /* address_count The count of valid IP address */
3455 /* */
3456 /* OUTPUT */
3457 /* */
3458 /* NX_SUCCESS Successful completion status */
3459 /* */
3460 /* CALLS */
3461 /* */
3462 /* None */
3463 /* */
3464 /* CALLED BY */
3465 /* */
3466 /* Application */
3467 /* */
3468 /* RELEASE HISTORY */
3469 /* */
3470 /* DATE NAME DESCRIPTION */
3471 /* */
3472 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3473 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3474 /* resulting in version 6.1 */
3475 /* */
3476 /**************************************************************************/
_nx_dhcpv6_get_valid_ip_address_count(NX_DHCPV6 * dhcpv6_ptr,UINT * address_count)3477 UINT _nx_dhcpv6_get_valid_ip_address_count(NX_DHCPV6 *dhcpv6_ptr, UINT *address_count)
3478 {
3479
3480 UINT ia_index;
3481
3482 /* Initialize data to zero. */
3483 *address_count = 0;
3484
3485 /* Check if the client currently has a valid IP address assigned. */
3486 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
3487 {
3488
3489 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID)
3490 {
3491
3492 /* Yes, get one, update the count. */
3493 (*address_count)++;
3494 }
3495 }
3496
3497 /* Return successful completion. */
3498 return NX_SUCCESS;
3499 }
3500
3501
3502 /**************************************************************************/
3503 /* */
3504 /* FUNCTION RELEASE */
3505 /* */
3506 /* _nxe_dhcpv6_get_valid_ip_address_lease_time PORTABLE C */
3507 /* 6.1 */
3508 /* AUTHOR */
3509 /* */
3510 /* Yuxin Zhou, Microsoft Corporation */
3511 /* */
3512 /* DESCRIPTION */
3513 /* */
3514 /* This function performs error checking on the get valid IP address, */
3515 /* the preferred lifetime and the valid lifetime by the address index. */
3516 /* */
3517 /* INPUT */
3518 /* */
3519 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3520 /* address_index The valid address index */
3521 /* ip_address Pointer to IP address */
3522 /* preferred_lifetime Pointer to preferred lifetime */
3523 /* valid_lifetime Pointer to valid lifetime */
3524 /* */
3525 /* OUTPUT */
3526 /* */
3527 /* status Actual completion status */
3528 /* NX_PTR_ERROR Invalid pointer input */
3529 /* */
3530 /* CALLS */
3531 /* */
3532 /* _nx_dhcpv6_get_lvalid_ip_address_lease_time */
3533 /* Actual get Client IP valid address*/
3534 /* and the lease time of IP */
3535 /* */
3536 /* CALLED BY */
3537 /* */
3538 /* Application Code */
3539 /* */
3540 /* RELEASE HISTORY */
3541 /* */
3542 /* DATE NAME DESCRIPTION */
3543 /* */
3544 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3545 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3546 /* resulting in version 6.1 */
3547 /* */
3548 /**************************************************************************/
_nxe_dhcpv6_get_valid_ip_address_lease_time(NX_DHCPV6 * dhcpv6_ptr,UINT address_index,NXD_ADDRESS * ip_address,ULONG * preferred_lifetime,ULONG * valid_lifetime)3549 UINT _nxe_dhcpv6_get_valid_ip_address_lease_time(NX_DHCPV6 *dhcpv6_ptr, UINT address_index, NXD_ADDRESS *ip_address,
3550 ULONG *preferred_lifetime, ULONG *valid_lifetime)
3551 {
3552
3553 UINT status;
3554
3555
3556 /* Check for valid pointer input. */
3557 if (!dhcpv6_ptr || !ip_address || !preferred_lifetime || !valid_lifetime )
3558 {
3559 return NX_PTR_ERROR;
3560 }
3561
3562 /* Check for appropriate caller. */
3563 NX_THREADS_ONLY_CALLER_CHECKING
3564
3565 /* Call the actual service. */
3566 status = _nx_dhcpv6_get_valid_ip_address_lease_time(dhcpv6_ptr, address_index, ip_address, preferred_lifetime, valid_lifetime);
3567
3568 /* Return completion status. */
3569 return status;
3570 }
3571
3572
3573 /**************************************************************************/
3574 /* */
3575 /* FUNCTION RELEASE */
3576 /* */
3577 /* _nx_dhcpv6_get_valid_ip_address_lease_time PORTABLE C */
3578 /* 6.1 */
3579 /* AUTHOR */
3580 /* */
3581 /* Yuxin Zhou, Microsoft Corporation */
3582 /* */
3583 /* DESCRIPTION */
3584 /* */
3585 /* This function retrieves the Client's valid global IP addresses, */
3586 /* preferred lifetime and valid lifetime by address index. */
3587 /* */
3588 /* INPUT */
3589 /* */
3590 /* dhcpv6_ptr Pointer to DHCPv6 Client */
3591 /* address_index The valid address index */
3592 /* ip_address Pointer to IPv6 address */
3593 /* preferred_lifetime Pointer to preferred lifetime */
3594 /* valid_lifetime Pointer to valid lifetime */
3595 /* */
3596 /* OUTPUT */
3597 /* */
3598 /* NX_SUCCESS Successful completion status */
3599 /* */
3600 /* CALLS */
3601 /* */
3602 /* None */
3603 /* */
3604 /* CALLED BY */
3605 /* */
3606 /* Application */
3607 /* */
3608 /* RELEASE HISTORY */
3609 /* */
3610 /* DATE NAME DESCRIPTION */
3611 /* */
3612 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3613 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3614 /* resulting in version 6.1 */
3615 /* */
3616 /**************************************************************************/
_nx_dhcpv6_get_valid_ip_address_lease_time(NX_DHCPV6 * dhcpv6_ptr,UINT address_index,NXD_ADDRESS * ip_address,ULONG * preferred_lifetime,ULONG * valid_lifetime)3617 UINT _nx_dhcpv6_get_valid_ip_address_lease_time(NX_DHCPV6 *dhcpv6_ptr, UINT address_index, NXD_ADDRESS *ip_address,
3618 ULONG *preferred_lifetime, ULONG *valid_lifetime)
3619 {
3620
3621 UINT status;
3622 UINT ia_index;
3623 UINT valid_ia_count;
3624
3625
3626 /* Initialize data to zero. */
3627 valid_ia_count = 0;
3628 *valid_lifetime = 0;
3629 *preferred_lifetime = 0;
3630 status = NX_DHCPV6_IA_ADDRESS_NOT_VALID;
3631
3632 /* Clear the address buffer. */
3633 SET_UNSPECIFIED_ADDRESS(&ip_address -> nxd_ip_address.v6[0]);
3634
3635 /* Check if the client currently has a valid IP address assigned. */
3636 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
3637 {
3638
3639 /* Skip empty or invalidated addresses. */
3640 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID)
3641 {
3642
3643 if((valid_ia_count++) == address_index)
3644 {
3645
3646 /* Yes, got it. */
3647 break;
3648 }
3649 }
3650 }
3651
3652 if(ia_index < NX_DHCPV6_MAX_IA_ADDRESS)
3653 {
3654
3655 /* Yes; return the assigned IP address from the DHCPv6 Client record. */
3656 COPY_IPV6_ADDRESS(&(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0]),
3657 &(ip_address -> nxd_ip_address.v6[0]));
3658
3659 /* Set the IP version. */
3660 ip_address -> nxd_ip_version = NX_IP_VERSION_V6;
3661
3662 /* Return the preferred lifetime and valid lifetime. */
3663 *preferred_lifetime = dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_preferred_lifetime;
3664 *valid_lifetime = dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime;
3665
3666 status = NX_SUCCESS;
3667 }
3668
3669 /* Return. */
3670 return status;
3671 }
3672
3673
3674 /**************************************************************************/
3675 /* */
3676 /* FUNCTION RELEASE */
3677 /* */
3678 /* _nx_dhcpv6_IP_lifetime_timeout_entry PORTABLE C */
3679 /* 6.1 */
3680 /* AUTHOR */
3681 /* */
3682 /* Yuxin Zhou, Microsoft Corporation */
3683 /* */
3684 /* DESCRIPTION */
3685 /* */
3686 /* This function is scheduled by the ThreadX scheduler on a user */
3687 /* configurable time interval. It updates the time accrued since the */
3688 /* Client was assigned its global IP address so that the DHCP Client */
3689 /* knows when to renew or rebind its IP address. */
3690 /* */
3691 /* INPUT */
3692 /* */
3693 /* dhcpv6_ptr_value Pointer to the DHCPV6 Client */
3694 /* */
3695 /* OUTPUT */
3696 /* */
3697 /* None */
3698 /* */
3699 /* CALLS */
3700 /* */
3701 /* None */
3702 /* */
3703 /* CALLED BY */
3704 /* */
3705 /* */
3706 /* RELEASE HISTORY */
3707 /* */
3708 /* DATE NAME DESCRIPTION */
3709 /* */
3710 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3711 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3712 /* resulting in version 6.1 */
3713 /* */
3714 /**************************************************************************/
_nx_dhcpv6_IP_lifetime_timeout_entry(ULONG dhcpv6_ptr_value)3715 VOID _nx_dhcpv6_IP_lifetime_timeout_entry(ULONG dhcpv6_ptr_value)
3716 {
3717
3718 NX_DHCPV6 *dhcpv6_ptr;
3719
3720
3721 /* Setup DHCPv6 Client pointer. */
3722 NX_TIMER_EXTENSION_PTR_GET(dhcpv6_ptr, NX_DHCPV6, dhcpv6_ptr_value)
3723
3724 /* Check if the DHCPv6 Client has valid IP address assigned and a finite IP
3725 address lease (no point in waiting for an infinite lease to time out!) */
3726 if ((dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1 != NX_DHCPV6_INFINITE_LEASE) &&
3727 (dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1 != 0))
3728 {
3729
3730 /* Update the time remaining on the Client IP address lease.
3731 The current time expressed in units of seconds. */
3732 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued += NX_DHCPV6_IP_LIFETIME_TIMER_INTERVAL;
3733 }
3734
3735 return;
3736 }
3737
3738
3739 /**************************************************************************/
3740 /* */
3741 /* FUNCTION RELEASE */
3742 /* */
3743 /* _nx_dhcpv6_process PORTABLE C */
3744 /* 6.1 */
3745 /* AUTHOR */
3746 /* */
3747 /* Yuxin Zhou, Microsoft Corporation */
3748 /* */
3749 /* DESCRIPTION */
3750 /* */
3751 /* This function executes the DHCPV6 Client request. It compiles */
3752 /* and sends the DHCPv6 request message, and updates the Client record */
3753 /* with server data. It maintains the DHCPv6 Client state and calls */
3754 /* the state change callback if one is registered with the DHCPv6 */
3755 /* Client. */
3756 /* */
3757 /* INPUT */
3758 /* */
3759 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
3760 /* */
3761 /* OUTPUT */
3762 /* */
3763 /* None */
3764 /* */
3765 /* CALLS */
3766 /* */
3767 /* _nx_dhcpv6_send_request Send the Client DHCPv6 request */
3768 /* _nx_dhcpv6_waiting_on_reply Wait for valid DHCPv6 server reply*/
3769 /* _nx_dhcpv6_request_decline Send the DHCPv6 DECLINE request */
3770 /* _nx_dhcpv6_register_IP_address Register Client IP address */
3771 /* _nx_dhcpv6_remove_assigned_address */
3772 /* Remove Client global IP address */
3773 /* _nx_dhcpv6_update_retransmit_info Update the retransmit information */
3774 /* _nx_dhcpv6_send_solicit Send the DHCPv6 solicit message */
3775 /* _nx_dhcpv6_flush_queue_packets Flush the queue packets */
3776 /* tx_mutex_get Obtain lock on Client resource */
3777 /* tx_mutex_put Release lock on Client resourse */
3778 /* tx_timer_deactivate Deactivate the session timer */
3779 /* */
3780 /* CALLED BY */
3781 /* */
3782 /* _nx_dhcpv6_thread_entry Processing thread for DHCPv6 */
3783 /* */
3784 /* RELEASE HISTORY */
3785 /* */
3786 /* DATE NAME DESCRIPTION */
3787 /* */
3788 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3789 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3790 /* resulting in version 6.1 */
3791 /* */
3792 /**************************************************************************/
_nx_dhcpv6_process(NX_DHCPV6 * dhcpv6_ptr)3793 VOID _nx_dhcpv6_process(NX_DHCPV6 *dhcpv6_ptr)
3794 {
3795
3796 UINT status;
3797 UCHAR original_state;
3798
3799 /* Initialize the DHCPv6 Client status as no errors. */
3800 dhcpv6_ptr -> nx_status_code = NX_DHCPV6_SUCCESS;
3801
3802 /* Clear any previous messages from the DHCPv6 server. */
3803 memset(dhcpv6_ptr -> nx_status_message, 0, NX_DHCPV6_MAX_MESSAGE_SIZE);
3804
3805 /* Remember the original DHCPv6 state for the changed state callback function. */
3806 original_state = dhcpv6_ptr -> nx_dhcpv6_state;
3807
3808 /* Process the DHCPv6 Client for the state it is in. */
3809 switch (dhcpv6_ptr -> nx_dhcpv6_state)
3810 {
3811
3812 /* The DHCPv6 remains initial status or DHCPv6 interactive process has completed.
3813 Just clear the timer and message ID. */
3814 case NX_DHCPV6_STATE_INIT:
3815 case NX_DHCPV6_STATE_BOUND_TO_ADDRESS:
3816 {
3817
3818 /* Clear the message id. */
3819 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
3820
3821 /* Deactivate the session timer of elapsed time. */
3822 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
3823
3824 /* Flush the queue packets. */
3825 _nx_dhcpv6_flush_queue_packets(dhcpv6_ptr);
3826
3827 return;
3828 }
3829
3830 /* The caller has requested to send a solicit message. */
3831 case NX_DHCPV6_STATE_SENDING_SOLICIT:
3832 {
3833
3834 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type = NX_DHCPV6_MESSAGE_TYPE_SOLICIT;
3835
3836 dhcpv6_ptr -> nx_dhcpv6_solicitations_sent++;
3837
3838 /* Send the DHCPV6 Solicit message. */
3839 status = _nx_dhcpv6_send_request(dhcpv6_ptr);
3840
3841 /* Check for error. */
3842 if (status != NX_SUCCESS)
3843 {
3844
3845 /* Return. Can't do any more now. */
3846 return;
3847 }
3848
3849 /* Make sure the server DUID is cleared. Client should be accepting any server reply. */
3850 memset(&(dhcpv6_ptr -> nx_dhcpv6_server_duid), 0, sizeof(NX_DHCPV6_DUID));
3851
3852 /* Wait for a reply from the server. This will also extract the
3853 server packet information and update the DHCPv6 Client record (and state). */
3854 status = _nx_dhcpv6_waiting_on_reply(dhcpv6_ptr);
3855
3856 /* Check for processing error or error code sent by server. As per RFC 3315 section 17.1.3,
3857 the Client ignores status errors (e.g. No Addresses Available) from the server, and continues
3858 sending Solicit messages. */
3859 if ((status != NX_SUCCESS) || (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS))
3860 {
3861
3862 /* Update the retransmission information. */
3863 if (_nx_dhcpv6_update_retransmit_info(dhcpv6_ptr))
3864 {
3865
3866 /* The retry limit on Solicit messages is exceeded. Set the CLient back to
3867 the INIT state and stop sending solicit messages for now. */
3868 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
3869
3870 /* Request attempt failed. The state change callback if set will be called. */
3871 }
3872 }
3873 else
3874 {
3875
3876 if(dhcpv6_ptr -> nx_dhcpv6_request_solicit_mode == NX_DHCPV6_SOLICIT_NORMAL)
3877 {
3878 /* Server has responded to and accepted the SOLICIT request with an ADVERTISE message.
3879 Move to the next state to continue the DHCPv6 protocol. */
3880
3881 /* Set the DHCP Client state to Requesting. */
3882 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_SENDING_REQUEST;
3883
3884 /* Reset the retransmission timeout and retry. */
3885 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_REQ_TRANSMISSION_TIMEOUT;
3886 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
3887
3888 /* Set the initaial elasped time of DHCPv6 message. */
3889 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
3890
3891 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
3892 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_REQ_TRANSMISSION_TIMEOUT;
3893 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_REQ_RETRANSMISSION_COUNT;
3894 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_REQ_RETRANSMISSION_TIMEOUT;
3895 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_REQ_RETRANSMISSION_DURATION;
3896
3897 /* The next sending packet is the new packet, so reset the message id. */
3898 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
3899
3900 /* Increment the number of solicitation responses. */
3901 dhcpv6_ptr -> nx_dhcpv6_solicitation_responses++;
3902 }
3903 else
3904 {
3905
3906 /* Server sending the REPLY message responded to and accepted the SOLICIT request with Rapid Commit option,
3907 Move to the next state to continue the DHCPv6 protocol. */
3908
3909 /* Set the initaial elasped time of DHCPv6 message. */
3910 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
3911
3912 /* Increment the number of solicitation responses. */
3913 dhcpv6_ptr -> nx_dhcpv6_solicitation_responses++;
3914
3915 /* Clear the message id. */
3916 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
3917
3918 /* Deactivate the session timer of elapsed time. */
3919 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
3920
3921 /* Set the DHCP Client state to Requesting. */
3922 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_BOUND_TO_ADDRESS;
3923
3924 /* Yes, get the IPv6 address by DHCPv6. set it. */
3925 status = _nx_dhcpv6_register_IP_address(dhcpv6_ptr);
3926
3927 }
3928
3929 }
3930
3931 break;
3932 }
3933
3934
3935 /* The DHCP Client is in the REQUEST state; send the Request message till the server responds
3936 or the number of retries exceeds the max. */
3937 case NX_DHCPV6_STATE_SENDING_REQUEST:
3938 {
3939
3940 /* Reset the initial timeout and zero out transmission count. */
3941 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type = NX_DHCPV6_MESSAGE_TYPE_REQUEST;
3942
3943 /* Transmit the Request message. */
3944 status = _nx_dhcpv6_send_request(dhcpv6_ptr);
3945
3946 /* Check for transmission error. */
3947 if (status != NX_SUCCESS)
3948 {
3949
3950 /* Return. Can't do any more now. */
3951 return;
3952 }
3953
3954 dhcpv6_ptr -> nx_dhcpv6_requests_sent++;
3955
3956 /* Send the message to the server. */
3957 status = _nx_dhcpv6_waiting_on_reply(dhcpv6_ptr);
3958
3959 /* Check for socket receive error or Server error code. */
3960 if ((status != NX_SUCCESS) || (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS))
3961 {
3962
3963 /* Check the status. */
3964 if ((status == NX_SUCCESS) &&
3965 ((dhcpv6_ptr -> nx_status_code == NX_DHCPV6_NOT_ON_LINK) ||
3966 (dhcpv6_ptr -> nx_status_code == NX_DHCPV6_NO_ADDRESS_AVAILABLE)))
3967 {
3968
3969 /* Indicate the DHCP Client process is idle. */
3970 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_TRUE;
3971
3972 /* The next sending packet is the new packet, so reset the message id. */
3973 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
3974
3975 /* Clear the assigned IP address. */
3976 _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr,NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
3977
3978 /* When the client receives a NotOnLink status from the server in response to a Request,
3979 the client can restart the DHCP server discovery process. RFC3315, Section18.1.8, Page48. */
3980 _nx_dhcpv6_request_solicit(dhcpv6_ptr);
3981 }
3982
3983 else
3984 {
3985
3986 /* Update the retransmission information. */
3987 if (_nx_dhcpv6_update_retransmit_info(dhcpv6_ptr))
3988 {
3989
3990 /* The retry limit on Request messages is exceeded. Set the Client back to
3991 the INIT state and stop sending request messages for now. */
3992 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
3993
3994 /* Request attempt failed. The state change callback if set will be called. */
3995 }
3996 }
3997 }
3998 else
3999 {
4000
4001 /* The Server responded to and accepted the REQUEST message. The Client is now bound to assigned
4002 IPv6 address. The Client must still register this IPv6 address with NetX Duo to verify it is
4003 unique on the network. */
4004
4005 /* Clear the time accrued on the new IP lease to zero. */
4006 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = 0;
4007
4008 /* The next sending packet is the new packet, so reset the message id. */
4009 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4010
4011 /* Receive the correct response, so deactivate the session timer of elapsed time. */
4012 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
4013
4014 /* Increment the number of Request responses received. */
4015 dhcpv6_ptr -> nx_dhcpv6_request_responses++;
4016
4017 /* Indicate the Client is bound to an assigned IPv6 address. */
4018 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_BOUND_TO_ADDRESS;
4019
4020 /* Yes, get the IPv6 address by DHCPv6. set it. */
4021 status = _nx_dhcpv6_register_IP_address(dhcpv6_ptr);
4022 }
4023
4024 break;
4025 }
4026
4027 /* The caller has requested a RENEW request message be sent. */
4028 case NX_DHCPV6_STATE_SENDING_RENEW:
4029 {
4030
4031 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type = NX_DHCPV6_MESSAGE_TYPE_RENEW;
4032
4033 dhcpv6_ptr -> nx_dhcpv6_renews_sent++;
4034
4035 /* Send the DHCPV6 RENEW message. */
4036 status = _nx_dhcpv6_send_request(dhcpv6_ptr);
4037
4038 /* Check for transmission error. */
4039 if (status != NX_SUCCESS)
4040 {
4041
4042 /* Return. Can't do any more now. */
4043 return;
4044 }
4045
4046 /* Send the message to the server. */
4047 status = _nx_dhcpv6_waiting_on_reply(dhcpv6_ptr);
4048
4049 /* Check for socket receive error or Server error code. */
4050 if ((status != NX_SUCCESS) ||
4051 (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS) ||
4052 ((dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_IA_ADDRESS_OPTION) == 0))
4053 {
4054
4055 /* Process the NoBinding status. */
4056 if ((status == NX_SUCCESS) && (dhcpv6_ptr -> nx_status_code == NX_DHCPV6_NO_BINDING))
4057 {
4058
4059 /* When the client receives a Reply message in response to a Renew or Rebind message,
4060 send a Request message if the IA contains a Status Code option with the NoBinding status.
4061 RFC 3315, Sectoon 18.1.8, Page 48. */
4062 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_SENDING_REQUEST;
4063
4064 /* Reset the retransmission timeout and retry. */
4065 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_REQ_TRANSMISSION_TIMEOUT;
4066 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
4067
4068 /* Set the initaial elasped time of DHCPv6 message. */
4069 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
4070
4071 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
4072 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_REQ_TRANSMISSION_TIMEOUT;
4073 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_REQ_RETRANSMISSION_COUNT;
4074 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_REQ_RETRANSMISSION_TIMEOUT;
4075 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_REQ_RETRANSMISSION_DURATION;
4076
4077 /* The next sending packet is the new packet, so reset the message id. */
4078 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4079 }
4080 else
4081 {
4082
4083 /* Update the retransmission information. */
4084 if (_nx_dhcpv6_update_retransmit_info(dhcpv6_ptr))
4085 {
4086
4087 /* Clear the assigned IP address. */
4088 _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
4089
4090 /* The retry limit on Renew messages is exceeded. Set the Client back to
4091 the INIT state and stop sending Renew messages for now. */
4092 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4093
4094 /* Renew attempt failed. The state change callback if set will be called. */
4095 }
4096 }
4097 }
4098 else
4099 {
4100
4101 /* The Server responded to and accepted our RENEW request. Update the Client to a bound
4102 state and reset the lease timers. */
4103
4104 /* Indicate the Client is bound to an assigned IPv6 address. */
4105 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_BOUND_TO_ADDRESS;
4106
4107 /* Reset the time keeper! */
4108 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = 0;
4109
4110 /* The next sending packet is the new packet, so reset the message id. */
4111 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4112
4113 /* Receive the correct response, so deactivate the session timer of elapsed time. */
4114 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
4115
4116 /* Yes, get the IPv6 address by DHCPv6. set it. */
4117 status = _nx_dhcpv6_register_IP_address(dhcpv6_ptr);
4118
4119 /* Increment the number of renew responses received. */
4120 dhcpv6_ptr -> nx_dhcpv6_renew_responses++;
4121 }
4122
4123 break;
4124 }
4125
4126 /* The caller has requested to send a rebind request message. */
4127 case NX_DHCPV6_STATE_SENDING_REBIND:
4128 {
4129
4130 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type = NX_DHCPV6_MESSAGE_TYPE_REBIND;
4131
4132 /* Increase the count of retries. */
4133 dhcpv6_ptr -> nx_dhcpv6_rebinds_sent++;
4134
4135 /* Send the DHCPV6 Rebind message. */
4136 status = _nx_dhcpv6_send_request(dhcpv6_ptr);
4137
4138 /* Check for socket send error. */
4139 if (status != NX_SUCCESS)
4140 {
4141
4142 /* Return. Can't do any more now. */
4143 return;
4144 }
4145
4146 /* Make sure the server DUID is cleared. Client should be accepting any server reply. */
4147 memset(&(dhcpv6_ptr -> nx_dhcpv6_server_duid), 0, sizeof(NX_DHCPV6_DUID));
4148
4149 /* Send the message to the server. */
4150 status = _nx_dhcpv6_waiting_on_reply(dhcpv6_ptr);
4151
4152 /* Check for socket receive error or Server error code. */
4153 if ((status != NX_SUCCESS) ||
4154 (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS) ||
4155 ((dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_IA_ADDRESS_OPTION) == 0))
4156 {
4157
4158 /* Process the NoBinding status. */
4159 if ((status == NX_SUCCESS) && (dhcpv6_ptr -> nx_status_code == NX_DHCPV6_NO_BINDING))
4160 {
4161
4162 /* When the client receives a Reply message in response to a Renew or Rebind message,
4163 send a Request message if the IA contains a Status Code option with the NoBinding status.
4164 RFC 3315, Section 18.1.8, Page 48. */
4165 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_SENDING_REQUEST;
4166
4167 /* Reset the retransmission timeout and retry. */
4168 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_REQ_TRANSMISSION_TIMEOUT;
4169 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
4170
4171 /* Set the initaial elasped time of DHCPv6 message. */
4172 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
4173
4174 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
4175 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_REQ_TRANSMISSION_TIMEOUT;
4176 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_REQ_RETRANSMISSION_COUNT;
4177 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_REQ_RETRANSMISSION_TIMEOUT;
4178 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_REQ_RETRANSMISSION_DURATION;
4179
4180 /* The next sending packet is the new packet, so reset the message id. */
4181 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4182 }
4183 else
4184 {
4185
4186 /* Update the retransmission information. */
4187 if (_nx_dhcpv6_update_retransmit_info(dhcpv6_ptr))
4188 {
4189
4190 /* Clear the assigned IP address. */
4191 _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
4192
4193 /* The retry limit on Rebind messages is exceeded. Set the Client back to
4194 the INIT state and stop sending Rebind messages for now. */
4195 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4196
4197 /* Rebind attempt failed. The client state change callback if set will be called. */
4198 }
4199 }
4200 }
4201 else
4202 {
4203
4204 /* Make sure the Client state is set to Bound to an assigned IPv6 address. */
4205 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_BOUND_TO_ADDRESS;
4206
4207 /* Reset the time keeper! */
4208 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = 0;
4209
4210 /* The next sending packet is the new packet, so reset the message id. */
4211 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4212
4213 /* Yes, get the IPv6 address by DHCPv6. set it. */
4214 status = _nx_dhcpv6_register_IP_address(dhcpv6_ptr);
4215
4216 /* Increment the number of rebind responses received. */
4217 dhcpv6_ptr -> nx_dhcpv6_rebind_responses++;
4218
4219 /* Receive the correct response, so deactivate the session timer of elapsed time. */
4220 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
4221 }
4222
4223 break;
4224 }
4225
4226 case NX_DHCPV6_STATE_SENDING_CONFIRM:
4227 {
4228
4229 /* Set the message type. */
4230 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type = NX_DHCPV6_MESSAGE_TYPE_CONFIRM;
4231
4232 /* Increase the count of retries. */
4233 dhcpv6_ptr -> nx_dhcpv6_confirms_sent++;
4234
4235 /* Send the DHCPV6 Confirm message. */
4236 status = _nx_dhcpv6_send_request(dhcpv6_ptr);
4237
4238 /* Send the message until we get a reply from the server. */
4239 status = _nx_dhcpv6_waiting_on_reply(dhcpv6_ptr);
4240
4241 /* Check for socket receive error or Server error code. */
4242 if ((status != NX_SUCCESS) || (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS))
4243 {
4244
4245 if ((status == NX_SUCCESS) && (dhcpv6_ptr -> nx_status_code == NX_DHCPV6_NOT_ON_LINK))
4246 {
4247
4248 /* Indicate the DHCP Client process is idle. */
4249 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_TRUE;
4250
4251 /* The next sending packet is the new packet, so reset the message id. */
4252 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4253
4254 /* Clear the assigned IP address. */
4255 _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr,NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
4256
4257 /* When the client receives a NotOnLink status from the server in response to a Confirm messag,
4258 the client performs DHCP server solicitation. RFC3315, Section18.1.8, Page48. */
4259 _nx_dhcpv6_request_solicit(dhcpv6_ptr);
4260 }
4261
4262 /* Retransmit the Confirm message. */
4263 else
4264 {
4265
4266 /* Update the retransmission information. */
4267 if (_nx_dhcpv6_update_retransmit_info(dhcpv6_ptr))
4268 {
4269
4270 /* The retry limit on Confirm messages is exceeded. Set the Client back to
4271 the INIT state and stop sending rebind messages for now. */
4272 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4273
4274 /* Confirm request failed. The state change callback if set will be called. */
4275 }
4276 }
4277 }
4278 else
4279 {
4280
4281 /* Successful confirmation. Set the assigned address status to valid (confirmed). */
4282
4283 /* Yes, get the IPv6 address by DHCPv6. set it. */
4284 status = _nx_dhcpv6_register_IP_address(dhcpv6_ptr);
4285
4286 /* Increment the number of responses to confirm. */
4287 dhcpv6_ptr -> nx_dhcpv6_confirm_responses++;
4288
4289 /* Restore the Client state depending on its IANA address status. */
4290 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_BOUND_TO_ADDRESS;
4291
4292 /* The next sending packet is the new packet, so reset the message id. */
4293 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4294
4295 /* Receive the correct response, so deactivate the session timer of elapsed time. */
4296 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
4297 }
4298
4299 break;
4300
4301 }
4302
4303 case NX_DHCPV6_STATE_SENDING_RELEASE:
4304 {
4305
4306 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type = NX_DHCPV6_MESSAGE_TYPE_RELEASE;
4307
4308 /* Increase the count of releases. */
4309 dhcpv6_ptr -> nx_dhcpv6_releases_sent++;
4310
4311 /* Send the DHCPV6 Release message. */
4312 status = _nx_dhcpv6_send_request(dhcpv6_ptr);
4313
4314 /* Check for socket error. */
4315 if (status != NX_SUCCESS)
4316 {
4317
4318 /* Return. Can't do any more now. */
4319 return;
4320 }
4321
4322 /* Send the message to the server. */
4323 status = _nx_dhcpv6_waiting_on_reply(dhcpv6_ptr);
4324
4325 /* Check for socket receive error. For the release message, consider the release
4326 request completed if the server responds, regardless of Server error code. RFC 3315 Section 18.1.8 */
4327 if (status != NX_SUCCESS)
4328 {
4329
4330 /* Update the retransmission information. */
4331 if (_nx_dhcpv6_update_retransmit_info(dhcpv6_ptr))
4332 {
4333
4334 /* Clear global ip address and lifetime parameters from the Client record. */
4335 _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
4336
4337 /* The retry limit on release messages is exceeded. Set the Client back to
4338 the INIT state and stop sending rebind messages for now. */
4339 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4340
4341 /* No response to release message from server. The state change callback if set will be called. */
4342 }
4343 }
4344 else
4345 {
4346 /* Increment the number of responses to release request. */
4347 dhcpv6_ptr -> nx_dhcpv6_release_responses++;
4348
4349 /* The next sending packet is the new packet, so reset the message id. */
4350 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4351
4352 /* Receive the correct response, so deactivate the session timer of elapsed time. */
4353 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
4354
4355 /* Clear global ip address and lifetime parameters from the Client record. */
4356 _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
4357
4358 /* Update the Client state to not bound. */
4359 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4360 }
4361
4362 break;
4363 }
4364
4365 case NX_DHCPV6_STATE_SENDING_DECLINE:
4366 {
4367
4368 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type = NX_DHCPV6_MESSAGE_TYPE_DECLINE;
4369
4370 /* Increase the count of declines. */
4371 dhcpv6_ptr -> nx_dhcpv6_declines_sent++;
4372
4373 /* Send the DHCPV6 Decline message. */
4374 status = _nx_dhcpv6_send_request(dhcpv6_ptr);
4375
4376 /* Check for interal error. */
4377 if (status != NX_SUCCESS)
4378 {
4379
4380 /* Return. Can't do any more now. */
4381 return;
4382 }
4383
4384 /* Send the message to the server. */
4385 status = _nx_dhcpv6_waiting_on_reply(dhcpv6_ptr);
4386
4387 /* Check for socket receive error. For the decline message, consider the release
4388 request completed if the server responds, regardless of Server error code. RFC3315,Section 18.1.7 */
4389 if (status != NX_SUCCESS)
4390 {
4391
4392 /* Update the retransmission information. */
4393 if (_nx_dhcpv6_update_retransmit_info(dhcpv6_ptr))
4394 {
4395
4396 /* Clear global ip address and lifetime parameters from the Client record. */
4397 _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
4398
4399 /* The retry limit on decline messages is exceeded. Set the Client back to
4400 the INIT state and stop sending rebind messages for now. */
4401 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4402
4403 /* No response to decline message from server. The state change callback if set will be called. */
4404 }
4405 }
4406 else
4407 {
4408
4409 /* Increment the number of server responses to Decline request. */
4410 dhcpv6_ptr -> nx_dhcpv6_decline_responses++;
4411
4412 /* The next sending packet is the new packet, so reset the message id. */
4413 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4414
4415 /* Receive the correct response, so deactivate the session timer of elapsed time. */
4416 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
4417
4418 /* Clear global ip address and lifetime parameters from the Client record. */
4419 status = _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
4420
4421 /* Change the DHCPv6 Client to the unbound state. */
4422 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4423 }
4424
4425 break;
4426 }
4427
4428 case NX_DHCPV6_STATE_SENDING_INFORM_REQUEST:
4429 {
4430
4431 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type = NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST;
4432
4433 /* Increase the count of declines. */
4434 dhcpv6_ptr -> nx_dhcpv6_inform_req_sent++;
4435
4436 /* Send the Inform Request message. */
4437 status = _nx_dhcpv6_send_request(dhcpv6_ptr);
4438
4439 /* Check for transmission error. */
4440 if (status != NX_SUCCESS)
4441 {
4442
4443 /* Return. Nothing more to do. */
4444 return;
4445 }
4446
4447 /* Wait for a reply from the server. This will also extract the
4448 server packet information and update the DHCPv6 Client state. */
4449 status = _nx_dhcpv6_waiting_on_reply(dhcpv6_ptr);
4450
4451 /* Check for socket receive error or Server error code. */
4452 if ((status != NX_SUCCESS) || (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS))
4453 {
4454
4455 /* Update the retransmission information. */
4456 if (_nx_dhcpv6_update_retransmit_info(dhcpv6_ptr))
4457 {
4458
4459 /* The retry limit on decline messages is exceeded. Set the Client back to
4460 the INIT state and stop sending rebind messages for now. */
4461 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4462 }
4463 }
4464 else
4465 {
4466 /* Increment the number of responses to Inform Request received. */
4467 dhcpv6_ptr -> nx_dhcpv6_inform_req_responses++;
4468
4469 /* The next sending packet is the new packet, so reset the message id. */
4470 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = 0;
4471
4472 /* Receive the correct response, so deactivate the session timer of elapsed time. */
4473 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
4474
4475 /* Restore the Client state depending on its IANA address status. */
4476 if (dhcpv6_ptr -> nx_dhcpv6_ia[0].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID)
4477 {
4478 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_BOUND_TO_ADDRESS;
4479 }
4480 else
4481 {
4482 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
4483 }
4484 }
4485
4486 break;
4487 }
4488
4489 default:
4490 {
4491
4492 /* Unknown or unsupported DHCPv6 request (state). */
4493 return;
4494 }
4495 }
4496
4497 /* Is there a state change callback registered with the Client? */
4498 if ((dhcpv6_ptr -> nx_dhcpv6_state_change_callback) && (original_state != (dhcpv6_ptr -> nx_dhcpv6_state)))
4499 {
4500
4501 /* Yes, call the the state change callback with the original and new state. */
4502 (dhcpv6_ptr -> nx_dhcpv6_state_change_callback)(dhcpv6_ptr, original_state, dhcpv6_ptr -> nx_dhcpv6_state);
4503 }
4504
4505 return;
4506 }
4507
4508
4509 /**************************************************************************/
4510 /* */
4511 /* FUNCTION RELEASE */
4512 /* */
4513 /* _nx_dhcpv6_process_client_duid PORTABLE C */
4514 /* 6.1 */
4515 /* AUTHOR */
4516 /* */
4517 /* Yuxin Zhou, Microsoft Corporation */
4518 /* */
4519 /* DESCRIPTION */
4520 /* */
4521 /* This function extracts the client DUID from the server reply and */
4522 /* verifies that it matches the Client DUID on record. */
4523 /* */
4524 /* INPUT */
4525 /* */
4526 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
4527 /* option_data Pointer to option data */
4528 /* option_length Size of option data */
4529 /* */
4530 /* OUTPUT */
4531 /* */
4532 /* NX_SUCCESS Successful completion status */
4533 /* NX_DHCPV6_INVALID_CLIENT_DUID Client DUID is missing data or */
4534 /* does not match the DUID on record*/
4535 /* CALLS */
4536 /* */
4537 /* _nx_dhcpv6_utility_get_data Parses data from specified buffer */
4538 /* */
4539 /* CALLED BY */
4540 /* */
4541 /* _nx_dhcpv6_extract_packet_information */
4542 /* Extracts server reply from packet */
4543 /* */
4544 /* RELEASE HISTORY */
4545 /* */
4546 /* DATE NAME DESCRIPTION */
4547 /* */
4548 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4549 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
4550 /* packet length verification, */
4551 /* resulting in version 6.1 */
4552 /* */
4553 /**************************************************************************/
_nx_dhcpv6_process_client_duid(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length)4554 UINT _nx_dhcpv6_process_client_duid(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length)
4555 {
4556
4557 ULONG data;
4558 UINT index = 0;
4559
4560
4561 /* The Client should already have its own DUID on record. So just parse the
4562 data and compare each DUID field with the Client's DUID. */
4563
4564 /* Check option length for DUID type and hardware type. */
4565 if (option_length < 4)
4566 {
4567 return(NX_DHCPV6_INVALID_CLIENT_DUID);
4568 }
4569
4570 /* Extract the DUID type which should be the next 2 bytes. */
4571 _nx_dhcpv6_utility_get_data((option_data + index), 2, &data);
4572
4573 /* Does this match the Client DUID type on record? */
4574 if (data != (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_type))
4575 {
4576
4577 /* No, return the error status to reject this packet. */
4578 return NX_DHCPV6_INVALID_CLIENT_DUID;
4579 }
4580
4581 index += 2;
4582
4583 /* Extract the hardware type which should be the next 2 bytes. */
4584 _nx_dhcpv6_utility_get_data((option_data + index), 2, &data);
4585
4586 /* Does this match the Client DUID hardware type on record? */
4587 if (data != (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_hardware_type))
4588 {
4589
4590 /* No, return the error status to reject this packet. */
4591 return NX_DHCPV6_INVALID_CLIENT_DUID;
4592 }
4593
4594 index += 2;
4595
4596 /* IS this a link layer plus time DUID type? */
4597 if ((dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_type) == NX_DHCPV6_DUID_TYPE_LINK_TIME)
4598 {
4599
4600 /* Check option length for time. */
4601 if (index + 4 > option_length)
4602 {
4603 return(NX_DHCPV6_INVALID_CLIENT_DUID);
4604 }
4605
4606 /* Yes; Extract the time which should be the next 4 bytes. */
4607 _nx_dhcpv6_utility_get_data((option_data + index), 4, &data);
4608
4609 /* Does this match the Client DUID time on record? */
4610 if (data != (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_duid_time))
4611 {
4612
4613 /* No, return the error status to reject this packet. */
4614 return NX_DHCPV6_INVALID_CLIENT_DUID;
4615 }
4616
4617 index += 4;
4618 }
4619
4620 /* Check the hardware type to extract the MSW. */
4621 if (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_ETHERNET)
4622 {
4623
4624 /* The length of link layer address is 48 bits. */
4625
4626 /* Check option length for 48 bits mac address. */
4627 if (index + 6 > option_length)
4628 {
4629 return(NX_DHCPV6_INVALID_CLIENT_DUID);
4630 }
4631
4632 /* Yes; Extract the link local address msw which should be the next 2 bytes. */
4633 _nx_dhcpv6_utility_get_data((option_data + index), 2, &data);
4634 index += 2;
4635 }
4636 else if (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_EUI_64)
4637 {
4638
4639 /* The length of link layer address is 64 bits. */
4640
4641 /* Check option length for 64 bits mac address. */
4642 if (index + 8 > option_length)
4643 {
4644 return(NX_DHCPV6_INVALID_CLIENT_DUID);
4645 }
4646
4647 /* Yes; Extract the link local address msw which should be the next 4 bytes. */
4648 _nx_dhcpv6_utility_get_data((option_data + index), 4, &data);
4649 index += 4;
4650 }
4651
4652 /* Does this match the Client DUID link layer most significant bytes on record? */
4653 if (data != (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw))
4654 {
4655
4656 /* No, return the error status to reject this packet. */
4657 return NX_DHCPV6_INVALID_CLIENT_DUID;
4658 }
4659
4660 /* Yes; Extract the link local address lsw which should be the next 4 bytes. */
4661 _nx_dhcpv6_utility_get_data((option_data + index), 4, &data);
4662 index += 4;
4663
4664 /* Does this match the Client DUID link layer least significant bytes on record? */
4665 if (data != ((dhcpv6_ptr -> nx_dhcpv6_client_duid).nx_link_layer_address_lsw))
4666 {
4667
4668 /* No, return the error status to reject this packet. */
4669 return NX_DHCPV6_INVALID_CLIENT_DUID;
4670 }
4671
4672 /* Are we past the end of the buffer. */
4673 if (index != option_length)
4674 {
4675
4676 /* Yes, return the error status to reject this packet. */
4677 return NX_DHCPV6_INVALID_CLIENT_DUID;
4678 }
4679
4680 return NX_SUCCESS;
4681 }
4682
4683
4684 /**************************************************************************/
4685 /* */
4686 /* FUNCTION RELEASE */
4687 /* */
4688 /* _nx_dhcpv6_process_domain_name PORTABLE C */
4689 /* 6.1 */
4690 /* AUTHOR */
4691 /* */
4692 /* Yuxin Zhou, Microsoft Corporation */
4693 /* */
4694 /* DESCRIPTION */
4695 /* */
4696 /* This function extracts the domain name option from the server reply.*/
4697 /* It will save as much of the domain name that will fit in the Client */
4698 /* domain name buffer. Buffer size is user configurable. */
4699 /* */
4700 /* INPUT */
4701 /* */
4702 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
4703 /* packet_start Pointer to packet buffer */
4704 /* option_data Pointer to option data */
4705 /* option_length Size of option data */
4706 /* */
4707 /* OUTPUT */
4708 /* */
4709 /* NX_SUCCESS Successful completion status */
4710 /* */
4711 /* CALLS */
4712 /* */
4713 /* _nx_dhcpv6_name_string_unencode Decode the name string */
4714 /* */
4715 /* CALLED BY */
4716 /* */
4717 /* _nx_dhcpv6_extract_packet_information */
4718 /* Extracts DHCPv6 options from */
4719 /* server reply */
4720 /* */
4721 /* RELEASE HISTORY */
4722 /* */
4723 /* DATE NAME DESCRIPTION */
4724 /* */
4725 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4726 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
4727 /* packet length verification, */
4728 /* resulting in version 6.1 */
4729 /* */
4730 /**************************************************************************/
_nx_dhcpv6_process_domain_name(NX_DHCPV6 * dhcpv6_ptr,UCHAR * packet_start,UCHAR * option_data,UINT option_length)4731 UINT _nx_dhcpv6_process_domain_name(NX_DHCPV6 *dhcpv6_ptr, UCHAR *packet_start, UCHAR *option_data, UINT option_length)
4732 {
4733
4734 UINT domain_name_length;
4735 UINT temp_length;
4736 UCHAR *domain_name_ptr;
4737 UCHAR *buffer_prepend_ptr;
4738 UINT buffer_size;
4739 UINT i;
4740
4741
4742 /* Initialize the value. */
4743 domain_name_length = 0;
4744 temp_length = 0;
4745 domain_name_ptr = option_data;
4746 buffer_prepend_ptr = &dhcpv6_ptr -> nx_dhcpv6_domain_name[0];
4747 buffer_size = NX_DHCPV6_DOMAIN_NAME_BUFFER_SIZE;
4748
4749 /* Process the domain search list options. */
4750 while(temp_length < option_length)
4751 {
4752
4753 /* Calculate the domain name length in the Domaim Search List option,include the null flag '\0'. */
4754 for (i = 0; (i + temp_length < option_length) && (domain_name_ptr[i] != '\0'); i++);
4755
4756 if (i + temp_length == option_length)
4757 {
4758 return(NX_DHCPV6_PROCESSING_ERROR);
4759 }
4760 else
4761 {
4762 temp_length += (i + 1);
4763 }
4764
4765 /* Check buffer size. */
4766 if (buffer_size < 1)
4767 {
4768 return(NX_DHCPV6_PROCESSING_ERROR);
4769 }
4770
4771 /* Record the real domain name and return the length, one less for NULL termination. */
4772 domain_name_length = _nx_dhcpv6_name_string_unencode(packet_start, (UINT)(domain_name_ptr - packet_start), buffer_prepend_ptr, (UINT)((buffer_size - 1) & 0xFFFFFFFF));
4773
4774 /* Check the domain name length. */
4775 if(!domain_name_length)
4776 {
4777
4778 /* Process error, return. */
4779 return NX_DHCPV6_PROCESSING_ERROR;
4780 }
4781
4782 else
4783 {
4784
4785 /* Update the buffer value,include the null flag '\0'. */
4786 domain_name_ptr += temp_length;
4787 buffer_prepend_ptr += (domain_name_length + 1);
4788 buffer_size -= (domain_name_length + 1);
4789 }
4790 }
4791
4792 /* Return successful completion. */
4793 return NX_SUCCESS;
4794 }
4795
4796
4797
4798 /**************************************************************************/
4799 /* */
4800 /* FUNCTION RELEASE */
4801 /* */
4802 /* _nx_dhcpv6_name_string_encode PORTABLE C */
4803 /* 6.1 */
4804 /* AUTHOR */
4805 /* */
4806 /* Yuxin Zhou, Microsoft Corporation */
4807 /* */
4808 /* DESCRIPTION */
4809 /* */
4810 /* This function converts a string containing the name as a list of */
4811 /* labels separated by dots to the encoded list of labels specified */
4812 /* in RFC1035 for DNS servers. This conversion doesn't handle */
4813 /* compression and doesn't check on the lengths of the labels or the */
4814 /* entire name. */
4815 /* */
4816 /* INPUT */
4817 /* */
4818 /* ptr Pointer to destination */
4819 /* name Source name string */
4820 /* */
4821 /* OUTPUT */
4822 /* */
4823 /* count Count of characters encoded */
4824 /* */
4825 /* CALLS */
4826 /* */
4827 /* None */
4828 /* */
4829 /* CALLED BY */
4830 /* */
4831 /* _nx_dhcpv6_add_client_FQDN Add FQDN Option to DHCPv6 packet */
4832 /* */
4833 /* RELEASE HISTORY */
4834 /* */
4835 /* DATE NAME DESCRIPTION */
4836 /* */
4837 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4838 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4839 /* resulting in version 6.1 */
4840 /* */
4841 /**************************************************************************/
_nx_dhcpv6_name_string_encode(UCHAR * ptr,UCHAR * name)4842 UINT _nx_dhcpv6_name_string_encode(UCHAR *ptr, UCHAR *name)
4843 {
4844
4845 UCHAR *length;
4846 UINT count = 1;
4847
4848
4849 /* Point to the first character position in the buffer. This will point
4850 to the length of the following name. */
4851 length = ptr++;
4852
4853 /* Default the length to zero. */
4854 *length = 0;
4855
4856 /* Move through string, copying bytes and updating length.
4857 Whenever a "." is found, start a new string by updating the
4858 pointer to the length and setting the length to zero. */
4859 while (*name)
4860 {
4861
4862 /* Is a dot been found? */
4863 if (*name == '.')
4864 {
4865
4866 /* Yes, setup a new length pointer. */
4867 length = ptr++;
4868
4869 /* Default the length to zero. */
4870 *length = 0;
4871 name++;
4872 }
4873 else
4874 {
4875
4876 /* Copy a character to the destination. */
4877 *ptr++ = *name++;
4878
4879 /* Adjust the length of the current segment. */
4880 (*length)++;
4881 }
4882
4883 /* Increment the total count here. */
4884 count++;
4885 }
4886
4887 /* Add the final zero length, like a NULL terminator. */
4888 *ptr = 0;
4889
4890 /* Increment the total count. */
4891 count++;
4892
4893 /* Return the count. */
4894 return(count);
4895 }
4896
4897
4898 /**************************************************************************/
4899 /* */
4900 /* FUNCTION RELEASE */
4901 /* */
4902 /* _nx_dhcpv6_name_string_unencode PORTABLE C */
4903 /* 6.1.2 */
4904 /* AUTHOR */
4905 /* */
4906 /* Yuxin Zhou, Microsoft Corporation */
4907 /* */
4908 /* DESCRIPTION */
4909 /* */
4910 /* This function converts from the encoded list of labels as specified */
4911 /* in RFC 1035 to a string containing the name as a list of labels */
4912 /* separated by dots. */
4913 /* */
4914 /* INPUT */
4915 /* */
4916 /* data Pointer to buffer to decode */
4917 /* start Location of start of data */
4918 /* buffer Pointer to decoded data */
4919 /* size Size of data buffer to decode */
4920 /* */
4921 /* OUTPUT */
4922 /* */
4923 /* Size of decoded data */
4924 /* */
4925 /* CALLS */
4926 /* */
4927 /* None */
4928 /* */
4929 /* CALLED BY */
4930 /* */
4931 /* _nx_dhcpv6_process_domain_name Process the domain name */
4932 /* */
4933 /* RELEASE HISTORY */
4934 /* */
4935 /* DATE NAME DESCRIPTION */
4936 /* */
4937 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4938 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4939 /* resulting in version 6.1 */
4940 /* 11-09-2020 Yuxin Zhou Modified comment(s), fixed */
4941 /* domain name labelSize issue,*/
4942 /* resulting in version 6.1.2 */
4943 /* */
4944 /**************************************************************************/
_nx_dhcpv6_name_string_unencode(UCHAR * data,UINT start,UCHAR * buffer,UINT size)4945 UINT _nx_dhcpv6_name_string_unencode(UCHAR *data, UINT start, UCHAR *buffer, UINT size)
4946 {
4947
4948 UCHAR *character = data + start;
4949 UINT length = 0;
4950
4951
4952 /* As long as there is space in the buffer and we haven't
4953 found a zero terminating label */
4954 while ((size > length) && (*character != '\0'))
4955 {
4956
4957 UINT labelSize = *character++;
4958
4959 /* Check labelSize. */
4960 if (labelSize <= NX_DHCPV6_LABEL_MAX)
4961 {
4962
4963 /* Simple count, check for space and copy the label. */
4964 while ((size > length) && (labelSize > 0))
4965 {
4966
4967 *buffer++ = *character++;
4968 length++;
4969 labelSize--;
4970 }
4971
4972 /* Now add the '.' */
4973 *buffer++ = '.';
4974 length++;
4975 }
4976 else
4977 {
4978 /* Not defined or in compressed form. Based on section 8 of RFC 3315,
4979 a domain name, or list of domain names, in DHCP MUST NOT be stored
4980 in compressed form, so just fail */
4981 return(0);
4982 }
4983 }
4984
4985 /* Validate the length. */
4986 if (length == 0)
4987 {
4988 return(length);
4989 }
4990
4991 /* Done copying the data, set the last . to a trailing null */
4992 if (*(buffer - 1) == '.')
4993 {
4994
4995 buffer--;
4996 length --;
4997 }
4998
4999 /* Null terminate name. */
5000 *buffer = '\0';
5001
5002 /* Return name size. */
5003 return(length);
5004 }
5005
5006
5007 /**************************************************************************/
5008 /* */
5009 /* FUNCTION RELEASE */
5010 /* */
5011 /* _nx_dhcpv6_process_DNS_server PORTABLE C */
5012 /* 6.1 */
5013 /* AUTHOR */
5014 /* */
5015 /* Yuxin Zhou, Microsoft Corporation */
5016 /* */
5017 /* DESCRIPTION */
5018 /* */
5019 /* This function extracts the DNS server option from the server reply. */
5020 /* It will save as many DNS name server addresses as are in the reply */
5021 /* for which the Client is configured to save. */
5022 /* */
5023 /* INPUT */
5024 /* */
5025 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
5026 /* option_data Pointer to option data */
5027 /* option_length Size of option data */
5028 /* */
5029 /* OUTPUT */
5030 /* */
5031 /* NX_SUCCESS Successful completion status */
5032 /* NX_DHCPV6_INVALID_OPTION_DATA DNS server option missing data or */
5033 /* improperly formatted */
5034 /* */
5035 /* CALLS */
5036 /* */
5037 /* memcpy Copies specified area of memory */
5038 /* */
5039 /* CALLED BY */
5040 /* */
5041 /* _nx_dhcpv6_extract_packet_information */
5042 /* Extracts DHCPv6 options from */
5043 /* server reply */
5044 /* */
5045 /* RELEASE HISTORY */
5046 /* */
5047 /* DATE NAME DESCRIPTION */
5048 /* */
5049 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5050 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
5051 /* packet length verification, */
5052 /* verified memcpy use cases, */
5053 /* resulting in version 6.1 */
5054 /* */
5055 /**************************************************************************/
_nx_dhcpv6_process_DNS_server(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length)5056 UINT _nx_dhcpv6_process_DNS_server(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length)
5057 {
5058
5059 UINT index = 0;
5060 UINT w, j = 0;
5061
5062
5063 /* Loop through the length of the buffer to parse. */
5064 while ((index + 16) <= option_length)
5065 {
5066
5067 /* Is the DHCPv6 Client configured to store another DNS server address? */
5068 if (j < NX_DHCPV6_NUM_DNS_SERVERS)
5069 {
5070
5071 /* Set the IP version. */
5072 dhcpv6_ptr -> nx_dhcpv6_DNS_name_server_address[j].nxd_ip_version = NX_IP_VERSION_V6;
5073
5074 /* Get the next IPv6 DNS server address. */
5075 for (w = 0; w <= 3; w++)
5076 {
5077
5078 /* Yes; copy the next word into the current DNS server address. */
5079 memcpy(&(dhcpv6_ptr -> nx_dhcpv6_DNS_name_server_address[j].nxd_ip_address.v6[w]), /* Use case of memcpy is verified. */
5080 (option_data + index), sizeof(ULONG));
5081
5082 /* Adjust for endianness. */
5083 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_DNS_name_server_address[j].nxd_ip_address.v6[w]);
5084
5085 /* Move to the next IPv6 address word. */
5086 index += 4;
5087 }
5088
5089 /* Get the next DNS server address in the reply buffer. */
5090 j++;
5091 }
5092 else
5093 {
5094
5095 /* Move to the next IPv6 address. */
5096 index += 16;
5097 }
5098 }
5099
5100 /* Is there any more data in the buffer? */
5101 if (index != option_length)
5102 {
5103
5104 /* Yes, not sure what is going on with this packet. Treat as an error. */
5105 return NX_DHCPV6_INVALID_OPTION_DATA;
5106 }
5107
5108 return NX_SUCCESS;
5109 }
5110
5111
5112 /**************************************************************************/
5113 /* */
5114 /* FUNCTION RELEASE */
5115 /* */
5116 /* _nx_dhcpv6_process_ia PORTABLE C */
5117 /* 6.1 */
5118 /* AUTHOR */
5119 /* */
5120 /* Yuxin Zhou, Microsoft Corporation */
5121 /* */
5122 /* DESCRIPTION */
5123 /* */
5124 /* This function extracts the IA address option from the server reply. */
5125 /* It also checks that the server preferred and valid lifetimes are */
5126 /* legitamate. If the IANA option contains an IA option, that will also*/
5127 /* be processed as well as any status code options. */
5128 /* */
5129 /* INPUT */
5130 /* */
5131 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
5132 /* option_data Pointer to option data */
5133 /* option_length Size of option data */
5134 /* ia_index The index of IA address */
5135 /* */
5136 /* OUTPUT */
5137 /* */
5138 /* NX_SUCCESS Successful completion status */
5139 /* NX_DHCPV6_INVALID_IA_DATA IA option is missing data or */
5140 /* improperly formatted */
5141 /* NX_DHCPV6_INVALID_IA_TIME IA option lifetime data is invalid*/
5142 /* NX_DHCPV6_UNKNOWN_OPTION Unkonw option type */
5143 /* */
5144 /* CALLS */
5145 /* */
5146 /* _nx_dhcpv6_utility_get_block_option_length */
5147 /* Get the option code and length */
5148 /* _nx_dhcpv6_process_status Processes STAUTS in reply buffer */
5149 /* nx_dhcpv6_server_error_handler Pointer to error code handler */
5150 /* memcpy Copies specified area of memory */
5151 /* */
5152 /* CALLED BY */
5153 /* */
5154 /* _nx_dhcpv6_process_iana Processes IANA in reply buffer */
5155 /* DHCPv6 request */
5156 /* */
5157 /* RELEASE HISTORY */
5158 /* */
5159 /* DATE NAME DESCRIPTION */
5160 /* */
5161 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5162 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
5163 /* packet length verification, */
5164 /* verified memcpy use cases, */
5165 /* resulting in version 6.1 */
5166 /* */
5167 /**************************************************************************/
_nx_dhcpv6_process_ia(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length,UINT ia_index)5168 UINT _nx_dhcpv6_process_ia(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length, UINT ia_index)
5169 {
5170
5171 ULONG preferred_lifetime;
5172 ULONG valid_lifetime;
5173 UINT index = 0, w;
5174 UINT status;
5175 ULONG ia_option_code, ia_option_length;
5176
5177
5178 /* Fill in the IA address code and length. Client might already have one on
5179 record, but use the server's data instead. */
5180 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_op_code = (USHORT)NX_DHCPV6_OP_IA_ADDRESS;
5181 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_option_length = (USHORT)option_length;
5182
5183 /* Check option length for Ipv6 address (16 bytes), preferred-lifetime (4 bytes) and valid-lifetime (4 bytes). */
5184 if (option_length < 24)
5185 {
5186 return(NX_DHCPV6_INVALID_IA_DATA);
5187 }
5188
5189 /* Process IPv6 address. */
5190 for (w = 0; w <= 3; w++)
5191 {
5192
5193 /* Copy each IPv6 address word into the IA address. */
5194 memcpy(&(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[w]), /* Use case of memcpy is verified. */
5195 (option_data + index), sizeof(ULONG));
5196
5197 /* Adjust for endianness. */
5198 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[w]);
5199
5200 /* Move to the next IPv6 address word. */
5201 index += 4;
5202 }
5203
5204 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_version = NX_IP_VERSION_V6;
5205
5206 /* Copy the lifetime data from the reply buffer to temporary variables.*/
5207 memcpy(&preferred_lifetime, (option_data + index), sizeof(ULONG)); /* Use case of memcpy is verified. */
5208 index += 4;
5209
5210 /* Adjust for endianness. */
5211 NX_CHANGE_ULONG_ENDIAN(preferred_lifetime);
5212
5213 memcpy(&valid_lifetime, (option_data + index), sizeof(ULONG)); /* Use case of memcpy is verified. */
5214 index += 4;
5215
5216 /* Adjust for endianness. */
5217 NX_CHANGE_ULONG_ENDIAN(valid_lifetime);
5218
5219 /* Check for invalid lifetime data. The preferred lifetime MUST be less than
5220 the valid lifetime. Note that a zero lifetime is acceptable
5221 (the server is letting the Client use its own preference). */
5222 if (preferred_lifetime > valid_lifetime)
5223 {
5224 /* Discard this address. We cannot use it. */
5225 return NX_DHCPV6_INVALID_IA_TIME;
5226 }
5227
5228 /* OK to assign time data to the client. */
5229 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_preferred_lifetime = preferred_lifetime;
5230 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime = valid_lifetime;
5231
5232 /* Update the address status. */
5233 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_INVALID)
5234 {
5235 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status = NX_DHCPV6_IA_ADDRESS_STATE_INITIAL;
5236 }
5237
5238 /* Update the map status, 0xFFFFFFFF indicate the IPv6 address of IA option has been processed. */
5239 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_map = 0xFFFFFFFF;
5240
5241 /* Check if we're at the end of option data yet. */
5242 if (index == option_length)
5243 {
5244
5245 /* Yes, all done. */
5246 return NX_SUCCESS;
5247 }
5248
5249 /* Check option length for status code option. */
5250 if (index + 4 > option_length)
5251 {
5252 return(NX_DHCPV6_INVALID_IA_DATA);
5253 }
5254
5255 /* Process the status code option. */
5256 status = _nx_dhcpv6_utility_get_block_option_length(option_data + index, &ia_option_code, &ia_option_length);
5257
5258 /* Check that the block data is valid. */
5259 if (status != NX_SUCCESS)
5260 {
5261
5262 /* No, return the error status. */
5263 return status;
5264 }
5265
5266 /* Skip status option code and length. */
5267 index += 4;
5268
5269 /* This is a double check to verify we haven't gone off the end of the packet buffer. */
5270 if (index + ia_option_length > option_length)
5271 {
5272 return (NX_DHCPV6_INVALID_IA_DATA);
5273 }
5274
5275 /* Check if this is an IAaddr status option request. */
5276 if (ia_option_code == NX_DHCPV6_OP_STATUS_CODE)
5277 {
5278 /* The IAaddr option returned by the DHCPv6 server includes a status option. */
5279
5280 /* Process the status. */
5281 status = _nx_dhcpv6_process_status(dhcpv6_ptr, (option_data + index), ia_option_length);
5282
5283 /* Now check on the server status of the previous option in the DHCP message. */
5284 if ((status == NX_SUCCESS) && (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS))
5285 {
5286
5287 /* Does the dhcpv6 client have a server error handler? */
5288 if (dhcpv6_ptr -> nx_dhcpv6_server_error_handler)
5289 {
5290
5291 /* Call the error handler with status code, option (IAaddr) and which message type it refers to. */
5292 dhcpv6_ptr -> nx_dhcpv6_server_error_handler(dhcpv6_ptr, NX_DHCPV6_ERROR_STATUS_CODE_IN_IA_ADDRESS, dhcpv6_ptr -> nx_status_code,
5293 dhcpv6_ptr -> nx_dhcpv6_received_message_type);
5294 }
5295 }
5296
5297 /* Check for errors processing the DHCPv6 message. */
5298 if (status != NX_SUCCESS)
5299 {
5300
5301 /* Abort further processing. Return error status. */
5302 return status;
5303 }
5304 }
5305
5306 else
5307 {
5308 return NX_DHCPV6_UNKNOWN_OPTION;
5309 }
5310
5311 /* Keep track of how far into the packet we have parsed. */
5312 index += ia_option_length;
5313
5314 /* Check if we went past the reported size of IA address data. */
5315 if (index != option_length)
5316 {
5317
5318 /* Return an error status. Cannot accept this reply. */
5319 return NX_DHCPV6_INVALID_IA_DATA;
5320 }
5321
5322 return NX_SUCCESS;
5323 }
5324
5325
5326 /**************************************************************************/
5327 /* */
5328 /* FUNCTION RELEASE */
5329 /* */
5330 /* _nx_dhcpv6_process_iana PORTABLE C */
5331 /* 6.1 */
5332 /* AUTHOR */
5333 /* */
5334 /* Yuxin Zhou, Microsoft Corporation */
5335 /* */
5336 /* DESCRIPTION */
5337 /* */
5338 /* This function extracts the IANA option from the server reply. It */
5339 /* verifies the IANA option ID matches the IANA option ID on client */
5340 /* record. It also checks that the server T1 and T2 lease times are */
5341 /* legitamate. If the IANA option contains an IA option, that will also*/
5342 /* be processed as well as any status code options. */
5343 /* */
5344 /* INPUT */
5345 /* */
5346 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
5347 /* option_data Pointer to option data */
5348 /* option_length Size of option data */
5349 /* */
5350 /* OUTPUT */
5351 /* */
5352 /* status Actual completion status */
5353 /* NX_DHCPV6_BAD_IANA_ID IANA option ID does not match IANA*/
5354 /* option on client record */
5355 /* NX_DHCPV6_INVALID_IANA_TIME IANA T1 and T2 values are invalid */
5356 /* NX_DHCPV6_STATE_IP_FAILURE Indicates server rejected IANA/IA */
5357 /* NX_DHCPV6_INVALID_IANA_DATA IANA option is missing data or */
5358 /* improperly formatted */
5359 /* CALLS */
5360 /* */
5361 /* _nx_dhcpv6_utility_get_data Parses data from reply buffer */
5362 /* _nx_dhcpv6_utility_get_block_option_length */
5363 /* Parses option header from buffer */
5364 /* _nx_dhcpv6_process_ia Process IA option in reply buffer */
5365 /* _nx_dhcpv6_process_status Process status option in buffer */
5366 /* nx_dhcpv6_server_error_handler Pointer to server error code handler*/
5367 /* */
5368 /* CALLED BY */
5369 /* */
5370 /* _nx_dhcpv6_extract_packet_information */
5371 /* Extracts server reply from packet */
5372 /* */
5373 /* RELEASE HISTORY */
5374 /* */
5375 /* DATE NAME DESCRIPTION */
5376 /* */
5377 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5378 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
5379 /* packet length verification, */
5380 /* resulting in version 6.1 */
5381 /* */
5382 /**************************************************************************/
_nx_dhcpv6_process_iana(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length)5383 UINT _nx_dhcpv6_process_iana(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length)
5384 {
5385
5386 UINT status;
5387 ULONG T1, T2, data;
5388 UINT index = 0;
5389 ULONG iana_option_code, iana_option_length;
5390 UINT ia_index;
5391 UINT ia_count = 0;
5392 UINT ia_status;
5393
5394
5395 /* Check option length for IANA ID. */
5396 if (option_length < 4)
5397 {
5398 return(NX_DHCPV6_INVALID_IANA_DATA);
5399 }
5400
5401 /* Get the IANA ID. */
5402 memcpy(&data, (option_data + index), 4); /* Use case of memcpy is verified. */
5403
5404 /* Adjust for endianness. */
5405 NX_CHANGE_ULONG_ENDIAN(data);
5406
5407 /* The server response must return the correct IANA ID; this is applicable
5408 to clients configured with more than one IANA. */
5409 if (data != (dhcpv6_ptr -> nx_dhcpv6_iana.nx_IA_NA_id))
5410 {
5411
5412 /* IANA does not match. */
5413 return NX_DHCPV6_BAD_IANA_ID;
5414 }
5415
5416 /* Update the write location index. */
5417 index += 4;
5418
5419 /* Check option length for T1 and T2. */
5420 if (index + 8 > option_length)
5421 {
5422 return(NX_DHCPV6_INVALID_IANA_DATA);
5423 }
5424
5425 /* Copy T1 and T2 from the buffer into temporary variables. */
5426 memcpy(&T1, (option_data + index), 4); /* Use case of memcpy is verified. */
5427 index += 4;
5428
5429 /* Adjust for endianness. */
5430 NX_CHANGE_ULONG_ENDIAN(T1);
5431
5432 memcpy(&T2, (option_data + index), 4); /* Use case of memcpy is verified. */
5433 index += 4;
5434
5435 /* Adjust for endianness. */
5436 NX_CHANGE_ULONG_ENDIAN(T2);
5437
5438 /* Check for invalid T1/T2 lifetimes. */
5439 if (T1 > T2)
5440 {
5441
5442 /* Reject the server DHCPv6 response. */
5443 return NX_DHCPV6_INVALID_IANA_TIME;
5444 }
5445
5446 /* Record the T1 and T2. */
5447 /* Yes, the server will let the Client use its own T1 time? */
5448 if (T1 != 0)
5449 {
5450
5451 /* Now, assign the server T1 to the client IA-NA. */
5452 dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1 = T1;
5453 }
5454
5455 /* Yes,the server will let the Client use its own T2 time? */
5456 if (T2 != 0)
5457 {
5458 /* Now, assign the server T2 to the client IA-NA. */
5459 dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2 = T2;
5460 }
5461
5462 /* Check if we're at the end of option data yet. */
5463 if (index == option_length)
5464 {
5465
5466 /* Yes, all done. */
5467 return NX_SUCCESS;
5468 }
5469
5470 /* If the reply message includes IA address option, clear the record. */
5471 if(dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_IA_ADDRESS_OPTION)
5472 {
5473
5474 /* Clear the IA address table according to the address map value. */
5475 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
5476 {
5477
5478 /* The reply message does not include this IA option.*/
5479 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_map == 0)
5480 {
5481
5482 /* Clear it. */
5483 status = _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, ia_index);
5484 }
5485 }
5486 }
5487
5488 /* Now we recurse into the options embedded in the IANA option. */
5489 while (index + 4 <= option_length)
5490 {
5491
5492 /* Get the next option code and length. */
5493 status = _nx_dhcpv6_utility_get_block_option_length((option_data + index), &iana_option_code, &iana_option_length);
5494
5495 /* Check that the block data is valid. */
5496 if (status != NX_SUCCESS)
5497 {
5498
5499 /* No, return the error status. */
5500 return status;
5501 }
5502
5503 /* Skip IANA sub option code and length. */
5504 index += 4;
5505
5506 /* This is a double check to verify we haven't gone off the end of the packet buffer. */
5507 if (index + iana_option_length > option_length)
5508 {
5509 return (NX_DHCPV6_INVALID_IANA_DATA);
5510 }
5511
5512 /* Check if this is an IA address option request. */
5513 if (iana_option_code == NX_DHCPV6_OP_IA_ADDRESS)
5514 {
5515
5516 /* Set the ia count to record the IA option of reply message. */
5517 ia_count ++;
5518 ia_status = 0;
5519
5520 /* First, find the same IPv6 address. */
5521 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
5522 {
5523
5524 /* The IPv6 address is new,so find the empty space to record it. */
5525 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_map == ia_count)
5526 {
5527
5528 /* Yes, find it, update the IA option. */
5529 status = _nx_dhcpv6_process_ia(dhcpv6_ptr, (option_data + index), iana_option_length, ia_index);
5530
5531 /* Check the process status. */
5532 if (status != NX_SUCCESS)
5533 {
5534
5535 /* No, return the error status. */
5536 return status;
5537 }
5538
5539 /* Yes, set success. */
5540 ia_status = 1;
5541
5542 break;
5543 }
5544 }
5545
5546 /* Record the IA option failure. */
5547 if(ia_status == 0)
5548 {
5549
5550 /* Second, find one empty IA to record it. */
5551 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
5552 {
5553
5554 /* The IPv6 address is new,so find the empty space to record it. */
5555 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_map == 0)
5556 {
5557
5558 /* Yes, it is available, update the IA option. */
5559 status = _nx_dhcpv6_process_ia(dhcpv6_ptr, (option_data + index), iana_option_length, ia_index);
5560
5561 /* Check the process status. */
5562 if (status != NX_SUCCESS)
5563 {
5564
5565 /* No, return the error status. */
5566 return status;
5567 }
5568
5569 break;
5570 }
5571 }
5572 }
5573 }
5574
5575 /* Check if this is an IAaddr status option request. */
5576 if (iana_option_code == NX_DHCPV6_OP_STATUS_CODE)
5577 {
5578 /* The IAaddr option returned by the DHCPv6 server includes a status option. */
5579
5580 /* Process the status. */
5581 status = _nx_dhcpv6_process_status(dhcpv6_ptr, (option_data + index), iana_option_length);
5582
5583 /* Now check on the server status of the previous option in the DHCP message. */
5584 if ((status == NX_SUCCESS) && (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS))
5585 {
5586
5587 /* Does the dhcpv6 client have a server error handler? */
5588 if (dhcpv6_ptr -> nx_dhcpv6_server_error_handler)
5589 {
5590
5591 /* Call the error handler with status code, option (IA_NA) and which message type it refers to. */
5592 dhcpv6_ptr -> nx_dhcpv6_server_error_handler(dhcpv6_ptr, NX_DHCPV6_ERROR_STATUS_CODE_IN_IA_NA, dhcpv6_ptr -> nx_status_code,
5593 dhcpv6_ptr -> nx_dhcpv6_received_message_type);
5594 }
5595 }
5596
5597 /* Check for errors processing the DHCPv6 message. */
5598 if (status != NX_SUCCESS)
5599 {
5600
5601 /* Abort further processing. Return error status. */
5602 return status;
5603 }
5604 }
5605
5606 /* Keep track of how far into the packet we have parsed. */
5607 index += iana_option_length;
5608 }
5609
5610 return NX_SUCCESS;
5611 }
5612
5613
5614 /**************************************************************************/
5615 /* */
5616 /* FUNCTION RELEASE */
5617 /* */
5618 /* _nx_dhcpv6_process_preference PORTABLE C */
5619 /* 6.1 */
5620 /* AUTHOR */
5621 /* */
5622 /* Yuxin Zhou, Microsoft Corporation */
5623 /* */
5624 /* DESCRIPTION */
5625 /* */
5626 /* This function extracts the preference option from the server reply. */
5627 /* It will save as much of the time zone that will fit in the Client */
5628 /* time zone buffer. Buffer size is user configurable. */
5629 /* */
5630 /* INPUT */
5631 /* */
5632 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
5633 /* option_data Pointer to option data */
5634 /* option_length Size of option data */
5635 /* */
5636 /* OUTPUT */
5637 /* */
5638 /* NX_SUCCESS Successful completion status */
5639 /* NX_DHCPV6_INVALID_PREF_DATA Preference option is missing data */
5640 /* or improperly formatted */
5641 /* CALLS */
5642 /* */
5643 /* None */
5644 /* */
5645 /* CALLED BY */
5646 /* */
5647 /* _nx_dhcpv6_extract_packet_information */
5648 /* Extracts DHCPv6 options from */
5649 /* server reply */
5650 /* */
5651 /* RELEASE HISTORY */
5652 /* */
5653 /* DATE NAME DESCRIPTION */
5654 /* */
5655 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5656 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
5657 /* packet length verification, */
5658 /* resulting in version 6.1 */
5659 /* */
5660 /**************************************************************************/
_nx_dhcpv6_process_preference(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length)5661 UINT _nx_dhcpv6_process_preference(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length)
5662 {
5663
5664
5665 /* Fill in the option code and length. */
5666 dhcpv6_ptr -> nx_dhcpv6_preference.nx_op_code = NX_DHCPV6_OP_PREFERENCE;
5667 dhcpv6_ptr -> nx_dhcpv6_preference.nx_option_length = (USHORT)option_length;
5668
5669 /* Check option length for preference value. */
5670 if (option_length != 1)
5671 {
5672 return(NX_DHCPV6_INVALID_PREF_DATA);
5673 }
5674
5675 /* Get the server preference field, and apply to the DHCPv6 Client. */
5676 dhcpv6_ptr -> nx_dhcpv6_preference.nx_pref_value = (USHORT)(*option_data);
5677
5678 return NX_SUCCESS;
5679 }
5680
5681
5682 /**************************************************************************/
5683 /* */
5684 /* FUNCTION RELEASE */
5685 /* */
5686 /* _nx_dhcpv6_process_server_duid PORTABLE C */
5687 /* 6.1 */
5688 /* AUTHOR */
5689 /* */
5690 /* Yuxin Zhou, Microsoft Corporation */
5691 /* */
5692 /* DESCRIPTION */
5693 /* */
5694 /* This function extracts the server DUID from the server reply and, */
5695 /* if the Client already has a DHCPv6 server on record, verifies that */
5696 /* it matches the Client's server DUID. */
5697 /* */
5698 /* INPUT */
5699 /* */
5700 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
5701 /* option_data Pointer to option data */
5702 /* option_length Size of option data */
5703 /* */
5704 /* OUTPUT */
5705 /* */
5706 /* NX_SUCCESS Successful completion status */
5707 /* NX_DHCPV6_INVALID_SERVER_DUID Server DUID is missing data or */
5708 /* does not match the DUID on record*/
5709 /* CALLS */
5710 /* */
5711 /* _nx_dhcpv6_utility_get_data Parses data from specified buffer */
5712 /* */
5713 /* CALLED BY */
5714 /* */
5715 /* _nx_dhcpv6_extract_packet_information */
5716 /* Extracts server reply from packet */
5717 /* */
5718 /* RELEASE HISTORY */
5719 /* */
5720 /* DATE NAME DESCRIPTION */
5721 /* */
5722 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5723 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
5724 /* packet length verification, */
5725 /* resulting in version 6.1 */
5726 /* */
5727 /**************************************************************************/
_nx_dhcpv6_process_server_duid(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length)5728 UINT _nx_dhcpv6_process_server_duid(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length)
5729 {
5730
5731 UINT index = 0;
5732 ULONG temp_type;
5733 ULONG temp_hardware_type;
5734 ULONG temp_time = 0;
5735 ULONG temp_msw = 0;
5736 ULONG temp_lsw = 0;
5737
5738
5739 /* Set the DHCPv6 option header fields for a Server DUID. */
5740 dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_op_code = NX_DHCPV6_OP_SERVER_ID;
5741 dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_option_length = (USHORT)option_length;
5742
5743 /* Check option length for DUID type and hardware type. */
5744 if (option_length < 4)
5745 {
5746 return(NX_DHCPV6_INVALID_SERVER_DUID);
5747 }
5748
5749 /* Extract the DUID type which should be the next 2 bytes. */
5750 _nx_dhcpv6_utility_get_data((option_data + index), 2, &temp_type);
5751
5752 /* Update the index for moving the buffer pointer forward. */
5753 index += 2;
5754
5755 /* Extract the hardware type which should be the next 2 bytes. */
5756 _nx_dhcpv6_utility_get_data((option_data + index), 2, &temp_hardware_type);
5757
5758 /* Update the index for moving the buffer pointer forward. */
5759 index += 2;
5760
5761 /* Is this a link layer plus time DUID type? */
5762 if (temp_type == NX_DHCPV6_DUID_TYPE_LINK_TIME)
5763 {
5764
5765 /* Check option length for time. */
5766 if (index + 4 > option_length)
5767 {
5768 return(NX_DHCPV6_INVALID_SERVER_DUID);
5769 }
5770
5771 /* Yes; Extract the time which should be the next 4 bytes. */
5772 _nx_dhcpv6_utility_get_data((option_data + index), 4, &temp_time);
5773
5774 /* Update the index for moving the buffer pointer forward. */
5775 index += 4;
5776 }
5777
5778 /* Check the hardware type to extract the MSW. */
5779 if (temp_hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_ETHERNET)
5780 {
5781
5782 /* The length of link layer address is 48 bits. */
5783
5784 /* Check option length for 48 bits mac address. */
5785 if (index + 6 > option_length)
5786 {
5787 return(NX_DHCPV6_INVALID_SERVER_DUID);
5788 }
5789
5790 /* Yes; Extract the link local address msw which should be the next 2 bytes. */
5791 _nx_dhcpv6_utility_get_data((option_data + index), 2, &temp_msw);
5792
5793 /* Update the index for moving the buffer pointer forward. */
5794 index += 2;
5795 }
5796 else if (temp_hardware_type == NX_DHCPV6_CLIENT_HARDWARE_TYPE_EUI_64)
5797 {
5798
5799 /* The length of link layer address is 64 bits. */
5800
5801 /* Check option length for 64 bits mac address. */
5802 if (index + 8 > option_length)
5803 {
5804 return(NX_DHCPV6_INVALID_SERVER_DUID);
5805 }
5806
5807 /* Yes; Extract the link local address msw which should be the next 4 bytes. */
5808 _nx_dhcpv6_utility_get_data((option_data + index), 4, &temp_msw);
5809
5810 /* Update the index for moving the buffer pointer forward. */
5811 index += 4;
5812 }
5813
5814 /* Yes; Extract the link local address lsw which should be the next 4 bytes. */
5815 _nx_dhcpv6_utility_get_data((option_data + index), 4, &temp_lsw);
5816
5817 /* Update the index for moving the buffer pointer forward. */
5818 index += 4;
5819
5820 /* Check if we are past the end of the buffer. */
5821 if (index != option_length)
5822 {
5823
5824 /* Yes, return the error status to reject the packet. */
5825 return NX_DHCPV6_INVALID_SERVER_DUID;
5826 }
5827
5828 /* If the client state in SENDING SOLICIT/CONFRIM/REBIND/INFORM_REQUEST, record the server DUID. */
5829 if (dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_SOLICIT ||
5830 dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_CONFIRM ||
5831 dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_REBIND ||
5832 dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_INFORM_REQUEST )
5833 {
5834
5835 /* No previous server DUID in the Client record. Copy it over now. */
5836 dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_duid_type = (USHORT)temp_type;
5837
5838 /* Is this a TIME Duid type? */
5839 if (temp_type == NX_DHCPV6_DUID_TYPE_LINK_TIME)
5840 {
5841
5842 /* Yes, write in the time data. */
5843 dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_duid_time = temp_time;
5844 }
5845
5846 dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_hardware_type = (USHORT)temp_hardware_type;
5847 dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw = temp_msw;
5848 dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_lsw = temp_lsw;
5849 }
5850 else
5851 {
5852
5853 /* Yes; Verify this Server DUID matches the Server DUID from the Client record. */
5854 if ((dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_duid_time != temp_time) ||
5855 (dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw != temp_msw) ||
5856 (dhcpv6_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_lsw != temp_lsw))
5857 {
5858
5859 /* It doesn't. Return an error status to reject this packet! */
5860 return NX_DHCPV6_INVALID_SERVER_DUID;
5861 }
5862 }
5863
5864 /* Return successful completion status. */
5865 return NX_SUCCESS;
5866 }
5867
5868
5869 /**************************************************************************/
5870 /* */
5871 /* FUNCTION RELEASE */
5872 /* */
5873 /* _nx_dhcpv6_process_status PORTABLE C */
5874 /* 6.1 */
5875 /* AUTHOR */
5876 /* */
5877 /* Yuxin Zhou, Microsoft Corporation */
5878 /* */
5879 /* DESCRIPTION */
5880 /* */
5881 /* This function extracts the option status option from the server */
5882 /* reply. It also attempts to save the as much of server status message*/
5883 /* that will fit into the status message buffer. */
5884 /* */
5885 /* INPUT */
5886 /* */
5887 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
5888 /* option_data Pointer to option data */
5889 /* option_length Size of option data */
5890 /* */
5891 /* OUTPUT */
5892 /* */
5893 /* NX_SUCCESS Successful completion status */
5894 /* */
5895 /* CALLS */
5896 /* */
5897 /* memcpy Copies specified area of memory */
5898 /* */
5899 /* CALLED BY */
5900 /* */
5901 /* _nx_dhcpv6_process_iana Processes IANA in reply buffer */
5902 /* DHCPv6 request */
5903 /* _nx_dhcpv6_process_ia Processes IA in reply buffer */
5904 /* */
5905 /* RELEASE HISTORY */
5906 /* */
5907 /* DATE NAME DESCRIPTION */
5908 /* */
5909 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5910 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
5911 /* packet length verification, */
5912 /* verified memcpy use cases, */
5913 /* resulting in version 6.1 */
5914 /* */
5915 /**************************************************************************/
_nx_dhcpv6_process_status(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length)5916 UINT _nx_dhcpv6_process_status(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length)
5917 {
5918
5919 UINT index = 0;
5920 UINT message_length;
5921 ULONG status_code;
5922
5923
5924 /* Check option length for status code. */
5925 if (option_length < 2)
5926 {
5927 return(NX_DHCPV6_INVALID_OPTION_DATA);
5928 }
5929
5930 /* Get the status field itself. */
5931 _nx_dhcpv6_utility_get_data((option_data + index), sizeof(USHORT), &status_code);
5932
5933 /* Update the index for moving the buffer pointer forward. */
5934 index += 2;
5935
5936 /* Set the status code. */
5937 dhcpv6_ptr -> nx_status_code = (USHORT)status_code;
5938
5939 /* Now figure out how much of the message we can save, if not all of it. */
5940 if ((option_length - 2) > NX_DHCPV6_MAX_MESSAGE_SIZE)
5941 {
5942
5943 /* Store up to this much, message is truncated but possibly still useful. */
5944 message_length = NX_DHCPV6_MAX_MESSAGE_SIZE;
5945 }
5946 else
5947 {
5948
5949 /* Store all of it. */
5950 message_length = option_length - 2;
5951 }
5952
5953 /* Copy the status into the Client record. */
5954 memcpy(dhcpv6_ptr -> nx_status_message, (option_data + index), message_length); /* Use case of memcpy is verified. */
5955
5956 return NX_SUCCESS;
5957 }
5958
5959
5960 /**************************************************************************/
5961 /* */
5962 /* FUNCTION RELEASE */
5963 /* */
5964 /* _nx_dhcpv6_process_time_zone PORTABLE C */
5965 /* 6.1 */
5966 /* AUTHOR */
5967 /* */
5968 /* Yuxin Zhou, Microsoft Corporation */
5969 /* */
5970 /* DESCRIPTION */
5971 /* */
5972 /* This function extracts the time zone option from the server reply. */
5973 /* It will save as much of the time zone that will fit in the Client */
5974 /* time zone buffer. Buffer size is user configurable. */
5975 /* */
5976 /* INPUT */
5977 /* */
5978 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
5979 /* option_data Pointer to option data */
5980 /* option_length Size of option data */
5981 /* */
5982 /* OUTPUT */
5983 /* */
5984 /* NX_SUCCESS Successful completion status */
5985 /* */
5986 /* CALLS */
5987 /* */
5988 /* None */
5989 /* */
5990 /* CALLED BY */
5991 /* */
5992 /* _nx_dhcpv6_extract_packet_information */
5993 /* Extracts DHCPv6 options from */
5994 /* server reply */
5995 /* */
5996 /* RELEASE HISTORY */
5997 /* */
5998 /* DATE NAME DESCRIPTION */
5999 /* */
6000 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6001 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6002 /* packet length verification, */
6003 /* resulting in version 6.1 */
6004 /* */
6005 /**************************************************************************/
_nx_dhcpv6_process_time_zone(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length)6006 UINT _nx_dhcpv6_process_time_zone(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length)
6007 {
6008
6009 UINT i;
6010
6011
6012 /* Make sure the time zone fits in the client buffer. */
6013 if (option_length > NX_DHCPV6_TIME_ZONE_BUFFER_SIZE)
6014 {
6015
6016 /* It doesn't. Fit what we can. */
6017 option_length = NX_DHCPV6_TIME_ZONE_BUFFER_SIZE;
6018 }
6019
6020 /* Copy the time zone from the buffer to the Client record. */
6021 for (i = 0; i < option_length; i++)
6022 {
6023
6024 dhcpv6_ptr -> nx_dhcpv6_time_zone[i] = *(option_data + i);
6025 }
6026
6027 /* Return completion status. */
6028 return NX_SUCCESS;
6029 }
6030
6031
6032 /**************************************************************************/
6033 /* */
6034 /* FUNCTION RELEASE */
6035 /* */
6036 /* _nx_dhcpv6_process_time_server PORTABLE C */
6037 /* 6.1 */
6038 /* AUTHOR */
6039 /* */
6040 /* Yuxin Zhou, Microsoft Corporation */
6041 /* */
6042 /* DESCRIPTION */
6043 /* */
6044 /* This function extracts the time server option from the server reply.*/
6045 /* It will save as many time server addresses as are in the reply for */
6046 /* which the Client is configured to save. */
6047 /* */
6048 /* INPUT */
6049 /* */
6050 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
6051 /* option_data Pointer to option data */
6052 /* option_length Size of option data */
6053 /* */
6054 /* OUTPUT */
6055 /* */
6056 /* NX_SUCCESS Successful completion status */
6057 /* */
6058 /* CALLS */
6059 /* */
6060 /* memcpy Copies specified area of memory */
6061 /* */
6062 /* CALLED BY */
6063 /* */
6064 /* _nx_dhcpv6_extract_packet_information */
6065 /* Extracts DHCPv6 options from */
6066 /* server reply */
6067 /* */
6068 /* RELEASE HISTORY */
6069 /* */
6070 /* DATE NAME DESCRIPTION */
6071 /* */
6072 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6073 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6074 /* packet length verification, */
6075 /* verified memcpy use cases, */
6076 /* resulting in version 6.1 */
6077 /* */
6078 /**************************************************************************/
_nx_dhcpv6_process_time_server(NX_DHCPV6 * dhcpv6_ptr,UCHAR * option_data,UINT option_length)6079 UINT _nx_dhcpv6_process_time_server(NX_DHCPV6 *dhcpv6_ptr, UCHAR *option_data, UINT option_length)
6080 {
6081
6082 UINT index = 0;
6083 UINT w, j = 0;
6084
6085
6086 /* Loop through the length of the buffer to parse. */
6087 while (index + 16 <= option_length)
6088 {
6089
6090 /* Check that the DHCPv6 Client configured to store this time server address e.g. it may
6091 only store one address, but the server could be sending two or more. */
6092 if (j < NX_DHCPV6_NUM_TIME_SERVERS)
6093 {
6094
6095 /* Set the IP version. */
6096 dhcpv6_ptr -> nx_dhcpv6_time_server_address[j].nxd_ip_version = NX_IP_VERSION_V6;
6097
6098 /* Get the next IPv6 time server address. */
6099 for (w = 0; w <= 3; w++)
6100 {
6101
6102 /* Yes; copy each IPv6 address word into the time server address. */
6103 memcpy(&(dhcpv6_ptr -> nx_dhcpv6_time_server_address[j].nxd_ip_address.v6[w]), /* Use case of memcpy is verified. */
6104 (option_data + index), sizeof(ULONG));
6105
6106 /* Adjust for endianness. */
6107 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ptr -> nx_dhcpv6_time_server_address[j].nxd_ip_address.v6[w]);
6108
6109 /* Move to the next IPv6 address word. */
6110 index += 4;
6111 }
6112
6113 /* Start parsing the next time server address, if there is one. */
6114 j++;
6115 }
6116 else
6117 {
6118
6119 /* Move to the next timer server address. */
6120 index += 16;
6121 }
6122 }
6123
6124 /* Is there any more data in this option? */
6125 if (index != option_length)
6126 {
6127
6128 /* Yes, treat as in improperly formatted packet. */
6129 return NX_DHCPV6_INVALID_OPTION_DATA;
6130 }
6131
6132 return NX_SUCCESS;
6133 }
6134
6135
6136 /**************************************************************************/
6137 /* */
6138 /* FUNCTION RELEASE */
6139 /* */
6140 /* _nx_dhcpv6_remove_assigned_address PORTABLE C */
6141 /* 6.1 */
6142 /* AUTHOR */
6143 /* */
6144 /* Yuxin Zhou, Microsoft Corporation */
6145 /* */
6146 /* DESCRIPTION */
6147 /* */
6148 /* This function removes the DHCPv6 Client address from the Client */
6149 /* record and from the IP address table. IP lease lifetimes and IP */
6150 /* addresses in the Client record are also cleared. */
6151 /* */
6152 /* INPUT */
6153 /* */
6154 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6155 /* */
6156 /* OUTPUT */
6157 /* */
6158 /* NX_SUCCESS Successful Completion status */
6159 /* NX_INVALID_INTERFACE Invalid index in IP address table*/
6160 /* status Failed mutex get */
6161 /* */
6162 /* CALLS */
6163 /* */
6164 /* tx_mutex_get Get exclusive lock on time keeper*/
6165 /* tx_mutex_put Release the lock on time keeper */
6166 /* _nx_dhcpv6_set_IP_address_NULL Set the IP address to NULL */
6167 /* */
6168 /* CALLED BY */
6169 /* */
6170 /* nx_dhcpv6_process */
6171 /* */
6172 /* RELEASE HISTORY */
6173 /* */
6174 /* DATE NAME DESCRIPTION */
6175 /* */
6176 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6177 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6178 /* resulting in version 6.1 */
6179 /* */
6180 /**************************************************************************/
_nx_dhcpv6_remove_assigned_address(NX_DHCPV6 * dhcpv6_ptr,UINT ia_index)6181 UINT _nx_dhcpv6_remove_assigned_address(NX_DHCPV6 *dhcpv6_ptr, UINT ia_index)
6182 {
6183 UINT index;
6184
6185 /* Only clear one address. */
6186 if(ia_index != NX_DHCPV6_REMOVE_ALL_IA_ADDRESS)
6187 {
6188
6189 /* Check for invalid IA index. */
6190 if (ia_index >= NX_DHCPV6_MAX_IA_ADDRESS)
6191 {
6192 return(NX_DHCPV6_REACHED_MAX_IA_ADDRESS);
6193 }
6194
6195 if((dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status) &&
6196 (dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index] != 0) &&
6197 (dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index] != 0xFFFFFFFF))
6198 {
6199
6200 /* Now remove the address from the IP address table. */
6201 nxd_ipv6_address_delete(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index]);
6202
6203 /* Set the address index to invalid. */
6204 dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index] = 0xFFFFFFFF;
6205 }
6206
6207 /* Clear the IA data. */
6208 memset(&dhcpv6_ptr -> nx_dhcpv6_ia[ia_index], 0, sizeof(NX_DHCPV6_IA_ADDRESS));
6209
6210 }
6211
6212 /* Clear the all addresses. */
6213 else
6214 {
6215
6216 /* Zero out time accrued on the current lease. */
6217 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = 0;
6218
6219 /* Set all lease lifetime and time fields to zero. */
6220 dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
6221 dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
6222
6223 /* Delete the IPv6 address of IP instance. */
6224 for(index = 0; index < NX_DHCPV6_MAX_IA_ADDRESS; index++)
6225 {
6226
6227 if((dhcpv6_ptr -> nx_dhcpv6_ia[index].nx_address_status) &&
6228 (dhcpv6_ptr -> nx_dhcpv6_client_address_index[index] != 0) &&
6229 (dhcpv6_ptr -> nx_dhcpv6_client_address_index[index] != 0xFFFFFFFF))
6230 {
6231
6232 /* Now remove the address from the IP address table. */
6233 nxd_ipv6_address_delete(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, dhcpv6_ptr -> nx_dhcpv6_client_address_index[index]);
6234
6235 /* Set the address index to invalid. */
6236 dhcpv6_ptr -> nx_dhcpv6_client_address_index[index] = 0xFFFFFFFF;
6237 }
6238 }
6239
6240 /* Clear the all IA data. */
6241 memset(&dhcpv6_ptr -> nx_dhcpv6_ia[0], 0, NX_DHCPV6_MAX_IA_ADDRESS * sizeof(NX_DHCPV6_IA_ADDRESS));
6242
6243 /* Removed the default router. */
6244 if (dhcpv6_ptr -> nx_dhcpv6_state >= NX_DHCPV6_STATE_SENDING_RENEW)
6245 {
6246 nxd_ipv6_default_router_delete(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, &(dhcpv6_ptr -> nx_dhcpv6_server_address));
6247 memset(&(dhcpv6_ptr -> nx_dhcpv6_server_address), 0, sizeof(NXD_ADDRESS));
6248 }
6249 }
6250
6251 /* Clear the all address. */
6252 return NX_SUCCESS;
6253 }
6254
6255
6256 /**************************************************************************/
6257 /* */
6258 /* FUNCTION RELEASE */
6259 /* */
6260 /* _nx_dhcpv6_request PORTABLE C */
6261 /* 6.1 */
6262 /* AUTHOR */
6263 /* */
6264 /* Yuxin Zhou, Microsoft Corporation */
6265 /* */
6266 /* DESCRIPTION */
6267 /* */
6268 /* This function sets the DHCPv6 Client state with the supplied state */
6269 /* (request). The DHCP Client thread will detect a state change and */
6270 /* process the new state. */
6271 /* */
6272 /* Note the return status only reflects the outcome of sending the */
6273 /* message, it does not indicate whether the request was successfully */
6274 /* granted. The host application is notified of "state" changes e.g. */
6275 /* NX_DHCPV6_STATE_SUCCESS or NX_DHCPV6_STATE_IP_FAILURE in the */
6276 /* callback function nx_dhcpv6_state_change_callback. */
6277 /* */
6278 /* INPUT */
6279 /* */
6280 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6281 /* dhcpv6_state State for making DHCPv6 request */
6282 /* */
6283 /* OUTPUT */
6284 /* */
6285 /* NX_SUCCESS Successful completion status */
6286 /* NX_DHCP_NOT_STARTED DHCPv6 Client not started */
6287 /* status Get mutex status */
6288 /* */
6289 /* CALLS */
6290 /* */
6291 /* tx_mutex_get Get DHCPv6 Client mutex */
6292 /* tx_mutex_put Releases the Client mutex */
6293 /* */
6294 /* CALLED BY */
6295 /* */
6296 /* _nx_dhcpv6_request_solicit Submits a SOLICIT request to Client*/
6297 /* _nx_dhcpv6_request_renew Submits a RENEW request to Client */
6298 /* _nx_dhcpv6_request_rebind Submits a REBIND request to Client */
6299 /* _nx_dhcpv6_request_release Submits a RELEASE request to Client*/
6300 /* _nx_dhcpv6_request_decline Submits a DECLINE request to Client*/
6301 /* _nx_dhcpv6_request_confirm Submits a CONFIRM request to Client*/
6302 /* _nx_dhcpv6_request_inform_request */
6303 /* Submits an Inform Request request */
6304 /* to Client */
6305 /* */
6306 /* RELEASE HISTORY */
6307 /* */
6308 /* DATE NAME DESCRIPTION */
6309 /* */
6310 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6311 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6312 /* resulting in version 6.1 */
6313 /* */
6314 /**************************************************************************/
_nx_dhcpv6_request(NX_DHCPV6 * dhcpv6_ptr,UINT dhcpv6_state)6315 UINT _nx_dhcpv6_request(NX_DHCPV6 *dhcpv6_ptr, UINT dhcpv6_state)
6316 {
6317
6318 UINT status;
6319
6320
6321 /* First get an exclusive lock on the DHCPv6 Client. */
6322 status = tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
6323
6324 /* Check for error. */
6325 if (status != TX_SUCCESS)
6326 {
6327
6328 /* Return the error status. */
6329 return status;
6330 }
6331
6332 /* Determine if DHCP is started. */
6333 if (dhcpv6_ptr -> nx_dhcpv6_started == NX_FALSE)
6334 {
6335
6336 /* Release the DHCP mutex. */
6337 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
6338
6339
6340 /* DHCP is not started so it can't be stopped. */
6341 return(NX_DHCPV6_NOT_STARTED);
6342 }
6343
6344 /* Wait for an opportunity to stop the DHCPv6 Client thread e.g. not in the midst of
6345 modifying the host DHCP profile! */
6346 while (dhcpv6_ptr -> nx_dhcpv6_sleep_flag != NX_TRUE)
6347 {
6348
6349 /* Release the DHCP mutex. */
6350 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
6351
6352 /* Sleep temporarily. */
6353 tx_thread_sleep(1);
6354
6355 /* Get the DHCP mutex. */
6356 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
6357 }
6358
6359 /* Set the Client state to process the DHCPv6 request. */
6360 dhcpv6_ptr -> nx_dhcpv6_state = (UCHAR)dhcpv6_state;
6361
6362 /* Release the Client mutex. */
6363 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
6364
6365 return NX_SUCCESS;
6366 }
6367
6368
6369 /**************************************************************************/
6370 /* */
6371 /* FUNCTION RELEASE */
6372 /* */
6373 /* _nxe_dhcpv6_request_confirm PORTABLE C */
6374 /* 6.1 */
6375 /* AUTHOR */
6376 /* */
6377 /* Yuxin Zhou, Microsoft Corporation */
6378 /* */
6379 /* DESCRIPTION */
6380 /* */
6381 /* This function performs error checking on the NetX DHCPv6 Confirm */
6382 /* request service. */
6383 /* */
6384 /* INPUT */
6385 /* */
6386 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6387 /* */
6388 /* OUTPUT */
6389 /* */
6390 /* status Completion status */
6391 /* NX_PTR_ERROR Invalid pointer input */
6392 /* */
6393 /* */
6394 /* CALLS */
6395 /* */
6396 /* _nx_dhcpv6_request_confirm Actual DHCPV6 process Confirm */
6397 /* request service */
6398 /* */
6399 /* CALLED BY */
6400 /* */
6401 /* Application Code */
6402 /* */
6403 /* RELEASE HISTORY */
6404 /* */
6405 /* DATE NAME DESCRIPTION */
6406 /* */
6407 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6408 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6409 /* resulting in version 6.1 */
6410 /* */
6411 /**************************************************************************/
_nxe_dhcpv6_request_confirm(NX_DHCPV6 * dhcpv6_ptr)6412 UINT _nxe_dhcpv6_request_confirm(NX_DHCPV6 *dhcpv6_ptr)
6413 {
6414
6415 UINT status;
6416
6417
6418 /* Check for invalid pointer input. */
6419 if (!dhcpv6_ptr)
6420 {
6421
6422 return NX_PTR_ERROR;
6423 }
6424
6425 /* Check for appropriate caller. */
6426 NX_THREADS_ONLY_CALLER_CHECKING
6427
6428 /* Call the actual service. */
6429 status = _nx_dhcpv6_request_confirm(dhcpv6_ptr);
6430
6431 /* Return completion status. */
6432 return status;
6433 }
6434
6435
6436 /**************************************************************************/
6437 /* */
6438 /* FUNCTION RELEASE */
6439 /* */
6440 /* _nx_dhcpv6_request_confirm PORTABLE C */
6441 /* 6.1 */
6442 /* AUTHOR */
6443 /* */
6444 /* Yuxin Zhou, Microsoft Corporation */
6445 /* */
6446 /* DESCRIPTION */
6447 /* */
6448 /* This function sends a confirm request to the server for the Client */
6449 /* to know the DHCPv6 IP address already assigned to it by the server. */
6450 /* */
6451 /* A host application should call this service after a host has been */
6452 /* disconnected from the network or powered down to verify its address */
6453 /* is still valid. */
6454 /* */
6455 /* INPUT */
6456 /* */
6457 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6458 /* */
6459 /* OUTPUT */
6460 /* */
6461 /* status Completion status */
6462 /* */
6463 /* CALLS */
6464 /* */
6465 /* _nx_dhcpv6_request Actual DHCPV6 request service */
6466 /* tx_timer_activate Activate the session timer */
6467 /* */
6468 /* CALLED BY */
6469 /* */
6470 /* Application Code */
6471 /* */
6472 /* RELEASE HISTORY */
6473 /* */
6474 /* DATE NAME DESCRIPTION */
6475 /* */
6476 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6477 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6478 /* resulting in version 6.1 */
6479 /* */
6480 /**************************************************************************/
_nx_dhcpv6_request_confirm(NX_DHCPV6 * dhcpv6_ptr)6481 UINT _nx_dhcpv6_request_confirm(NX_DHCPV6 *dhcpv6_ptr)
6482 {
6483
6484 UINT status;
6485
6486 /* Set the initial and max retransmission timeouts, and max number of retries. */
6487 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_CONFIRM_TRANSMISSION_TIMEOUT;
6488 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
6489
6490 /* Set the initaial elasped time of DHCPv6 message. */
6491 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
6492
6493 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
6494 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_CONFIRM_TRANSMISSION_TIMEOUT;
6495 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_CONFIRM_RETRANSMISSION_COUNT;
6496 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_CONFIRM_RETRANSMISSION_TIMEOUT;
6497 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_CONFIRM_RETRANSMISSION_DURATION;
6498
6499 /* Activate the session timer to update the elapsed time. */
6500 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_session_timer);
6501
6502 /* Call the internal function. */
6503 status = _nx_dhcpv6_request(dhcpv6_ptr, NX_DHCPV6_STATE_SENDING_CONFIRM);
6504
6505 /* Return completion status. */
6506 return status;
6507 }
6508
6509
6510 /**************************************************************************/
6511 /* */
6512 /* FUNCTION RELEASE */
6513 /* */
6514 /* _nx_dhcpv6_request_decline PORTABLE C */
6515 /* 6.1 */
6516 /* AUTHOR */
6517 /* */
6518 /* Yuxin Zhou, Microsoft Corporation */
6519 /* */
6520 /* DESCRIPTION */
6521 /* */
6522 /* This function sends a decline request to the server for the Client */
6523 /* to tell the server it does not accept the assigned address. */
6524 /* */
6525 /* INPUT */
6526 /* */
6527 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6528 /* */
6529 /* OUTPUT */
6530 /* */
6531 /* status Completion status */
6532 /* */
6533 /* CALLS */
6534 /* */
6535 /* _nx_dhcpv6_request Actual DHCPV6 request service */
6536 /* tx_timer_activate Activate the session timer */
6537 /* */
6538 /* CALLED BY */
6539 /* */
6540 /* _nx_dhcpv6_process Processes server replies to */
6541 /* DHCPv6 Client requests */
6542 /* */
6543 /* RELEASE HISTORY */
6544 /* */
6545 /* DATE NAME DESCRIPTION */
6546 /* */
6547 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6548 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6549 /* resulting in version 6.1 */
6550 /* */
6551 /**************************************************************************/
_nx_dhcpv6_request_decline(NX_DHCPV6 * dhcpv6_ptr)6552 UINT _nx_dhcpv6_request_decline(NX_DHCPV6 *dhcpv6_ptr)
6553 {
6554
6555 UINT status;
6556 UINT ia_index;
6557
6558 /* Set the initial and max retransmission timeout and max number of retries. */
6559 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_DECLINE_TRANSMISSION_TIMEOUT;
6560 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
6561
6562 /* Set the initaial elasped time of DHCPv6 message. */
6563 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
6564
6565 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
6566 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_DECLINE_TRANSMISSION_TIMEOUT;
6567 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_DECLINE_RETRANSMISSION_COUNT;
6568 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_DECLINE_RETRANSMISSION_TIMEOUT;
6569 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_DECLINE_RETRANSMISSION_DURATION;
6570
6571 /* Activate the session timer to update the elapsed time. */
6572 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_session_timer);
6573
6574 /* Now remove the address from the IP address table,the client MUST NOT use any of the addresses it is declining
6575 as the source address in the Release message or in any subsequently transmitted message, RFC3315,section18.1.7.. */
6576
6577 /* Set the DHCPv6 Client IPv6 addresses. */
6578 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
6579 {
6580
6581 /* Now remove the address from the IP address table,the client MUST NOT use any of the addresses it is declining
6582 as the source address in the Release message or in any subsequently transmitted message, RFC3315,section18.1.7.. */
6583
6584 /* Verify we have a valid address index. */
6585 if(dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index] >= NX_MAX_IPV6_ADDRESSES)
6586 {
6587
6588 return NX_INVALID_INTERFACE;
6589 }
6590
6591 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_DAD_FAILURE)
6592 {
6593 /* Remove the address from the IP instance address table. */
6594
6595 nxd_ipv6_address_delete(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index]);
6596
6597 /* Record the address index in the Client record. */
6598 dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index] = 0xFFFFFFFF;
6599 }
6600 }
6601
6602 /* Call the internal function and return completion status. */
6603 status = _nx_dhcpv6_request(dhcpv6_ptr, NX_DHCPV6_STATE_SENDING_DECLINE);
6604
6605 /* Return completion status. */
6606 return status;
6607 }
6608
6609
6610 /**************************************************************************/
6611 /* */
6612 /* FUNCTION RELEASE */
6613 /* */
6614 /* _nxe_dhcpv6_request_inform_request PORTABLE C */
6615 /* 6.1 */
6616 /* AUTHOR */
6617 /* */
6618 /* Yuxin Zhou, Microsoft Corporation */
6619 /* */
6620 /* DESCRIPTION */
6621 /* */
6622 /* This function performs error checking on the NetX DHCPv6 information*/
6623 /* request service. */
6624 /* */
6625 /* INPUT */
6626 /* */
6627 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6628 /* */
6629 /* OUTPUT */
6630 /* */
6631 /* status Completion status */
6632 /* NX_PTR_ERROR Invalid pointer input */
6633 /* */
6634 /* */
6635 /* CALLS */
6636 /* */
6637 /* _nx_dhcpv6_request_inform_request Actual DHCPV6 process Inform */
6638 /* Request request service */
6639 /* */
6640 /* CALLED BY */
6641 /* */
6642 /* Application Code */
6643 /* */
6644 /* RELEASE HISTORY */
6645 /* */
6646 /* DATE NAME DESCRIPTION */
6647 /* */
6648 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6649 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6650 /* resulting in version 6.1 */
6651 /* */
6652 /**************************************************************************/
_nxe_dhcpv6_request_inform_request(NX_DHCPV6 * dhcpv6_ptr)6653 UINT _nxe_dhcpv6_request_inform_request(NX_DHCPV6 *dhcpv6_ptr)
6654 {
6655
6656 UINT status;
6657
6658
6659 /* Check for invalid pointer input. */
6660 if (!dhcpv6_ptr)
6661 {
6662 return NX_PTR_ERROR;
6663 }
6664
6665 /* Check for appropriate caller. */
6666 NX_THREADS_ONLY_CALLER_CHECKING
6667
6668 /* Call the actual service. */
6669 status = _nx_dhcpv6_request_inform_request(dhcpv6_ptr);
6670
6671 /* Return completion status. */
6672 return status;
6673 }
6674
6675
6676 /**************************************************************************/
6677 /* */
6678 /* FUNCTION RELEASE */
6679 /* */
6680 /* _nx_dhcpv6_request_inform_request PORTABLE C */
6681 /* 6.1 */
6682 /* AUTHOR */
6683 /* */
6684 /* Yuxin Zhou, Microsoft Corporation */
6685 /* */
6686 /* DESCRIPTION */
6687 /* */
6688 /* This function sends a inform request to the server for the Client */
6689 /* to obtain network parameters from any DHCPv6 server on the network. */
6690 /* */
6691 /* INPUT */
6692 /* */
6693 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6694 /* */
6695 /* OUTPUT */
6696 /* */
6697 /* status Completion status */
6698 /* */
6699 /* CALLS */
6700 /* */
6701 /* _nx_dhcpv6_request Actual DHCPV6 request service */
6702 /* tx_timer_activate Activate the session timer */
6703 /* */
6704 /* CALLED BY */
6705 /* */
6706 /* Application Code */
6707 /* */
6708 /* RELEASE HISTORY */
6709 /* */
6710 /* DATE NAME DESCRIPTION */
6711 /* */
6712 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6713 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6714 /* resulting in version 6.1 */
6715 /* */
6716 /**************************************************************************/
_nx_dhcpv6_request_inform_request(NX_DHCPV6 * dhcpv6_ptr)6717 UINT _nx_dhcpv6_request_inform_request(NX_DHCPV6 *dhcpv6_ptr)
6718 {
6719
6720 UINT status;
6721
6722
6723 /* Set the initial and max retransmission timeout and max number of retries. */
6724 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_INFORM_TRANSMISSION_TIMEOUT;
6725 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
6726
6727 /* Set the initaial elasped time of DHCPv6 message. */
6728 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
6729
6730 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
6731 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_INFORM_TRANSMISSION_TIMEOUT;
6732 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_INFORM_RETRANSMISSION_COUNT;
6733 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_INFORM_RETRANSMISSION_TIMEOUT;
6734 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_INFORM_RETRANSMISSION_DURATION;
6735
6736 /* Activate the session timer to update the elapsed time. */
6737 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_session_timer);
6738
6739 /* Call the internal function and return completion status. */
6740 status = _nx_dhcpv6_request(dhcpv6_ptr, NX_DHCPV6_STATE_SENDING_INFORM_REQUEST);
6741
6742 /* Return actual completion status. */
6743 return status;
6744 }
6745
6746
6747 /**************************************************************************/
6748 /* */
6749 /* FUNCTION RELEASE */
6750 /* */
6751 /* _nxe_dhcpv6_request_option_DNS_server PORTABLE C */
6752 /* 6.1 */
6753 /* AUTHOR */
6754 /* */
6755 /* Yuxin Zhou, Microsoft Corporation */
6756 /* */
6757 /* DESCRIPTION */
6758 /* */
6759 /* This function performs error checking on the NetX submit and process*/
6760 /* the DNS server request option from the DHPCv6 Server service. */
6761 /* */
6762 /* INPUT */
6763 /* */
6764 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6765 /* enable Flag indicating if the DNS server*/
6766 /* request enabled or disabled */
6767 /* OUTPUT */
6768 /* */
6769 /* status Completion status */
6770 /* NX_PTR_ERROR Invalid pointer input */
6771 /* */
6772 /* */
6773 /* CALLS */
6774 /* */
6775 /* _nx_dhcpv6_request_option_DNS_server */
6776 /* Actual DHCPV6 process DNS server */
6777 /* request service */
6778 /* */
6779 /* CALLED BY */
6780 /* */
6781 /* Application Code */
6782 /* */
6783 /* RELEASE HISTORY */
6784 /* */
6785 /* DATE NAME DESCRIPTION */
6786 /* */
6787 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6788 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6789 /* resulting in version 6.1 */
6790 /* */
6791 /**************************************************************************/
_nxe_dhcpv6_request_option_DNS_server(NX_DHCPV6 * dhcpv6_ptr,UINT enable)6792 UINT _nxe_dhcpv6_request_option_DNS_server(NX_DHCPV6 *dhcpv6_ptr, UINT enable)
6793 {
6794
6795 UINT status;
6796
6797 /* Check for invalid pointer input. */
6798 if (!dhcpv6_ptr)
6799 {
6800
6801 return NX_PTR_ERROR;
6802 }
6803
6804 /* Check for appropriate caller. */
6805 NX_THREADS_ONLY_CALLER_CHECKING
6806
6807 /* Call the actual service. */
6808 status = _nx_dhcpv6_request_option_DNS_server(dhcpv6_ptr, enable);
6809
6810 /* Return completion status. */
6811 return status;
6812 }
6813
6814
6815 /**************************************************************************/
6816 /* */
6817 /* FUNCTION RELEASE */
6818 /* */
6819 /* _nx_dhcpv6_request_option_DNS_server PORTABLE C */
6820 /* 6.1 */
6821 /* AUTHOR */
6822 /* */
6823 /* Yuxin Zhou, Microsoft Corporation */
6824 /* */
6825 /* DESCRIPTION */
6826 /* */
6827 /* This function enables or disables the DHCPv6 DNS server option. If */
6828 /* enabled this option is added to the option list in DHCPv6 messages */
6829 /* the Client sends to the server. */
6830 /* */
6831 /* INPUT */
6832 /* */
6833 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
6834 /* enable Flag indicating if the DNS server*/
6835 /* request enabled or disabled */
6836 /* */
6837 /* OUTPUT */
6838 /* */
6839 /* NX_SUCCESS Successful completion status */
6840 /* */
6841 /* CALLS */
6842 /* */
6843 /* None */
6844 /* */
6845 /* CALLED BY */
6846 /* */
6847 /* Application code */
6848 /* */
6849 /* RELEASE HISTORY */
6850 /* */
6851 /* DATE NAME DESCRIPTION */
6852 /* */
6853 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6854 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6855 /* resulting in version 6.1 */
6856 /* */
6857 /**************************************************************************/
_nx_dhcpv6_request_option_DNS_server(NX_DHCPV6 * dhcpv6_ptr,UINT enable)6858 UINT _nx_dhcpv6_request_option_DNS_server(NX_DHCPV6 *dhcpv6_ptr, UINT enable)
6859 {
6860
6861 /* Are we enabling this feature? */
6862 if (enable == NX_TRUE)
6863 {
6864
6865 /* Yes, register this option request with the DHCPv6 Client. */
6866 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request |= (USHORT)NX_DHCPV6_DNS_SERVER_OPTION;
6867 }
6868 else
6869 {
6870
6871 /* Clear this option request with the DHCPv6 Client. */
6872 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request &= (USHORT)(~NX_DHCPV6_DNS_SERVER_OPTION);
6873 }
6874
6875 /* Return successful completion. */
6876 return NX_SUCCESS;
6877 }
6878
6879
6880 /**************************************************************************/
6881 /* */
6882 /* FUNCTION RELEASE */
6883 /* */
6884 /* _nxe_dhcpv6_request_option_domain_name PORTABLE C */
6885 /* 6.1 */
6886 /* AUTHOR */
6887 /* */
6888 /* Yuxin Zhou, Microsoft Corporation */
6889 /* */
6890 /* DESCRIPTION */
6891 /* */
6892 /* This function performs error checking on the NetX submit and process*/
6893 /* the domain name request option from the DHPCv6 Server service. */
6894 /* */
6895 /* INPUT */
6896 /* */
6897 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
6898 /* enable Flag indicating if the domain name*/
6899 /* request enabled or disabled */
6900 /* OUTPUT */
6901 /* */
6902 /* status Completion status */
6903 /* NX_PTR_ERROR Invalid pointer input */
6904 /* */
6905 /* */
6906 /* CALLS */
6907 /* */
6908 /* _nx_dhcpv6_request_option_time_server */
6909 /* Actual DHCPV6 process domain name*/
6910 /* request service */
6911 /* */
6912 /* CALLED BY */
6913 /* */
6914 /* Application Code */
6915 /* */
6916 /* RELEASE HISTORY */
6917 /* */
6918 /* DATE NAME DESCRIPTION */
6919 /* */
6920 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6921 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6922 /* resulting in version 6.1 */
6923 /* */
6924 /**************************************************************************/
_nxe_dhcpv6_request_option_domain_name(NX_DHCPV6 * dhcpv6_ptr,UINT enable)6925 UINT _nxe_dhcpv6_request_option_domain_name(NX_DHCPV6 *dhcpv6_ptr, UINT enable)
6926 {
6927
6928 UINT status;
6929
6930
6931 /* Check for invalid pointer input. */
6932 if (!dhcpv6_ptr)
6933 {
6934
6935 return NX_PTR_ERROR;
6936 }
6937
6938 /* Check for appropriate caller. */
6939 NX_THREADS_ONLY_CALLER_CHECKING
6940
6941 /* Call the actual service. */
6942 status = _nx_dhcpv6_request_option_domain_name(dhcpv6_ptr, enable);
6943
6944 /* Return completion status. */
6945 return status;
6946 }
6947
6948
6949 /**************************************************************************/
6950 /* */
6951 /* FUNCTION RELEASE */
6952 /* */
6953 /* _nx_dhcpv6_request_option_domain_name PORTABLE C */
6954 /* 6.1 */
6955 /* AUTHOR */
6956 /* */
6957 /* Yuxin Zhou, Microsoft Corporation */
6958 /* */
6959 /* DESCRIPTION */
6960 /* */
6961 /* This function enables or disables the DHCPv6 domain name option. If*/
6962 /* enabled this option is added to the option list in DHCPv6 messages */
6963 /* the Client sends to the server. */
6964 /* */
6965 /* INPUT */
6966 /* */
6967 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
6968 /* enable Flag indicating if the domain name*/
6969 /* request enabled or disabled */
6970 /* */
6971 /* OUTPUT */
6972 /* */
6973 /* NX_SUCCESS Successful completion status */
6974 /* */
6975 /* CALLS */
6976 /* */
6977 /* None */
6978 /* */
6979 /* CALLED BY */
6980 /* */
6981 /* Application code */
6982 /* */
6983 /* RELEASE HISTORY */
6984 /* */
6985 /* DATE NAME DESCRIPTION */
6986 /* */
6987 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6988 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6989 /* resulting in version 6.1 */
6990 /* */
6991 /**************************************************************************/
_nx_dhcpv6_request_option_domain_name(NX_DHCPV6 * dhcpv6_ptr,UINT enable)6992 UINT _nx_dhcpv6_request_option_domain_name(NX_DHCPV6 *dhcpv6_ptr, UINT enable)
6993 {
6994
6995 /* Are we enabling this feature? */
6996 if (enable == NX_TRUE)
6997 {
6998 /* Yes, register this option request with the DHCPv6 Client. */
6999 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request |= (USHORT)NX_DHCPV6_DOMAIN_NAME_OPTION;
7000 }
7001 else
7002 {
7003
7004 /* Clear this option request with the DHCPv6 Client. */
7005 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request &= (USHORT)(~NX_DHCPV6_DOMAIN_NAME_OPTION);
7006 }
7007
7008 return NX_SUCCESS;
7009 }
7010
7011
7012 /**************************************************************************/
7013 /* */
7014 /* FUNCTION RELEASE */
7015 /* */
7016 /* _nxe_dhcpv6_request_option_time_server PORTABLE C */
7017 /* 6.1 */
7018 /* AUTHOR */
7019 /* */
7020 /* Yuxin Zhou, Microsoft Corporation */
7021 /* */
7022 /* DESCRIPTION */
7023 /* */
7024 /* This function performs error checking on the NetX submit and process*/
7025 /* the time server request option from the DHPCv6 Server service. */
7026 /* */
7027 /* INPUT */
7028 /* */
7029 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
7030 /* enable Flag indicating if the time server*/
7031 /* request enabled or disabled */
7032 /* OUTPUT */
7033 /* */
7034 /* status Completion status */
7035 /* NX_PTR_ERROR Invalid pointer input */
7036 /* */
7037 /* */
7038 /* CALLS */
7039 /* */
7040 /* _nx_dhcpv6_request_option_time_server */
7041 /* Actual DHCPV6 process time server*/
7042 /* request service */
7043 /* */
7044 /* CALLED BY */
7045 /* */
7046 /* Application Code */
7047 /* */
7048 /* RELEASE HISTORY */
7049 /* */
7050 /* DATE NAME DESCRIPTION */
7051 /* */
7052 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7053 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7054 /* resulting in version 6.1 */
7055 /* */
7056 /**************************************************************************/
_nxe_dhcpv6_request_option_time_server(NX_DHCPV6 * dhcpv6_ptr,UINT enable)7057 UINT _nxe_dhcpv6_request_option_time_server(NX_DHCPV6 *dhcpv6_ptr, UINT enable)
7058 {
7059
7060 UINT status;
7061
7062
7063 /* Check for invalid pointer input. */
7064 if (!dhcpv6_ptr)
7065 {
7066 return NX_PTR_ERROR;
7067 }
7068
7069 /* Check for appropriate caller. */
7070 NX_THREADS_ONLY_CALLER_CHECKING
7071
7072 /* Call the actual service. */
7073 status = _nx_dhcpv6_request_option_time_server(dhcpv6_ptr, enable);
7074
7075 /* Return completion status. */
7076 return status;
7077 }
7078
7079
7080 /**************************************************************************/
7081 /* */
7082 /* FUNCTION RELEASE */
7083 /* */
7084 /* _nx_dhcpv6_request_option_time_server PORTABLE C */
7085 /* 6.1 */
7086 /* AUTHOR */
7087 /* */
7088 /* Yuxin Zhou, Microsoft Corporation */
7089 /* */
7090 /* DESCRIPTION */
7091 /* */
7092 /* This function enables or disables the DHCPv6 time server option. If*/
7093 /* enabled this option is added to the option list in DHCPv6 messages */
7094 /* the Client sends to the server. */
7095 /* */
7096 /* INPUT */
7097 /* */
7098 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
7099 /* enable Flag indicating if the time server*/
7100 /* request enabled or disabled */
7101 /* */
7102 /* OUTPUT */
7103 /* */
7104 /* status Actual completion status */
7105 /* NX_SUCCESS Successful completion status */
7106 /* */
7107 /* CALLS */
7108 /* */
7109 /* None */
7110 /* */
7111 /* CALLED BY */
7112 /* */
7113 /* Application code */
7114 /* */
7115 /* RELEASE HISTORY */
7116 /* */
7117 /* DATE NAME DESCRIPTION */
7118 /* */
7119 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7120 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7121 /* resulting in version 6.1 */
7122 /* */
7123 /**************************************************************************/
_nx_dhcpv6_request_option_time_server(NX_DHCPV6 * dhcpv6_ptr,UINT enable)7124 UINT _nx_dhcpv6_request_option_time_server(NX_DHCPV6 *dhcpv6_ptr, UINT enable)
7125 {
7126
7127 /* Is the caller requesting the time server option? */
7128 if (enable == NX_TRUE)
7129 {
7130 /* Yes, register this option request with the DHCPv6 Client. */
7131 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request |= (USHORT)NX_DHCPV6_SNTP_SERVER_OPTION;
7132 }
7133 else
7134 {
7135
7136 /* Clear this option request with the DHCPv6 Client. */
7137 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request &= (USHORT)(~NX_DHCPV6_SNTP_SERVER_OPTION);
7138 }
7139
7140 return NX_SUCCESS;
7141 }
7142
7143
7144 /**************************************************************************/
7145 /* */
7146 /* FUNCTION RELEASE */
7147 /* */
7148 /* _nxe_dhcpv6_request_option_timezone PORTABLE C */
7149 /* 6.1 */
7150 /* AUTHOR */
7151 /* */
7152 /* Yuxin Zhou, Microsoft Corporation */
7153 /* */
7154 /* DESCRIPTION */
7155 /* */
7156 /* This function performs error checking on the NetX submit and process*/
7157 /* the time zone request option from the DHPCv6 Server service. */
7158 /* */
7159 /* INPUT */
7160 /* */
7161 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
7162 /* enable Flag indicating if the time zone */
7163 /* request enabled or disabled */
7164 /* OUTPUT */
7165 /* */
7166 /* status Completion status */
7167 /* NX_PTR_ERROR Invalid pointer input */
7168 /* */
7169 /* */
7170 /* CALLS */
7171 /* */
7172 /* _nx_dhcpv6_request_option_time_zone Actual DHCPV6 process time zone */
7173 /* request service */
7174 /* */
7175 /* CALLED BY */
7176 /* */
7177 /* Application Code */
7178 /* */
7179 /* RELEASE HISTORY */
7180 /* */
7181 /* DATE NAME DESCRIPTION */
7182 /* */
7183 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7184 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7185 /* resulting in version 6.1 */
7186 /* */
7187 /**************************************************************************/
_nxe_dhcpv6_request_option_timezone(NX_DHCPV6 * dhcpv6_ptr,UINT enable)7188 UINT _nxe_dhcpv6_request_option_timezone(NX_DHCPV6 *dhcpv6_ptr, UINT enable)
7189 {
7190
7191 UINT status;
7192
7193
7194 /* Check for invalid pointer input. */
7195 if (!dhcpv6_ptr)
7196 {
7197
7198 return NX_PTR_ERROR;
7199 }
7200
7201 /* Check for appropriate caller. */
7202 NX_THREADS_ONLY_CALLER_CHECKING
7203
7204 /* Call the actual service. */
7205 status = _nx_dhcpv6_request_option_timezone(dhcpv6_ptr, enable);
7206
7207 /* Return completion status. */
7208 return status;
7209 }
7210
7211
7212 /**************************************************************************/
7213 /* */
7214 /* FUNCTION RELEASE */
7215 /* */
7216 /* _nx_dhcpv6_request_option_timezone PORTABLE C */
7217 /* 6.1 */
7218 /* AUTHOR */
7219 /* */
7220 /* Yuxin Zhou, Microsoft Corporation */
7221 /* */
7222 /* DESCRIPTION */
7223 /* */
7224 /* This function enables or disables the DHCPv6 time zone option. If */
7225 /* enabled this option is added to the option list in DHCPv6 messages */
7226 /* the Client sends to the server. */
7227 /* */
7228 /* INPUT */
7229 /* */
7230 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7231 /* enable Flag indicating if the time zone */
7232 /* request enabled or disabled */
7233 /* */
7234 /* OUTPUT */
7235 /* */
7236 /* NX_SUCCESS Successful completion status */
7237 /* */
7238 /* CALLS */
7239 /* */
7240 /* None */
7241 /* */
7242 /* CALLED BY */
7243 /* */
7244 /* Application code */
7245 /* */
7246 /* RELEASE HISTORY */
7247 /* */
7248 /* DATE NAME DESCRIPTION */
7249 /* */
7250 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7251 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7252 /* resulting in version 6.1 */
7253 /* */
7254 /**************************************************************************/
_nx_dhcpv6_request_option_timezone(NX_DHCPV6 * dhcpv6_ptr,UINT enable)7255 UINT _nx_dhcpv6_request_option_timezone(NX_DHCPV6 *dhcpv6_ptr, UINT enable)
7256 {
7257
7258 /* Are we enabling this feature? */
7259 if (enable == NX_TRUE)
7260 {
7261 /* Yes, register this option request with the DHCPv6 Client. */
7262 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request |= NX_DHCPV6_NEW_POSIX_TIMEZONE_OPTION;
7263 }
7264 else
7265 {
7266
7267 /* Clear this option request with the DHCPv6 Client. */
7268 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request &= (USHORT)(~NX_DHCPV6_NEW_POSIX_TIMEZONE_OPTION);
7269 }
7270
7271 return NX_SUCCESS;
7272 }
7273
7274
7275
7276 /**************************************************************************/
7277 /* */
7278 /* FUNCTION RELEASE */
7279 /* */
7280 /* _nxe_dhcpv6_request_option_FQDN PORTABLE C */
7281 /* 6.1 */
7282 /* AUTHOR */
7283 /* */
7284 /* Yuxin Zhou, Microsoft Corporation */
7285 /* */
7286 /* DESCRIPTION */
7287 /* */
7288 /* This function performs error checking on the request fully qualified*/
7289 /* domain name option service. */
7290 /* */
7291 /* INPUT */
7292 /* */
7293 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7294 /* domain_name DHCPv6 CLient domain name */
7295 /* op DHCPv6 Client operation */
7296 /* */
7297 /* OUTPUT */
7298 /* */
7299 /* status Completion status */
7300 /* NX_PTR_ERROR Invalid pointer input */
7301 /* */
7302 /* */
7303 /* CALLS */
7304 /* */
7305 /* _nx_dhcpv6_request_option_FQDN Actual DHCPv6 process FQDN */
7306 /* */
7307 /* CALLED BY */
7308 /* */
7309 /* Application Code */
7310 /* */
7311 /* RELEASE HISTORY */
7312 /* */
7313 /* DATE NAME DESCRIPTION */
7314 /* */
7315 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7316 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7317 /* resulting in version 6.1 */
7318 /* */
7319 /**************************************************************************/
_nxe_dhcpv6_request_option_FQDN(NX_DHCPV6 * dhcpv6_ptr,CHAR * domain_name,UINT op)7320 UINT _nxe_dhcpv6_request_option_FQDN(NX_DHCPV6 *dhcpv6_ptr, CHAR *domain_name, UINT op)
7321 {
7322
7323 UINT status;
7324
7325
7326 /* Check for invalid pointer input. */
7327 if ((!dhcpv6_ptr) || (!domain_name))
7328 {
7329 return NX_PTR_ERROR;
7330 }
7331
7332 /* Check for appropriate caller. */
7333 NX_THREADS_ONLY_CALLER_CHECKING
7334
7335 /* Call the actual service. */
7336 status = _nx_dhcpv6_request_option_FQDN(dhcpv6_ptr, domain_name, op);
7337
7338 /* Return completion status. */
7339 return status;
7340 }
7341
7342
7343 /**************************************************************************/
7344 /* */
7345 /* FUNCTION RELEASE */
7346 /* */
7347 /* _nx_dhcpv6_request_option_FQDN PORTABLE C */
7348 /* 6.1 */
7349 /* AUTHOR */
7350 /* */
7351 /* Yuxin Zhou, Microsoft Corporation */
7352 /* */
7353 /* DESCRIPTION */
7354 /* */
7355 /* This function processes the DHCPv6 Client fully qualified domain */
7356 /* name. DHCPv6 Client sends this option to indicate if the server */
7357 /* SHOULD or SHOULD NOT perform the AAAA RR or DNS updates. */
7358 /* */
7359 /* INPUT */
7360 /* */
7361 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7362 /* domain_name DHCPv6 CLient domain name */
7363 /* op DHCPv6 Client operation */
7364 /* */
7365 /* OUTPUT */
7366 /* */
7367 /* NX_SUCCESS Successful completion status */
7368 /* */
7369 /* CALLS */
7370 /* */
7371 /* None */
7372 /* */
7373 /* CALLED BY */
7374 /* */
7375 /* Application code */
7376 /* */
7377 /* RELEASE HISTORY */
7378 /* */
7379 /* DATE NAME DESCRIPTION */
7380 /* */
7381 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7382 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7383 /* resulting in version 6.1 */
7384 /* */
7385 /**************************************************************************/
_nx_dhcpv6_request_option_FQDN(NX_DHCPV6 * dhcpv6_ptr,CHAR * domain_name,UINT op)7386 UINT _nx_dhcpv6_request_option_FQDN(NX_DHCPV6 *dhcpv6_ptr, CHAR *domain_name, UINT op)
7387 {
7388 UINT name_length;
7389
7390 /* Set the Client FQDN option code. */
7391 dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_op_code = NX_DHCPV6_OP_CLIENT_FQDN;
7392
7393 /* Check domain name lengrh. The total length of a domain name is restricted to 255 octets or less. RFC1035. */
7394 if (_nx_utility_string_length_check(domain_name, &name_length, NX_DHCPV6_MAX_NAME_SIZE))
7395 {
7396 return(NX_DHCPV6_PARAM_ERROR);
7397 }
7398
7399 /* Set the Client FQDN option length. 1 + length of domain name(domain name length + label + terminator) . */
7400 dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_op_length = (USHORT)(1 + name_length + 2);
7401
7402 /* Set the Client fully qualified domain name. */
7403 dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_domain_name = domain_name;
7404
7405 /* Flags Field.
7406 0 1 2 3 4 5 6 7
7407 +-+-+-+-+-+-+-+-+
7408 | MBZ |N|O|S|
7409 +-+-+-+-+-+-+-+-+
7410 */
7411
7412 /* Set the flags. */
7413 if (op == NX_DHCPV6_CLIENT_DESIRES_UPDATE_AAAA_RR)
7414 {
7415
7416 /* DHCPv6 Client chooses to update the FQDN-to-IPv6 address mapping for FQDN and address(es) used by the Cslient.
7417 Set the "S", "O" and "N" bits as 0. */
7418 dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_flags = 0x00;
7419 }
7420 else if (op == NX_DHCPV6_CLIENT_DESIRES_SERVER_DO_DNS_UPDATE)
7421 {
7422
7423 /* DHCPv6 Client chooses to update the FQDN-to-IPv6 address mapping for FQDN and address(es) used by the Client to the Server.
7424 Set the "S" bit as 1, Set "O" and "N" bits as 0. */
7425 dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_flags = 0x01;
7426 }
7427 else
7428 {
7429
7430 /* DHCPv6 Client choose to request that the Server perform no DNS updates on its behalf.
7431 Set the "N" bit as 1, Set "O" and "S" bits as 0. */
7432 dhcpv6_ptr -> nx_dhcpv6_client_FQDN.nx_flags = 0x04;
7433 }
7434
7435 /* Yes, register this option request with the DHCPv6 Client. */
7436 dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request |= NX_DHCPV6_CLIENT_FQDN_OPTION;
7437
7438 return NX_SUCCESS;
7439 }
7440
7441
7442 /**************************************************************************/
7443 /* */
7444 /* FUNCTION RELEASE */
7445 /* */
7446 /* _nx_dhcpv6_request_rebind PORTABLE C */
7447 /* 6.1 */
7448 /* AUTHOR */
7449 /* */
7450 /* Yuxin Zhou, Microsoft Corporation */
7451 /* */
7452 /* DESCRIPTION */
7453 /* */
7454 /* This function sends a rebind request to the server for the Client to*/
7455 /* obtain or rebind an IP address with a DHCPv6 server on the network. */
7456 /* */
7457 /* Note: the Client thread task will detect when it is time to rebind */
7458 /* the Client IP address and call the expired address handler if one is*/
7459 /* set. The expired address handler is where the host should call this*/
7460 /* service from. */
7461 /* */
7462 /* INPUT */
7463 /* */
7464 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7465 /* */
7466 /* OUTPUT */
7467 /* */
7468 /* NX_SUCCESS Rebind already initiated */
7469 /* status Completion status */
7470 /* */
7471 /* CALLS */
7472 /* */
7473 /* _nx_dhcpv6_request Actual DHCPV6 request service */
7474 /* tx_timer_activate Activate the session timer */
7475 /* */
7476 /* CALLED BY */
7477 /* */
7478 /* Application Code */
7479 /* _nx_dhcpv6_thread_entry DHCPv6 Client thread task */
7480 /* */
7481 /* RELEASE HISTORY */
7482 /* */
7483 /* DATE NAME DESCRIPTION */
7484 /* */
7485 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7486 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7487 /* resulting in version 6.1 */
7488 /* */
7489 /**************************************************************************/
_nx_dhcpv6_request_rebind(NX_DHCPV6 * dhcpv6_ptr)7490 UINT _nx_dhcpv6_request_rebind(NX_DHCPV6 *dhcpv6_ptr)
7491 {
7492
7493 UINT status;
7494 UINT ia_index;
7495 UINT max_valid_lifetime = 0;
7496
7497
7498 /* Is the Client state set to REBIND yet? */
7499 if (dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_REBIND)
7500 {
7501
7502 /* Yes, the rebind process is already started. No need to re-request it.
7503 Also must not zero out retry count or reset timeout back to starting value. */
7504 return NX_SUCCESS;
7505 }
7506
7507
7508 /* Set the initial and max retransmission timeouts and max number of retries. */
7509 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_REBIND_TRANSMISSION_TIMEOUT;
7510 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
7511
7512 /* Set the initaial elasped time of DHCPv6 message. */
7513 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
7514
7515 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
7516 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_REBIND_TRANSMISSION_TIMEOUT;
7517 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_REBIND_RETRANSMISSION_COUNT;
7518 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_REBIND_RETRANSMISSION_TIMEOUT;
7519
7520 /* Find the max valid lifetime. */
7521 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
7522 {
7523
7524 /* Check the address status. */
7525 if((dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID) &&
7526 (dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime > max_valid_lifetime))
7527 {
7528
7529 /* Find the max valid lifetime of all IAs. */
7530 max_valid_lifetime = dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime;
7531 }
7532 }
7533
7534 /* Set the max duration time.The message exchange is terminated when the valid lifetimes of all the addresses assigned to the IA expire,
7535 RFC3315, Section18.1.4, Page43. */
7536 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = max_valid_lifetime;
7537
7538 /* Activate the session timer to update the elapsed time. */
7539 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_session_timer);
7540
7541 /* Call the internal function and return completion status. */
7542 status = _nx_dhcpv6_request(dhcpv6_ptr, NX_DHCPV6_STATE_SENDING_REBIND);
7543
7544 /* Return the actual completion status. */
7545 return status;
7546 }
7547
7548
7549 /**************************************************************************/
7550 /* */
7551 /* FUNCTION RELEASE */
7552 /* */
7553 /* _nxe_dhcpv6_request_release PORTABLE C */
7554 /* 6.1 */
7555 /* AUTHOR */
7556 /* */
7557 /* Yuxin Zhou, Microsoft Corporation */
7558 /* */
7559 /* DESCRIPTION */
7560 /* */
7561 /* This function performs error checking on the NetX DHCPv6 Release */
7562 /* request service. */
7563 /* */
7564 /* INPUT */
7565 /* */
7566 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7567 /* */
7568 /* OUTPUT */
7569 /* */
7570 /* status Completion status */
7571 /* NX_PTR_ERROR Invalid pointer input */
7572 /* */
7573 /* */
7574 /* CALLS */
7575 /* */
7576 /* _nx_dhcpv6_request_release Actual DHCPV6 process Release */
7577 /* request service */
7578 /* */
7579 /* CALLED BY */
7580 /* */
7581 /* Application Code */
7582 /* */
7583 /* RELEASE HISTORY */
7584 /* */
7585 /* DATE NAME DESCRIPTION */
7586 /* */
7587 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7588 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7589 /* resulting in version 6.1 */
7590 /* */
7591 /**************************************************************************/
_nxe_dhcpv6_request_release(NX_DHCPV6 * dhcpv6_ptr)7592 UINT _nxe_dhcpv6_request_release(NX_DHCPV6 *dhcpv6_ptr)
7593 {
7594
7595 UINT status;
7596
7597 /* Check for invalid pointer input. */
7598 if (!dhcpv6_ptr)
7599 {
7600 return NX_PTR_ERROR;
7601 }
7602
7603 /* Check for appropriate caller. */
7604 NX_THREADS_ONLY_CALLER_CHECKING
7605
7606 /* Call the actual service. */
7607 status = _nx_dhcpv6_request_release(dhcpv6_ptr);
7608
7609 /* Return completion status. */
7610 return status;
7611 }
7612
7613
7614 /**************************************************************************/
7615 /* */
7616 /* FUNCTION RELEASE */
7617 /* */
7618 /* _nx_dhcpv6_request_release PORTABLE C */
7619 /* 6.1 */
7620 /* AUTHOR */
7621 /* */
7622 /* Yuxin Zhou, Microsoft Corporation */
7623 /* */
7624 /* DESCRIPTION */
7625 /* */
7626 /* This function sends a release request to the server for the Client */
7627 /* to release a assigned IP address back to the DHCPv6 server who */
7628 /* previously assigned it. */
7629 /* */
7630 /* INPUT */
7631 /* */
7632 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7633 /* */
7634 /* OUTPUT */
7635 /* */
7636 /* status Actual completion status */
7637 /* NX_DHCPV6_IA_ADDRESS_NOT_VALID Client not assigned an address */
7638 /* */
7639 /* CALLS */
7640 /* */
7641 /* _nx_dhcpv6_request Actual DHCPV6 request service */
7642 /* tx_timer_activate Activate the session timer */
7643 /* */
7644 /* CALLED BY */
7645 /* */
7646 /* Application Code */
7647 /* */
7648 /* RELEASE HISTORY */
7649 /* */
7650 /* DATE NAME DESCRIPTION */
7651 /* */
7652 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7653 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7654 /* resulting in version 6.1 */
7655 /* */
7656 /**************************************************************************/
_nx_dhcpv6_request_release(NX_DHCPV6 * dhcpv6_ptr)7657 UINT _nx_dhcpv6_request_release(NX_DHCPV6 *dhcpv6_ptr)
7658 {
7659
7660 UINT status;
7661 UINT ia_index;
7662
7663 /* Check if the Client is bound to an assigned address. */
7664 if((dhcpv6_ptr -> nx_dhcpv6_state != NX_DHCPV6_STATE_BOUND_TO_ADDRESS) &&
7665 (dhcpv6_ptr -> nx_dhcpv6_state != NX_DHCPV6_STATE_SENDING_RENEW) &&
7666 (dhcpv6_ptr -> nx_dhcpv6_state != NX_DHCPV6_STATE_SENDING_REBIND))
7667 {
7668
7669 /* It is not. The host application should use the nx_dhcpv6_stop if the DHCP Client
7670 has simply failed to obtain an IP address from the server instead. */
7671
7672 /* Benign error so return successful outcome. */
7673 return NX_DHCPV6_IA_ADDRESS_NOT_VALID;
7674 }
7675
7676 /* Set the initial and max retransmission timeouts and max number of retries. */
7677 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_RELEASE_TRANSMISSION_TIMEOUT;
7678 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
7679
7680 /* Set the initaial elasped time of DHCPv6 message. */
7681 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
7682
7683 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
7684 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_RELEASE_TRANSMISSION_TIMEOUT;
7685 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_RELEASE_RETRANSMISSION_COUNT;
7686 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_RELEASE_RETRANSMISSION_TIMEOUT;
7687 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_RELEASE_RETRANSMISSION_DURATION;
7688
7689 /* Activate the session timer to update the elapsed time. */
7690 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_session_timer);
7691
7692 /* Set the DHCPv6 Client IPv6 addresses. */
7693 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
7694 {
7695
7696 /* Now remove the address from the IP address table,the client MUST NOT use any of the addresses it is declining
7697 as the source address in the Release message or in any subsequently transmitted message, RFC3315,section18.1.7.. */
7698
7699 /* Verify we have a valid address index. */
7700 if(dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index] >= NX_MAX_IPV6_ADDRESSES)
7701 {
7702
7703 return NX_INVALID_INTERFACE;
7704 }
7705
7706 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_op_code)
7707 {
7708 /* Remove the address from the IP instance address table. */
7709
7710 nxd_ipv6_address_delete(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index]);
7711
7712 /* Record the address index in the Client record. */
7713 dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index] = 0xFFFFFFFF;
7714 }
7715 }
7716
7717 /* Call the internal function and return completion status. */
7718 status = _nx_dhcpv6_request(dhcpv6_ptr, NX_DHCPV6_STATE_SENDING_RELEASE);
7719
7720 /* Return completion status. */
7721 return status;
7722 }
7723
7724
7725 /**************************************************************************/
7726 /* */
7727 /* FUNCTION RELEASE */
7728 /* */
7729 /* _nx_dhcpv6_request_renew PORTABLE C */
7730 /* 6.1 */
7731 /* AUTHOR */
7732 /* */
7733 /* Yuxin Zhou, Microsoft Corporation */
7734 /* */
7735 /* DESCRIPTION */
7736 /* */
7737 /* This function calls the internal request service to renew the */
7738 /* DHCPv6 IP address assigned to it by the server. */
7739 /* */
7740 /* Note: the Client thread task will detect when it is time to renew */
7741 /* the Client IP address and call the deprecated address handler if one*/
7742 /* is set. The deprecated address handler is where the host should */
7743 /* call this service from. */
7744 /* */
7745 /* INPUT */
7746 /* */
7747 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7748 /* */
7749 /* OUTPUT */
7750 /* */
7751 /* NX_SUCCESS Renew already initiated */
7752 /* status Completion status */
7753 /* */
7754 /* CALLS */
7755 /* */
7756 /* _nx_dhcpv6_request Actual DHCPV6 request service */
7757 /* tx_timer_activate Activate the session timer */
7758 /* */
7759 /* CALLED BY */
7760 /* */
7761 /* Application Code */
7762 /* _nx_dhcpv6_thread_entry DHCPv6 Client thread task */
7763 /* */
7764 /* RELEASE HISTORY */
7765 /* */
7766 /* DATE NAME DESCRIPTION */
7767 /* */
7768 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7769 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7770 /* resulting in version 6.1 */
7771 /* */
7772 /**************************************************************************/
_nx_dhcpv6_request_renew(NX_DHCPV6 * dhcpv6_ptr)7773 UINT _nx_dhcpv6_request_renew(NX_DHCPV6 *dhcpv6_ptr)
7774 {
7775
7776 UINT status;
7777
7778
7779 /* Is the Client state set to RENEW yet? */
7780 if (dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_RENEW)
7781 {
7782
7783 /* Yes, the renew process is already started. No need to re-request it.
7784 Also must not zero out retry count or reset timeout back to starting value. */
7785 return NX_SUCCESS;
7786 }
7787
7788 /* Set initial retry and timeout values for sending the Renew request. */
7789 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
7790 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_RENEW_TRANSMISSION_TIMEOUT;
7791
7792 /* Set the initaial elasped time of DHCPv6 message. */
7793 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
7794
7795 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
7796 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_RENEW_TRANSMISSION_TIMEOUT;
7797 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_RENEW_RETRANSMISSION_COUNT;
7798 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_RENEW_RETRANSMISSION_TIMEOUT;
7799 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2;
7800
7801 /* Activate the session timer to update the elapsed time. */
7802 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_session_timer);
7803
7804 /* Set the Client to the Renewing state for the DHCP Client thread to process. */
7805 status = _nx_dhcpv6_request(dhcpv6_ptr, NX_DHCPV6_STATE_SENDING_RENEW);
7806
7807 /* Actual completion status. */
7808 return status;
7809 }
7810
7811
7812 /**************************************************************************/
7813 /* */
7814 /* FUNCTION RELEASE */
7815 /* */
7816 /* _nxe_dhcpv6_request_solicit PORTABLE C */
7817 /* 6.1 */
7818 /* AUTHOR */
7819 /* */
7820 /* Yuxin Zhou, Microsoft Corporation */
7821 /* */
7822 /* DESCRIPTION */
7823 /* */
7824 /* This function performs error checking on the NetX DHCPv6 solicit */
7825 /* request service. */
7826 /* */
7827 /* INPUT */
7828 /* */
7829 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7830 /* */
7831 /* OUTPUT */
7832 /* */
7833 /* status Completion status */
7834 /* NX_PTR_ERROR Invalid pointer input */
7835 /* */
7836 /* */
7837 /* CALLS */
7838 /* */
7839 /* _nx_dhcpv6_request_solicit Actual DHCPV6 process Solicit */
7840 /* request service */
7841 /* */
7842 /* CALLED BY */
7843 /* */
7844 /* Application Code */
7845 /* */
7846 /* RELEASE HISTORY */
7847 /* */
7848 /* DATE NAME DESCRIPTION */
7849 /* */
7850 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7851 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7852 /* resulting in version 6.1 */
7853 /* */
7854 /**************************************************************************/
_nxe_dhcpv6_request_solicit(NX_DHCPV6 * dhcpv6_ptr)7855 UINT _nxe_dhcpv6_request_solicit(NX_DHCPV6 *dhcpv6_ptr)
7856 {
7857
7858 UINT status;
7859
7860
7861 /* Check for invalid pointer input. */
7862 if (!dhcpv6_ptr)
7863 {
7864 return NX_PTR_ERROR;
7865 }
7866
7867 /* Check for appropriate caller. */
7868 NX_THREADS_ONLY_CALLER_CHECKING
7869
7870 /* Call the actual service. */
7871 status = _nx_dhcpv6_request_solicit(dhcpv6_ptr);
7872
7873 /* Return completion status. */
7874 return status;
7875 }
7876
7877
7878 /**************************************************************************/
7879 /* */
7880 /* FUNCTION RELEASE */
7881 /* */
7882 /* _nx_dhcpv6_request_solicit PORTABLE C */
7883 /* 6.1 */
7884 /* AUTHOR */
7885 /* */
7886 /* Yuxin Zhou, Microsoft Corporation */
7887 /* */
7888 /* DESCRIPTION */
7889 /* */
7890 /* This function sends a solicit request for the Client to obtain an IP*/
7891 /* address from any DHCPv6 server on the network. */
7892 /* */
7893 /* INPUT */
7894 /* */
7895 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7896 /* */
7897 /* OUTPUT */
7898 /* */
7899 /* status Completion status */
7900 /* */
7901 /* CALLS */
7902 /* */
7903 /* _nx_dhcpv6_request Actual DHCPV6 request service */
7904 /* tx_timer_activate Activate the session timer */
7905 /* */
7906 /* CALLED BY */
7907 /* */
7908 /* Application Code */
7909 /* _nx_dhcpv6_process Send the DHCPv6 solicit message */
7910 /* */
7911 /* RELEASE HISTORY */
7912 /* */
7913 /* DATE NAME DESCRIPTION */
7914 /* */
7915 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7916 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7917 /* resulting in version 6.1 */
7918 /* */
7919 /**************************************************************************/
_nx_dhcpv6_request_solicit(NX_DHCPV6 * dhcpv6_ptr)7920 UINT _nx_dhcpv6_request_solicit(NX_DHCPV6 *dhcpv6_ptr)
7921 {
7922
7923 UINT status;
7924
7925
7926 /* Set the mode of sending the solicit message. Do not override a rapid option if set. */
7927 if (dhcpv6_ptr ->nx_dhcpv6_request_solicit_mode != NX_DHCPV6_SOLICIT_RAPID)
7928 {
7929
7930 /* Set the mode of sending the solicit message. */
7931 dhcpv6_ptr -> nx_dhcpv6_request_solicit_mode = NX_DHCPV6_SOLICIT_NORMAL;
7932 }
7933
7934 /* Set the initial and maximum timeout and retries. */
7935 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_SOL_TRANSMISSION_TIMEOUT;
7936 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
7937
7938 /* Set the initaial elasped time of DHCPv6 message. */
7939 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
7940
7941 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
7942 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_SOL_TRANSMISSION_TIMEOUT;
7943 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_SOL_RETRANSMISSION_COUNT;
7944 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_SOL_RETRANSMISSION_TIMEOUT;
7945 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_SOL_RETRANSMISSION_DURATION;
7946
7947 /* Reset the preference value if the Client previously accepted an Advertise message. */
7948 dhcpv6_ptr -> nx_dhcpv6_preference.nx_pref_value = 0;
7949
7950 /* Activate the session timer to update the elapsed time. */
7951 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_session_timer);
7952
7953 /* Set the Client to the Solicity state for the DHCP Client thread to process. */
7954 status = _nx_dhcpv6_request(dhcpv6_ptr, NX_DHCPV6_STATE_SENDING_SOLICIT);
7955
7956 /* Return the completion status. */
7957 return status;
7958 }
7959
7960
7961 /**************************************************************************/
7962 /* */
7963 /* FUNCTION RELEASE */
7964 /* */
7965 /* _nxe_dhcpv6_request_solicit_rapid PORTABLE C */
7966 /* 6.1 */
7967 /* AUTHOR */
7968 /* */
7969 /* Yuxin Zhou, Microsoft Corporation */
7970 /* */
7971 /* DESCRIPTION */
7972 /* */
7973 /* This function performs error checking on the NetX DHCPv6 solicit */
7974 /* request service with rapid commit option. */
7975 /* */
7976 /* INPUT */
7977 /* */
7978 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
7979 /* */
7980 /* OUTPUT */
7981 /* */
7982 /* status Completion status */
7983 /* NX_PTR_ERROR Invalid pointer input */
7984 /* */
7985 /* */
7986 /* CALLS */
7987 /* */
7988 /* _nx_dhcpv6_request_solicit_rapid Actual DHCPV6 process Solicit */
7989 /* request service */
7990 /* */
7991 /* CALLED BY */
7992 /* */
7993 /* Application Code */
7994 /* */
7995 /* RELEASE HISTORY */
7996 /* */
7997 /* DATE NAME DESCRIPTION */
7998 /* */
7999 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8000 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8001 /* resulting in version 6.1 */
8002 /* */
8003 /**************************************************************************/
_nxe_dhcpv6_request_solicit_rapid(NX_DHCPV6 * dhcpv6_ptr)8004 UINT _nxe_dhcpv6_request_solicit_rapid(NX_DHCPV6 *dhcpv6_ptr)
8005 {
8006
8007 UINT status;
8008
8009
8010 /* Check for invalid pointer input. */
8011 if (!dhcpv6_ptr)
8012 {
8013 return NX_PTR_ERROR;
8014 }
8015
8016 /* Check for appropriate caller. */
8017 NX_THREADS_ONLY_CALLER_CHECKING
8018
8019 /* Call the actual service. */
8020 status = _nx_dhcpv6_request_solicit_rapid(dhcpv6_ptr);
8021
8022 /* Return completion status. */
8023 return status;
8024 }
8025
8026
8027 /**************************************************************************/
8028 /* */
8029 /* FUNCTION RELEASE */
8030 /* */
8031 /* _nx_dhcpv6_request_solicit_rapid PORTABLE C */
8032 /* 6.1 */
8033 /* AUTHOR */
8034 /* */
8035 /* Yuxin Zhou, Microsoft Corporation */
8036 /* */
8037 /* DESCRIPTION */
8038 /* */
8039 /* This function sends a solicit request with rapid commit option for */
8040 /* the Client to rapidly obtain an IP address from any DHCPv6 server. */
8041 /* */
8042 /* INPUT */
8043 /* */
8044 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
8045 /* */
8046 /* OUTPUT */
8047 /* */
8048 /* status Completion status */
8049 /* */
8050 /* CALLS */
8051 /* */
8052 /* _nx_dhcpv6_request Actual DHCPV6 request service */
8053 /* tx_timer_activate Activate the session timer */
8054 /* */
8055 /* CALLED BY */
8056 /* */
8057 /* Application Code */
8058 /* */
8059 /* RELEASE HISTORY */
8060 /* */
8061 /* DATE NAME DESCRIPTION */
8062 /* */
8063 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8064 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8065 /* resulting in version 6.1 */
8066 /* */
8067 /**************************************************************************/
_nx_dhcpv6_request_solicit_rapid(NX_DHCPV6 * dhcpv6_ptr)8068 UINT _nx_dhcpv6_request_solicit_rapid(NX_DHCPV6 *dhcpv6_ptr)
8069 {
8070
8071 UINT status;
8072
8073
8074 /* Set the mode of sending the solicit message. */
8075 dhcpv6_ptr ->nx_dhcpv6_request_solicit_mode = NX_DHCPV6_SOLICIT_RAPID;
8076
8077 /* Set the initial and maximum timeout and retries. */
8078 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = NX_DHCPV6_INIT_SOL_TRANSMISSION_TIMEOUT;
8079 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
8080
8081 /* Set the initaial elasped time of DHCPv6 message. */
8082 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
8083
8084 /* Set the retransmission information(IRT, MRC, MRT, MRD). */
8085 dhcpv6_ptr -> nx_dhcpv6_init_retransmission_timeout = NX_DHCPV6_INIT_SOL_TRANSMISSION_TIMEOUT;
8086 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count = NX_DHCPV6_MAX_SOL_RETRANSMISSION_COUNT;
8087 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout = NX_DHCPV6_MAX_SOL_RETRANSMISSION_TIMEOUT;
8088 dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration = NX_DHCPV6_MAX_SOL_RETRANSMISSION_DURATION;
8089
8090 /* Reset the preference value if the Client previously accepted an Advertise message. */
8091 dhcpv6_ptr -> nx_dhcpv6_preference.nx_pref_value = 0;
8092
8093 /* Activate the session timer to update the elapsed time. */
8094 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_session_timer);
8095
8096 /* Set the Client to the Solicity state for the DHCP Client thread to process. */
8097 status = _nx_dhcpv6_request(dhcpv6_ptr, NX_DHCPV6_STATE_SENDING_SOLICIT);
8098
8099 /* Return the completion status. */
8100 return status;
8101 }
8102
8103
8104 /**************************************************************************/
8105 /* */
8106 /* FUNCTION RELEASE */
8107 /* */
8108 /* _nxe_dhcpv6_resume PORTABLE C */
8109 /* 6.1 */
8110 /* AUTHOR */
8111 /* */
8112 /* Yuxin Zhou, Microsoft Corporation */
8113 /* */
8114 /* DESCRIPTION */
8115 /* */
8116 /* This function performs error checking on the resume NetX DHCPv6 */
8117 /* client task service. */
8118 /* */
8119 /* INPUT */
8120 /* */
8121 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
8122 /* */
8123 /* OUTPUT */
8124 /* */
8125 /* OUTPUT */
8126 /* */
8127 /* status Completion status */
8128 /* NX_PTR_ERROR Invalid pointer input */
8129 /* */
8130 /* CALLS */
8131 /* */
8132 /* _nx_dhcpv6_resume Actual DHCPV6 resume function */
8133 /* */
8134 /* CALLED BY */
8135 /* */
8136 /* Application Code */
8137 /* */
8138 /* RELEASE HISTORY */
8139 /* */
8140 /* DATE NAME DESCRIPTION */
8141 /* */
8142 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8143 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8144 /* resulting in version 6.1 */
8145 /* */
8146 /**************************************************************************/
_nxe_dhcpv6_resume(NX_DHCPV6 * dhcpv6_ptr)8147 UINT _nxe_dhcpv6_resume(NX_DHCPV6 *dhcpv6_ptr)
8148 {
8149
8150 UINT status;
8151
8152
8153 /* Check for invalid input pointer. */
8154 if ((dhcpv6_ptr == NX_NULL) || (dhcpv6_ptr -> nx_dhcpv6_id != NX_DHCPV6_ID))
8155 {
8156 return(NX_PTR_ERROR);
8157 }
8158
8159 /* Check for appropriate caller. */
8160 NX_THREADS_ONLY_CALLER_CHECKING
8161
8162 /* Call actual DHCPV6 stop service. */
8163 status = _nx_dhcpv6_resume(dhcpv6_ptr);
8164
8165 /* Return status. */
8166 return(status);
8167 }
8168
8169
8170 /**************************************************************************/
8171 /* */
8172 /* FUNCTION RELEASE */
8173 /* */
8174 /* _nx_dhcpv6_resume PORTABLE C */
8175 /* 6.1 */
8176 /* AUTHOR */
8177 /* */
8178 /* Yuxin Zhou, Microsoft Corporation */
8179 /* */
8180 /* DESCRIPTION */
8181 /* */
8182 /* This function resumes DHCPV6 processing thread and updates the */
8183 /* DHCPv6 client state according to nx_dhcpv6_IP_lifetime_time_accrued.*/
8184 /* */
8185 /* INPUT */
8186 /* */
8187 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
8188 /* */
8189 /* OUTPUT */
8190 /* */
8191 /* status Actual completion status */
8192 /* */
8193 /* CALLS */
8194 /* */
8195 /* nx_dhcpv6_start Starts DHCPV6 thread task */
8196 /* */
8197 /* CALLED BY */
8198 /* */
8199 /* Application Code */
8200 /* */
8201 /* RELEASE HISTORY */
8202 /* */
8203 /* DATE NAME DESCRIPTION */
8204 /* */
8205 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8206 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8207 /* resulting in version 6.1 */
8208 /* */
8209 /**************************************************************************/
_nx_dhcpv6_resume(NX_DHCPV6 * dhcpv6_ptr)8210 UINT _nx_dhcpv6_resume(NX_DHCPV6 *dhcpv6_ptr)
8211 {
8212
8213 UINT status;
8214 UCHAR original_state;
8215
8216 /* Get the DHCP mutex. */
8217 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
8218
8219 /* Determine if DHCPV6 has already been started. */
8220 if (dhcpv6_ptr -> nx_dhcpv6_started)
8221 {
8222
8223 /* Release the DHCPv6 Client mutex. */
8224 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
8225
8226 /* Error, the DHCPV6 client has already been started. */
8227 return(NX_DHCPV6_ALREADY_STARTED);
8228 }
8229
8230 /* Determine if Client has created its DUID and IANA yet. */
8231 if ((dhcpv6_ptr -> nx_dhcpv6_ip_ptr == NX_NULL) ||
8232 (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_option_length == 0) ||
8233 (dhcpv6_ptr -> nx_dhcpv6_iana.nx_option_length == 0))
8234 {
8235
8236 /* Release the DHCPv6 Client mutex. */
8237 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
8238
8239 /* No, this DHCPv6 Client is not ready to run! */
8240 return NX_DHCPV6_MISSING_REQUIRED_OPTIONS;
8241 }
8242
8243 /* Remember the original DHCPv6 state for the changed state callback function. */
8244 original_state = dhcpv6_ptr -> nx_dhcpv6_state;
8245
8246 /* Bind the UDP socket to the DHCPV6 Client port. */
8247 status = nx_udp_socket_bind(&(dhcpv6_ptr -> nx_dhcpv6_socket), NX_DHCPV6_CLIENT_UDP_PORT, TX_WAIT_FOREVER);
8248
8249 /* Check for success */
8250 if (status)
8251 {
8252
8253 /* Release the DHCPv6 Client mutex. */
8254 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
8255
8256 /* Return completion status. */
8257 return(status);
8258 }
8259
8260 /* Check the DHCPv6 Client state. */
8261 if ((dhcpv6_ptr -> nx_dhcpv6_state != NX_DHCPV6_STATE_BOUND_TO_ADDRESS) &&
8262 (dhcpv6_ptr -> nx_dhcpv6_state != NX_DHCPV6_STATE_SENDING_RENEW) &&
8263 (dhcpv6_ptr -> nx_dhcpv6_state != NX_DHCPV6_STATE_SENDING_REBIND))
8264 {
8265
8266 /* Set the DHCPv6 Client state to Init.*/
8267 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
8268
8269 /* Clear the session time, lease lifetime, retransmission counters. */
8270 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
8271 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = 0;
8272 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = 0;
8273 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
8274 }
8275 else
8276 {
8277
8278 /* Check the accrued time to upate the state. */
8279 if ((dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_BOUND_TO_ADDRESS) && ((dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued >= dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2)))
8280 {
8281
8282 /* Update the status as NX_DHCPV6_STATE_SENDING_RENEW to send rebinding message in _nx_dhcpv6_thread_entry function. */
8283 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_SENDING_RENEW;
8284 }
8285 }
8286
8287
8288 /* Set the DHCPv6 started flag to indicate DHCPv6 Client is now running. */
8289 dhcpv6_ptr -> nx_dhcpv6_started = NX_TRUE;
8290
8291 /* Activate the DHCPv6 timers. */
8292 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer);
8293
8294 /* Resume the DHCPv6 processing thread. */
8295 tx_thread_resume(&(dhcpv6_ptr -> nx_dhcpv6_thread));
8296
8297 /* Is there a state change callback registered with the Client? */
8298 if ((dhcpv6_ptr -> nx_dhcpv6_state_change_callback) && (original_state != (dhcpv6_ptr -> nx_dhcpv6_state)))
8299 {
8300
8301 /* Yes, call the the state change callback with the original and new state. */
8302 (dhcpv6_ptr -> nx_dhcpv6_state_change_callback)(dhcpv6_ptr, original_state, dhcpv6_ptr -> nx_dhcpv6_state);
8303 }
8304
8305 /* Release the DHCPv6 Client mutex. */
8306 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
8307
8308 /* Return completion status. */
8309 return(status);
8310 }
8311
8312
8313 /**************************************************************************/
8314 /* */
8315 /* FUNCTION RELEASE */
8316 /* */
8317 /* _nx_dhcpv6_send_request PORTABLE C */
8318 /* 6.1.12 */
8319 /* AUTHOR */
8320 /* */
8321 /* Yuxin Zhou, Microsoft Corporation */
8322 /* */
8323 /* DESCRIPTION */
8324 /* */
8325 /* This function sends a DHCPV6 request to the server. All options */
8326 /* required for each Client DHCPv6 message are compiled into the Client */
8327 /* request package. Since each message must have a unique transaction */
8328 /* ID, it is up to the caller to set the Client transaction ID in the */
8329 /* Client record before calling this service. The server reply must */
8330 /* contain the matching message transaction ID for each message type the*/
8331 /* Client sends it. This function will check for invalid message types. */
8332 /* */
8333 /* To send a message, the Client allocates a packet from its own packet */
8334 /* pool. It then must set the IPv6 packet interface depending if the */
8335 /* Client has a valid global IP address or is using its link local */
8336 /* address till it can get a global IP address. It can send the packet */
8337 /* either to all servers on its network or include server and relays */
8338 /* (user configurable). */
8339 /* */
8340 /* INPUT */
8341 /* */
8342 /* dhcpv6_ptr Pointer to DHCPV6 Client */
8343 /* */
8344 /* OUTPUT */
8345 /* */
8346 /* status Actual completion status */
8347 /* NX_DHCPV6_ILLEGAL_MESSAGE_TYPE Illegal message type to send */
8348 /* */
8349 /* CALLS */
8350 /* */
8351 /* nx_packet_allocate Allocate a DHCPV6 packet */
8352 /* nx_packet_release Release DHCPV6 packet */
8353 /* nx_udp_socket_send Send DHCPV6 packet */
8354 /* _nx_dhcpv6_add_client_duid Add Client DUID to request */
8355 /* _nx_dhcpv6_add_server_duid Add server DUID to request */
8356 /* _nx_dhcpv6_add_elapsed_time Add elapsed time option */
8357 /* _nx_dhcpv6_add_iana Add IANA option to request */
8358 /* _nx_dhcpv6_add_ia_address Add IA address option */
8359 /* _nx_dhcpv6_add_option_request Add option request option */
8360 /* memcpy Copy specified area of memory */
8361 /* */
8362 /* CALLED BY */
8363 /* */
8364 /* _nx_dhcpv6_process Process DHCPv6 client request */
8365 /* _nx_dhcpv6_waiting_on_reply Process replies to valid server*/
8366 /* reply received */
8367 /* RELEASE HISTORY */
8368 /* */
8369 /* DATE NAME DESCRIPTION */
8370 /* */
8371 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8372 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
8373 /* packet length verification, */
8374 /* verified memcpy use cases, */
8375 /* fixed compiler warnings, */
8376 /* resulting in version 6.1 */
8377 /* 07-29-2022 Yuxin Zhou Modified comment(s), supported*/
8378 /* adding user options, */
8379 /* resulting in version 6.1.12 */
8380 /* */
8381 /**************************************************************************/
_nx_dhcpv6_send_request(NX_DHCPV6 * dhcpv6_ptr)8382 UINT _nx_dhcpv6_send_request(NX_DHCPV6 *dhcpv6_ptr)
8383 {
8384
8385 NX_PACKET *packet_ptr;
8386 UCHAR *buffer;
8387 UINT status;
8388 ULONG message_word;
8389 UINT index;
8390 NX_INTERFACE *interface_ptr;
8391 NXD_IPV6_ADDRESS *ipv6_address;
8392 ULONG available_payload;
8393 UCHAR *user_option_ptr;
8394 UINT user_option_length;
8395
8396
8397 /* Initialize local variables. */
8398 index = 0;
8399
8400 /* Check for invalid or illegal message type. */
8401 if ((dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_ADVERTISE) ||
8402 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_REPLY) ||
8403 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == NX_DHCPV6_MESSAGE_TYPE_RECONFIGURE) ||
8404 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type > NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST) ||
8405 (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type == 0))
8406 {
8407
8408 /* Return error status. */
8409 return NX_DHCPV6_ILLEGAL_MESSAGE_TYPE;
8410 }
8411
8412 /* Allocate a DHCPV6 packet. */
8413 status = nx_packet_allocate(dhcpv6_ptr -> nx_dhcpv6_pool_ptr, &packet_ptr, NX_IPv6_UDP_PACKET, NX_DHCPV6_PACKET_TIME_OUT);
8414
8415 /* Was the packet allocation successful? */
8416 if (status != NX_SUCCESS)
8417 {
8418
8419 /* Return status. */
8420 return(status);
8421 }
8422
8423 /* Verify packet payload. */
8424 if ((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 4)
8425 {
8426 nx_packet_release(packet_ptr);
8427 return(NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD);
8428 }
8429
8430 /* Indicate this is an IPv6 packet. */
8431 packet_ptr -> nx_packet_ip_version = NX_IP_VERSION_V6;
8432
8433 /* Setup the buffer pointer. */
8434 buffer = packet_ptr -> nx_packet_prepend_ptr;
8435
8436 /* Use the message id value to judge whether the next packet is retransmit packet or not.
8437 If the id value is 0, indicate the new dhcpv6 request, then generate a random number, else,leave the transaction ID unchanged.
8438 A client MUST leave the transaction ID unchanged in retransmissions of a message,RFC3315,section 15.1,page 28. */
8439 if(dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid == 0)
8440 {
8441
8442 /* Generate "random" transaction ID using physical address and a random factor for each request
8443 to the Server. The Server must include a matching transaction ID in its reply. */
8444 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid =
8445 ((dhcpv6_ptr -> nx_dhcpv6_ip_ptr -> nx_ip_arp_physical_address_msw) ^
8446 (dhcpv6_ptr -> nx_dhcpv6_ip_ptr -> nx_ip_arp_physical_address_lsw) ^
8447 (ULONG)(NX_RAND()));
8448
8449 /* Now reduce it to three bytes. */
8450 dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid = (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid & (ULONG)(0x0ffffff));
8451 }
8452
8453 /* Clear memory to make the message header. */
8454 memset(&message_word, 0, sizeof(ULONG));
8455
8456 /* Add the message type and transaction ID as the DHCPv6 header fields. */
8457 message_word = (((ULONG)(dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type)) << 24);
8458
8459 message_word |= (((ULONG)(0x0ffffff)) & (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid));
8460
8461 /* Adjust for endianness. */
8462 NX_CHANGE_ULONG_ENDIAN(message_word);
8463
8464 /* Copy the message header to the packet buffer. */
8465 memcpy(buffer, &message_word, 4); /* Use case of memcpy is verified. */
8466
8467 /* Update the buffer 'pointer'. */
8468 index += (ULONG)sizeof(ULONG);
8469
8470 /* Add the Client DUID to the packet buffer. */
8471 status = _nx_dhcpv6_add_client_duid(dhcpv6_ptr, buffer, &index);
8472
8473 /* Check for error. */
8474 if(status != NX_SUCCESS)
8475 {
8476
8477 nx_packet_release(packet_ptr);
8478
8479 return status;
8480 }
8481
8482 /* Determine if any additional options need to be added relative to the DHCPV6 message type. */
8483 switch (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type)
8484 {
8485
8486 case NX_DHCPV6_MESSAGE_TYPE_SOLICIT:
8487 {
8488 /* Append the IA-NA option and depending on host state. */
8489 status = _nx_dhcpv6_add_iana(dhcpv6_ptr, buffer, &index);
8490
8491 /* Check for internal errors. */
8492 if (status != NX_SUCCESS)
8493 {
8494
8495 nx_packet_release(packet_ptr);
8496
8497 /* Return the error status and abort. */
8498 return status;
8499 }
8500
8501 /* Compute the session time so far and add an elapsed time option. */
8502 status = _nx_dhcpv6_add_elapsed_time(dhcpv6_ptr, buffer, &index);
8503
8504 /* Check for internal errors. */
8505 if (status != NX_SUCCESS)
8506 {
8507
8508 nx_packet_release(packet_ptr);
8509
8510 /* Return the error status and abort. */
8511 return status;
8512 }
8513
8514 /* Did the Client ask for a DHCPv6 Client FQDN option ?
8515 A client MUST only include the Client FQDN option in SOLICIT, REQUEST, RENEW, or REBIND messsage. */
8516 if (dhcpv6_ptr ->nx_dhcpv6_client_FQDN.nx_op_code)
8517 {
8518
8519 /* Add the option request. */
8520 status = _nx_dhcpv6_add_client_FQDN(dhcpv6_ptr, buffer, &index);
8521
8522 /* Check for internal error. */
8523 if (status != NX_SUCCESS)
8524 {
8525
8526 nx_packet_release(packet_ptr);
8527
8528 /* Return the error status and abort. */
8529 return status;
8530 }
8531 }
8532
8533 /* Did the Client ask for a requested option? */
8534 if (dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request)
8535 {
8536
8537 /* Add the option request. */
8538 status = _nx_dhcpv6_add_option_request(dhcpv6_ptr, buffer, &index);
8539
8540 /* Check for internal error. */
8541 if (status != NX_SUCCESS)
8542 {
8543
8544 nx_packet_release(packet_ptr);
8545
8546 /* Return the error status and abort. */
8547 return status;
8548 }
8549 }
8550
8551 /* Did the Client ask for rapid commit option? */
8552 if (dhcpv6_ptr -> nx_dhcpv6_request_solicit_mode == NX_DHCPV6_SOLICIT_RAPID)
8553 {
8554
8555 /* Compute the available payload for DHCP data in the packet buffer. */
8556 available_payload = (ULONG)(dhcpv6_ptr -> nx_dhcpv6_pool_ptr -> nx_packet_pool_payload_size -
8557 sizeof(NX_IPV6_HEADER) - sizeof(NX_UDP_HEADER) - index);
8558
8559 /* Check if the data will fit in the packet buffer. */
8560 if (available_payload < sizeof(ULONG))
8561 {
8562
8563 /* Hmmm... not enough! Can't do it. */
8564 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
8565 }
8566
8567 /* Add the rapid commit option request. */
8568 /* Clear memory to make the message header, and add the message type. */
8569 memset(&message_word, 0, sizeof(ULONG));
8570
8571 /* Add the message type. */
8572 message_word = (((ULONG)NX_DHCPV6_OP_RAPID_COMMIT) << 16);
8573
8574 /* Adjust for endianness. */
8575 NX_CHANGE_ULONG_ENDIAN(message_word);
8576
8577 /* Copy the message to the packet buffer. */
8578 memcpy((buffer + index), &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
8579
8580 /* Update the index. */
8581 index += (ULONG)sizeof(ULONG);
8582 }
8583
8584 /* Increment the number of Solicit messages sent. */
8585 dhcpv6_ptr -> nx_dhcpv6_solicitations_sent++;
8586
8587 break;
8588 }
8589
8590 case NX_DHCPV6_MESSAGE_TYPE_REQUEST:
8591 {
8592 /* Compute the session time so far and add an elapsed time option. */
8593 status = _nx_dhcpv6_add_elapsed_time(dhcpv6_ptr, buffer, &index);
8594
8595 /* Check for internal error. */
8596 if (status != NX_SUCCESS)
8597 {
8598
8599 nx_packet_release(packet_ptr);
8600
8601 /* Return error status. */
8602 return status;
8603 }
8604
8605 /* Add the server DUID just extracted from the Server Advertise message. */
8606 status = _nx_dhcpv6_add_server_duid(dhcpv6_ptr, buffer, &index);
8607
8608 /* Check for internal error. */
8609 if (status != NX_SUCCESS)
8610 {
8611
8612 nx_packet_release(packet_ptr);
8613
8614 /* Return error status. */
8615 return status;
8616 }
8617
8618 /* Append an IA-NA with the IA address option received from server added to the IA-NA option. */
8619 status = _nx_dhcpv6_add_iana(dhcpv6_ptr, buffer, &index);
8620
8621 /* Check for internal error. */
8622 if (status != NX_SUCCESS)
8623 {
8624
8625 nx_packet_release(packet_ptr);
8626
8627 /* Return error status. */
8628 return status;
8629 }
8630
8631 /* Did the Client ask for a DHCPv6 Client FQDN option ?
8632 A client MUST only include the Client FQDN option in SOLICIT, REQUEST, RENEW, or REBIND messsage. */
8633 if (dhcpv6_ptr ->nx_dhcpv6_client_FQDN.nx_op_code)
8634 {
8635
8636 /* Add the option request. */
8637 status = _nx_dhcpv6_add_client_FQDN(dhcpv6_ptr, buffer, &index);
8638
8639 /* Check for internal error. */
8640 if (status != NX_SUCCESS)
8641 {
8642
8643 nx_packet_release(packet_ptr);
8644
8645 /* Return the error status and abort. */
8646 return status;
8647 }
8648 }
8649
8650 /* Did the Client ask for a requested option? */
8651 if (dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request)
8652 {
8653 /* Add the server DUID just extracted from the Server Advertise message. */
8654 status = _nx_dhcpv6_add_option_request(dhcpv6_ptr, buffer, &index);
8655
8656 /* Check for internal error. */
8657 if (status != NX_SUCCESS)
8658 {
8659
8660 nx_packet_release(packet_ptr);
8661
8662 /* Return error status. */
8663 return status;
8664 }
8665 }
8666
8667 /* Increment the number of Request messages sent. */
8668 dhcpv6_ptr -> nx_dhcpv6_requests_sent++;
8669
8670 break;
8671 }
8672
8673 case NX_DHCPV6_MESSAGE_TYPE_RENEW:
8674 {
8675 /* Compute the session time so far and add an elapsed time option. */
8676 status = _nx_dhcpv6_add_elapsed_time(dhcpv6_ptr, buffer, &index);
8677
8678 /* Check for internal error. */
8679 if (status != NX_SUCCESS)
8680 {
8681
8682 nx_packet_release(packet_ptr);
8683
8684 /* Return error status. */
8685 return status;
8686 }
8687
8688 /* Add the server DUID just extracted from the Server Advertise message. */
8689 status = _nx_dhcpv6_add_server_duid(dhcpv6_ptr, buffer, &index);
8690
8691 /* Check for internal error. */
8692 if (status != NX_SUCCESS)
8693 {
8694
8695 nx_packet_release(packet_ptr);
8696
8697 /* Return error status. */
8698 return status;
8699 }
8700
8701 status = _nx_dhcpv6_add_iana(dhcpv6_ptr, buffer, &index);
8702
8703 /* Check for internal errors. */
8704 if (status != NX_SUCCESS)
8705 {
8706
8707 nx_packet_release(packet_ptr);
8708
8709 /* Return the error status and abort. */
8710 return status;
8711 }
8712
8713 /* Did the Client ask for a DHCPv6 Client FQDN option ?
8714 A client MUST only include the Client FQDN option in SOLICIT, REQUEST, RENEW, or REBIND messsage. */
8715 if (dhcpv6_ptr ->nx_dhcpv6_client_FQDN.nx_op_code)
8716 {
8717
8718 /* Add the option request. */
8719 status = _nx_dhcpv6_add_client_FQDN(dhcpv6_ptr, buffer, &index);
8720
8721 /* Check for internal error. */
8722 if (status != NX_SUCCESS)
8723 {
8724
8725 nx_packet_release(packet_ptr);
8726
8727 /* Return the error status and abort. */
8728 return status;
8729 }
8730 }
8731
8732 /* A client MAY include an Option Request option in a Solicit, Request, Renew, Rebind, Confirm or Information-request
8733 message to inform the server about options the client wants the server to send to the client. RFC3315, Section22.7, Page78.*/
8734 if (dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request)
8735 {
8736 /* Add the server DUID just extracted from the Server Advertise message. */
8737 status = _nx_dhcpv6_add_option_request(dhcpv6_ptr, buffer, &index);
8738
8739 /* Check for internal error. */
8740 if (status != NX_SUCCESS)
8741 {
8742
8743 nx_packet_release(packet_ptr);
8744
8745 /* Return error status. */
8746 return status;
8747 }
8748 }
8749
8750 dhcpv6_ptr -> nx_dhcpv6_renews_sent++;
8751
8752 break;
8753 }
8754
8755 case NX_DHCPV6_MESSAGE_TYPE_REBIND:
8756 {
8757 /* Compute the session time so far and add an elapsed time option. */
8758 status = _nx_dhcpv6_add_elapsed_time(dhcpv6_ptr, buffer, &index);
8759
8760 /* Check for internal errors. */
8761 if (status != NX_SUCCESS)
8762 {
8763
8764 nx_packet_release(packet_ptr);
8765
8766 /* Return the error status and abort. */
8767 return status;
8768 }
8769
8770 /* Rebind message includes the current IA/IA-NA, current IA address. */
8771 status = _nx_dhcpv6_add_iana(dhcpv6_ptr, buffer, &index);
8772
8773 /* Check for internal errors. */
8774 if (status != NX_SUCCESS)
8775 {
8776
8777 nx_packet_release(packet_ptr);
8778
8779 /* Return the error status and abort. */
8780 return status;
8781 }
8782
8783 /* Did the Client ask for a DHCPv6 Client FQDN option ?
8784 A client MUST only include the Client FQDN option in SOLICIT, REQUEST, RENEW, or REBIND messsage. */
8785 if (dhcpv6_ptr ->nx_dhcpv6_client_FQDN.nx_op_code)
8786 {
8787
8788 /* Add the option request. */
8789 status = _nx_dhcpv6_add_client_FQDN(dhcpv6_ptr, buffer, &index);
8790
8791 /* Check for internal error. */
8792 if (status != NX_SUCCESS)
8793 {
8794
8795 nx_packet_release(packet_ptr);
8796
8797 /* Return the error status and abort. */
8798 return status;
8799 }
8800 }
8801
8802 /* Did the Client ask for a requested option? */
8803 if (dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request)
8804 {
8805
8806 /* Add the server DUID just extracted from the Server Advertise message. */
8807 status = _nx_dhcpv6_add_option_request(dhcpv6_ptr, buffer, &index);
8808
8809 /* Check for internal errors. */
8810 if (status != NX_SUCCESS)
8811 {
8812
8813 nx_packet_release(packet_ptr);
8814
8815 /* Return the error status and abort. */
8816 return status;
8817 }
8818 }
8819
8820 /* Increment the number of Solicit messages sent. */
8821 dhcpv6_ptr -> nx_dhcpv6_rebinds_sent++;
8822
8823 break;
8824 }
8825
8826 case NX_DHCPV6_MESSAGE_TYPE_CONFIRM:
8827 {
8828 /* Compute the session time so far and add an elapsed time option. */
8829 status = _nx_dhcpv6_add_elapsed_time(dhcpv6_ptr, buffer, &index);
8830
8831 /* Check for internal errors. */
8832 if (status != NX_SUCCESS)
8833 {
8834
8835 nx_packet_release(packet_ptr);
8836
8837 /* Return the error status and abort. */
8838 return status;
8839 }
8840
8841 /* Rebind message includes the current IA/IA-NA, current IA address. */
8842 status = _nx_dhcpv6_add_iana(dhcpv6_ptr, buffer, &index);
8843
8844 /* Check for internal errors. */
8845 if (status != NX_SUCCESS)
8846 {
8847
8848 /* Return the error status and abort. */
8849 return status;
8850 }
8851
8852 /* A client MAY include an Option Request option in a Solicit, Request, Renew, Rebind, Confirm or Information-request
8853 message to inform the server about options the client wants the server to send to the client. RFC3315, Section22.7, Page78.*/
8854 if (dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request)
8855 {
8856 /* Add the server DUID just extracted from the Server Advertise message. */
8857 status = _nx_dhcpv6_add_option_request(dhcpv6_ptr, buffer, &index);
8858
8859 /* Check for internal error. */
8860 if (status != NX_SUCCESS)
8861 {
8862
8863 nx_packet_release(packet_ptr);
8864
8865 /* Return error status. */
8866 return status;
8867 }
8868 }
8869
8870 /* Increment the number of Solicit messages sent. */
8871 dhcpv6_ptr -> nx_dhcpv6_confirms_sent++;
8872
8873 break;
8874 }
8875
8876 case NX_DHCPV6_MESSAGE_TYPE_DECLINE:
8877 {
8878
8879 /* Add the server DUID just extracted from the Server Advertise message. */
8880 status = _nx_dhcpv6_add_server_duid(dhcpv6_ptr, buffer, &index);
8881
8882 /* Check for internal error. */
8883 if (status != NX_SUCCESS)
8884 {
8885
8886 nx_packet_release(packet_ptr);
8887
8888 /* Return error status. */
8889 return status;
8890 }
8891
8892 /* Compute the session time so far and add an elapsed time option. */
8893 status = _nx_dhcpv6_add_elapsed_time(dhcpv6_ptr, buffer, &index);
8894
8895 /* Check for internal errors. */
8896 if (status != NX_SUCCESS)
8897 {
8898
8899 /* Return the error status and abort. */
8900 return status;
8901 }
8902
8903 /* Decling the message in the current IA/IA-NA, current IA address. */
8904 status = _nx_dhcpv6_add_iana(dhcpv6_ptr, buffer, &index);
8905
8906 /* Check for internal errors. */
8907 if (status != NX_SUCCESS)
8908 {
8909
8910 nx_packet_release(packet_ptr);
8911
8912 /* Return the error status and abort. */
8913 return status;
8914 }
8915
8916 /* Increment the number of Decline messages sent. */
8917 dhcpv6_ptr -> nx_dhcpv6_declines_sent++;
8918
8919 break;
8920 }
8921
8922 case NX_DHCPV6_MESSAGE_TYPE_RELEASE:
8923 {
8924
8925 /* Add the server DUID just extracted from the Server Advertise message. */
8926 status = _nx_dhcpv6_add_server_duid(dhcpv6_ptr, buffer, &index);
8927
8928 /* Check for internal error. */
8929 if (status != NX_SUCCESS)
8930 {
8931
8932 nx_packet_release(packet_ptr);
8933
8934 /* Return error status. */
8935 return status;
8936 }
8937
8938 /* Compute the session time so far and add an elapsed time option. */
8939 status = _nx_dhcpv6_add_elapsed_time(dhcpv6_ptr, buffer, &index);
8940
8941 /* Check for internal errors. */
8942 if (status != NX_SUCCESS)
8943 {
8944
8945 nx_packet_release(packet_ptr);
8946
8947 /* Return the error status and abort. */
8948 return status;
8949 }
8950
8951 /* Decling the message in the current IA/IA-NA, current IA address. */
8952 status = _nx_dhcpv6_add_iana(dhcpv6_ptr, buffer, &index);
8953
8954 /* Check for internal errors. */
8955 if (status != NX_SUCCESS)
8956 {
8957
8958 nx_packet_release(packet_ptr);
8959
8960 /* Return the error status and abort. */
8961 return status;
8962 }
8963
8964 /* Increment the number of Releases messages sent. */
8965 dhcpv6_ptr -> nx_dhcpv6_releases_sent++;
8966
8967 break;
8968 }
8969
8970 case NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST:
8971 {
8972
8973 /* Did the Client ask for a requested option? */
8974 if (!dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request)
8975 {
8976
8977 /* No, so don't bother sending out the request. */
8978
8979 nx_packet_release(packet_ptr);
8980
8981 return NX_SUCCESS;
8982 }
8983
8984 /* Compute the session time so far and add an elapsed time option. */
8985 status = _nx_dhcpv6_add_elapsed_time(dhcpv6_ptr, buffer, &index);
8986
8987 /* Check for internal error. */
8988 if (status != NX_SUCCESS)
8989 {
8990
8991 nx_packet_release(packet_ptr);
8992
8993 /* Return error status. */
8994 return status;
8995 }
8996
8997 /* Did the Client ask for a requested option? */
8998 if (dhcpv6_ptr -> nx_dhcpv6_option_request.nx_op_request)
8999 {
9000 /* Add the server DUID just extracted from the Server Advertise message. */
9001 status = _nx_dhcpv6_add_option_request(dhcpv6_ptr, buffer, &index);
9002
9003 /* Check for internal error. */
9004 if (status != NX_SUCCESS)
9005 {
9006
9007 nx_packet_release(packet_ptr);
9008
9009 /* Return error status. */
9010 return status;
9011 }
9012 }
9013
9014 /* Increment the number of Inform Request messages sent. */
9015 dhcpv6_ptr -> nx_dhcpv6_inform_req_sent++;
9016
9017 break;
9018 }
9019
9020 default:
9021 {
9022 nx_packet_release(packet_ptr);
9023
9024 return NX_DHCPV6_UNKNOWN_MSG_TYPE;
9025 }
9026 }
9027
9028 /* Add any user supplied options to the buffer. */
9029 if (dhcpv6_ptr -> nx_dhcpv6_user_option_add)
9030 {
9031
9032 /* Set the pointer for adding user option. */
9033 user_option_ptr = buffer + index;
9034
9035 /* Calculate the available length for user options. */
9036 user_option_length = (UINT)(packet_ptr -> nx_packet_data_end - user_option_ptr);
9037
9038 /* Add the specific DHCP option user wanted. */
9039 if (dhcpv6_ptr -> nx_dhcpv6_user_option_add(dhcpv6_ptr, dhcpv6_ptr -> nx_dhcpv6_client_interface_index, dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type, user_option_ptr, &user_option_length) == NX_TRUE)
9040 {
9041
9042 /* Update the index to include the user options. */
9043 index += user_option_length;
9044 }
9045 else
9046 {
9047
9048 /* Invalid user options. Release the packet. */
9049 nx_packet_release(packet_ptr);
9050 return(NX_DHCPV6_UNKNOWN_OPTION);
9051 }
9052 }
9053
9054 /* Setup the packet pointers. */
9055 packet_ptr -> nx_packet_length = index;
9056
9057 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + index;
9058
9059 /* Select Client Source address:
9060 1. When a client sends a DHCP message to the All_DHCP_Relay_Agents_and_Servers address,
9061 the client must use a link-local address assigned to the interface for which it
9062 is requesting configuration as the source address.
9063 2. When a client sends a DHCP message directly to a server using unicast,
9064 the source address must be an address assigned to the interface for which the
9065 client is interested in obtaining configuration.
9066 RFC 3315, Section 16. Client Source Address and Interface Selection, Page 32. */
9067
9068 /* Set the interface pointer. */
9069 interface_ptr = &(dhcpv6_ptr -> nx_dhcpv6_ip_ptr -> nx_ip_interface[dhcpv6_ptr ->nx_dhcpv6_client_interface_index]);
9070
9071 /* Check the destination address. */
9072 if (CHECK_IPV6_ADDRESSES_SAME(dhcpv6_ptr -> nx_dhcpv6_client_destination_address.nxd_ip_address.v6, All_DHCPv6_Relay_Servers_Address.nxd_ip_address.v6))
9073 {
9074
9075 /* Find the link-local address as source adress. Get first address from interface. */
9076 ipv6_address = interface_ptr -> nxd_interface_ipv6_address_list_head;
9077
9078 /* Loop to check the address. */
9079 while (ipv6_address)
9080 {
9081
9082 /* Check for a valid address. */
9083 if (ipv6_address -> nxd_ipv6_address_state != NX_IPV6_ADDR_STATE_VALID)
9084 {
9085 ipv6_address = ipv6_address -> nxd_ipv6_address_next;
9086 }
9087
9088 /* Check for link-local address. */
9089 else if (IPv6_Address_Type(ipv6_address -> nxd_ipv6_address) & IPV6_ADDRESS_LINKLOCAL)
9090 {
9091
9092 /* Find the Link-Local Address. */
9093 break;
9094 }
9095 else
9096 {
9097 ipv6_address = ipv6_address -> nxd_ipv6_address_next;
9098 }
9099 }
9100
9101 /* Check if found the link-local address. */
9102 if(ipv6_address == NX_NULL)
9103 {
9104
9105 /* No valid link-local address. */
9106 nx_packet_release(packet_ptr);
9107 return(NX_IP_ADDRESS_ERROR);
9108 }
9109 }
9110 else
9111 {
9112
9113 /* Find the source address. */
9114 status = _nxd_ipv6_interface_find(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, dhcpv6_ptr -> nx_dhcpv6_client_destination_address.nxd_ip_address.v6,
9115 &ipv6_address, interface_ptr);
9116
9117 /* Check if found the address. */
9118 if (status)
9119 {
9120
9121 /* No valid source address. */
9122 nx_packet_release(packet_ptr);
9123 return(NX_IP_ADDRESS_ERROR);
9124 }
9125 }
9126
9127 /* Send the packet out! */
9128 status = _nxd_udp_socket_source_send(&(dhcpv6_ptr -> nx_dhcpv6_socket), packet_ptr,
9129 &dhcpv6_ptr -> nx_dhcpv6_client_destination_address, NX_DHCPV6_SERVER_UDP_PORT,
9130 ipv6_address -> nxd_ipv6_address_index);
9131
9132 /* If an error is detected, the packet was not sent and we have to release the packet. */
9133 if (status != NX_SUCCESS)
9134 {
9135
9136 /* Release the packet. */
9137 nx_packet_release(packet_ptr);
9138 }
9139
9140 /* Return completion status. */
9141 return(status);
9142 }
9143
9144
9145 /**************************************************************************/
9146 /* */
9147 /* FUNCTION RELEASE */
9148 /* */
9149 /* _nx_dhcpv6_session_timeout_entry PORTABLE C */
9150 /* 6.1 */
9151 /* AUTHOR */
9152 /* */
9153 /* Yuxin Zhou, Microsoft Corporation */
9154 /* */
9155 /* DESCRIPTION */
9156 /* */
9157 /* This function updates the Client session duration time with the */
9158 /* Server. This information is used for the Elapsed Time data in DHCPv6*/
9159 /* Client messages sends to the server as part of the DHCPv6 protocol. */
9160 /* */
9161 /* INPUT */
9162 /* */
9163 /* dhcpv6_ptr_value Pointer to the DHCPV6 Client */
9164 /* */
9165 /* OUTPUT */
9166 /* */
9167 /* None */
9168 /* */
9169 /* CALLS */
9170 /* */
9171 /* None */
9172 /* */
9173 /* CALLED BY */
9174 /* */
9175 /* */
9176 /* RELEASE HISTORY */
9177 /* */
9178 /* DATE NAME DESCRIPTION */
9179 /* */
9180 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9181 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9182 /* resulting in version 6.1 */
9183 /* */
9184 /**************************************************************************/
_nx_dhcpv6_session_timeout_entry(ULONG dhcpv6_ptr_value)9185 VOID _nx_dhcpv6_session_timeout_entry(ULONG dhcpv6_ptr_value)
9186 {
9187
9188 NX_DHCPV6 *dhcpv6_ptr;
9189
9190
9191 /* Setup DHCPv6 Client pointer. */
9192 NX_TIMER_EXTENSION_PTR_GET(dhcpv6_ptr, NX_DHCPV6, dhcpv6_ptr_value)
9193
9194 /* Check the elapsed time, the time is expressed in hundredths of 1 second, 65500 is the largest time value. */
9195 if(dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time < 65500)
9196 {
9197
9198 /* Update the elapsed time of current DHCP session.
9199 This time is expressed in hundredths of a second. */
9200 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = (USHORT)(dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time + NX_DHCPV6_SESSION_TIMER_INTERVAL * 100);
9201 }
9202 else
9203 {
9204
9205 /* Set the value 0xFFFF to represent any elapsed time values greater than the largest time value . */
9206 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0xFFFF;
9207 }
9208 return;
9209 }
9210
9211 /**************************************************************************/
9212 /* */
9213 /* FUNCTION RELEASE */
9214 /* */
9215 /* _nxe_dhcpv6_set_time_accrued PORTABLE C */
9216 /* 6.1 */
9217 /* AUTHOR */
9218 /* */
9219 /* Yuxin Zhou, Microsoft Corporation */
9220 /* */
9221 /* DESCRIPTION */
9222 /* */
9223 /* This function performs error checking on the set time accrued on */
9224 /* Client IP lease service. */
9225 /* */
9226 /* INPUT */
9227 /* */
9228 /* dhcpv6_ptr Pointer to DHCPv6 Client */
9229 /* time_accrued Pointer to time since IP lease */
9230 /* assigned (secs) */
9231 /* */
9232 /* OUTPUT */
9233 /* */
9234 /* status Actual completion status */
9235 /* NX_PTR_ERROR Invalid pointer input */
9236 /* */
9237 /* CALLS */
9238 /* */
9239 /* _nx_dhcpv6_set_time_accrued Actual set time accrued on Client */
9240 /* IP address lease service */
9241 /* */
9242 /* CALLED BY */
9243 /* */
9244 /* Application Code */
9245 /* */
9246 /* RELEASE HISTORY */
9247 /* */
9248 /* DATE NAME DESCRIPTION */
9249 /* */
9250 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9251 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9252 /* resulting in version 6.1 */
9253 /* */
9254 /**************************************************************************/
_nxe_dhcpv6_set_time_accrued(NX_DHCPV6 * dhcpv6_ptr,ULONG time_accrued)9255 UINT _nxe_dhcpv6_set_time_accrued(NX_DHCPV6 *dhcpv6_ptr, ULONG time_accrued)
9256 {
9257
9258 UINT status;
9259
9260
9261 /* Check for valid pointer input. */
9262 if (!dhcpv6_ptr)
9263 {
9264 return NX_PTR_ERROR;
9265 }
9266
9267 /* Call the actual service. */
9268 status = _nx_dhcpv6_set_time_accrued(dhcpv6_ptr, time_accrued);
9269
9270 /* Return completion status. */
9271 return status;
9272 }
9273
9274
9275 /**************************************************************************/
9276 /* */
9277 /* FUNCTION RELEASE */
9278 /* */
9279 /* _nx_dhcpv6_set_time_accrued PORTABLE C */
9280 /* 6.1 */
9281 /* AUTHOR */
9282 /* */
9283 /* Yuxin Zhou, Microsoft Corporation */
9284 /* */
9285 /* DESCRIPTION */
9286 /* */
9287 /* This function enables the host to set the time accrued on the */
9288 /* Client's IP address lease. The caller must first suspend the */
9289 /* DHCPv6 Client using the nx_dhcpv6_suspend service before using this */
9290 /* service. */
9291 /* */
9292 /* INPUT */
9293 /* */
9294 /* dhcpv6_ptr Pointer to DHCPv6 Client */
9295 /* time_accrued Pointer to time to set the */
9296 /* lient accrued time (secs) */
9297 /* */
9298 /* OUTPUT */
9299 /* */
9300 /* NX_SUCCESS Successful completion status */
9301 /* */
9302 /* CALLS */
9303 /* */
9304 /* None */
9305 /* */
9306 /* CALLED BY */
9307 /* */
9308 /* Application */
9309 /* */
9310 /* RELEASE HISTORY */
9311 /* */
9312 /* DATE NAME DESCRIPTION */
9313 /* */
9314 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9315 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9316 /* resulting in version 6.1 */
9317 /* */
9318 /**************************************************************************/
_nx_dhcpv6_set_time_accrued(NX_DHCPV6 * dhcpv6_ptr,ULONG time_accrued)9319 UINT _nx_dhcpv6_set_time_accrued(NX_DHCPV6 *dhcpv6_ptr, ULONG time_accrued)
9320 {
9321
9322
9323 /* Check if the DHCPv6 Client has been started. */
9324 if (dhcpv6_ptr -> nx_dhcpv6_started)
9325 {
9326 /* It has. We cannot set the time accrued if the DHCPv6 client thread is running. */
9327 return NX_DHCPV6_ALREADY_STARTED;
9328 }
9329
9330 /* Set the time accrued on the Client IP address lease. */
9331 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = time_accrued;
9332
9333 /* Return successful completion. */
9334 return NX_SUCCESS;
9335 }
9336
9337
9338 /**************************************************************************/
9339 /* */
9340 /* FUNCTION RELEASE */
9341 /* */
9342 /* _nxe_dhcpv6_client_set_interface PORTABLE C */
9343 /* 6.1 */
9344 /* AUTHOR */
9345 /* */
9346 /* Yuxin Zhou, Microsoft Corporation */
9347 /* */
9348 /* DESCRIPTION */
9349 /* */
9350 /* This function performs error checking on the set client interface */
9351 /* service. */
9352 /* */
9353 /* INPUT */
9354 /* */
9355 /* dhcpv6_ptr Pointer to DHCPv6 Client */
9356 /* interface_index Index for DHCP network interface*/
9357 /* */
9358 /* OUTPUT */
9359 /* */
9360 /* status Actual completion status */
9361 /* NX_PTR_ERROR Invalid pointer input */
9362 /* NX_INVALID_INTERFACE Invalid interface index input */
9363 /* */
9364 /* CALLS */
9365 /* */
9366 /* _nx_dhcpv6_client_set_interface Actual set interface service */
9367 /* */
9368 /* CALLED BY */
9369 /* */
9370 /* Application Code */
9371 /* */
9372 /* RELEASE HISTORY */
9373 /* */
9374 /* DATE NAME DESCRIPTION */
9375 /* */
9376 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9377 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9378 /* resulting in version 6.1 */
9379 /* */
9380 /**************************************************************************/
_nxe_dhcpv6_client_set_interface(NX_DHCPV6 * dhcpv6_ptr,UINT interface_index)9381 UINT _nxe_dhcpv6_client_set_interface(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index)
9382 {
9383
9384 UINT status;
9385
9386
9387 /* Check for valid pointer input. */
9388 if (!dhcpv6_ptr)
9389 {
9390 return NX_PTR_ERROR;
9391 }
9392
9393 /* Check for an invalid interface specified. */
9394 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
9395 {
9396 return NX_INVALID_INTERFACE;
9397 }
9398
9399 /* Call the actual service. */
9400 status = _nx_dhcpv6_client_set_interface(dhcpv6_ptr, interface_index);
9401
9402 /* Return completion status. */
9403 return status;
9404 }
9405
9406
9407 /**************************************************************************/
9408 /* */
9409 /* FUNCTION RELEASE */
9410 /* */
9411 /* _nx_dhcpv6_client_set_interface PORTABLE C */
9412 /* 6.1 */
9413 /* AUTHOR */
9414 /* */
9415 /* Yuxin Zhou, Microsoft Corporation */
9416 /* */
9417 /* DESCRIPTION */
9418 /* */
9419 /* This function specifies the physical interface for DHCP */
9420 /* communications with the server in NetX Duo environments that support*/
9421 /* mult-homed hosts. */
9422 /* */
9423 /* INPUT */
9424 /* */
9425 /* dhcpv6_ptr Pointer to DHCPv6 Client */
9426 /* interface_index Index for DHCP network interface*/
9427 /* */
9428 /* OUTPUT */
9429 /* */
9430 /* NX_SUCCESS Successful completion status */
9431 /* NX_NOT_ENABLED NetXDuo version does not support*/
9432 /* multiple network interfaces */
9433 /* */
9434 /* CALLS */
9435 /* */
9436 /* None */
9437 /* */
9438 /* CALLED BY */
9439 /* */
9440 /* Application */
9441 /* */
9442 /* RELEASE HISTORY */
9443 /* */
9444 /* DATE NAME DESCRIPTION */
9445 /* */
9446 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9447 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9448 /* resulting in version 6.1 */
9449 /* */
9450 /**************************************************************************/
_nx_dhcpv6_client_set_interface(NX_DHCPV6 * dhcpv6_ptr,UINT interface_index)9451 UINT _nx_dhcpv6_client_set_interface(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index)
9452 {
9453
9454
9455 /* Set the client interface. */
9456 dhcpv6_ptr -> nx_dhcpv6_client_interface_index = interface_index;
9457
9458 /* Return successful completion. */
9459 return NX_SUCCESS;
9460 }
9461
9462
9463 /**************************************************************************/
9464 /* */
9465 /* FUNCTION RELEASE */
9466 /* */
9467 /* _nxe_dhcpv6_client_set_destination_address PORTABLE C */
9468 /* 6.1 */
9469 /* AUTHOR */
9470 /* */
9471 /* Yuxin Zhou, Microsoft Corporation */
9472 /* */
9473 /* DESCRIPTION */
9474 /* */
9475 /* This function performs error checking on the set destination */
9476 /* address service. */
9477 /* */
9478 /* INPUT */
9479 /* */
9480 /* dhcpv6_ptr Pointer to DHCPv6 Client */
9481 /* destination_address Destination address */
9482 /* */
9483 /* OUTPUT */
9484 /* */
9485 /* status Actual completion status */
9486 /* NX_PTR_ERROR Invalid pointer input */
9487 /* */
9488 /* CALLS */
9489 /* */
9490 /* _nx_dhcpv6_client_set_destination_address */
9491 /* Actual set address service */
9492 /* */
9493 /* CALLED BY */
9494 /* */
9495 /* Application Code */
9496 /* */
9497 /* RELEASE HISTORY */
9498 /* */
9499 /* DATE NAME DESCRIPTION */
9500 /* */
9501 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9502 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9503 /* resulting in version 6.1 */
9504 /* */
9505 /**************************************************************************/
_nxe_dhcpv6_client_set_destination_address(NX_DHCPV6 * dhcpv6_ptr,NXD_ADDRESS * destination_address)9506 UINT _nxe_dhcpv6_client_set_destination_address(NX_DHCPV6 *dhcpv6_ptr, NXD_ADDRESS *destination_address)
9507 {
9508
9509 UINT status;
9510
9511
9512 /* Check for invalid input pointer. */
9513 if ((dhcpv6_ptr == NX_NULL) || (dhcpv6_ptr -> nx_dhcpv6_id != NX_DHCPV6_ID))
9514 {
9515 return(NX_PTR_ERROR);
9516 }
9517
9518 /* Check for an invalid address type. */
9519 if (destination_address -> nxd_ip_version != NX_IP_VERSION_V6)
9520 {
9521
9522 /* Invalid address type. */
9523 return(NX_DHCPV6_PARAM_ERROR);
9524 }
9525
9526 /* Check if the server address is unspecified (::). */
9527 if(CHECK_UNSPECIFIED_ADDRESS(destination_address -> nxd_ip_address.v6))
9528 {
9529
9530 /* Null address input. */
9531 return(NX_DHCPV6_PARAM_ERROR);
9532 }
9533
9534 /* Call the actual service. */
9535 status = _nx_dhcpv6_client_set_destination_address(dhcpv6_ptr, destination_address);
9536
9537 /* Return completion status. */
9538 return(status);
9539 }
9540
9541
9542 /**************************************************************************/
9543 /* */
9544 /* FUNCTION RELEASE */
9545 /* */
9546 /* _nx_dhcpv6_client_set_destination_address PORTABLE C */
9547 /* 6.1 */
9548 /* AUTHOR */
9549 /* */
9550 /* Yuxin Zhou, Microsoft Corporation */
9551 /* */
9552 /* DESCRIPTION */
9553 /* */
9554 /* This function set the destination address where DHCP message should */
9555 /* be sent. By default is All_DHCP_Relay_Agents_and_Servers(FF02::1:2).*/
9556 /* */
9557 /* INPUT */
9558 /* */
9559 /* dhcpv6_ptr Pointer to DHCPv6 Client */
9560 /* destination_address Destination address */
9561 /* */
9562 /* OUTPUT */
9563 /* */
9564 /* NX_SUCCESS Successful completion status */
9565 /* */
9566 /* CALLS */
9567 /* */
9568 /* None */
9569 /* */
9570 /* CALLED BY */
9571 /* */
9572 /* Application */
9573 /* */
9574 /* RELEASE HISTORY */
9575 /* */
9576 /* DATE NAME DESCRIPTION */
9577 /* */
9578 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9579 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9580 /* resulting in version 6.1 */
9581 /* */
9582 /**************************************************************************/
_nx_dhcpv6_client_set_destination_address(NX_DHCPV6 * dhcpv6_ptr,NXD_ADDRESS * destination_address)9583 UINT _nx_dhcpv6_client_set_destination_address(NX_DHCPV6 *dhcpv6_ptr, NXD_ADDRESS *destination_address)
9584 {
9585
9586
9587 /* Get the DHCP mutex. */
9588 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_WAIT_FOREVER);
9589
9590 /* Set the destination address. */
9591 COPY_NXD_ADDRESS(destination_address, &(dhcpv6_ptr -> nx_dhcpv6_client_destination_address));
9592
9593 /* Release the DHCPv6 Client mutex. */
9594 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
9595
9596 /* Return successful completion. */
9597 return NX_SUCCESS;
9598 }
9599
9600
9601 /**************************************************************************/
9602 /* */
9603 /* FUNCTION RELEASE */
9604 /* */
9605 /* _nxe_dhcpv6_start PORTABLE C */
9606 /* 6.1 */
9607 /* AUTHOR */
9608 /* */
9609 /* Yuxin Zhou, Microsoft Corporation */
9610 /* */
9611 /* DESCRIPTION */
9612 /* */
9613 /* This function performs error checking on the NetX start the dhcpv6 */
9614 /* client service. */
9615 /* */
9616 /* INPUT */
9617 /* */
9618 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
9619 /* */
9620 /* OUTPUT */
9621 /* */
9622 /* status Completion status */
9623 /* NX_PTR_ERROR Invalid pointer input */
9624 /* */
9625 /* */
9626 /* CALLS */
9627 /* */
9628 /* _nx_dhcpv6_start Actual DHCPV6 start function */
9629 /* */
9630 /* CALLED BY */
9631 /* */
9632 /* Application Code */
9633 /* */
9634 /* RELEASE HISTORY */
9635 /* */
9636 /* DATE NAME DESCRIPTION */
9637 /* */
9638 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9639 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9640 /* resulting in version 6.1 */
9641 /* */
9642 /**************************************************************************/
_nxe_dhcpv6_start(NX_DHCPV6 * dhcpv6_ptr)9643 UINT _nxe_dhcpv6_start(NX_DHCPV6 *dhcpv6_ptr)
9644 {
9645
9646 UINT status;
9647
9648
9649 /* Check for invalid input pointer. */
9650 if ((dhcpv6_ptr == NX_NULL) || (dhcpv6_ptr -> nx_dhcpv6_id != NX_DHCPV6_ID))
9651 {
9652 return(NX_PTR_ERROR);
9653 }
9654
9655 /* Check for appropriate caller. */
9656 NX_THREADS_ONLY_CALLER_CHECKING
9657
9658 /* Call actual DHCPV6 start service. */
9659 status = _nx_dhcpv6_start(dhcpv6_ptr);
9660
9661 /* Return status. */
9662 return(status);
9663 }
9664
9665
9666 /**************************************************************************/
9667 /* */
9668 /* FUNCTION RELEASE */
9669 /* */
9670 /* _nx_dhcpv6_start PORTABLE C */
9671 /* 6.1 */
9672 /* AUTHOR */
9673 /* */
9674 /* Yuxin Zhou, Microsoft Corporation */
9675 /* */
9676 /* DESCRIPTION */
9677 /* */
9678 /* This function starts the DHCPV6 processing thread and readies the */
9679 /* DHCPv6 Client to initiate DHCPv6 requests. The Client state is set */
9680 /* to INIT and awaits the host application requesting a DHCPv6 meesage */
9681 /* sent e.g. the SOLICIT message. For hosts binding (or attempting to */
9682 /* obtain) a IP address in a previous session, this will clear session */
9683 /* parameters such as accrued lease time and message retry count. */
9684 /* */
9685 /* INPUT */
9686 /* */
9687 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
9688 /* */
9689 /* OUTPUT */
9690 /* */
9691 /* status Completion status */
9692 /* NX_DHCPV6_ALREADY_STARTED DHCPv6 Client already started */
9693 /* NX_DHCPV6_MISSING_REQUIRED_OPTIONS Client missing required options */
9694 /* */
9695 /* CALLS */
9696 /* */
9697 /* nx_udp_socket_create Create the Client UDP socket */
9698 /* nx_udp_socket_bind Bind the Client socket */
9699 /* nx_udp_socket_unbind Unbind the Client socket */
9700 /* tx_timer_activate Activate Client timers */
9701 /* tx_timer_deactivate Deactivate Client timers */
9702 /* tx_thread_resume Resume Client thread task */
9703 /* */
9704 /* CALLED BY */
9705 /* */
9706 /* Application Code */
9707 /* */
9708 /* RELEASE HISTORY */
9709 /* */
9710 /* DATE NAME DESCRIPTION */
9711 /* */
9712 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9713 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9714 /* resulting in version 6.1 */
9715 /* */
9716 /**************************************************************************/
_nx_dhcpv6_start(NX_DHCPV6 * dhcpv6_ptr)9717 UINT _nx_dhcpv6_start(NX_DHCPV6 *dhcpv6_ptr)
9718 {
9719
9720 UINT status;
9721
9722
9723 /* Get the DHCP mutex. */
9724 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
9725
9726 /* Determine if DHCPV6 has already been started. */
9727 if (dhcpv6_ptr -> nx_dhcpv6_started)
9728 {
9729
9730 /* Release the DHCPv6 Client mutex. */
9731 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
9732
9733 /* Error, the DHCPV6 client has already been started. */
9734 return(NX_DHCPV6_ALREADY_STARTED);
9735 }
9736
9737 /* Determine if Client has created its DUID and IANA yet. */
9738 if ((dhcpv6_ptr -> nx_dhcpv6_ip_ptr == NX_NULL) ||
9739 (dhcpv6_ptr -> nx_dhcpv6_client_duid.nx_option_length == 0) ||
9740 (dhcpv6_ptr -> nx_dhcpv6_iana.nx_option_length == 0))
9741 {
9742
9743 /* Release the DHCPv6 Client mutex. */
9744 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
9745
9746 /* No, this DHCPv6 Client is not ready to run! */
9747 return NX_DHCPV6_MISSING_REQUIRED_OPTIONS;
9748 }
9749
9750 /* Set the DHCPv6 Client state to Init.*/
9751 dhcpv6_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_INIT;
9752
9753 /* Clear the session time, lease lifetime, retransmission counters. */
9754 dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = 0;
9755 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = 0;
9756 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = 0;
9757 dhcpv6_ptr -> nx_dhcpv6_retransmission_count = 0;
9758
9759 /* Bind the UDP socket to the DHCPV6 Client port. */
9760 status = nx_udp_socket_bind(&(dhcpv6_ptr -> nx_dhcpv6_socket), NX_DHCPV6_CLIENT_UDP_PORT, TX_WAIT_FOREVER);
9761
9762 /* Check for success */
9763 if (status == NX_SUCCESS)
9764 {
9765
9766 /* Resume the DHCPv6 processing thread. */
9767 status = tx_thread_resume(&(dhcpv6_ptr -> nx_dhcpv6_thread));
9768
9769 /* Determine if the resume was successful. */
9770 if (status == NX_SUCCESS)
9771 {
9772
9773 /* Set the DHCPv6 started flag to indicate DHCPv6 Client is now running. */
9774 dhcpv6_ptr -> nx_dhcpv6_started = NX_TRUE;
9775
9776 /* Activate the DHCPv6 timers. */
9777 tx_timer_activate(&dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer);
9778 }
9779 else
9780 {
9781
9782 /* Error, unbind the DHCPv6 socket. */
9783 nx_udp_socket_unbind(&(dhcpv6_ptr -> nx_dhcpv6_socket));
9784 }
9785 }
9786
9787 /* Release the DHCPv6 Client mutex. */
9788 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
9789
9790 /* Return completion status. */
9791 return(status);
9792 }
9793
9794
9795 /**************************************************************************/
9796 /* */
9797 /* FUNCTION RELEASE */
9798 /* */
9799 /* _nxe_dhcpv6_suspend PORTABLE C */
9800 /* 6.1 */
9801 /* AUTHOR */
9802 /* */
9803 /* Yuxin Zhou, Microsoft Corporation */
9804 /* */
9805 /* DESCRIPTION */
9806 /* */
9807 /* This function performs error checking on the suspend NetX DHCPv6 */
9808 /* client task service. */
9809 /* */
9810 /* INPUT */
9811 /* */
9812 /* dhcpv6_ptr Pointer to DHCPV6 Client instance*/
9813 /* */
9814 /* OUTPUT */
9815 /* */
9816 /* status Completion status */
9817 /* NX_PTR_ERROR Invalid pointer input */
9818 /* */
9819 /* CALLS */
9820 /* */
9821 /* _nx_dhcpv6_suspend Actual DHCPV6 suspend function */
9822 /* */
9823 /* CALLED BY */
9824 /* */
9825 /* Application Code */
9826 /* */
9827 /* RELEASE HISTORY */
9828 /* */
9829 /* DATE NAME DESCRIPTION */
9830 /* */
9831 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9832 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9833 /* resulting in version 6.1 */
9834 /* */
9835 /**************************************************************************/
_nxe_dhcpv6_suspend(NX_DHCPV6 * dhcpv6_ptr)9836 UINT _nxe_dhcpv6_suspend(NX_DHCPV6 *dhcpv6_ptr)
9837 {
9838
9839 UINT status;
9840
9841
9842 /* Check for invalid input pointer. */
9843 if ((dhcpv6_ptr == NX_NULL) || (dhcpv6_ptr -> nx_dhcpv6_id != NX_DHCPV6_ID))
9844 {
9845
9846 return(NX_PTR_ERROR);
9847 }
9848
9849 /* Check for appropriate caller. */
9850 NX_THREADS_ONLY_CALLER_CHECKING
9851
9852 /* Call actual DHCPV6 stop service. */
9853 status = _nx_dhcpv6_suspend(dhcpv6_ptr);
9854
9855 /* Return status. */
9856 return(status);
9857 }
9858
9859
9860 /**************************************************************************/
9861 /* */
9862 /* FUNCTION RELEASE */
9863 /* */
9864 /* _nx_dhcpv6_suspend PORTABLE C */
9865 /* 6.1 */
9866 /* AUTHOR */
9867 /* */
9868 /* Yuxin Zhou, Microsoft Corporation */
9869 /* */
9870 /* DESCRIPTION */
9871 /* */
9872 /* This function suspends (stops) DHCPV6 processing thread, stops the */
9873 /* DHCP session and IP address lease timers, and clears the started */
9874 /* status of the DHCPv6 Client. It resets the DHCPv6 Client to the */
9875 /* INIT. The DHCP socket is unbound and the DHCP thread aborted. */
9876 /* */
9877 /* INPUT */
9878 /* */
9879 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
9880 /* */
9881 /* OUTPUT */
9882 /* */
9883 /* NX_SUCCESS Successful completion status */
9884 /* NX_DHCPV6_NOT_STARTED Task not running; can't be */
9885 /* suspended */
9886 /* */
9887 /* CALLS */
9888 /* */
9889 /* tx_thread_suspend Suspend DHCPV6 thread task */
9890 /* tx_timer_deactivate Deactivate timer */
9891 /* */
9892 /* CALLED BY */
9893 /* */
9894 /* Application Code */
9895 /* */
9896 /* RELEASE HISTORY */
9897 /* */
9898 /* DATE NAME DESCRIPTION */
9899 /* */
9900 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9901 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9902 /* resulting in version 6.1 */
9903 /* */
9904 /**************************************************************************/
_nx_dhcpv6_suspend(NX_DHCPV6 * dhcpv6_ptr)9905 UINT _nx_dhcpv6_suspend(NX_DHCPV6 *dhcpv6_ptr)
9906 {
9907
9908 UINT status;
9909
9910
9911 status = _nx_dhcpv6_stop(dhcpv6_ptr);
9912
9913 return status;
9914 }
9915
9916
9917 /**************************************************************************/
9918 /* */
9919 /* FUNCTION RELEASE */
9920 /* */
9921 /* _nx_dhcpv6_stop PORTABLE C */
9922 /* 6.1 */
9923 /* AUTHOR */
9924 /* */
9925 /* Yuxin Zhou, Microsoft Corporation */
9926 /* */
9927 /* DESCRIPTION */
9928 /* */
9929 /* This function performs error checking on the DHCPv6 Client stop */
9930 /* service. */
9931 /* */
9932 /* INPUT */
9933 /* */
9934 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
9935 /* */
9936 /* OUTPUT */
9937 /* */
9938 /* status Actual completion status */
9939 /* */
9940 /* CALLS */
9941 /* */
9942 /* _nx_dhcpv6_stop Actual stop DHCPV6 thread task */
9943 /* */
9944 /* CALLED BY */
9945 /* */
9946 /* Application Code */
9947 /* */
9948 /* RELEASE HISTORY */
9949 /* */
9950 /* DATE NAME DESCRIPTION */
9951 /* */
9952 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9953 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9954 /* resulting in version 6.1 */
9955 /* */
9956 /**************************************************************************/
_nxe_dhcpv6_stop(NX_DHCPV6 * dhcpv6_ptr)9957 UINT _nxe_dhcpv6_stop(NX_DHCPV6 *dhcpv6_ptr)
9958 {
9959
9960 UINT status;
9961
9962
9963 /* Check for invalid input pointer. */
9964 if ((dhcpv6_ptr == NX_NULL) || (dhcpv6_ptr -> nx_dhcpv6_id != NX_DHCPV6_ID))
9965 {
9966 return(NX_PTR_ERROR);
9967 }
9968
9969 /* Check for appropriate caller. */
9970 NX_THREADS_ONLY_CALLER_CHECKING
9971
9972 /* Call actual DHCPV6 stop service. */
9973 status = _nx_dhcpv6_stop(dhcpv6_ptr);
9974
9975 /* Return status. */
9976 return(status);
9977 }
9978
9979 /**************************************************************************/
9980 /* */
9981 /* FUNCTION RELEASE */
9982 /* */
9983 /* _nx_dhcpv6_stop PORTABLE C */
9984 /* 6.1 */
9985 /* AUTHOR */
9986 /* */
9987 /* Yuxin Zhou, Microsoft Corporation */
9988 /* */
9989 /* DESCRIPTION */
9990 /* */
9991 /* This function suspends (stops) DHCPV6 processing thread, stops the */
9992 /* DHCP session and IP address lease timers. The DHCP socket is unbound*/
9993 /* and the DHCP thread aborted. */
9994 /* */
9995 /* Stopping the DHCP Client is necessary to restart the DHCP client, */
9996 /* example if a previously assigned address is declined or released, */
9997 /* and the host would like to solicit an IP address again. */
9998 /* */
9999 /* INPUT */
10000 /* */
10001 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
10002 /* */
10003 /* OUTPUT */
10004 /* */
10005 /* NX_SUCCESS Successful completion status */
10006 /* NX_DHCPV6_NOT_STARTED Task not running; can't be */
10007 /* suspended */
10008 /* */
10009 /* CALLS */
10010 /* */
10011 /* tx_thread_suspend Suspend DHCPV6 thread task */
10012 /* tx_timer_deactivate Deactivate timer */
10013 /* tx_mutex_get Obtain Client mutex */
10014 /* tx_mutex_put Release Client mutex */
10015 /* */
10016 /* CALLED BY */
10017 /* */
10018 /* Application Code */
10019 /* */
10020 /* RELEASE HISTORY */
10021 /* */
10022 /* DATE NAME DESCRIPTION */
10023 /* */
10024 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10025 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10026 /* resulting in version 6.1 */
10027 /* */
10028 /**************************************************************************/
10029
_nx_dhcpv6_stop(NX_DHCPV6 * dhcpv6_ptr)10030 UINT _nx_dhcpv6_stop(NX_DHCPV6 *dhcpv6_ptr)
10031 {
10032
10033 UINT current_preemption;
10034
10035
10036 /* Get the DHCP mutex. */
10037 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
10038
10039 /* Determine if DHCPV6 is started. */
10040 if (dhcpv6_ptr -> nx_dhcpv6_started == NX_FALSE)
10041 {
10042
10043 /* Release the DHCP mutex. */
10044 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
10045
10046 /* DHCPV6 has not been started so we cannot stop it. */
10047 return(NX_DHCPV6_NOT_STARTED);
10048 }
10049
10050 /* Clear the DHCPV6 started flag to indicate DHCPV6 task is not running. */
10051 dhcpv6_ptr -> nx_dhcpv6_started = NX_FALSE;
10052
10053 /* Disable preemption for critical section. */
10054 tx_thread_preemption_change(tx_thread_identify(), 0, ¤t_preemption);
10055
10056 /* Loop to wait for the DHCP Client thread to be in a position to be stopped. */
10057 while (dhcpv6_ptr -> nx_dhcpv6_sleep_flag != NX_TRUE)
10058 {
10059
10060 /* Release the DHCP mutex. */
10061 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
10062
10063 /* Sleep temporarily. */
10064 tx_thread_sleep(1);
10065
10066 /* Get the DHCP mutex. */
10067 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
10068 }
10069
10070 /* Clear the flag. */
10071 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_FALSE;
10072
10073 /* Suspend the DHCP thread. */
10074 tx_thread_suspend(&(dhcpv6_ptr -> nx_dhcpv6_thread));
10075
10076 /* Abort the wait on the DHCP Client thread. */
10077 tx_thread_wait_abort(&(dhcpv6_ptr -> nx_dhcpv6_thread));
10078
10079 /* Unbind the port. */
10080 nx_udp_socket_unbind(&(dhcpv6_ptr -> nx_dhcpv6_socket));
10081
10082 /* Stop the timers. */
10083 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_timer));
10084 tx_timer_deactivate(&(dhcpv6_ptr -> nx_dhcpv6_session_timer));
10085
10086 /* Restore preemption. */
10087 tx_thread_preemption_change(tx_thread_identify(), current_preemption, ¤t_preemption);
10088
10089
10090 /* Release the DHCP mutex. */
10091 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
10092
10093 /* Return completion status. */
10094 return(NX_SUCCESS);
10095 }
10096
10097 /**************************************************************************/
10098 /* */
10099 /* FUNCTION RELEASE */
10100 /* */
10101 /* _nxd_dhcpv6_reinitialize PORTABLE C */
10102 /* 6.1 */
10103 /* AUTHOR */
10104 /* */
10105 /* Yuxin Zhou, Microsoft Corporation */
10106 /* */
10107 /* DESCRIPTION */
10108 /* */
10109 /* This function performs error checking for the reinitializes the */
10110 /* DHCPv6 Client service. */
10111 /* */
10112 /* INPUT */
10113 /* */
10114 /* dhcpv6_ptr Pointer to DHCPv6 Client */
10115 /* */
10116 /* OUTPUT */
10117 /* */
10118 /* status Actual completion status */
10119 /* */
10120 /* CALLS */
10121 /* */
10122 /* _nx_dhcpv6_reinitialize Actual clear address service */
10123 /* */
10124 /* CALLED BY */
10125 /* */
10126 /* Application Code */
10127 /* */
10128 /* RELEASE HISTORY */
10129 /* */
10130 /* DATE NAME DESCRIPTION */
10131 /* */
10132 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10133 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10134 /* resulting in version 6.1 */
10135 /* */
10136 /**************************************************************************/
10137
_nxe_dhcpv6_reinitialize(NX_DHCPV6 * dhcpv6_ptr)10138 UINT _nxe_dhcpv6_reinitialize(NX_DHCPV6 *dhcpv6_ptr)
10139 {
10140
10141 UINT status;
10142
10143 if (dhcpv6_ptr == NX_NULL)
10144 {
10145 return NX_PTR_ERROR;
10146 }
10147
10148 /* Check for appropriate caller. */
10149 NX_THREADS_ONLY_CALLER_CHECKING
10150
10151 status = _nx_dhcpv6_reinitialize(dhcpv6_ptr);
10152
10153 return status;
10154 }
10155
10156 /**************************************************************************/
10157 /* */
10158 /* FUNCTION RELEASE */
10159 /* */
10160 /* _nx_dhcpv6_reinitialize PORTABLE C */
10161 /* 6.1 */
10162 /* AUTHOR */
10163 /* */
10164 /* Yuxin Zhou, Microsoft Corporation */
10165 /* */
10166 /* DESCRIPTION */
10167 /* */
10168 /* This function reinitializes the DHCP instance for restarting the */
10169 /* DHCP client state machine and re-running the DHCPv6 protocol. This */
10170 /* is not necessary if the Client has not previously obtained an */
10171 /* IP address from the server. The IP address in both the DHCP Client */
10172 /* data record and in the IP instance is cleared. */
10173 /* */
10174 /* Note: the host MUST stop the DHCPv6 client before calling this */
10175 /* service with the nx_dhcpv6_stop service. */
10176 /* */
10177 /* INPUT */
10178 /* */
10179 /* dhcpv6_ptr Pointer to DHCPv6 Client */
10180 /* */
10181 /* OUTPUT */
10182 /* */
10183 /* NX_DHCPV6_ALREADY_STARTED DHCPv6 client is running */
10184 /* status Actual completion status */
10185 /* */
10186 /* CALLS */
10187 /* */
10188 /* _nx_dhcpv6_remove_assigned_address Clears client IP address */
10189 /* */
10190 /* CALLED BY */
10191 /* */
10192 /* Application Code */
10193 /* */
10194 /* RELEASE HISTORY */
10195 /* */
10196 /* DATE NAME DESCRIPTION */
10197 /* */
10198 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10199 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10200 /* resulting in version 6.1 */
10201 /* */
10202 /**************************************************************************/
10203
_nx_dhcpv6_reinitialize(NX_DHCPV6 * dhcpv6_ptr)10204 UINT _nx_dhcpv6_reinitialize(NX_DHCPV6 *dhcpv6_ptr)
10205 {
10206
10207 UINT status;
10208
10209
10210 /* Check that the DHCPv6 client is started. */
10211 if (dhcpv6_ptr -> nx_dhcpv6_started == NX_TRUE)
10212 {
10213
10214 /* Need to stop the DHCP client before we can reinitialize it. */
10215 return NX_DHCPV6_ALREADY_STARTED;
10216 }
10217
10218 /* This clears the assigned IP address from the Client record, as well as
10219 removes the assigned IP address from the IP address table. */
10220 status = _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, NX_DHCPV6_REMOVE_ALL_IA_ADDRESS);
10221
10222 return status;
10223 }
10224
10225
10226 /**************************************************************************/
10227 /* */
10228 /* FUNCTION RELEASE */
10229 /* */
10230 /* _nx_dhcpv6_thread_entry PORTABLE C */
10231 /* 6.1 */
10232 /* AUTHOR */
10233 /* */
10234 /* Yuxin Zhou, Microsoft Corporation */
10235 /* */
10236 /* DESCRIPTION */
10237 /* */
10238 /* This function is the background processing thread for the DHCPV6 */
10239 /* Client. It waits to be notified by ThreadX event flags when to */
10240 /* perform certain actions. These include updating the time remaining */
10241 /* on the Client IP address lease time, and maintaining the duration of*/
10242 /* the current Client Server session (if Client has made a request). */
10243 /* It will terminate if a host application handler is called and */
10244 /* indicates the Client should abort. */
10245 /* */
10246 /* INPUT */
10247 /* */
10248 /* info Pointer to DHCPV6 Client instance*/
10249 /* */
10250 /* OUTPUT */
10251 /* */
10252 /* None */
10253 /* */
10254 /* CALLS */
10255 /* */
10256 /* tx_event_flags_get Receive notice of event flags set */
10257 /* tx_mutex_get Obtain lock on Client resource */
10258 /* tx_mutex_put Release lock on Client resource */
10259 /* _nx_dhcpv6_request_renew Initiate the RENEW request */
10260 /* _nx_dhcpv6_request_rebind Initiate the REBIND request */
10261 /* _nx_dhcpv6_request_decline Initiate the DECLINE request */
10262 /* _nx_dhcpv6_remove_assigned_address */
10263 /* Remove the assigned IPv6 address */
10264 /* */
10265 /* CALLED BY */
10266 /* */
10267 /* ThreadX */
10268 /* */
10269 /* RELEASE HISTORY */
10270 /* */
10271 /* DATE NAME DESCRIPTION */
10272 /* */
10273 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10274 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10275 /* resulting in version 6.1 */
10276 /* */
10277 /**************************************************************************/
_nx_dhcpv6_thread_entry(ULONG info)10278 VOID _nx_dhcpv6_thread_entry(ULONG info)
10279 {
10280
10281 UINT status;
10282 NX_DHCPV6 *dhcpv6_ptr;
10283 UINT current_preemption;
10284 ULONG dhcpv6_events;
10285 UINT ia_index;
10286 UINT original_state;
10287
10288 /* Setup the DHCPV6 Client pointer. */
10289 NX_THREAD_EXTENSION_PTR_GET(dhcpv6_ptr, NX_DHCPV6, info)
10290
10291 /* Process periodic DHCPv6 Client tasks. */
10292 do
10293 {
10294
10295 /* Loop to get the DHCP mutex to handle error, release, and
10296 stop requests properly. */
10297 do
10298 {
10299
10300 /* Get the DHCP mutex. */
10301 status = tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
10302
10303 } while (status != TX_SUCCESS);
10304
10305
10306 /* Check the state of the DHCP Client state for further DHCP messaging. */
10307 _nx_dhcpv6_process(dhcpv6_ptr);
10308
10309 /* Release the DHCP mutex. */
10310 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
10311
10312 /* Disable preemption for critical section. */
10313 tx_thread_preemption_change(tx_thread_identify(), 0, ¤t_preemption);
10314
10315 /* Indicate the DHCP Client process is idle. */
10316 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_TRUE;
10317
10318 /* Sleep for timer interval. */
10319 tx_thread_sleep(NX_DHCPV6_SESSION_TIMER_INTERVAL);
10320
10321 /* Clear flag to indicate DHCP thread is not in a position to be stopped. */
10322 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_FALSE;
10323
10324 /* Restore original preemption. */
10325 tx_thread_preemption_change(tx_thread_identify(), current_preemption, ¤t_preemption);
10326
10327 /* Check the expiration on valid and preferred lifetimes only if the Client is in the Bound state. */
10328 if (dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_BOUND_TO_ADDRESS)
10329 {
10330
10331 /* At time T1 for an IA, the client initiates a Renew message exchange to extend the lifetimes. RFC3315,page 42.*/
10332 if (dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued >= dhcpv6_ptr -> nx_dhcpv6_iana.nx_T1)
10333 {
10334
10335 /* Indicate the DHCP Client process is idle while the handler executes. */
10336 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_TRUE;
10337
10338 /* Sending the renew message. */
10339 _nx_dhcpv6_request_renew(dhcpv6_ptr);
10340
10341 /* Reset flag to indicate DHCP thread is not idle (not stoppable). */
10342 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_FALSE;
10343 }
10344 }
10345
10346 /* Check the expiration on valid and preferred lifetimes only if the Client is in the sending renew state. */
10347 if (dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_RENEW)
10348 {
10349
10350 /* At time T2 for an IA, The Client initiates a Rebind message exchanges. RFC3315, page 43. */
10351 if (dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued >= dhcpv6_ptr -> nx_dhcpv6_iana.nx_T2)
10352 {
10353
10354 /* Indicate the DHCP Client process is idle while the handler executes. */
10355 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_TRUE;
10356
10357 /* Sending the rebind message. */
10358 _nx_dhcpv6_request_rebind(dhcpv6_ptr);
10359
10360 /* Reset flag to indicate DHCP thread is not idle (not stoppable). */
10361 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_FALSE;
10362 }
10363 }
10364
10365 /* Check the DHCPv6 Client state. */
10366 if ((dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_BOUND_TO_ADDRESS) ||
10367 (dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_RENEW) ||
10368 (dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_REBIND))
10369 {
10370
10371 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
10372 {
10373
10374 /* Has the IP address valid lifetime expired? */
10375 if ((dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status) &&
10376 (dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued >= dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_valid_lifetime))
10377 {
10378
10379 /* Save the existing state of the DHCPv6 Client. */
10380 original_state = dhcpv6_ptr -> nx_dhcpv6_state;
10381
10382 /* Clear the assigned IP address. */
10383 _nx_dhcpv6_remove_assigned_address(dhcpv6_ptr, ia_index);
10384
10385 /* Indicate the DHCP Client process is idle while the handler executes. */
10386 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_TRUE;
10387
10388 /* Restart the Client to the solicit IP address request state. */
10389 _nx_dhcpv6_request_solicit(dhcpv6_ptr);
10390
10391 /* Indicate the DHCP Client process is idle while the handler executes. */
10392 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_FALSE;
10393
10394 if (dhcpv6_ptr -> nx_dhcpv6_state_change_callback && (original_state != dhcpv6_ptr -> nx_dhcpv6_state))
10395 {
10396 /* Yes, call the state change callback with the original and new state. */
10397 (dhcpv6_ptr -> nx_dhcpv6_state_change_callback)(dhcpv6_ptr, original_state, dhcpv6_ptr -> nx_dhcpv6_state);
10398 }
10399 }
10400 }
10401 }
10402
10403
10404
10405 /* Pickup IP event flags. */
10406 status = tx_event_flags_get(&(_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_events), NX_IP_ALL_EVENTS, TX_OR_CLEAR, &dhcpv6_events, TX_NO_WAIT);
10407
10408 /* Check for an IP receive packet event. */
10409 if ((status == TX_SUCCESS) && (dhcpv6_events & NX_DHCPV6_DAD_FAILURE_EVENT))
10410 {
10411
10412 /* Indicate the DHCP Client process is idle while the handler executes. */
10413 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_TRUE;
10414
10415 /* The DAD process failure, send DHCPv6 DECLINE message. */
10416 _nx_dhcpv6_request_decline(dhcpv6_ptr);
10417
10418 dhcpv6_events = dhcpv6_events & ~(ULONG)(NX_DHCPV6_DAD_FAILURE_EVENT);
10419
10420 /* Reset flag to indicate DHCP thread is not idle (not stoppable). */
10421 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_FALSE;
10422 }
10423
10424 } while (1);
10425
10426 }
10427
10428
10429 /**************************************************************************/
10430 /* */
10431 /* FUNCTION RELEASE */
10432 /* */
10433 /* _nx_dhcpv6_utility_get_block_option_length PORTABLE C */
10434 /* 6.1 */
10435 /* AUTHOR */
10436 /* */
10437 /* Yuxin Zhou, Microsoft Corporation */
10438 /* */
10439 /* DESCRIPTION */
10440 /* */
10441 /* This function parses the input buffer (assuming to be an option */
10442 /* block in a server reply) for option code and length. It assumes the */
10443 /* buffer pointer is pointed to the first byte of the option buffer. */
10444 /* */
10445 /* INPUT */
10446 /* */
10447 /* dhcpv6_ Pointer to DHCPv6 Client */
10448 /* option Option code of requested data */
10449 /* buffer_ptr Buffer to copy data to */
10450 /* length Size of buffer */
10451 /* valid */
10452 /* */
10453 /* OUTPUT */
10454 /* */
10455 /* status Completion status */
10456 /* NX_DHCPV6_INCOMPLETE_OPTION_BLOCK Unknown option specified */
10457 /* */
10458 /* CALLS */
10459 /* */
10460 /* _nx_dhcpv6_utility_get_data Parses a specific data from the */
10461 /* DHCPv6 option */
10462 /* */
10463 /* CALLED BY */
10464 /* */
10465 /* _nx_dhcpv6_utility_get_block_option_length */
10466 /* Parses option code and length */
10467 /* _nx_dhcpv6_extract_packet_information */
10468 /* Parses each option from server */
10469 /* reply and updates Client record */
10470 /* */
10471 /* RELEASE HISTORY */
10472 /* */
10473 /* DATE NAME DESCRIPTION */
10474 /* */
10475 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10476 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10477 /* resulting in version 6.1 */
10478 /* */
10479 /**************************************************************************/
_nx_dhcpv6_utility_get_block_option_length(UCHAR * buffer_ptr,ULONG * option,ULONG * length)10480 UINT _nx_dhcpv6_utility_get_block_option_length(UCHAR *buffer_ptr, ULONG *option, ULONG *length)
10481 {
10482
10483 /* Initialize to zero. */
10484 *option = 0;
10485 *length = 0;
10486
10487 /* First byte should be the op code. */
10488 _nx_dhcpv6_utility_get_data(buffer_ptr, 2, option);
10489
10490 buffer_ptr += 2;
10491
10492 /* Next byte should be the option length. */
10493 _nx_dhcpv6_utility_get_data(buffer_ptr, 2, length);
10494
10495 /* Buffer is now pointed at the data (past the length field). */
10496 buffer_ptr += 2;
10497
10498 /* Check for null data. */
10499 if (*option == 0)
10500 {
10501
10502 return NX_DHCPV6_INCOMPLETE_OPTION_BLOCK;
10503 }
10504
10505 return(NX_SUCCESS);
10506
10507 }
10508
10509
10510 /**************************************************************************/
10511 /* */
10512 /* FUNCTION RELEASE */
10513 /* */
10514 /* _nx_dhcpv6_utility_get_data PORTABLE C */
10515 /* 6.1 */
10516 /* AUTHOR */
10517 /* */
10518 /* Yuxin Zhou, Microsoft Corporation */
10519 /* */
10520 /* DESCRIPTION */
10521 /* */
10522 /* This function parses the input buffer and returns numeric data */
10523 /* specified by the size argument, up to 4 bytes long. Note that if */
10524 /* caller is using this utility to extract bytes from a DHCPv6 packet */
10525 /* there is no need for byte swapping, as compared to using memcpy in */
10526 /* which case there is for little endian processors. */
10527 /* */
10528 /* INPUT */
10529 /* */
10530 /* buffer Pointer to data buffer */
10531 /* value Pointer to data parsed from buffer*/
10532 /* size Size of buffer */
10533 /* */
10534 /* OUTPUT */
10535 /* */
10536 /* NX_DHCPV6_INVALID_DATA_SIZE Requested data size too large */
10537 /* NX_SUCCESS Successful completion status */
10538 /* */
10539 /* CALLS */
10540 /* */
10541 /* None */
10542 /* */
10543 /* CALLED BY */
10544 /* _nx_dhcpv6_process_server_duid Process server duid in server reply*/
10545 /* _nx_dhcpv6_process_client_duid Process server duid in server reply*/
10546 /* _nx_dhcpv6_utility_get_block_option_length */
10547 /* Parses option code and length */
10548 /* _nx_dhcpv6_extract_packet_information */
10549 /* Parses each option from server */
10550 /* reply and updates Client record */
10551 /* */
10552 /* RELEASE HISTORY */
10553 /* */
10554 /* DATE NAME DESCRIPTION */
10555 /* */
10556 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10557 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10558 /* resulting in version 6.1 */
10559 /* */
10560 /**************************************************************************/
_nx_dhcpv6_utility_get_data(UCHAR * buffer,UINT size,ULONG * value)10561 UINT _nx_dhcpv6_utility_get_data(UCHAR *buffer, UINT size, ULONG *value)
10562 {
10563
10564
10565 /* Check that the size of the data fits in a ULONG. */
10566 if (size > sizeof(ULONG))
10567 {
10568 return NX_DHCPV6_INVALID_DATA_SIZE;
10569 }
10570
10571 *value = 0;
10572
10573 /* Process the data retrieval request. */
10574 while (size-- > 0)
10575 {
10576
10577 /* Build return value. */
10578 *value = (((*value) << 8) | (*buffer));
10579 buffer++;
10580 }
10581
10582 /* Return value. */
10583 return NX_SUCCESS;
10584 }
10585
10586
10587 /**************************************************************************/
10588 /* */
10589 /* FUNCTION RELEASE */
10590 /* */
10591 /* _nx_dhcpv6_utility_time_randomize PORTABLE C */
10592 /* 6.1 */
10593 /* AUTHOR */
10594 /* */
10595 /* Yuxin Zhou, Microsoft Corporation */
10596 /* */
10597 /* DESCRIPTION */
10598 /* */
10599 /* This function returns a value of between -1 seconds and 1 second */
10600 /* in system ticks. It is used to randomize timeouts as required by */
10601 /* the RFC's so as to not overload a network server after power out. */
10602 /* */
10603 /* INPUT */
10604 /* */
10605 /* None */
10606 /* */
10607 /* OUTPUT */
10608 /* */
10609 /* ticks Number of ticks between 1 & -1*/
10610 /* */
10611 /* CALLS */
10612 /* */
10613 /* None */
10614 /* */
10615 /* CALLED BY */
10616 /* */
10617 /* _nx_dhcpv6_convert_delay_to_ticks Convert seconds to ticks */
10618 /* */
10619 /* RELEASE HISTORY */
10620 /* */
10621 /* DATE NAME DESCRIPTION */
10622 /* */
10623 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10624 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10625 /* resulting in version 6.1 */
10626 /* */
10627 /**************************************************************************/
_nx_dhcpv6_utility_time_randomize(void)10628 INT _nx_dhcpv6_utility_time_randomize(void)
10629 {
10630
10631 UINT temp;
10632 UINT sign;
10633 INT temp_signed;
10634
10635 temp = (UINT)(NX_RAND());
10636 temp &= (UINT)(0x001F);
10637 sign = (temp & (UINT)(0x8));
10638 temp_signed = (INT)temp;
10639
10640 /* Try for a number between 0 and 0x1F. */
10641 if (sign)
10642 {
10643 temp_signed = -temp_signed;
10644 }
10645
10646 return temp_signed;
10647
10648 }
10649
10650 /**************************************************************************/
10651 /* */
10652 /* FUNCTION RELEASE */
10653 /* */
10654 /* _nx_dhcpv6_waiting_on_reply PORTABLE C */
10655 /* 6.1 */
10656 /* AUTHOR */
10657 /* */
10658 /* Yuxin Zhou, Microsoft Corporation */
10659 /* */
10660 /* DESCRIPTION */
10661 /* */
10662 /* This function waits to receive a DHCPv6 server packet for the wait */
10663 /* time set by the DHCPv6 client previously. If a reply is received, */
10664 /* call function to process it. */
10665 /* */
10666 /* INPUT */
10667 /* */
10668 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
10669 /* */
10670 /* OUTPUT */
10671 /* */
10672 /* status Actual completion status */
10673 /* NX_SUCCESS Valid packet received */
10674 /* */
10675 /* CALLS */
10676 /* */
10677 /* nx_udp_socket_receive Receive UDP packet */
10678 /* nx_packet_release Release packet to packet pool */
10679 /* _nx_dhcpv6_packet_procss Process the dhcpv6 packet */
10680 /* _nx_dhcpv6_flush_queue_packets Flush the queue packets */
10681 /* */
10682 /* CALLED BY */
10683 /* */
10684 /* _nx_dhcpv6_process Process current client state */
10685 /* */
10686 /* RELEASE HISTORY */
10687 /* */
10688 /* DATE NAME DESCRIPTION */
10689 /* */
10690 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10691 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10692 /* fixed compiler warnings, */
10693 /* resulting in version 6.1 */
10694 /* */
10695 /**************************************************************************/
_nx_dhcpv6_waiting_on_reply(NX_DHCPV6 * dhcpv6_ptr)10696 UINT _nx_dhcpv6_waiting_on_reply(NX_DHCPV6 *dhcpv6_ptr)
10697 {
10698
10699 UINT current_preemption;
10700 UINT status;
10701 NX_PACKET *packet_ptr;
10702 ULONG start_time;
10703 ULONG current_time;
10704 ULONG elapsed_time;
10705 ULONG receive_wait;
10706 UINT time_remaining;
10707 UINT valid_answer;
10708
10709 /* Initialize the parameters. */
10710 packet_ptr = NX_NULL;
10711 valid_answer = NX_FALSE;
10712 time_remaining = dhcpv6_ptr -> nx_dhcpv6_transmission_timeout;
10713
10714 /* Wait in short intervals to receive a valid packet while continuously checking for packets not intended
10715 for this DHCP Client to be removed from the receive queue. */
10716 do
10717 {
10718
10719 /* Release the DHCP mutex while the Client will be blocked on a receive socket call. */
10720 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
10721
10722 /* Disable preemption for critical section. */
10723 tx_thread_preemption_change(tx_thread_identify(), 0, ¤t_preemption);
10724
10725 /* Indicate the DHCP Client can be stopped. */
10726 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_TRUE;
10727
10728 start_time = tx_time_get();
10729
10730 if (time_remaining < NX_DHCPV6_TIME_INTERVAL)
10731 {
10732 receive_wait = time_remaining;
10733 }
10734 else
10735 {
10736 receive_wait = NX_DHCPV6_TIME_INTERVAL;
10737 }
10738
10739 status = nx_udp_socket_receive(&(dhcpv6_ptr -> nx_dhcpv6_socket), &packet_ptr, receive_wait);
10740
10741 /* Indicate the DHCP Client can not be stopped. */
10742 dhcpv6_ptr -> nx_dhcpv6_sleep_flag = NX_FALSE;
10743
10744 /* Restore preemption/ end of critical section. */
10745 tx_thread_preemption_change(tx_thread_identify(), current_preemption, ¤t_preemption);
10746
10747 /* Yes, receive a packet. */
10748 if (status == NX_SUCCESS)
10749 {
10750
10751 /* Get the DHCP mutex. */
10752 while((tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_NO_WAIT) != TX_SUCCESS) &&
10753 (time_remaining > 0))
10754 {
10755
10756 if (time_remaining < NX_DHCPV6_TIME_INTERVAL)
10757 {
10758 tx_thread_sleep(time_remaining);
10759 time_remaining = 0;
10760 }
10761 else
10762 {
10763 tx_thread_sleep(NX_DHCPV6_TIME_INTERVAL);
10764 time_remaining = (UINT)(time_remaining - NX_DHCPV6_TIME_INTERVAL);
10765 }
10766 }
10767
10768 /* Process the dhcpv6 packet. */
10769 status = _nx_dhcpv6_packet_process(dhcpv6_ptr, packet_ptr);
10770
10771 /* Check the status. */
10772 if(status == NX_SUCCESS)
10773 {
10774
10775 /* Yes, Get a valid advertise or reply message. */
10776 valid_answer = NX_TRUE;
10777
10778 /* DHCPv6 client MUST collect Advertise messages for the first RT seconds,
10779 unless it receives an Advertise message with a preference value of 255.
10780 RFC 3315, Section 17.1.2, Page 34. */
10781 if((dhcpv6_ptr -> nx_dhcpv6_state == NX_DHCPV6_STATE_SENDING_SOLICIT) &&
10782 (dhcpv6_ptr -> nx_dhcpv6_retransmission_count == 0))
10783 {
10784
10785 /* Process the rapid solicit mode. */
10786 if(dhcpv6_ptr -> nx_dhcpv6_request_solicit_mode == NX_DHCPV6_SOLICIT_RAPID)
10787 {
10788
10789 /* Client terminates the waiting process as soon as a reply message
10790 with a Rapid Commit option is received. RFC3315, Section17.1.2, Page34. */
10791 break;
10792 }
10793
10794 /* Process the normal solicit mode. */
10795 if(dhcpv6_ptr -> nx_dhcpv6_preference.nx_pref_value == 255)
10796 {
10797
10798 /* If the client receives an Advertise message that includes a Preference option with
10799 a preference value of 255, the client can terminates the waiting. */
10800 break;
10801 }
10802 }
10803 else
10804 {
10805
10806 /* Yes, Get the answer. */
10807 break;
10808 }
10809 }
10810 }
10811
10812 /* How much time has elapsed? */
10813 current_time = tx_time_get();
10814
10815 /* Has the time wrapped? */
10816 if (current_time >= start_time)
10817 {
10818 /* No, simply subtract to get the elapsed time. */
10819 elapsed_time = current_time - start_time;
10820 }
10821 else
10822 {
10823
10824 /* Yes it has. Time has rolled over the 32-bit boundary. */
10825 elapsed_time = (((ULONG) 0xFFFFFFFF) - start_time) + current_time;
10826 }
10827
10828 /* Update the time remaining. */
10829 if (time_remaining > elapsed_time)
10830 {
10831 time_remaining -= elapsed_time;
10832 }
10833 else
10834 {
10835 /* Time is up, break out of this loop. */
10836 time_remaining = 0;
10837
10838 /* But not before restoring preemption/ end of critical section! */
10839 tx_thread_preemption_change(tx_thread_identify(), current_preemption, ¤t_preemption);
10840
10841 break;
10842 }
10843
10844 } while(time_remaining > 0);
10845
10846 /* Flush the queue packets. */
10847 _nx_dhcpv6_flush_queue_packets(dhcpv6_ptr);
10848
10849 /* Check the valid answer flag. */
10850 if (valid_answer == NX_TRUE)
10851 {
10852 return NX_SUCCESS;
10853 }
10854 else
10855 {
10856 return NX_DHCPV6_INVALID_SERVER_PACKET;
10857 }
10858 }
10859
10860
10861 /**************************************************************************/
10862 /* */
10863 /* FUNCTION RELEASE */
10864 /* */
10865 /* _nx_dhcpv6_packet_process PORTABLE C */
10866 /* 6.1 */
10867 /* AUTHOR */
10868 /* */
10869 /* Yuxin Zhou, Microsoft Corporation */
10870 /* */
10871 /* DESCRIPTION */
10872 /* */
10873 /* This function process the receive pacet. the data is copied to */
10874 /* another packet from the DHCPv6 Client packet pool,and the original */
10875 /* received packet is released back to the receive pool immediately. */
10876 /* Then process the reply message. */
10877 /* */
10878 /* INPUT */
10879 /* */
10880 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
10881 /* packet_ptr Pointer to received packet */
10882 /* */
10883 /* OUTPUT */
10884 /* */
10885 /* status Actual completion status */
10886 /* NX_SUCCESS Process correctly */
10887 /* */
10888 /* CALLS */
10889 /* */
10890 /* nx_udp_socket_extract Get the reply information */
10891 /* nx_packet_release Release packet to packet pool */
10892 /* nx_packet_allocate Allocate a new packet. */
10893 /* nx_packet_data_extract_offset Store the received pacet data. */
10894 /* _nx_dhcpv6_scan_packet_options Scan and record the reply options. */
10895 /* _nx_dhcpv6_preprocess_packet_information */
10896 /* Preprocess the packet according to */
10897 /* the options record. */
10898 /* _nx_dhcpv6_extract_packet_information */
10899 /* Extract server reply data */
10900 /* */
10901 /* CALLED BY */
10902 /* */
10903 /* _nx_dhcpv6_waiting_on_reply Process current client message */
10904 /* */
10905 /* RELEASE HISTORY */
10906 /* */
10907 /* DATE NAME DESCRIPTION */
10908 /* */
10909 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10910 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10911 /* resulting in version 6.1 */
10912 /* */
10913 /**************************************************************************/
_nx_dhcpv6_packet_process(NX_DHCPV6 * dhcpv6_ptr,NX_PACKET * packet_ptr)10914 UINT _nx_dhcpv6_packet_process(NX_DHCPV6 *dhcpv6_ptr, NX_PACKET *packet_ptr)
10915 {
10916
10917 UINT status;
10918 UINT port;
10919 ULONG bytes_copied;
10920 NXD_ADDRESS server_IP_Address;
10921 NX_PACKET *new_packet_ptr;
10922
10923
10924 /* Check for valid packet length (message type and ID). */
10925 if (packet_ptr -> nx_packet_length < 4)
10926 {
10927
10928 /* Release the packet. */
10929 nx_packet_release(packet_ptr);
10930
10931 /* Return. */
10932 return(NX_DHCPV6_INVALID_DATA_SIZE);
10933 }
10934
10935 /* Extract the IP and port number from the packet and set the reply address. */
10936 status = nxd_udp_source_extract(packet_ptr, &server_IP_Address, &port);
10937
10938 /* Check status. */
10939 if (status != NX_SUCCESS)
10940 {
10941
10942 /* Release the packet. We don't want it. */
10943 nx_packet_release(packet_ptr);
10944
10945 /* Error extracting packet source information, return error status. */
10946 return(status);
10947 }
10948
10949 /* Copy the received packet into the packet allocated by the DHCPv6 Client. */
10950 status = nx_packet_allocate(dhcpv6_ptr -> nx_dhcpv6_pool_ptr,
10951 &new_packet_ptr, NX_IPv6_UDP_PACKET,
10952 NX_DHCPV6_PACKET_TIME_OUT);
10953
10954 /* Check for errors. */
10955 if (status != NX_SUCCESS)
10956 {
10957
10958 /* Release the receive packet. We can't use it. */
10959 nx_packet_release(packet_ptr);
10960
10961 return status;
10962 }
10963
10964 /* Verify the incoming packet does not exceed our DHCPv6 Client packet payload. */
10965 if ((ULONG)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr) < packet_ptr -> nx_packet_length)
10966 {
10967
10968 /* Release the packet allocated from the Client pool*/
10969 nx_packet_release(new_packet_ptr);
10970
10971 /* Release the received packet. We can't use it. */
10972 nx_packet_release(packet_ptr);
10973
10974 return(NX_DHCPV6_INVALID_DATA_SIZE);
10975 }
10976
10977 /* Use a packet from the DHCP Client as a buffer to store the received packet data.
10978 Then we can release the received packet back to its packet pool. */
10979 status = nx_packet_data_extract_offset(packet_ptr, 0,(VOID *)new_packet_ptr -> nx_packet_prepend_ptr, packet_ptr -> nx_packet_length, &bytes_copied);
10980
10981 /* Check status. */
10982 if ((status != NX_SUCCESS) || (bytes_copied == 0))
10983 {
10984
10985 /* Release the packet allocated from the Client pool*/
10986 nx_packet_release(new_packet_ptr);
10987
10988 /* Release the received packet. We can't use it. */
10989 nx_packet_release(packet_ptr);
10990
10991 /* Error extracting packet buffer, return error status. */
10992 return(status);
10993 }
10994
10995 /* Now we can release the received packet. */
10996 nx_packet_release(packet_ptr);
10997
10998 /* Update the new packet with the bytes copied. For chained packets, this will reflect the total
10999 'datagram' length. */
11000 new_packet_ptr -> nx_packet_length = bytes_copied;
11001 new_packet_ptr -> nx_packet_append_ptr = new_packet_ptr -> nx_packet_prepend_ptr + bytes_copied;
11002
11003 /* Process the DHCPv6 packet.*/
11004
11005 /* Scan the packet options and record it. */
11006 status = _nx_dhcpv6_scan_packet_options(dhcpv6_ptr, new_packet_ptr);
11007
11008 /* Check for errors processing the packet. */
11009 if (status != NX_SUCCESS)
11010 {
11011
11012 /* Release the Client packet. We can't use it. */
11013 nx_packet_release(new_packet_ptr);
11014
11015 /* Return error status. */
11016 return status;
11017 }
11018
11019 /* Preprocess the packet options. */
11020 status = _nx_dhcpv6_preprocess_packet_information(dhcpv6_ptr, new_packet_ptr);
11021
11022 /* Check for errors processing the packet. */
11023 if (status != NX_SUCCESS)
11024 {
11025
11026 /* Release the Client packet. We can't use it. */
11027 nx_packet_release(new_packet_ptr);
11028
11029 /* Return error status. */
11030 return status;
11031 }
11032
11033 /* Extract the info from the packet buffer into the Client record. */
11034 status = _nx_dhcpv6_extract_packet_information(dhcpv6_ptr, new_packet_ptr);
11035
11036 /* Release the Client packet. We are done with it. */
11037 nx_packet_release(new_packet_ptr);
11038
11039 /* Store the DHCPv6 server address. */
11040 if ((status == NX_SUCCESS) && (dhcpv6_ptr -> nx_dhcpv6_received_message_type == NX_DHCPV6_MESSAGE_TYPE_REPLY))
11041 {
11042 COPY_NXD_ADDRESS(&server_IP_Address, &(dhcpv6_ptr-> nx_dhcpv6_server_address));
11043 }
11044
11045 /* Successfully processed response from the server. */
11046 return status;
11047 }
11048
11049
11050 /**************************************************************************/
11051 /* */
11052 /* FUNCTION RELEASE */
11053 /* */
11054 /* _nx_dhcpv6_scan_packet_options PORTABLE C */
11055 /* 6.1 */
11056 /* AUTHOR */
11057 /* */
11058 /* Yuxin Zhou, Microsoft Corporation */
11059 /* */
11060 /* DESCRIPTION */
11061 /* */
11062 /* This function scan the packet options of DHCPv6 server response and */
11063 /* record the relevant options. */
11064 /* */
11065 /* INPUT */
11066 /* */
11067 /* dhcpv6_ptr Pointer to DHCPv6 Client */
11068 /* packet_ptr Pointer to received packet */
11069 /* */
11070 /* OUTPUT */
11071 /* */
11072 /* status Actual completion status */
11073 /* NX_SUCCESS Successful completion status */
11074 /* NX_DHCPV6_UNKNOWN_OPTION Unknown option in message */
11075 /* */
11076 /* CALLS */
11077 /* */
11078 /* _nx_dhcpv6_utility_get_block_option_length */
11079 /* Extract option and length data */
11080 /* memcpy Copies specified area of memory */
11081 /* */
11082 /* CALLED BY */
11083 /* */
11084 /* _nx_dhcpv6_packet_process Process dhcpv6 packet. */
11085 /* */
11086 /* RELEASE HISTORY */
11087 /* */
11088 /* DATE NAME DESCRIPTION */
11089 /* */
11090 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11091 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
11092 /* verified memcpy use cases, */
11093 /* resulting in version 6.1 */
11094 /* */
11095 /**************************************************************************/
_nx_dhcpv6_scan_packet_options(NX_DHCPV6 * dhcpv6_ptr,NX_PACKET * packet_ptr)11096 UINT _nx_dhcpv6_scan_packet_options(NX_DHCPV6 *dhcpv6_ptr, NX_PACKET *packet_ptr)
11097 {
11098
11099 UINT status;
11100 UCHAR *dhcpv6_option_ptr;
11101 UINT index;
11102 ULONG option_code;
11103 ULONG option_length;
11104 UCHAR *dhcpv6_iana_option_ptr;
11105 UINT iana_index;
11106 ULONG iana_option_code;
11107 ULONG iana_option_length;
11108 UCHAR *dhcpv6_ia_option_ptr;
11109 ULONG ia_option_index;
11110 ULONG ia_option_code;
11111 ULONG ia_option_length;
11112 ULONG ipv6_address[4];
11113 USHORT status_code;
11114 UINT ia_index;
11115 UINT w;
11116 UINT ia_count = 0;
11117
11118 /* Set a pointer to the start of DHCPv6 options. */
11119 dhcpv6_option_ptr = (packet_ptr -> nx_packet_prepend_ptr + 4);
11120
11121 /* Initialize local variables. */
11122 index = 4;
11123 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags = 0;
11124 dhcpv6_ptr -> nx_dhcpv6_reply_option_current_pref_value = 0;
11125
11126 /* Clear the IA address map status. */
11127 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
11128 {
11129
11130 dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_map = 0;
11131 }
11132
11133 /* Now parse all the DHCPv6 option blocks in the packet buffer. */
11134 /* 4 bytes is data pointer offset, and 4 bytes for option code and option length. */
11135 while (index + 4 <= packet_ptr -> nx_packet_length)
11136 {
11137
11138 /* Get the option code and length of data of the current option block. */
11139 status = _nx_dhcpv6_utility_get_block_option_length(dhcpv6_option_ptr, &option_code, &option_length);
11140
11141 /* Check that the block data is valid. */
11142 if (status != NX_SUCCESS)
11143 {
11144
11145 /* No, return the error status. */
11146 return status;
11147 }
11148
11149 /* Check if option data is in the packet. */
11150 if ((dhcpv6_option_ptr + 4 + option_length) > packet_ptr -> nx_packet_append_ptr)
11151 {
11152 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11153 }
11154
11155 /* Process the option code with an option specific API. */
11156 switch (option_code)
11157 {
11158
11159 /* Note - these 'process' functions will not move the buffer pointer. */
11160 case NX_DHCPV6_OP_CLIENT_ID:
11161 {
11162
11163 /* Yes, The message includes the Client DUID option. */
11164 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_CLIENT_ID_OPTION;
11165 break;
11166 }
11167
11168 case NX_DHCPV6_OP_SERVER_ID:
11169 {
11170
11171 /* Yes, The message includes the Server DUID option. */
11172 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_SERVER_ID_OPTION;
11173 break;
11174 }
11175 case NX_DHCPV6_OP_IA_NA:
11176 {
11177
11178 /* The minimum length of IANA option field is 12 bytes. */
11179 if (option_length < 12)
11180 {
11181 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11182 }
11183
11184 /* Yes, The message includes the Server DUID option. */
11185 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_IA_NA_OPTION;
11186
11187 /* Skip the IA_NA header data (4 bytes for IANA option code and option length, 12 bytes for IANA option field). */
11188 dhcpv6_iana_option_ptr = dhcpv6_option_ptr + 4 + 12;
11189 iana_index = 0;
11190
11191 /* Process the IA and status options embedded in the IANA option. */
11192 /* 12 bytes is IA_NA header, 4 bytes for iana sub option code and option length. */
11193 while(iana_index + 4 <= (option_length - 12))
11194 {
11195
11196 /* Get the next option code and length. */
11197 status = _nx_dhcpv6_utility_get_block_option_length(dhcpv6_iana_option_ptr, &iana_option_code, &iana_option_length);
11198
11199 /* Check if the option data is in the packet. */
11200 if ((dhcpv6_iana_option_ptr + 4 + iana_option_length) > packet_ptr -> nx_packet_append_ptr)
11201 {
11202 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11203 }
11204
11205 /* Check the IA address option embedded in the IANA option. */
11206 if(iana_option_code == NX_DHCPV6_OP_IA_ADDRESS)
11207 {
11208
11209 /* The minimum length of IA address option is 24 bytes. */
11210 if (iana_option_length < 24)
11211 {
11212 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11213 }
11214
11215 /* Yes, The message includes the IA option. */
11216 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_IA_ADDRESS_OPTION;
11217
11218 /* Increase the IA option count. */
11219 ia_count ++;
11220
11221 /* Skip the IA type and length option. */
11222 ia_option_index = 4;
11223
11224 /* Get the IPv6 address of IA option. */
11225 for (w = 0; w <= 3; w++)
11226 {
11227
11228 /* Copy each IPv6 address word into the IA address. */
11229 memcpy(&ipv6_address[w], (dhcpv6_iana_option_ptr + ia_option_index), sizeof(ULONG)); /* Use case of memcpy is verified. */
11230
11231 /* Adjust for endianness. */
11232 NX_CHANGE_ULONG_ENDIAN(ipv6_address[w]);
11233
11234 ia_option_index += 4;
11235 }
11236
11237 /* Check the IA table, find the same IPv6 address. */
11238 for(w = 0; w < NX_DHCPV6_MAX_IA_ADDRESS; w++)
11239 {
11240
11241 if(!(memcmp(&(dhcpv6_ptr->nx_dhcpv6_ia[w].nx_global_address.nxd_ip_address.v6[0]), &ipv6_address[0], 16)))
11242 {
11243
11244 /* Yes, it is, record the index to store the IA option, 0 means is IA address inexistence.
11245 Then update the IA option according to the IA count in nx_dhcpv6_update_ia function. */
11246 dhcpv6_ptr -> nx_dhcpv6_ia[w].nx_address_map = ia_count;
11247 break;
11248 }
11249 }
11250
11251 /* Check the IA option whether include the status codes or not. */
11252 /* 24 bytes is IA address option, 4 bytes for next option code and option length. */
11253 if(iana_option_length >= (24 + 4))
11254 {
11255
11256 /* Yes, include status codes, skip the IA header data. */
11257 dhcpv6_ia_option_ptr = dhcpv6_iana_option_ptr + 28;
11258
11259 /* Get the status code and length. */
11260 status = _nx_dhcpv6_utility_get_block_option_length(dhcpv6_ia_option_ptr, &ia_option_code, &ia_option_length);
11261
11262 /* Check if the option data is in the packet. */
11263 if ((dhcpv6_ia_option_ptr + 4 + ia_option_length) > packet_ptr -> nx_packet_append_ptr)
11264 {
11265 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11266 }
11267
11268 if(ia_option_code == NX_DHCPV6_OP_STATUS_CODE)
11269 {
11270 if (ia_option_length < 2)
11271 {
11272 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11273 }
11274
11275 /* Yes, the message includes the STATUS option, get the code. */
11276 memcpy(&status_code, (dhcpv6_ia_option_ptr + 4), sizeof(USHORT)); /* Use case of memcpy is verified. */
11277
11278 /* Adjust for endianness. */
11279 NX_CHANGE_USHORT_ENDIAN(status_code);
11280
11281 if(status_code == 0)
11282 {
11283
11284 /* Yes, The message includes the Success status option. */
11285 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_SUCCESS_OPTION;
11286 }
11287 else if(status_code == 1)
11288 {
11289
11290 /* Yes, The message includes the UnspecFail status option. */
11291 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_UNSPEC_FAIL_OPTION;
11292 }
11293 else if(status_code == 2)
11294 {
11295
11296 /* Yes, The message includes the NoAddrsAvail status option. */
11297 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NO_ADDR_AVAIL_OPTION;
11298 }
11299 else if(status_code == 3)
11300 {
11301
11302 /* Yes, The message includes the NoBinding status option. */
11303 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NO_BIND_OPTION;
11304 }
11305 else if(status_code == 4)
11306 {
11307
11308 /* Yes, The message includes the NotOnLink status option. */
11309 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NOT_ONLINK_OPTION;
11310 }
11311 else if(status_code == 5)
11312 {
11313
11314 /* Yes, The message includes the UseMulticast status option. */
11315 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_USE_MULTICAST_OPTION;
11316 }
11317 else
11318 {
11319
11320 /* This is an unsupported or unknown option. */
11321 return NX_DHCPV6_UNKNOWN_OPTION;
11322 }
11323
11324 }
11325 else
11326 {
11327
11328 /* This is an unsupported or unknown option. */
11329 return NX_DHCPV6_UNKNOWN_OPTION;
11330 }
11331 }
11332 }
11333
11334 /* Check if this is an status option request. */
11335 else if(iana_option_code == NX_DHCPV6_OP_STATUS_CODE)
11336 {
11337 if (iana_option_length < 2)
11338 {
11339 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11340 }
11341
11342 /* Yes, the message includes the STATUS option, get the code. */
11343 memcpy(&status_code, (dhcpv6_iana_option_ptr + 4), sizeof(USHORT)); /* Use case of memcpy is verified. */
11344
11345 /* Adjust for endianness. */
11346 NX_CHANGE_USHORT_ENDIAN(status_code);
11347
11348 if(status_code == 0)
11349 {
11350
11351 /* Yes, The message includes the Success status option. */
11352 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_SUCCESS_OPTION;
11353 }
11354 else if(status_code == 1)
11355 {
11356
11357 /* Yes, The message includes the UnspecFail status option. */
11358 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_UNSPEC_FAIL_OPTION;
11359 }
11360 else if(status_code == 2)
11361 {
11362
11363 /* Yes, The message includes the NoAddrsAvail status option. */
11364 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NO_ADDR_AVAIL_OPTION;
11365 }
11366 else if(status_code == 3)
11367 {
11368
11369 /* Yes, The message includes the NoBinding status option. */
11370 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NO_BIND_OPTION;
11371 }
11372 else if(status_code == 4)
11373 {
11374
11375 /* Yes, The message includes the NotOnLink status option. */
11376 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NOT_ONLINK_OPTION;
11377 }
11378 else if(status_code == 5)
11379 {
11380
11381 /* Yes, The message includes the UseMulticast status option. */
11382 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_USE_MULTICAST_OPTION;
11383 }
11384 else
11385 {
11386
11387 /* This is an unsupported or unknown option. */
11388 return NX_DHCPV6_UNKNOWN_OPTION;
11389 }
11390 }
11391 else
11392 {
11393
11394 /* This is an unsupported or unknown option. */
11395 return NX_DHCPV6_UNKNOWN_OPTION;
11396 }
11397
11398 /* Move to the next top level option. */
11399 dhcpv6_iana_option_ptr += iana_option_length + 4;
11400
11401 /* Update the iana_index. */
11402 iana_index += iana_option_length + 4;
11403
11404 }
11405
11406 break;
11407 }
11408
11409 case NX_DHCPV6_OP_PREFERENCE:
11410 {
11411
11412 /* The preference option length must be 1 byte. */
11413 if (option_length != 1)
11414 {
11415 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11416 }
11417
11418 /* Yes, The message includes the preference option. */
11419 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_PREFERENCE_OPTION;
11420
11421 /* Record the preference option value of current advetise message. */
11422 dhcpv6_ptr -> nx_dhcpv6_reply_option_current_pref_value = (USHORT)(*(dhcpv6_option_ptr + 4));
11423
11424 break;
11425 }
11426
11427 case NX_DHCPV6_OP_STATUS_CODE:
11428 {
11429
11430 /* The minimum length of status option is 2 bytes. */
11431 if (option_length < 2)
11432 {
11433 return(NX_DHCPV6_INCOMPLETE_OPTION_BLOCK);
11434 }
11435
11436 /* Yes, the message includes the STATUS option, get the code. */
11437 memcpy(&status_code, (dhcpv6_option_ptr + 4), sizeof(USHORT)); /* Use case of memcpy is verified. */
11438
11439 /* Adjust for endianness. */
11440 NX_CHANGE_USHORT_ENDIAN(status_code);
11441
11442 if(status_code == 0)
11443 {
11444
11445 /* Yes, The message includes the Success status option. */
11446 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_SUCCESS_OPTION;
11447 }
11448 else if(status_code == 1)
11449 {
11450
11451 /* Yes, The message includes the UnspecFail status option. */
11452 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_UNSPEC_FAIL_OPTION;
11453 }
11454 else if(status_code == 2)
11455 {
11456
11457 /* Yes, The message includes the NoAddrsAvail status option. */
11458 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NO_ADDR_AVAIL_OPTION;
11459 }
11460 else if(status_code == 3)
11461 {
11462
11463 /* Yes, The message includes the NoBinding status option. */
11464 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NO_BIND_OPTION;
11465 }
11466 else if(status_code == 4)
11467 {
11468
11469 /* Yes, The message includes the NotOnLink status option. */
11470 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_NOT_ONLINK_OPTION;
11471 }
11472 else if(status_code == 5)
11473 {
11474
11475 /* Yes, The message includes the UseMulticast status option. */
11476 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_STATUS_USE_MULTICAST_OPTION;
11477 }
11478 else
11479 {
11480
11481 /* This is an unsupported or unknown option. */
11482 return NX_DHCPV6_UNKNOWN_OPTION;
11483 }
11484 break;
11485 }
11486
11487 case NX_DHCPV6_OP_RAPID_COMMIT:
11488 {
11489
11490 /* Yes, The message includes the Rapid Commit option. */
11491 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_RAPID_COMMIT_OPTION;
11492 break;
11493 }
11494
11495 case NX_DHCPV6_OP_DNS_SERVER:
11496 {
11497
11498 /* Yes, The message includes the DNS server option. */
11499 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_DNS_SERVER_OPTION;
11500 break;
11501 }
11502
11503 case NX_DHCPV6_OP_DOMAIN_NAME:
11504 {
11505
11506 /* Yes, The message includes the domain name option. */
11507 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_DOMAIN_NAME_OPTION;
11508 break;
11509 }
11510
11511 case NX_DHCPV6_OP_SNTP_SERVER:
11512 {
11513
11514 /* Yes, The message includes the timer server option. */
11515 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_SNTP_SERVER_OPTION;
11516 break;
11517 }
11518
11519 case NX_DHCPV6_OP_CLIENT_FQDN:
11520 {
11521
11522 /* Yes, The message includes the Client FQDN option. */
11523 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_CLIENT_FQDN_OPTION;
11524 break;
11525 }
11526
11527 case NX_DHCPV6_OP_NEW_POSIX_TIMEZONE:
11528 {
11529
11530 /* Yes, The message includes the time zone option. */
11531 dhcpv6_ptr -> nx_dhcpv6_reply_option_flags |= NX_DHCPV6_INCLUDE_NEW_POSIX_TIIMEZONE_OPTION;
11532 break;
11533 }
11534
11535 default:
11536 {
11537 break;
11538 }
11539 }
11540
11541 /* Move to the next top level option. */
11542 dhcpv6_option_ptr += option_length + 4;
11543
11544 /* Keep track of how far into the packet we have parsed. */
11545 index += option_length + 4;
11546 }
11547
11548 /* Yes, scan is complete, just return success. */
11549 return NX_SUCCESS;
11550 }
11551
11552 /**************************************************************************/
11553 /* */
11554 /* FUNCTION RELEASE */
11555 /* */
11556 /* _nx_dhcpv6_preprocess_packet_information PORTABLE C */
11557 /* 6.1 */
11558 /* AUTHOR */
11559 /* */
11560 /* Yuxin Zhou, Microsoft Corporation */
11561 /* */
11562 /* DESCRIPTION */
11563 /* */
11564 /* This function preprocess packet information according to reply */
11565 /* message option. */
11566 /* */
11567 /* INPUT */
11568 /* */
11569 /* dhcpv6_ptr Pointer to DHCPv6 Client */
11570 /* packet_ptr Pointer to received packet */
11571 /* */
11572 /* OUTPUT */
11573 /* */
11574 /* NX_DHCPv6_SUCCESS Successful completion status */
11575 /* NX_DHCPV6_NO_DUID_OPTION Message has no DUID option */
11576 /* NX_DHCPV6_NO_RAPID_COMMIT_OPTION Message has no rapid */
11577 /* commit option */
11578 /* NX_DHCPV6_IA_ADDRESS_NOT_VALID Message has no IA option */
11579 /* NX_DHCPV6_EQUAL_OR_LESS_PREF_VALUE Preference value is equal to */
11580 /* or less than */
11581 /* NX_DHCPV6_UNKNOWN_MSG_TYPE Unknown message type */
11582 /* */
11583 /* CALLS */
11584 /* */
11585 /* _nx_dhcpv6_utility_get_data Get the data in reply message */
11586 /* */
11587 /* CALLED BY */
11588 /* */
11589 /* _nx_dhcpv6_packet_process Process the packet. */
11590 /* */
11591 /* RELEASE HISTORY */
11592 /* */
11593 /* DATE NAME DESCRIPTION */
11594 /* */
11595 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11596 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11597 /* resulting in version 6.1 */
11598 /* */
11599 /**************************************************************************/
_nx_dhcpv6_preprocess_packet_information(NX_DHCPV6 * dhcpv6_ptr,NX_PACKET * packet_ptr)11600 UINT _nx_dhcpv6_preprocess_packet_information(NX_DHCPV6 *dhcpv6_ptr, NX_PACKET *packet_ptr)
11601 {
11602
11603 ULONG received_message_type;
11604 ULONG returned_xid;
11605
11606 /* Preprocess the DHCPv6 packet. */
11607
11608 /* Extract the message type which should be the first byte. */
11609 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr, 1, &received_message_type);
11610
11611 /* Check for an illegal message type. */
11612 if ((received_message_type != NX_DHCPV6_MESSAGE_TYPE_ADVERTISE) &&
11613 (received_message_type != NX_DHCPV6_MESSAGE_TYPE_REPLY) &&
11614 (received_message_type != NX_DHCPV6_MESSAGE_TYPE_RECONFIGURE))
11615 {
11616
11617 /* These should only be sent to DHCPv6 servers! */
11618 return NX_DHCPV6_ILLEGAL_MESSAGE_TYPE;
11619 }
11620
11621 /* Set the received message type. */
11622 dhcpv6_ptr -> nx_dhcpv6_received_message_type = (UCHAR)received_message_type;
11623
11624 /* This is a unicast packet (valid). Parse the transaction ID. */
11625 _nx_dhcpv6_utility_get_data((packet_ptr -> nx_packet_prepend_ptr + 1), 3, &returned_xid);
11626
11627 /* Make sure the DHCP transaction ID matches our current session. */
11628 if (returned_xid != (dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_xid))
11629 {
11630
11631 /* Return the bad transmaction ID. */
11632 return NX_DHCPV6_BAD_TRANSACTION_ID;
11633 }
11634
11635 /* Check the options. */
11636 switch (dhcpv6_ptr -> nx_dhcpv6_state)
11637 {
11638
11639 /* The DHCPv6 remains initial status or DHCPv6 interactive process has been completed.
11640 Just clear the timer and message ID. */
11641 case NX_DHCPV6_STATE_BOUND_TO_ADDRESS:
11642 case NX_DHCPV6_STATE_INIT:
11643 {
11644
11645 /* In these state, DHCPv6 Client do not expect any packet. */
11646 return NX_DHCPV6_ILLEGAL_MESSAGE_TYPE;
11647 }
11648
11649 /* The DHCPv6 CLient has sent a solicit message and expect advertise message. */
11650 case NX_DHCPV6_STATE_SENDING_SOLICIT:
11651 {
11652
11653 /* DHCPv6 Client must discrd the received advertise messages
11654 that meet the message does not inlcude SERVER ID or CLIENT ID. */
11655 if(!(dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_CLIENT_ID_OPTION) ||
11656 !(dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_SERVER_ID_OPTION))
11657 {
11658
11659 /* The packet does not include DUID option.*/
11660 return NX_DHCPV6_NO_DUID_OPTION;
11661 }
11662
11663 /* DHcpv6 Client must ignore any advertise message that includes a status code option
11664 containing the value NoAddrsAvail. */
11665 if(dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_STATUS_NO_ADDR_AVAIL_OPTION)
11666 {
11667 return NX_DHCPV6_IA_ADDRESS_NOT_VALID;
11668 }
11669
11670 if(dhcpv6_ptr -> nx_dhcpv6_request_solicit_mode == NX_DHCPV6_SOLICIT_RAPID)
11671 {
11672 if(!(dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_RAPID_COMMIT_OPTION))
11673 {
11674
11675 return NX_DHCPV6_NO_RAPID_COMMIT_OPTION;
11676 }
11677 }
11678 else
11679 {
11680
11681 /* Check the preference value. */
11682 if((dhcpv6_ptr -> nx_dhcpv6_preference.nx_pref_value != 0) &&
11683 (dhcpv6_ptr -> nx_dhcpv6_reply_option_current_pref_value <= dhcpv6_ptr -> nx_dhcpv6_preference.nx_pref_value))
11684 {
11685
11686 /* The current preference value is equal to or less than the recorded preference valude,
11687 DHCPv6 Client need not process the message, return. */
11688 return NX_DHCPV6_EQUAL_OR_LESS_PREF_VALUE;
11689 }
11690 }
11691
11692 break;
11693 }
11694
11695 /* The DHCPv6 CLien has sent a request message and expect reply message. */
11696 case NX_DHCPV6_STATE_SENDING_REQUEST:
11697 case NX_DHCPV6_STATE_SENDING_RENEW:
11698 case NX_DHCPV6_STATE_SENDING_REBIND:
11699 case NX_DHCPV6_STATE_SENDING_CONFIRM:
11700 case NX_DHCPV6_STATE_SENDING_RELEASE:
11701 case NX_DHCPV6_STATE_SENDING_DECLINE:
11702 case NX_DHCPV6_STATE_SENDING_INFORM_REQUEST:
11703 {
11704
11705 /* DHCPv6 Client must discrd the received advertise messages
11706 that meet the message does not inlcude SERVE ID or CLIENT ID. */
11707 if(!(dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_CLIENT_ID_OPTION) ||
11708 !(dhcpv6_ptr -> nx_dhcpv6_reply_option_flags & NX_DHCPV6_INCLUDE_SERVER_ID_OPTION))
11709 {
11710
11711 /* The packet does not include DUID option.*/
11712 return NX_DHCPV6_NO_DUID_OPTION;
11713 }
11714 break;
11715 }
11716
11717 default:
11718 {
11719
11720 /* Unknown or unsupported DHCPv6 request (state). */
11721 return NX_DHCPV6_UNKNOWN_MSG_TYPE;
11722 }
11723 }
11724
11725 return NX_DHCPV6_SUCCESS;
11726 }
11727
11728
11729 /**************************************************************************/
11730 /* */
11731 /* FUNCTION RELEASE */
11732 /* */
11733 /* _nx_dhcpv6_extract_packet_information PORTABLE C */
11734 /* 6.1 */
11735 /* AUTHOR */
11736 /* */
11737 /* Yuxin Zhou, Microsoft Corporation */
11738 /* */
11739 /* DESCRIPTION */
11740 /* */
11741 /* This function parses the DHCPv6 server response to Client requests. */
11742 /* It checks for valid reply message types for the current Client */
11743 /* request, and if all is well, then parses each option in sequential */
11744 /* order and updates the server reply data to the Client record. At the*/
11745 /* end of the data extraction, it then verifies that the server reply */
11746 /* contained both valid Client and server DUID options. */
11747 /* */
11748 /* INPUT */
11749 /* */
11750 /* dhcpv6_ptr Pointer to DHCPv6 Client */
11751 /* packet_ptr Pointer to received packet */
11752 /* */
11753 /* OUTPUT */
11754 /* */
11755 /* status Actual completion status */
11756 /* NX_SUCCESS Successful completion status */
11757 /* NX_DHCPV6_ILLEGAL_MESSAGE_TYPE Packet message type illegal */
11758 /* NX_DHCPV6_BAD_TRANSACTION_ID Message ID fails to match up */
11759 /* NX_DHCPV6_PROCESSING_ERROR Packet length is different than */
11760 /* expected */
11761 /* NX_DHCPV6_UNKNOWN_OPTION Unknown option in message */
11762 /* NX_DHCPV6_MISSING_IANA_OPTION Message has no IANA option */
11763 /* */
11764 /* CALLS */
11765 /* */
11766 /* _nx_dhcpv6_utility_get_block_option_length */
11767 /* Extract option header data */
11768 /* _nx_dhcpv6_process_client_duid Extract Client DUID from reply */
11769 /* _nx_dhcpv6_process_server_duid Extract Server DUID from reply */
11770 /* _nx_dhcpv6_process_iana Extract IANA option from reply */
11771 /* _nx_dhcpv6_process_preference Extract server preference */
11772 /* _nx_dhcpv6_process_DNS_server Extract DNS server from reply */
11773 /* _nx_dhcpv6_process_time_server Extract time server from reply */
11774 /* _nx_dhcpv6_process_time_zone Extract time zone from reply */
11775 /* _nx_dhcpv6_process_domain_name Extract domain name from reply */
11776 /* */
11777 /* CALLED BY */
11778 /* */
11779 /* _nx_dhcpv6_packet_process Process the dhcpv6 reply message*/
11780 /* */
11781 /* RELEASE HISTORY */
11782 /* */
11783 /* DATE NAME DESCRIPTION */
11784 /* */
11785 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11786 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
11787 /* packet length verification, */
11788 /* resulting in version 6.1 */
11789 /* */
11790 /**************************************************************************/
_nx_dhcpv6_extract_packet_information(NX_DHCPV6 * dhcpv6_ptr,NX_PACKET * packet_ptr)11791 UINT _nx_dhcpv6_extract_packet_information(NX_DHCPV6 *dhcpv6_ptr, NX_PACKET *packet_ptr)
11792 {
11793
11794 UINT status;
11795 ULONG option_code;
11796 ULONG option_length;
11797 UCHAR *buffer_ptr;
11798 UINT index;
11799
11800 /* The DHCPv6 header has been processed in preprocess function, so process the options. */
11801 /* Set a pointer to the options of DHCPv6. */
11802 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr + 4;
11803
11804 /* Update index to the options. */
11805 index = 4;
11806
11807 /* Now parse all the DHCPv6 option blocks in the packet buffer. */
11808 while (index + 4 <= packet_ptr -> nx_packet_length)
11809 {
11810
11811 /* Get the option code and length of data of the current option block. */
11812 status = _nx_dhcpv6_utility_get_block_option_length(buffer_ptr, &option_code, &option_length);
11813
11814 /* Check that the block data is valid. */
11815 if (status != NX_SUCCESS)
11816 {
11817
11818 /* No, return the error status. */
11819 return status;
11820 }
11821
11822 /* Keep track of how far into the packet we have parsed. */
11823 index += option_length + 4;
11824
11825 /* This is a double check to verify we haven't gone off the end of the packet buffer. */
11826 if (index > packet_ptr -> nx_packet_length)
11827 {
11828 return(NX_DHCPV6_INVALID_DATA_SIZE);
11829 }
11830
11831 /* Update buffer pointer to option data. */
11832 buffer_ptr += 4;
11833
11834 /* Process the option code with an option specific API. */
11835 switch (option_code)
11836 {
11837
11838 /* Note - these 'process' functions will not move the buffer pointer. */
11839
11840 case NX_DHCPV6_OP_CLIENT_ID:
11841 {
11842
11843 /* Process the Client DUID. */
11844 status = _nx_dhcpv6_process_client_duid(dhcpv6_ptr, buffer_ptr, option_length);
11845
11846 break;
11847 }
11848
11849 case NX_DHCPV6_OP_SERVER_ID:
11850 {
11851
11852 /* Process the Server DUID. */
11853 status = _nx_dhcpv6_process_server_duid(dhcpv6_ptr, buffer_ptr, option_length);
11854
11855 break;
11856 }
11857 case NX_DHCPV6_OP_IA_NA:
11858 {
11859
11860 status = _nx_dhcpv6_process_iana(dhcpv6_ptr, buffer_ptr, option_length);
11861
11862 /* Note: this API directly handles any server error codes received. */
11863
11864 break;
11865 }
11866
11867 /* This should not happen. The IA address option must be embedded in the IANA option. */
11868 case NX_DHCPV6_OP_IA_ADDRESS:
11869 {
11870
11871 /* Don't process an IA address option outside of an address association (IANA). */
11872 status = NX_DHCPV6_MISSING_IANA_OPTION;
11873
11874 break;
11875 }
11876
11877 /* The RFC for DHCPv6 indicates any option can have a status option applied to it. So a status
11878 option outside of an IANA option (where it is usually found) has to be handled. */
11879 case NX_DHCPV6_OP_STATUS_CODE:
11880 {
11881 status = _nx_dhcpv6_process_status(dhcpv6_ptr, buffer_ptr, option_length);
11882
11883 /* Now check on the server status of the previous option in the DHCP message. */
11884 if ((status == NX_SUCCESS) && (dhcpv6_ptr -> nx_status_code != NX_DHCPV6_SUCCESS))
11885 {
11886
11887 /* Does the dhcpv6 client have a server error handler? */
11888 if (dhcpv6_ptr -> nx_dhcpv6_server_error_handler)
11889 {
11890
11891 /* Send the status and which option the status is reported for to the handler. */
11892 (dhcpv6_ptr -> nx_dhcpv6_server_error_handler)(dhcpv6_ptr, NX_DHCPV6_ERROR_STATUS_CODE_IN_OPTION_FIELD, dhcpv6_ptr -> nx_status_code,
11893 dhcpv6_ptr -> nx_dhcpv6_received_message_type);
11894 }
11895 }
11896
11897 break;
11898 }
11899
11900 /* Process the preference option. */
11901 case NX_DHCPV6_OP_PREFERENCE:
11902 {
11903
11904 status = _nx_dhcpv6_process_preference(dhcpv6_ptr, buffer_ptr, option_length);
11905 break;
11906 }
11907
11908 /* The remainder are RFC mandated option codes for specific options. Not all of these
11909 have been finalized by IANA as of this release. */
11910
11911 case NX_DHCPV6_OP_DNS_SERVER:
11912 {
11913
11914 status = _nx_dhcpv6_process_DNS_server(dhcpv6_ptr, buffer_ptr, option_length);
11915
11916 break;
11917 }
11918
11919 case NX_DHCPV6_OP_DOMAIN_NAME:
11920 {
11921 status = _nx_dhcpv6_process_domain_name(dhcpv6_ptr, packet_ptr -> nx_packet_prepend_ptr, buffer_ptr, option_length);
11922 break;
11923 }
11924
11925 case NX_DHCPV6_OP_SNTP_SERVER:
11926 {
11927
11928 status = _nx_dhcpv6_process_time_server(dhcpv6_ptr, buffer_ptr, option_length);
11929 break;
11930 }
11931
11932 case NX_DHCPV6_OP_NEW_POSIX_TIMEZONE:
11933 {
11934 status = _nx_dhcpv6_process_time_zone(dhcpv6_ptr, buffer_ptr, option_length);
11935 break;
11936 }
11937
11938 default:
11939 {
11940 break;
11941 }
11942 }
11943
11944 /* Check for errors from option block processing. */
11945 if (status != NX_SUCCESS)
11946 {
11947
11948 return status;
11949 }
11950
11951 /* Move to the next top level option. */
11952 buffer_ptr += option_length;
11953 }
11954
11955 /* Now, the index should be the packet length. */
11956 if(index != packet_ptr -> nx_packet_length)
11957 {
11958 return(NX_DHCPV6_INVALID_DATA_SIZE);
11959 }
11960
11961 /* Yes, the packet data processing is completed. */
11962 return NX_SUCCESS;
11963 }
11964
11965
11966 /**************************************************************************/
11967 /* */
11968 /* FUNCTION RELEASE */
11969 /* */
11970 /* _nx_dhcpv6_flush_queue_packets PORTABLE C */
11971 /* 6.1 */
11972 /* AUTHOR */
11973 /* */
11974 /* Yuxin Zhou, Microsoft Corporation */
11975 /* */
11976 /* DESCRIPTION */
11977 /* */
11978 /* This function flush the useless queue packets. */
11979 /* */
11980 /* INPUT */
11981 /* */
11982 /* dhcpv6_ptr Pointer to DHCPv6 Client */
11983 /* */
11984 /* OUTPUT */
11985 /* */
11986 /* None */
11987 /* */
11988 /* CALLS */
11989 /* */
11990 /* nx_udp_socket_receive Receive UDP packet */
11991 /* nx_packet_release Release packet to packet pool */
11992 /* */
11993 /* CALLED BY */
11994 /* */
11995 /* _nx_dhcpv6_process Process the DHCPv6 Client request */
11996 /* */
11997 /* RELEASE HISTORY */
11998 /* */
11999 /* DATE NAME DESCRIPTION */
12000 /* */
12001 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12002 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12003 /* resulting in version 6.1 */
12004 /* */
12005 /**************************************************************************/
_nx_dhcpv6_flush_queue_packets(NX_DHCPV6 * dhcpv6_ptr)12006 VOID _nx_dhcpv6_flush_queue_packets(NX_DHCPV6 *dhcpv6_ptr)
12007 {
12008
12009 UINT status = NX_SUCCESS;
12010 NX_PACKET *packet_ptr;
12011
12012
12013 /* Loop to receive the queue packets. */
12014 while(status == NX_SUCCESS)
12015 {
12016
12017 /* Receive the queue packets and release it. */
12018 status = nx_udp_socket_receive(&(dhcpv6_ptr -> nx_dhcpv6_socket), &packet_ptr, NX_NO_WAIT);
12019
12020 /* Check the status. */
12021 if (status == NX_SUCCESS)
12022 {
12023
12024 /* Release the packet. */
12025 nx_packet_release(packet_ptr);
12026 }
12027 }
12028 }
12029
12030
12031 /**************************************************************************/
12032 /* */
12033 /* FUNCTION RELEASE */
12034 /* */
12035 /* _nx_dhcpv6_update_retransmit_info PORTABLE C */
12036 /* 6.1 */
12037 /* AUTHOR */
12038 /* */
12039 /* Yuxin Zhou, Microsoft Corporation */
12040 /* */
12041 /* DESCRIPTION */
12042 /* */
12043 /* This function process the retransmission,update the retransmission */
12044 /* count and retransmission timeout according to the RFC3315,Section14.*/
12045 /* */
12046 /* INPUT */
12047 /* */
12048 /* dhcpv6_ptr Pointer to DHCPV6 Client instance */
12049 /* */
12050 /* OUTPUT */
12051 /* */
12052 /* status Actual completion status */
12053 /* NX_SUCCESS Valid retransmit */
12054 /* */
12055 /* CALLS */
12056 /* */
12057 /* */
12058 /* CALLED BY */
12059 /* */
12060 /* _nx_dhcpv6_process Process current client state */
12061 /* */
12062 /* RELEASE HISTORY */
12063 /* */
12064 /* DATE NAME DESCRIPTION */
12065 /* */
12066 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12067 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12068 /* resulting in version 6.1 */
12069 /* */
12070 /**************************************************************************/
_nx_dhcpv6_update_retransmit_info(NX_DHCPV6 * dhcpv6_ptr)12071 UINT _nx_dhcpv6_update_retransmit_info(NX_DHCPV6 *dhcpv6_ptr)
12072 {
12073
12074 /* Process the retransmission according to the RFC3315, Section 14, page26. */
12075 if((dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count != 0) || (dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration != 0))
12076 {
12077
12078 if((dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count != 0) &&
12079 (dhcpv6_ptr -> nx_dhcpv6_retransmission_count >= dhcpv6_ptr -> nx_dhcpv6_max_retransmission_count))
12080 {
12081
12082 /* Has reached the max retransmission count, return. */
12083 return NX_DHCPV6_REACHED_MAX_RETRANSMISSION_COUNT;
12084 }
12085
12086 if((dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration != 0) &&
12087 (dhcpv6_ptr -> nx_dhcpv6_elapsed_time.nx_session_time >= (dhcpv6_ptr -> nx_dhcpv6_max_retransmission_duration * 100)))
12088 {
12089
12090 /* Has reached the max retransmission timeout, return. */
12091 return NX_DHCPV6_REACHED_MAX_RETRANSMISSION_TIMEOUT;
12092 }
12093 }
12094
12095 /* Increase the count of retransmission. */
12096 dhcpv6_ptr -> nx_dhcpv6_retransmission_count++;
12097
12098 /* Double the retransmission timeout for the next retransmit. */
12099 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = 2 * dhcpv6_ptr -> nx_dhcpv6_transmission_timeout;
12100
12101 /* Is the retransmission timeout greater than the max allowable timeout, if there is one? */
12102 if ((dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout != 0) &&
12103 (dhcpv6_ptr -> nx_dhcpv6_transmission_timeout > dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout))
12104 {
12105
12106 /* Limit the transmission time to the max for the next message. */
12107 dhcpv6_ptr -> nx_dhcpv6_transmission_timeout = dhcpv6_ptr -> nx_dhcpv6_max_retransmission_timeout;
12108 }
12109
12110 /* Can retransmit the request. */
12111 return NX_SUCCESS;
12112 }
12113
12114
12115 /**************************************************************************/
12116 /* */
12117 /* FUNCTION RELEASE */
12118 /* */
12119 /* _nxe_dhcpv6_user_option_add_callback_set PORTABLE C */
12120 /* 6.1.12 */
12121 /* AUTHOR */
12122 /* */
12123 /* Yuxin Zhou, Microsoft Corporation */
12124 /* */
12125 /* DESCRIPTION */
12126 /* */
12127 /* This function performs error checking on the user option add */
12128 /* callback set service. */
12129 /* */
12130 /* INPUT */
12131 /* */
12132 /* dhcpv6_ptr Pointer to DHCPv6 instance */
12133 /* dhcpv6_user_option_add Pointer to application's */
12134 /* option add function */
12135 /* */
12136 /* OUTPUT */
12137 /* */
12138 /* status Completion status */
12139 /* */
12140 /* CALLS */
12141 /* */
12142 /* _nx_dhcpv6_user_option_add_callback_set Actual user option callback */
12143 /* set service */
12144 /* */
12145 /* CALLED BY */
12146 /* */
12147 /* Application Code */
12148 /* */
12149 /* RELEASE HISTORY */
12150 /* */
12151 /* DATE NAME DESCRIPTION */
12152 /* */
12153 /* 07-29-2022 Yuxin Zhou Initial Version 6.1.12 */
12154 /* */
12155 /**************************************************************************/
_nxe_dhcpv6_user_option_add_callback_set(NX_DHCPV6 * dhcpv6_ptr,UINT (* dhcpv6_user_option_add)(NX_DHCPV6 * dhcpv6_ptr,UINT interface_index,UINT message_type,UCHAR * user_option_ptr,UINT * user_option_length))12156 UINT _nxe_dhcpv6_user_option_add_callback_set(NX_DHCPV6 *dhcpv6_ptr, UINT (*dhcpv6_user_option_add)(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index, UINT message_type,
12157 UCHAR *user_option_ptr, UINT *user_option_length))
12158 {
12159
12160 UINT status;
12161
12162 /* Check for invalid input. */
12163 if ((dhcpv6_ptr == NX_NULL) || (dhcpv6_user_option_add == NX_NULL))
12164 {
12165 return(NX_PTR_ERROR);
12166 }
12167
12168 /* Call actual DHCPv6 user option callback set service. */
12169 status = _nx_dhcpv6_user_option_add_callback_set(dhcpv6_ptr, dhcpv6_user_option_add);
12170
12171 /* Return status. */
12172 return(status);
12173 }
12174
12175
12176 /**************************************************************************/
12177 /* */
12178 /* FUNCTION RELEASE */
12179 /* */
12180 /* _nx_dhcpv6_user_option_add_callback_set PORTABLE C */
12181 /* 6.1.12 */
12182 /* AUTHOR */
12183 /* */
12184 /* Yuxin Zhou, Microsoft Corporation */
12185 /* */
12186 /* DESCRIPTION */
12187 /* */
12188 /* This function sets the user option add callback. */
12189 /* */
12190 /* INPUT */
12191 /* */
12192 /* dhcpv6_ptr Pointer to DHCPv6 instance */
12193 /* dhcpv6_user_option_add Pointer to application's */
12194 /* option add function */
12195 /* */
12196 /* OUTPUT */
12197 /* */
12198 /* status Completion status */
12199 /* */
12200 /* CALLS */
12201 /* */
12202 /* None */
12203 /* */
12204 /* CALLED BY */
12205 /* */
12206 /* Application Code */
12207 /* */
12208 /* RELEASE HISTORY */
12209 /* */
12210 /* DATE NAME DESCRIPTION */
12211 /* */
12212 /* 07-29-2022 Yuxin Zhou Initial Version 6.1.12 */
12213 /* */
12214 /**************************************************************************/
_nx_dhcpv6_user_option_add_callback_set(NX_DHCPV6 * dhcpv6_ptr,UINT (* dhcpv6_user_option_add)(NX_DHCPV6 * dhcpv6_ptr,UINT interface_index,UINT message_type,UCHAR * user_option_ptr,UINT * user_option_length))12215 UINT _nx_dhcpv6_user_option_add_callback_set(NX_DHCPV6 *dhcpv6_ptr, UINT (*dhcpv6_user_option_add)(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index, UINT message_type,
12216 UCHAR *user_option_ptr, UINT *user_option_length))
12217 {
12218
12219 /* Obtain DHCPv6 Client protection mutex. */
12220 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), TX_WAIT_FOREVER);
12221
12222 /* Set the callback. */
12223 dhcpv6_ptr -> nx_dhcpv6_user_option_add = dhcpv6_user_option_add;
12224
12225 /* Release the mutex. */
12226 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
12227
12228 /* Return a successful status. */
12229 return(NX_SUCCESS);
12230 }
12231
12232
12233 #if !defined (NX_DISABLE_IPV6_DAD) && defined (NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY)
12234 /**************************************************************************/
12235 /* */
12236 /* FUNCTION RELEASE */
12237 /* */
12238 /* _nx_dhcpv6_ipv6_address_DAD_notify PORTABLE C */
12239 /* 6.1 */
12240 /* AUTHOR */
12241 /* */
12242 /* Yuxin Zhou, Microsoft Corporation */
12243 /* */
12244 /* DESCRIPTION */
12245 /* */
12246 /* This function is the IPv6 address perform DAD notify callback. */
12247 /* And set the DHCPv6 event to notify DHCPv6 Client thread. If this */
12248 /* function is used in DHCPv6 function, nxd_ipv6_address_change_notify */
12249 /* function should not be used again. */
12250 /* */
12251 /* INPUT */
12252 /* */
12253 /* ip_ptr Pointer to IP instance */
12254 /* status DAD process status */
12255 /* interface_index The interface index */
12256 /* ipv6_addr_index The IPv6 address index */
12257 /* ipv6_address Pointer to IPv6 address */
12258 /* */
12259 /* OUTPUT */
12260 /* */
12261 /* None */
12262 /* */
12263 /* CALLS */
12264 /* */
12265 /* tx_event_flags_set Set event flags to wake */
12266 /* DHCPv6 thread to process */
12267 /* */
12268 /* CALLED BY */
12269 /* */
12270 /* UDP receive callback */
12271 /* */
12272 /* RELEASE HISTORY */
12273 /* */
12274 /* DATE NAME DESCRIPTION */
12275 /* */
12276 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12277 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12278 /* resulting in version 6.1 */
12279 /* */
12280 /**************************************************************************/
_nx_dhcpv6_ipv6_address_DAD_notify(NX_IP * ip_ptr,UINT status,UINT interface_index,UINT ipv6_addr_index,ULONG * ipv6_address)12281 VOID _nx_dhcpv6_ipv6_address_DAD_notify(NX_IP *ip_ptr, UINT status, UINT interface_index, UINT ipv6_addr_index, ULONG *ipv6_address)
12282 {
12283 UINT ia_index;
12284
12285 NX_PARAMETER_NOT_USED(interface_index);
12286
12287 /* Make sure the DHCPv6 DAD instance is normal. */
12288 if((_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_id != NX_DHCPV6_ID) ||
12289 (!_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_name) ||
12290 (_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_ip_ptr != ip_ptr) ||
12291 (_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_state != NX_DHCPV6_STATE_BOUND_TO_ADDRESS))
12292 return;
12293
12294
12295 /* Check the DAD status. */
12296 if(status == NX_IPV6_ADDRESS_DAD_FAILURE)
12297 {
12298
12299 /* Now find where this address cross references in the DHCP address list. */
12300 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
12301 {
12302
12303 if((_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_client_address_index[ia_index] == ipv6_addr_index) &&
12304 (!memcmp(&(_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0]), ipv6_address, 16)))
12305 {
12306
12307 /* Set the IPv6 address status DAD failure. */
12308 _nx_dhcpv6_DAD_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status = NX_DHCPV6_IA_ADDRESS_STATE_DAD_FAILURE;
12309
12310 /* Wakeup DHCPv6 thread for processing DAD failure event. */
12311 tx_event_flags_set(&_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_events, NX_DHCPV6_DAD_FAILURE_EVENT, TX_OR);
12312
12313 break;
12314 }
12315 }
12316 }
12317
12318 /* Check the DAD status. */
12319 if(status == NX_IPV6_ADDRESS_DAD_SUCCESSFUL)
12320 {
12321
12322 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
12323 {
12324
12325 if((_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_client_address_index[ia_index] == ipv6_addr_index) &&
12326 (!memcmp(&(_nx_dhcpv6_DAD_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address.nxd_ip_address.v6[0]), ipv6_address, 16)))
12327 {
12328
12329 /* Set the IPv6 address status valid. */
12330 _nx_dhcpv6_DAD_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status = NX_DHCPV6_IA_ADDRESS_STATE_VALID;
12331
12332 break;
12333 }
12334 }
12335 }
12336
12337 return;
12338 }
12339 #endif
12340
12341
12342 #ifdef NX_DHCPV6_CLIENT_RESTORE_STATE
12343 /**************************************************************************/
12344 /* */
12345 /* FUNCTION RELEASE */
12346 /* */
12347 /* _nxe_dhcpv6_client_get_record PORTABLE C */
12348 /* 6.1 */
12349 /* AUTHOR */
12350 /* */
12351 /* Yuxin Zhou, Microsoft Corporation */
12352 /* */
12353 /* DESCRIPTION */
12354 /* */
12355 /* This function performs error checking on the get DHCPv6 Client */
12356 /* record service. */
12357 /* */
12358 /* INPUT */
12359 /* */
12360 /* dhcpv6_ptr Pointer to DHCPv6 instance */
12361 /* client_record_ptr Pointer to memory to save */
12362 /* Client record to */
12363 /* */
12364 /* OUTPUT */
12365 /* */
12366 /* NX_PTR_ERROR Invalid pointer input */
12367 /* status Completion status from */
12368 /* internal DHCP calls */
12369 /* */
12370 /* CALLS */
12371 /* */
12372 /* _nx_dhcpv6_client_create_record */
12373 /* */
12374 /* CALLED BY */
12375 /* */
12376 /* Application code */
12377 /* */
12378 /* RELEASE HISTORY */
12379 /* */
12380 /* DATE NAME DESCRIPTION */
12381 /* */
12382 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12383 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12384 /* resulting in version 6.1 */
12385 /* */
12386 /**************************************************************************/
_nxe_dhcpv6_client_get_record(NX_DHCPV6 * dhcpv6_ptr,NX_DHCPV6_CLIENT_RECORD * client_record_ptr)12387 UINT _nxe_dhcpv6_client_get_record(NX_DHCPV6 *dhcpv6_ptr, NX_DHCPV6_CLIENT_RECORD *client_record_ptr)
12388 {
12389
12390 UINT status;
12391
12392
12393 /* Check for invalid pointer input. */
12394 if ((dhcpv6_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
12395 {
12396 return NX_PTR_ERROR;
12397 }
12398
12399 /* Call actual DHCPv6 client get record service. */
12400 status = _nx_dhcpv6_client_get_record(dhcpv6_ptr, client_record_ptr);
12401
12402 return status;
12403 }
12404
12405 /**************************************************************************/
12406 /* */
12407 /* FUNCTION RELEASE */
12408 /* */
12409 /* _nx_dhcpv6_client_get_record PORTABLE C */
12410 /* 6.1 */
12411 /* AUTHOR */
12412 /* */
12413 /* Yuxin Zhou, Microsoft Corporation */
12414 /* */
12415 /* DESCRIPTION */
12416 /* */
12417 /* This function creates a DHCPv6 Client record for restoring the */
12418 /* Client state between power cycles or idle (sleep) mode. It then */
12419 /* copies the Client record to the supplied client record pointer. It */
12420 /* should be that the DHCPv6 Client state be restored from the Client */
12421 /* record saved to the input pointer client_record_ptr. */
12422 /* */
12423 /* INPUT */
12424 /* */
12425 /* dhcpv6_ptr Pointer to DHCPv6 instance */
12426 /* client_record_ptr Pointer to memory to save */
12427 /* Client record to */
12428 /* */
12429 /* OUTPUT */
12430 /* */
12431 /* NX_SUCCESS Successful completion status */
12432 /* NX_DHCPV6_NOT_BOUND DHCPv6 was not bound */
12433 /* */
12434 /* CALLS */
12435 /* */
12436 /* memcpy Copy specified area of memory */
12437 /* */
12438 /* CALLED BY */
12439 /* */
12440 /* Application code */
12441 /* */
12442 /* RELEASE HISTORY */
12443 /* */
12444 /* DATE NAME DESCRIPTION */
12445 /* */
12446 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12447 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
12448 /* verified memcpy use cases, */
12449 /* resulting in version 6.1 */
12450 /* */
12451 /**************************************************************************/
_nx_dhcpv6_client_get_record(NX_DHCPV6 * dhcpv6_ptr,NX_DHCPV6_CLIENT_RECORD * client_record_ptr)12452 UINT _nx_dhcpv6_client_get_record(NX_DHCPV6 *dhcpv6_ptr, NX_DHCPV6_CLIENT_RECORD *client_record_ptr)
12453 {
12454
12455
12456 /* Get the DHCP mutex. */
12457 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
12458
12459 /* Clear memory before filling with data. */
12460 memset(client_record_ptr, 0, sizeof(NX_DHCPV6_CLIENT_RECORD));
12461
12462 /* The DHCPv6 Client is not Bound to an IP address. Cannot create a record for restoring Client
12463 state if not bound to an IP lease. */
12464 if (dhcpv6_ptr -> nx_dhcpv6_state != NX_DHCPV6_STATE_BOUND_TO_ADDRESS)
12465 {
12466 return NX_DHCPV6_NOT_BOUND;
12467 }
12468
12469 /* Set the DHCPv6 record. */
12470 client_record_ptr -> nx_dhcpv6_state = dhcpv6_ptr -> nx_dhcpv6_state;
12471
12472 /* Set the interface and address index. */
12473 client_record_ptr -> nx_dhcpv6_client_interface_index = dhcpv6_ptr -> nx_dhcpv6_client_interface_index;
12474 memcpy(client_record_ptr -> nx_dhcpv6_client_address_index, dhcpv6_ptr -> nx_dhcpv6_client_address_index, sizeof(UINT) * NX_DHCPV6_MAX_IA_ADDRESS); /* Use case of memcpy is verified. */
12475
12476 /* Set the time since client set its IP address. */
12477 client_record_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued;
12478
12479 /* Set the Client DUID. */
12480 memcpy(&client_record_ptr -> nx_dhcpv6_client_duid, &dhcpv6_ptr -> nx_dhcpv6_client_duid, sizeof(NX_DHCPV6_DUID)); /* Use case of memcpy is verified. */
12481
12482 /* Set the Server DUID. */
12483 memcpy(&client_record_ptr -> nx_dhcpv6_server_duid, &dhcpv6_ptr -> nx_dhcpv6_server_duid, sizeof(NX_DHCPV6_DUID)); /* Use case of memcpy is verified. */
12484
12485 /* Set the IANA. */
12486 memcpy(&client_record_ptr -> nx_dhcpv6_iana, &dhcpv6_ptr -> nx_dhcpv6_iana, sizeof(NX_DHCPV6_IA_NA)); /* Use case of memcpy is verified. */
12487
12488 /* Set the IA Address. */
12489 memcpy(&client_record_ptr -> nx_dhcpv6_ia, &dhcpv6_ptr -> nx_dhcpv6_ia, sizeof(NX_DHCPV6_IA_ADDRESS) * NX_DHCPV6_MAX_IA_ADDRESS); /* Use case of memcpy is verified. */
12490
12491 /* Set the Option request. */
12492 memcpy(&client_record_ptr -> nx_dhcpv6_option_request, &dhcpv6_ptr -> nx_dhcpv6_option_request, sizeof(NX_DHCPV6_OPTIONREQUEST)); /* Use case of memcpy is verified. */
12493
12494 /* Set the Client FQDN. */
12495 memcpy(&client_record_ptr -> nx_dhcpv6_client_FQDN, &dhcpv6_ptr -> nx_dhcpv6_client_FQDN, sizeof(NX_DHCPV6_CLIENT_FQDN)); /* Use case of memcpy is verified. */
12496
12497 /* Set the dns name server address. */
12498 memcpy(&client_record_ptr -> nx_dhcpv6_DNS_name_server_address, &dhcpv6_ptr -> nx_dhcpv6_DNS_name_server_address, sizeof(NXD_ADDRESS) * NX_DHCPV6_NUM_DNS_SERVERS); /* Use case of memcpy is verified. */
12499
12500 /* Set the time server address. */
12501 memcpy(&client_record_ptr -> nx_dhcpv6_time_server_address, &dhcpv6_ptr -> nx_dhcpv6_time_server_address, sizeof(NXD_ADDRESS) * NX_DHCPV6_NUM_TIME_SERVERS); /* Use case of memcpy is verified. */
12502
12503 /* Set the domain name. */
12504 memcpy(client_record_ptr -> nx_dhcpv6_domain_name, dhcpv6_ptr -> nx_dhcpv6_domain_name, NX_DHCPV6_DOMAIN_NAME_BUFFER_SIZE); /* Use case of memcpy is verified. */
12505
12506 /* Set the time zone. */
12507 memcpy(client_record_ptr -> nx_dhcpv6_time_zone, dhcpv6_ptr -> nx_dhcpv6_time_zone, NX_DHCPV6_TIME_ZONE_BUFFER_SIZE); /* Use case of memcpy is verified. */
12508
12509 /* Release the DHCPv6 Client mutex. */
12510 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
12511
12512 return NX_SUCCESS;
12513 }
12514
12515
12516 /**************************************************************************/
12517 /* */
12518 /* FUNCTION RELEASE */
12519 /* */
12520 /* _nxe_dhcpv6_client_restore_record PORTABLE C */
12521 /* 6.1 */
12522 /* AUTHOR */
12523 /* */
12524 /* Yuxin Zhou, Microsoft Corporation */
12525 /* */
12526 /* DESCRIPTION */
12527 /* */
12528 /* This function performs error checking on the client restore service.*/
12529 /* */
12530 /* INPUT */
12531 /* */
12532 /* dhcpv6_ptr Pointer to DHCPv6 instance */
12533 /* client_record_ptr Pointer to previously saved */
12534 /* Client record */
12535 /* time_elapsed time input in timer ticks */
12536 /* */
12537 /* OUTPUT */
12538 /* */
12539 /* NX_PTR_ERRPR Invalid pointer input */
12540 /* status NetX completion status */
12541 /* */
12542 /* CALLS */
12543 /* */
12544 /* _nx_dhcp_client_restore_record */
12545 /* */
12546 /* CALLED BY */
12547 /* */
12548 /* Application code */
12549 /* */
12550 /* RELEASE HISTORY */
12551 /* */
12552 /* DATE NAME DESCRIPTION */
12553 /* */
12554 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12555 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12556 /* resulting in version 6.1 */
12557 /* */
12558 /**************************************************************************/
_nxe_dhcpv6_client_restore_record(NX_DHCPV6 * dhcpv6_ptr,NX_DHCPV6_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)12559 UINT _nxe_dhcpv6_client_restore_record(NX_DHCPV6 *dhcpv6_ptr, NX_DHCPV6_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
12560 {
12561
12562 UINT status;
12563
12564
12565 /* Check for invalid pointer input. */
12566 if ((dhcpv6_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
12567 {
12568 return NX_PTR_ERROR;
12569 }
12570
12571 /* Call actual DHCPv6 client get record service. */
12572 status = _nx_dhcpv6_client_restore_record(dhcpv6_ptr, client_record_ptr, time_elapsed);
12573
12574 return status;
12575 }
12576
12577 /**************************************************************************/
12578 /* */
12579 /* FUNCTION RELEASE */
12580 /* */
12581 /* _nx_dhcpv6_client_restore_record PORTABLE C */
12582 /* 6.1 */
12583 /* AUTHOR */
12584 /* */
12585 /* Yuxin Zhou, Microsoft Corporation */
12586 /* */
12587 /* DESCRIPTION */
12588 /* */
12589 /* This function updates the DHCPv6 CLient state with the supplied DHCP*/
12590 /* Client record pointed to by the client_record_ptr pointer. It then */
12591 /* updates the time out parameters of the DHCPv6 Client with the */
12592 /* time_elapsed parameter (in timer ticks). It is intended for */
12593 /* restoring Client state between reboots and assumes the DHCPv6 Client*/
12594 /* state was previously obtained and stored in NVRAM before power down.*/
12595 /* */
12596 /* Note: after restore the DHCPv6 Client record, should call */
12597 /* nx_dhcpv6_resume to update the DHCPv6 Client state and resume the */
12598 /* DHCPv6 processing thread. */
12599 /* */
12600 /* INPUT */
12601 /* */
12602 /* dhcpv6_ptr Pointer to DHCPv6 instance */
12603 /* client_record_ptr Pointer to previously saved */
12604 /* Client record */
12605 /* time_elapsed time input in timer ticks */
12606 /* */
12607 /* OUTPUT */
12608 /* */
12609 /* NX_SUCCESS Successful completion status */
12610 /* status NetX completion status */
12611 /* */
12612 /* CALLS */
12613 /* */
12614 /* nx_ip_interface_address_set */
12615 /* nx_ip_address_set */
12616 /* _nx_dhcp_client_update_time_remaining */
12617 /* memcpy */
12618 /* */
12619 /* CALLED BY */
12620 /* */
12621 /* Application code */
12622 /* */
12623 /* RELEASE HISTORY */
12624 /* */
12625 /* DATE NAME DESCRIPTION */
12626 /* */
12627 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12628 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
12629 /* verified memcpy use cases, */
12630 /* resulting in version 6.1 */
12631 /* */
12632 /**************************************************************************/
_nx_dhcpv6_client_restore_record(NX_DHCPV6 * dhcpv6_ptr,NX_DHCPV6_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)12633 UINT _nx_dhcpv6_client_restore_record(NX_DHCPV6 *dhcpv6_ptr, NX_DHCPV6_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
12634 {
12635
12636 UINT ia_index;
12637
12638
12639 /* Get the DHCP mutex. */
12640 tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), NX_DHCPV6_MUTEX_WAIT);
12641
12642 /* Set the DHCPv6 record. */
12643 dhcpv6_ptr -> nx_dhcpv6_state = client_record_ptr -> nx_dhcpv6_state;
12644
12645 /* Set the interface and address index. */
12646 dhcpv6_ptr -> nx_dhcpv6_client_interface_index = client_record_ptr -> nx_dhcpv6_client_interface_index;
12647 memcpy(dhcpv6_ptr -> nx_dhcpv6_client_address_index, client_record_ptr -> nx_dhcpv6_client_address_index, sizeof(UINT) * NX_DHCPV6_MAX_IA_ADDRESS); /* Use case of memcpy is verified. */
12648
12649 /* Set the Client DUID. */
12650 memcpy(&dhcpv6_ptr -> nx_dhcpv6_client_duid, &client_record_ptr -> nx_dhcpv6_client_duid, sizeof(NX_DHCPV6_DUID)); /* Use case of memcpy is verified. */
12651
12652 /* Set the Server DUID. */
12653 memcpy(&dhcpv6_ptr -> nx_dhcpv6_server_duid, &client_record_ptr -> nx_dhcpv6_server_duid, sizeof(NX_DHCPV6_DUID)); /* Use case of memcpy is verified. */
12654
12655 /* Set the IANA. */
12656 memcpy(&dhcpv6_ptr -> nx_dhcpv6_iana, &client_record_ptr -> nx_dhcpv6_iana, sizeof(NX_DHCPV6_IA_NA)); /* Use case of memcpy is verified. */
12657
12658 /* Set the IA Address. */
12659 memcpy(&dhcpv6_ptr -> nx_dhcpv6_ia, &client_record_ptr -> nx_dhcpv6_ia, sizeof(NX_DHCPV6_IA_ADDRESS) * NX_DHCPV6_MAX_IA_ADDRESS); /* Use case of memcpy is verified. */
12660
12661 /* Set the Option request. */
12662 memcpy(&dhcpv6_ptr -> nx_dhcpv6_option_request, &client_record_ptr -> nx_dhcpv6_option_request, sizeof(NX_DHCPV6_OPTIONREQUEST)); /* Use case of memcpy is verified. */
12663
12664 /* Set the Client FQDN. */
12665 memcpy(&dhcpv6_ptr -> nx_dhcpv6_client_FQDN, &client_record_ptr -> nx_dhcpv6_client_FQDN, sizeof(NX_DHCPV6_CLIENT_FQDN)); /* Use case of memcpy is verified. */
12666
12667 /* Set the dns name server address. */
12668 memcpy(&dhcpv6_ptr -> nx_dhcpv6_DNS_name_server_address, &client_record_ptr -> nx_dhcpv6_DNS_name_server_address, sizeof(NXD_ADDRESS) * NX_DHCPV6_NUM_DNS_SERVERS); /* Use case of memcpy is verified. */
12669
12670 /* Set the time server address. */
12671 memcpy(&dhcpv6_ptr -> nx_dhcpv6_time_server_address, &client_record_ptr -> nx_dhcpv6_time_server_address, sizeof(NXD_ADDRESS) * NX_DHCPV6_NUM_TIME_SERVERS); /* Use case of memcpy is verified. */
12672
12673 /* Set the domain name. */
12674 memcpy(dhcpv6_ptr -> nx_dhcpv6_domain_name, client_record_ptr -> nx_dhcpv6_domain_name, NX_DHCPV6_DOMAIN_NAME_BUFFER_SIZE); /* Use case of memcpy is verified. */
12675
12676 /* Set the time zone. */
12677 memcpy(dhcpv6_ptr -> nx_dhcpv6_time_zone, client_record_ptr -> nx_dhcpv6_time_zone, NX_DHCPV6_TIME_ZONE_BUFFER_SIZE); /* Use case of memcpy is verified. */
12678
12679 /* Set the time since client set its IP address. */
12680 dhcpv6_ptr -> nx_dhcpv6_IP_lifetime_time_accrued = (client_record_ptr -> nx_dhcpv6_IP_lifetime_time_accrued + time_elapsed);
12681
12682 /* Set the DHCPv6 Client IPv6 addresses. */
12683 for(ia_index = 0; ia_index < NX_DHCPV6_MAX_IA_ADDRESS; ia_index++)
12684 {
12685
12686 if(dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_address_status == NX_DHCPV6_IA_ADDRESS_STATE_VALID)
12687 {
12688
12689 /* Add the address to the IP instance address table. */
12690 nxd_ipv6_address_set(dhcpv6_ptr -> nx_dhcpv6_ip_ptr, dhcpv6_ptr -> nx_dhcpv6_client_interface_index,
12691 &dhcpv6_ptr -> nx_dhcpv6_ia[ia_index].nx_global_address, 64, &dhcpv6_ptr -> nx_dhcpv6_client_address_index[ia_index]);
12692 }
12693 }
12694
12695 /* Release the DHCPv6 Client mutex. */
12696 tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex));
12697
12698 return NX_SUCCESS;
12699 }
12700 #endif /* NX_DHCPV6_CLIENT_RESTORE_STATE */
12701 #endif /* FEATURE_NX_IPV6 */
12702