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 Server) */
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_server.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 /**************************************************************************/
51 /* */
52 /* FUNCTION RELEASE */
53 /* */
54 /* _nxe_dhcpv6_server_create PORTABLE C */
55 /* 6.1 */
56 /* AUTHOR */
57 /* */
58 /* Yuxin Zhou, Microsoft Corporation */
59 /* */
60 /* DESCRIPTION */
61 /* */
62 /* This function performs error checking on the NetX create dhcpv6 */
63 /* server service. */
64 /* */
65 /* INPUT */
66 /* */
67 /* dhcpv6_server_ptr Pointer to DHCPV6 server */
68 /* ip_ptr Pointer to server IP instance */
69 /* name_ptr DHCPV6 name pointer */
70 /* packet_pool_ptr Pointer to server packet pool */
71 /* stack_ptr Pointer to free memory */
72 /* stack_size Size of server stack memory */
73 /* dhcpv6_address_declined_handler Declined address request handler*/
74 /* dhcpv6_option_request_handler Option request handler */
75 /* */
76 /* OUTPUT */
77 /* */
78 /* status Completion status */
79 /* NX_PTR_ERROR Invalid pointer input */
80 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
81 /* */
82 /* CALLS */
83 /* */
84 /* _nx_dhcpv6_server_create DHCPV6 server create service */
85 /* */
86 /* CALLED BY */
87 /* */
88 /* Application Code */
89 /* */
90 /* RELEASE HISTORY */
91 /* */
92 /* DATE NAME DESCRIPTION */
93 /* */
94 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
95 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
96 /* resulting in version 6.1 */
97 /* */
98 /**************************************************************************/
_nxe_dhcpv6_server_create(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_IP * ip_ptr,CHAR * name_ptr,NX_PACKET_POOL * packet_pool_ptr,VOID * stack_ptr,ULONG stack_size,VOID (* dhcpv6_address_declined_handler)(struct NX_DHCPV6_SERVER_STRUCT * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr,UINT message),VOID (* dhcpv6_option_request_handler)(struct NX_DHCPV6_SERVER_STRUCT * dhcpv6_server_ptr,UINT option_request,UCHAR * buffer_ptr,UINT * index))99 UINT _nxe_dhcpv6_server_create(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_IP *ip_ptr, CHAR *name_ptr,
100 NX_PACKET_POOL *packet_pool_ptr, VOID *stack_ptr, ULONG stack_size,
101 VOID (*dhcpv6_address_declined_handler)(struct NX_DHCPV6_SERVER_STRUCT *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr, UINT message),
102 VOID (*dhcpv6_option_request_handler)(struct NX_DHCPV6_SERVER_STRUCT *dhcpv6_server_ptr, UINT option_request, UCHAR *buffer_ptr, UINT *index))
103 {
104
105 UINT status;
106
107
108 /* Check for invalid pointer input. */
109 if (!dhcpv6_server_ptr ||!ip_ptr || !packet_pool_ptr || !stack_ptr)
110 {
111
112 return NX_PTR_ERROR;
113 }
114
115 /* Check for invalid non pointer input. */
116 if ((ip_ptr -> nx_ip_id != NX_IP_ID) || (stack_size < TX_MINIMUM_STACK))
117 {
118
119 return NX_DHCPV6_PARAM_ERROR;
120 }
121
122 /* Call actual DHCPV6 server create service. */
123 status = _nx_dhcpv6_server_create(dhcpv6_server_ptr, ip_ptr, name_ptr, packet_pool_ptr, stack_ptr, stack_size,
124 dhcpv6_address_declined_handler, dhcpv6_option_request_handler);
125
126 /* Return status. */
127 return(status);
128 }
129
130
131 /**************************************************************************/
132 /* */
133 /* FUNCTION RELEASE */
134 /* */
135 /* _nx_dhcpv6_server_create PORTABLE C */
136 /* 6.1 */
137 /* AUTHOR */
138 /* */
139 /* Yuxin Zhou, Microsoft Corporation */
140 /* */
141 /* DESCRIPTION */
142 /* */
143 /* This function creates the DHCPv6 Client instance with a Netx packet */
144 /* pool, processing thread, and various flag event queues, timers and */
145 /* mutexes necessary for DHCPv6 Client operations. */
146 /* */
147 /* Note: User is encouraged to call nx_dhcpv6_server_option_request */
148 /* _handler_set to set the option request handler. */
149 /* */
150 /* INPUT */
151 /* */
152 /* dhcpv6_server_ptr Pointer to DHCPV6 Server */
153 /* ip_ptr Pointer to Server IP instance */
154 /* name_ptr DHCPV6 name pointer */
155 /* packet_pool_ptr Pointer to Server packet pool */
156 /* stack_ptr Pointer to free memory */
157 /* stack_size Size of server stack memory */
158 /* dhcpv6_address_declined_handler Declined address request handler*/
159 /* dhcpv6_option_request_handler Option request handler */
160 /* */
161 /* OUTPUT */
162 /* */
163 /* status Actual completion status */
164 /* NX_SUCCESS Successful completion status */
165 /* */
166 /* CALLS */
167 /* */
168 /* tx_event_flags_create Create ThreadX flag event queue*/
169 /* tx_mutex_create Create mutex lock on resource */
170 /* nx_packet_pool_delete Delete the DHCPV6 packet pool */
171 /* nx_udp_socket_create Create the DHCPV6 UDP socket */
172 /* nx_udp_socket_delete Delete the DHCPV6 UDP socket */
173 /* tx_mutex_create Create DHCPV6 mutex */
174 /* tx_mutex_delete Delete DHCPV6 mutex */
175 /* tx_thread_create Create DHCPV6 processing thread*/
176 /* tx_thread_delete Delete DHCPV6 processing thread*/
177 /* tx_timer_create Create DHCPV6 timer */
178 /* tx_timer_delete Delete DHCPV6 timer */
179 /* */
180 /* CALLED BY */
181 /* */
182 /* Application Code */
183 /* */
184 /* RELEASE HISTORY */
185 /* */
186 /* DATE NAME DESCRIPTION */
187 /* */
188 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
189 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
190 /* resulting in version 6.1 */
191 /* */
192 /**************************************************************************/
_nx_dhcpv6_server_create(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_IP * ip_ptr,CHAR * name_ptr,NX_PACKET_POOL * packet_pool_ptr,VOID * stack_ptr,ULONG stack_size,VOID (* dhcpv6_address_declined_handler)(struct NX_DHCPV6_SERVER_STRUCT * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr,UINT message),VOID (* dhcpv6_option_request_handler)(struct NX_DHCPV6_SERVER_STRUCT * dhcpv6_server_ptr,UINT option_request,UCHAR * buffer_ptr,UINT * index))193 UINT _nx_dhcpv6_server_create(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_IP *ip_ptr, CHAR *name_ptr,
194 NX_PACKET_POOL *packet_pool_ptr, VOID *stack_ptr, ULONG stack_size,
195 VOID (*dhcpv6_address_declined_handler)(struct NX_DHCPV6_SERVER_STRUCT *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr, UINT message),
196 VOID (*dhcpv6_option_request_handler)(struct NX_DHCPV6_SERVER_STRUCT *dhcpv6_server_ptr, UINT option_request, UCHAR *buffer_ptr, UINT *index))
197 {
198
199 UINT i, status;
200 NX_DHCPV6_CLIENT *dhcpv6_client_ptr;
201
202
203 /* Initialize the DHCPV6 control block to zero. */
204 memset((void *) dhcpv6_server_ptr, 0, sizeof(NX_DHCPV6_SERVER));
205
206 /* Default the server global index to index 1. If otherwise, the host
207 application must set the DHCPv6 interface before it can start
208 the Server (nx_dhcpv6_server_interface_set). */
209 dhcpv6_server_ptr -> nx_dhcpv6_server_ga_address_index = 1;
210
211 /* Link the DHCPv6 server with the IP instance. */
212 dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr = ip_ptr;
213
214 /* Set the DHCPV6 name. */
215 dhcpv6_server_ptr -> nx_dhcpv6_server_name = name_ptr;
216
217 /* Set the server packet pool. */
218 dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr = packet_pool_ptr;
219
220 /* Create the IP timer event flag instance. */
221 status = tx_event_flags_create(&dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events, "DHCPv6 Server Timer Events Queue");
222
223 /* Check for error. */
224 if (status != TX_SUCCESS)
225 {
226
227 return status;
228 }
229
230 /* Create the DHCPV6 mutex for the Server instance. */
231 status = tx_mutex_create(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex), "DHCPV6 Server Mutex", TX_NO_INHERIT);
232
233 /* Determine if the mutexes creation was successful. */
234 if (status)
235 {
236
237 /* Delete the flag queue. */
238 tx_event_flags_delete(&dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events);
239
240 /* No, return error status. */
241 return status;
242 }
243
244 /* Create the DHCPV6 processing thread. */
245 status = tx_thread_create(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread), "NetX DHCPV6 Server", _nx_dhcpv6_server_thread_entry,
246 (ULONG)(ALIGN_TYPE)dhcpv6_server_ptr, stack_ptr, stack_size,
247 NX_DHCPV6_SERVER_THREAD_PRIORITY, NX_DHCPV6_SERVER_THREAD_PRIORITY, 1, TX_DONT_START);
248
249 NX_THREAD_EXTENSION_PTR_SET(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread), dhcpv6_server_ptr)
250
251 /* Determine if the thread creation was successful. */
252 if (status)
253 {
254
255 /* Delete the server protection mutex. */
256 tx_mutex_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex));
257
258 /* Delete the flag queue. */
259 tx_event_flags_delete(&dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events);
260
261 /* No, return error status. */
262 return status;
263 }
264
265 /* Create the DHCPV6 timer for keeping track of IP lease time expiration. */
266 status = tx_timer_create(&(dhcpv6_server_ptr -> nx_dhcpv6_lease_timer), "NetX DHCPV6 Server Lease timer",
267 _nx_dhcpv6_server_lease_timeout_entry, (ULONG)(ALIGN_TYPE)dhcpv6_server_ptr,
268 (NX_DHCPV6_IP_LEASE_TIMER_INTERVAL * NX_DHCPV6_SERVER_TICKS_PER_SECOND) ,
269 (NX_DHCPV6_IP_LEASE_TIMER_INTERVAL * NX_DHCPV6_SERVER_TICKS_PER_SECOND),
270 TX_NO_ACTIVATE);
271
272 NX_TIMER_EXTENSION_PTR_SET(&(dhcpv6_server_ptr -> nx_dhcpv6_lease_timer), dhcpv6_server_ptr)
273
274 if (status != NX_SUCCESS)
275 {
276
277 /* Delete the DHCPv6 Server thread. */
278 tx_thread_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread));
279
280 /* Delete the server protection mutex. */
281 tx_mutex_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex));
282
283 /* Delete the flag queue. */
284 tx_event_flags_delete(&dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events);
285 }
286
287 /* Create the DHCPV6 timer for keeping track of the DHCPv6 Client session time. */
288 status = tx_timer_create(&(dhcpv6_server_ptr -> nx_dhcpv6_session_timer), "NetX DHCPV6 Session Duration timer",
289 _nx_dhcpv6_server_session_timeout_entry, (ULONG)(ALIGN_TYPE)dhcpv6_server_ptr,
290 (NX_DHCPV6_SESSION_TIMER_INTERVAL * NX_DHCPV6_SERVER_TICKS_PER_SECOND),
291 (NX_DHCPV6_SESSION_TIMER_INTERVAL * NX_DHCPV6_SERVER_TICKS_PER_SECOND),
292 TX_NO_ACTIVATE);
293
294 NX_TIMER_EXTENSION_PTR_SET(&(dhcpv6_server_ptr -> nx_dhcpv6_session_timer), dhcpv6_server_ptr)
295
296 if (status != NX_SUCCESS)
297 {
298
299 /* Delete the server lease timer. */
300 tx_timer_delete( &(dhcpv6_server_ptr -> nx_dhcpv6_lease_timer));
301
302 /* Delete the DHCPv6 Server thread. */
303 tx_thread_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread));
304
305 /* Delete the server protection mutex. */
306 tx_mutex_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex));
307
308 /* Delete the flag queue. */
309 tx_event_flags_delete(&dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events);
310 }
311
312 /* Initialize the DHCPv6 client control blocks */
313 for (i = 0; i < NX_DHCPV6_MAX_CLIENTS; i++)
314 {
315
316 /* Set a local pointer for convenience. */
317 dhcpv6_client_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_clients[i];
318
319 /* Clear the client record. */
320 memset(dhcpv6_client_ptr, 0, sizeof(NX_DHCPV6_CLIENT));
321 }
322
323 /* Determine if the timers creation were successful. */
324 if (status)
325 {
326
327 /* Delete the server lease timer. */
328 tx_timer_delete( &(dhcpv6_server_ptr -> nx_dhcpv6_lease_timer));
329
330 /* Delete the server serssion timer. */
331 tx_timer_delete( &(dhcpv6_server_ptr -> nx_dhcpv6_session_timer));
332
333 /* Delete the DHCPv6 Server thread. */
334 tx_thread_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread));
335
336 /* Delete the server protection mutex. */
337 tx_mutex_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex));
338
339 /* Delete the flag queue. */
340 tx_event_flags_delete(&dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events);
341
342 /* Return error status. */
343 return status;
344 }
345
346 /* Save the DHCPV6 instance pointer in the socket. */
347 dhcpv6_server_ptr -> nx_dhcpv6_server_socket.nx_udp_socket_reserved_ptr = (void *) dhcpv6_server_ptr;
348
349 /* Set the DHCPv6 Client ID. */
350 dhcpv6_server_ptr -> nx_dhcpv6_id = NX_DHCPV6_SERVER_ID;
351
352 /* Set the server preference for clients using multicast only for all request message types. */
353 dhcpv6_server_ptr -> nx_dhcpv6_server_multicast_only = NX_TRUE;
354
355 /* Assign the various handlers (server error messages, state change and expired/deprecated addresses). */
356 dhcpv6_server_ptr -> nx_dhcpv6_IP_address_declined_handler = dhcpv6_address_declined_handler;
357 dhcpv6_server_ptr -> nx_dhcpv6_server_option_request_handler = dhcpv6_option_request_handler;
358
359 /* Return a successful status. */
360 return(NX_SUCCESS);
361 }
362
363
364 /**************************************************************************/
365 /* */
366 /* FUNCTION RELEASE */
367 /* */
368 /* _nxe_dhcpv6_server_option_request_handler_set PORTABLE C */
369 /* 6.1 */
370 /* AUTHOR */
371 /* */
372 /* Yuxin Zhou, Microsoft Corporation */
373 /* */
374 /* DESCRIPTION */
375 /* */
376 /* This function performs error checking on the NetX set dhcpv6 server */
377 /* option request callback service. */
378 /* */
379 /* INPUT */
380 /* */
381 /* dhcpv6_server_ptr Pointer to DHCPV6 server */
382 /* dhcpv6_option_request_handler_extended */
383 /* Extended option request handler */
384 /* */
385 /* OUTPUT */
386 /* */
387 /* status Completion status */
388 /* NX_PTR_ERROR Invalid pointer input */
389 /* */
390 /* CALLS */
391 /* */
392 /* _nx_dhcpv6_server_option_request_handler_set */
393 /* DHCPV6 server create service */
394 /* */
395 /* CALLED BY */
396 /* */
397 /* Application Code */
398 /* */
399 /* RELEASE HISTORY */
400 /* */
401 /* DATE NAME DESCRIPTION */
402 /* */
403 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
404 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
405 /* resulting in version 6.1 */
406 /* */
407 /**************************************************************************/
_nxe_dhcpv6_server_option_request_handler_set(NX_DHCPV6_SERVER * dhcpv6_server_ptr,VOID (* dhcpv6_option_request_handler_extended)(struct NX_DHCPV6_SERVER_STRUCT * dhcpv6_server_ptr,UINT option_request,UCHAR * buffer_ptr,UINT * index,UINT available_payload))408 UINT _nxe_dhcpv6_server_option_request_handler_set(NX_DHCPV6_SERVER *dhcpv6_server_ptr,
409 VOID (*dhcpv6_option_request_handler_extended)(struct NX_DHCPV6_SERVER_STRUCT *dhcpv6_server_ptr, UINT option_request,
410 UCHAR *buffer_ptr, UINT *index, UINT available_payload))
411 {
412
413 UINT status;
414
415
416 /* Check for invalid pointer input. */
417 if ((!dhcpv6_server_ptr) || (!dhcpv6_option_request_handler_extended))
418 {
419 return NX_PTR_ERROR;
420 }
421
422 /* Call actual DHCPV6 server option request handler set service. */
423 status = _nx_dhcpv6_server_option_request_handler_set(dhcpv6_server_ptr, dhcpv6_option_request_handler_extended);
424
425 /* Return status. */
426 return(status);
427 }
428
429
430 /**************************************************************************/
431 /* */
432 /* FUNCTION RELEASE */
433 /* */
434 /* _nx_dhcpv6_server_option_request_handler_set PORTABLE C */
435 /* 6.1 */
436 /* AUTHOR */
437 /* */
438 /* Yuxin Zhou, Microsoft Corporation */
439 /* */
440 /* DESCRIPTION */
441 /* */
442 /* This function sets the DHCPv6 option request handler. */
443 /* */
444 /* INPUT */
445 /* */
446 /* dhcpv6_server_ptr Pointer to DHCPV6 server */
447 /* dhcpv6_option_request_handler_extended */
448 /* Extended option request handler */
449 /* */
450 /* OUTPUT */
451 /* */
452 /* status Actual completion status */
453 /* NX_SUCCESS Successful completion status */
454 /* */
455 /* CALLS */
456 /* */
457 /* None */
458 /* */
459 /* CALLED BY */
460 /* */
461 /* Application Code */
462 /* */
463 /* RELEASE HISTORY */
464 /* */
465 /* DATE NAME DESCRIPTION */
466 /* */
467 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
468 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
469 /* resulting in version 6.1 */
470 /* */
471 /**************************************************************************/
_nx_dhcpv6_server_option_request_handler_set(NX_DHCPV6_SERVER * dhcpv6_server_ptr,VOID (* dhcpv6_option_request_handler_extended)(struct NX_DHCPV6_SERVER_STRUCT * dhcpv6_server_ptr,UINT option_request,UCHAR * buffer_ptr,UINT * index,UINT available_payload))472 UINT _nx_dhcpv6_server_option_request_handler_set(NX_DHCPV6_SERVER *dhcpv6_server_ptr,
473 VOID (*dhcpv6_option_request_handler_extended)(struct NX_DHCPV6_SERVER_STRUCT *dhcpv6_server_ptr, UINT option_request,
474 UCHAR *buffer_ptr, UINT *index, UINT available_payload))
475 {
476
477
478 /* Set the extended handler callback. */
479 dhcpv6_server_ptr -> nx_dhcpv6_server_option_request_handler_extended = dhcpv6_option_request_handler_extended;
480
481 /* Return success. */
482 return(NX_SUCCESS);
483 }
484
485
486 /**************************************************************************/
487 /* */
488 /* FUNCTION RELEASE */
489 /* */
490 /* _nxe_dhcpv6_add_client_record PORTABLE C */
491 /* 6.1 */
492 /* AUTHOR */
493 /* */
494 /* Yuxin Zhou, Microsoft Corporation */
495 /* */
496 /* DESCRIPTION */
497 /* */
498 /* This function performs error checking for the copy client data */
499 /* service. */
500 /* */
501 /* INPUT */
502 /* */
503 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
504 /* table_index Table index to store client data */
505 /* message_xid Client transaction ID */
506 /* client_address IP address leased to client */
507 /* client_state Client DHCPv6 state e.g. bound */
508 /* IP_lease_time_accrued Time expired on current IP lease */
509 /* valid_lifetime When address becomes invalid */
510 /* duid_type Type of Client DUID */
511 /* duid_hardware DUID hardware (usually ethernet) */
512 /* physical_address_msw MSB of client mac address */
513 /* physical_address_lsw LSB of client mac address */
514 /* duid_time Time for link layer time DUID */
515 /* duid_vendor_number Enterprise ID for Vendor DUID */
516 /* duid_vendor_private Pointer to private ID for DUID */
517 /* duid_private_length Vendor Duid private ID length */
518 /* */
519 /* OUTPUT */
520 /* */
521 /* NX_SUCCESS Successful IP address copy */
522 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
523 /* NX_DHCPV6_TABLE_FULL No empty slot for client data */
524 /* */
525 /* CALLS */
526 /* */
527 /* _nx_dhcpv6_add_client_record Actual copy client data service */
528 /* */
529 /* CALLED BY */
530 /* */
531 /* Application code */
532 /* */
533 /* RELEASE HISTORY */
534 /* */
535 /* DATE NAME DESCRIPTION */
536 /* */
537 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
538 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
539 /* resulting in version 6.1 */
540 /* */
541 /**************************************************************************/
_nxe_dhcpv6_add_client_record(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT table_index,ULONG message_xid,NXD_ADDRESS * client_address,UINT client_state,ULONG IP_lease_time_accrued,ULONG valid_lifetime,UINT duid_type,UINT duid_hardware,ULONG physical_address_msw,ULONG physical_address_lsw,ULONG duid_time,ULONG duid_vendor_number,UCHAR * duid_vendor_private,UINT duid_private_length)542 UINT _nxe_dhcpv6_add_client_record(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, ULONG message_xid, NXD_ADDRESS *client_address, UINT client_state,
543 ULONG IP_lease_time_accrued, ULONG valid_lifetime, UINT duid_type, UINT duid_hardware, ULONG physical_address_msw,
544 ULONG physical_address_lsw, ULONG duid_time, ULONG duid_vendor_number, UCHAR *duid_vendor_private, UINT duid_private_length)
545 {
546
547 UINT status;
548
549 /* Check for invalid pointer input. */
550 if ((dhcpv6_server_ptr == NX_NULL) || (client_address == NX_NULL))
551 {
552
553 return NX_PTR_ERROR;
554 }
555
556 /* Check for missing transaction ID or DUID type. */
557 if ((message_xid == 0) || (duid_type == 0))
558 {
559 return NX_INVALID_PARAMETERS;
560 }
561
562 /* Check for missing time expired on the lease (if client in a bound state). */
563 if ((IP_lease_time_accrued == 0) && (client_state == NX_DHCPV6_STATE_BOUND))
564 {
565 return NX_INVALID_PARAMETERS;
566 }
567
568 /* Check for invalid enterprise DUID data if type is enterprise. */
569 if (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_VENDOR_ASSIGNED)
570 {
571
572 if ((duid_private_length == 0) || (duid_vendor_private == NX_NULL))
573 {
574
575 return NX_INVALID_PARAMETERS;
576 }
577 }
578 /* Check for invalid LINK LAYER duid data. */
579 else if ((duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME) || (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_ONLY))
580 {
581
582 if ((physical_address_msw == 0) && (physical_address_lsw == 0))
583 {
584 return NX_INVALID_PARAMETERS;
585 }
586
587 if ((duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME) && (duid_time == 0))
588 {
589 return NX_INVALID_PARAMETERS;
590 }
591 }
592
593 /* Call the actual service and return completion status. */
594 status = _nx_dhcpv6_add_client_record(dhcpv6_server_ptr, table_index, message_xid, client_address, client_state,
595 IP_lease_time_accrued, valid_lifetime, duid_type, duid_hardware, physical_address_msw, physical_address_lsw,
596 duid_time, duid_vendor_number, duid_vendor_private, duid_private_length);
597 return status;
598 }
599
600
601 /**************************************************************************/
602 /* */
603 /* FUNCTION RELEASE */
604 /* */
605 /* _nx_dhcpv6_add_client_record PORTABLE C */
606 /* 6.1 */
607 /* AUTHOR */
608 /* */
609 /* Yuxin Zhou, Microsoft Corporation */
610 /* */
611 /* DESCRIPTION */
612 /* */
613 /* This function copies the input data into a DHCPv6 Client record and */
614 /* stored in the server's Client table. It then uses the Client IP */
615 /* address to find the matching record in the server IP lease table to */
616 /* cross link the tables. */
617 /* */
618 /* This is intended to satisfy the DHCPv6 protocol requirement that a */
619 /* DHPCv6 Server be able to store and retrieve lease data from */
620 /* nonvolatile memory e..g between reboots. */
621 /* */
622 /* INPUT */
623 /* */
624 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
625 /* table_index Table index to store client data */
626 /* message_xid Client transaction ID */
627 /* client_address IP address leased to client */
628 /* client_state Client DHCPv6 state e.g. bound */
629 /* IP_lease_time_accrued Time expired on current IP lease */
630 /* valid_lifetime When address becomes invalid */
631 /* duid_type Type of Client DUID */
632 /* duid_hardware DUID hardware (usually ethernet) */
633 /* physical_address_msw MSB of client mac address */
634 /* physical_address_lsw LSB of client mac address */
635 /* duid_time Time for link layer time DUID */
636 /* duid_vendor_number Enterprise ID for Vendor DUID */
637 /* duid_vendor_private Pointer to private ID for DUID */
638 /* duid_private_length Vendor Duid private ID length */
639 /* */
640 /* OUTPUT */
641 /* */
642 /* NX_SUCCESS Successful IP address copy */
643 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
644 /* NX_DHCPV6_TABLE_FULL No empty slot for client data */
645 /* */
646 /* CALLS */
647 /* */
648 /* memcpy Copy data to specified memory */
649 /* */
650 /* CALLED BY */
651 /* */
652 /* Application code */
653 /* */
654 /* RELEASE HISTORY */
655 /* */
656 /* DATE NAME DESCRIPTION */
657 /* */
658 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
659 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
660 /* verified memcpy use cases, */
661 /* resulting in version 6.1 */
662 /* */
663 /**************************************************************************/
_nx_dhcpv6_add_client_record(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT table_index,ULONG message_xid,NXD_ADDRESS * client_address,UINT client_state,ULONG IP_lease_time_accrued,ULONG valid_lifetime,UINT duid_type,UINT duid_hardware,ULONG physical_address_msw,ULONG physical_address_lsw,ULONG duid_time,ULONG duid_vendor_number,UCHAR * duid_vendor_private,UINT duid_private_length)664 UINT _nx_dhcpv6_add_client_record(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, ULONG message_xid, NXD_ADDRESS *client_address, UINT client_state,
665 ULONG IP_lease_time_accrued, ULONG valid_lifetime, UINT duid_type, UINT duid_hardware, ULONG physical_address_msw,
666 ULONG physical_address_lsw, ULONG duid_time, ULONG duid_vendor_number, UCHAR *duid_vendor_private, UINT duid_private_length)
667 {
668
669 UINT i;
670 UINT found = NX_FALSE;
671 NX_DHCPV6_CLIENT *dhcpv6_client_ptr;
672
673
674 /* Check if a table index was specified. */
675 if (table_index != 0xFFFFFFFF)
676 {
677
678 /* Check if it is a valid index. */
679 if (table_index >= NX_DHCPV6_MAX_CLIENTS)
680 {
681
682 /* No, return a parameter error. */
683 return NX_INVALID_PARAMETERS;
684 }
685
686 /* Check if it is actually empty. */
687 if (dhcpv6_server_ptr -> nx_dhcpv6_clients[table_index].nx_dhcpv6_message_xid != 0)
688 {
689
690 /* Not empty. Indicate we'll have to find an empty slot. */
691 table_index = 0xFFFFFFFF;
692 }
693 }
694
695 /* Check if we still need to find a slot. */
696 if (table_index == 0xFFFFFFFF)
697 {
698
699 /* We do, so loop through client records to find one. */
700 for (i = 0; i < NX_DHCPV6_MAX_CLIENTS; i++)
701 {
702
703 /* Is this an empty slot? */
704 if (dhcpv6_server_ptr -> nx_dhcpv6_clients[i].nx_dhcpv6_message_xid == 0)
705 {
706
707 /* This is available. */
708 table_index = i;
709 break;
710 }
711 }
712
713 /* Do we have a slot? */
714 if (i == NX_DHCPV6_MAX_CLIENTS)
715 {
716
717 /* No, Indicate the table is full. */
718 return NX_DHCPV6_TABLE_FULL;
719 }
720 }
721
722 /* Create the table entry. */
723
724 /* Fill in the generic client information. */
725 dhcpv6_client_ptr = &(dhcpv6_server_ptr -> nx_dhcpv6_clients[table_index]);
726 dhcpv6_client_ptr -> nx_dhcpv6_id = NX_DHCPV6_CLIENT_ID;
727 dhcpv6_client_ptr -> nx_dhcpv6_message_xid = message_xid;
728 dhcpv6_client_ptr -> nx_dhcpv6_state = (UCHAR)client_state;
729 dhcpv6_client_ptr -> nx_dhcpv6_IP_lease_time_accrued = IP_lease_time_accrued;
730 memcpy(&(dhcpv6_client_ptr -> nx_dhcpv6_server_duid), &(dhcpv6_server_ptr -> nx_dhcpv6_server_duid), sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
731
732 /*Fill in the Client DUID information. */
733 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_op_code = NX_DHCPV6_OP_DUID_CLIENT;
734 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_hardware_type = (USHORT)duid_hardware;
735 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_type = (USHORT)duid_type;
736
737 /* Determine DUID type to fill in the rest of the DUID fields. */
738 if (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_VENDOR_ASSIGNED)
739 {
740
741 /* Validate the DUID private length. */
742 if (duid_private_length > NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_LENGTH)
743 {
744 return NX_DHCPV6_INVALID_DUID;
745 }
746
747 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_enterprise_number = duid_vendor_number;
748 memcpy(&(dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_private_identifier[0]), duid_vendor_private, duid_private_length); /* Use case of memcpy is verified. */
749 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = (USHORT)(duid_private_length + 6);
750 }
751 else
752 {
753
754 /* Either link layer or link layer plus time. */
755 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw = (USHORT)physical_address_msw;
756 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw = physical_address_lsw;
757 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = 10;
758
759 if (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
760 {
761
762 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = 14;
763 dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_time = duid_time;
764 }
765 }
766
767 /* Fill in the necessary IA-NA and IA Address option fields. */
768 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code = NX_DHCPV6_OP_IA_ADDRESS;
769 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_option_length = 24;
770 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = valid_lifetime;
771 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0; /* Don't care */
772 COPY_NXD_ADDRESS(client_address, &(dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address));
773
774 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_op_code = NX_DHCPV6_OP_OPTION_STATUS;
775 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_option_length = 2; /* No message */
776 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_SUCCESS;
777
778 /* Now access the server lease table to find this client's lease. */
779 for (i = 0; i < NX_DHCPV6_MAX_LEASES; i++)
780 {
781
782 /* Compare our client's assigned IP address with this lease table entry. */
783 if(CHECK_IPV6_ADDRESSES_SAME(&(client_address -> nxd_ip_address.v6[0]),
784 &(dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0])))
785 {
786
787 /* They match! Cross link the tables. */
788 dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_assigned_to = dhcpv6_client_ptr;
789 found = NX_TRUE;
790 break;
791 }
792 }
793
794 if (!found)
795 {
796
797 /* This client apparently does not have a valid IP lease. Ok to keep in the tables,
798 but they will need to request an IP address! */
799 return NX_DHCPV6_ADDRESS_NOT_FOUND;
800 }
801
802 return NX_SUCCESS;
803
804 }
805
806
807 /**************************************************************************/
808 /* */
809 /* FUNCTION RELEASE */
810 /* */
811 /* _nxe_dhcpv6_retrieve_client_record PORTABLE C */
812 /* 6.1 */
813 /* AUTHOR */
814 /* */
815 /* Yuxin Zhou, Microsoft Corporation */
816 /* */
817 /* DESCRIPTION */
818 /* */
819 /* This function performs error checking on the retrieve DHCPv6 Client */
820 /* record service. */
821 /* */
822 /* INPUT */
823 /* */
824 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
825 /* table_index Table index to store client data */
826 /* message_xid Client transaction ID */
827 /* client_address IP address leased to client */
828 /* client_state Client DHCPv6 state e.g. bound */
829 /* IP_lease_time_accrued Time expired on current IP lease */
830 /* valid_lifetime When address becomes invalid */
831 /* duid_type Type of Client DUID */
832 /* duid_hardware DUID hardware (usually ethernet) */
833 /* physical_address_msw MSB of client mac address */
834 /* physical_address_lsw LSB of client mac address */
835 /* duid_time Time for link layer time DUID */
836 /* duid_vendor_number Enterprise ID for Vendor DUID */
837 /* duid_vendor_private Pointer to private ID for DUID */
838 /* duid_private_length Vendor Duid private ID length */
839 /* */
840 /* OUTPUT */
841 /* */
842 /* NX_SUCCESS Successful IP address copy */
843 /* NX_INVALID_PARAMETERS Invalid non pointer input */
844 /* */
845 /* CALLS */
846 /* */
847 /* _nx_dhcpv6_retrieve_client_record Actual retrieve client data */
848 /* service */
849 /* */
850 /* CALLED BY */
851 /* */
852 /* Application code */
853 /* */
854 /* RELEASE HISTORY */
855 /* */
856 /* DATE NAME DESCRIPTION */
857 /* */
858 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
859 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
860 /* resulting in version 6.1 */
861 /* */
862 /**************************************************************************/
_nxe_dhcpv6_retrieve_client_record(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT table_index,ULONG * message_xid,NXD_ADDRESS * client_address,UINT * client_state,ULONG * IP_lease_time_accrued,ULONG * valid_lifetime,UINT * duid_type,UINT * duid_hardware,ULONG * physical_address_msw,ULONG * physical_address_lsw,ULONG * duid_time,ULONG * duid_vendor_number,UCHAR * duid_vendor_private,UINT * duid_private_length)863 UINT _nxe_dhcpv6_retrieve_client_record(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, ULONG *message_xid, NXD_ADDRESS *client_address, UINT *client_state,
864 ULONG *IP_lease_time_accrued, ULONG *valid_lifetime, UINT *duid_type, UINT *duid_hardware, ULONG *physical_address_msw,
865 ULONG *physical_address_lsw, ULONG *duid_time, ULONG *duid_vendor_number, UCHAR *duid_vendor_private, UINT *duid_private_length)
866 {
867
868 UINT status;
869
870
871 /* Check for invalid parameters. */
872 if (table_index >= NX_DHCPV6_MAX_CLIENTS)
873 {
874 return NX_INVALID_PARAMETERS;
875 }
876
877 /* Check for invalid pointer input. */
878 if ((dhcpv6_server_ptr == NX_NULL) || (message_xid == NX_NULL) || (client_address == NX_NULL) || (client_state == NX_NULL) ||
879 (IP_lease_time_accrued == NX_NULL) || (valid_lifetime == NX_NULL) || (duid_type == NX_NULL))
880 {
881
882 return NX_PTR_ERROR;
883 }
884
885
886 /* Call the actual service. */
887 status = _nx_dhcpv6_retrieve_client_record(dhcpv6_server_ptr, table_index, message_xid, client_address, client_state,
888 IP_lease_time_accrued, valid_lifetime, duid_type, duid_hardware, physical_address_msw,
889 physical_address_lsw, duid_time, duid_vendor_number, duid_vendor_private, duid_private_length);
890
891 return status;
892 }
893
894
895 /**************************************************************************/
896 /* */
897 /* FUNCTION RELEASE */
898 /* */
899 /* _nx_dhcpv6_retrieve_client_record PORTABLE C */
900 /* 6.1 */
901 /* AUTHOR */
902 /* */
903 /* Yuxin Zhou, Microsoft Corporation */
904 /* */
905 /* DESCRIPTION */
906 /* */
907 /* This function returns DHCPv6 Client record data at the specified */
908 /* index into the server table to the caller. Note that if a slot in */
909 /* the server's client table is empty, evidenced by a zero transaction */
910 /* ID, the service returns null data in all parameters with a successful*/
911 /* completion status. */
912 /* */
913 /* This is intended to satisfy the DHCPv6 protocol requirement that a */
914 /* DHPCv6 Server be able to store and retrieve IP lease data from */
915 /* nonvolatile memory e..g between reboots. */
916 /* */
917 /* INPUT */
918 /* */
919 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
920 /* table_index Table index to store client data */
921 /* message_xid Client transaction ID */
922 /* client_address IP address leased to client */
923 /* client_state Client DHCPv6 state e.g. bound */
924 /* IP_lease_time_accrued Time expired on current IP lease */
925 /* valid_lifetime When address becomes invalid */
926 /* duid_type Type of Client DUID */
927 /* duid_hardware DUID hardware (usually ethernet) */
928 /* physical_address_msw MSB of client mac address */
929 /* physical_address_lsw LSB of client mac address */
930 /* duid_time Time for link layer time DUID */
931 /* duid_vendor_number Enterprise ID for Vendor DUID */
932 /* duid_vendor_private Pointer to private ID for DUID */
933 /* duid_private_length Vendor Duid private ID length */
934 /* */
935 /* OUTPUT */
936 /* */
937 /* NX_SUCCESS Successful IP address copy */
938 /* NX_PTR_ERROR Invalid pointer input */
939 /* NX_INVALID_PARAMETERS Invalid non pointer input */
940 /* NX_DHCPV6_INVALID_DUID Malformed DUID retrieved */
941 /* */
942 /* CALLS */
943 /* */
944 /* COPY_NXD_ADDRESS Copy IPv6 address to specified */
945 /* memory (holding an IPv6 address*/
946 /* */
947 /* CALLED BY */
948 /* */
949 /* Application code */
950 /* */
951 /* RELEASE HISTORY */
952 /* */
953 /* DATE NAME DESCRIPTION */
954 /* */
955 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
956 /* 09-30-2020 Yuxin Zhou Modified comment(s), corrected*/
957 /* the length of identifier, */
958 /* resulting in version 6.1 */
959 /* */
960 /**************************************************************************/
_nx_dhcpv6_retrieve_client_record(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT table_index,ULONG * message_xid,NXD_ADDRESS * client_address,UINT * client_state,ULONG * IP_lease_time_accrued,ULONG * valid_lifetime,UINT * duid_type,UINT * duid_hardware,ULONG * physical_address_msw,ULONG * physical_address_lsw,ULONG * duid_time,ULONG * duid_vendor_number,UCHAR * duid_vendor_private,UINT * duid_private_length)961 UINT _nx_dhcpv6_retrieve_client_record(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, ULONG *message_xid, NXD_ADDRESS *client_address, UINT *client_state,
962 ULONG *IP_lease_time_accrued, ULONG *valid_lifetime, UINT *duid_type, UINT *duid_hardware, ULONG *physical_address_msw,
963 ULONG *physical_address_lsw, ULONG *duid_time, ULONG *duid_vendor_number, UCHAR *duid_vendor_private, UINT *duid_private_length)
964 {
965
966 NX_DHCPV6_CLIENT *client_ptr;
967 INT length;
968
969
970 /* Get a local pointer for convenience. */
971 client_ptr = &(dhcpv6_server_ptr ->nx_dhcpv6_clients[table_index]);
972
973 /* Load the generic client data. */
974 *message_xid = client_ptr -> nx_dhcpv6_message_xid;
975
976 /* Is this an empty record? */
977 if (*message_xid == 0)
978 {
979
980 /* Yes so return null data. */
981 memset(client_address, 0, sizeof(NXD_ADDRESS));
982 *client_state = 0;
983 *IP_lease_time_accrued = 0;
984 *valid_lifetime = 0;
985 *duid_type = 0;
986 if (duid_hardware)
987 *duid_hardware = 0;
988 if (physical_address_msw)
989 *physical_address_msw = 0;
990 if (physical_address_lsw)
991 *physical_address_lsw = 0;
992 if (duid_time)
993 *duid_time = 0;
994 if (duid_vendor_number)
995 *duid_vendor_number = 0;
996 if (duid_private_length)
997 *duid_private_length = 0;
998
999 return NX_SUCCESS;
1000 }
1001
1002 /* Not an empty record. Extract the data! */
1003 COPY_NXD_ADDRESS(&(client_ptr -> nx_dhcpv6_ia.nx_global_address), client_address);
1004 *client_state = client_ptr -> nx_dhcpv6_state;
1005 *IP_lease_time_accrued = client_ptr -> nx_dhcpv6_IP_lease_time_accrued;
1006 *valid_lifetime = client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime;
1007 *duid_type = client_ptr -> nx_dhcpv6_client_duid.nx_duid_type;
1008
1009 /* If this is a LINK LAYER Duid type, load the appropriate data. */
1010 if ((*duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_ONLY) || (*duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME))
1011 {
1012
1013 /* Check for invalid pointer input for DUID of the link layer type. */
1014 if ((duid_hardware == NX_NULL) || (physical_address_msw == NX_NULL) || (physical_address_lsw == NX_NULL))
1015 {
1016 return NX_PTR_ERROR;
1017 }
1018
1019 *duid_hardware = client_ptr -> nx_dhcpv6_client_duid.nx_hardware_type;
1020 *physical_address_msw = client_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw;
1021 *physical_address_lsw = client_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw;
1022
1023 if (*duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
1024 {
1025
1026 if (duid_time == NX_NULL)
1027 {
1028 return NX_PTR_ERROR;
1029 }
1030
1031 *duid_time = client_ptr -> nx_dhcpv6_client_duid.nx_duid_time;
1032 }
1033 }
1034 else
1035 {
1036
1037 /* Client DUID type is vendor assigned. */
1038
1039 /* Check for valid pointer input for enterprise ID data */
1040 if ((duid_vendor_number == NX_NULL) || (duid_vendor_private == NX_NULL) || (duid_private_length == NX_NULL))
1041 {
1042 return NX_PTR_ERROR;
1043 }
1044
1045 *duid_vendor_number = client_ptr -> nx_dhcpv6_client_duid.nx_duid_enterprise_number;
1046 length = client_ptr -> nx_dhcpv6_client_duid.nx_option_length - 6;
1047 if (length < 0)
1048 {
1049 return NX_DHCPV6_INVALID_DUID;
1050 }
1051
1052 /* NOTE: The duid_vendor_private buffer is provided by user, and the buffer size must be not less than NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_LENGTH. */
1053 memcpy(duid_vendor_private, &(client_ptr -> nx_dhcpv6_client_duid.nx_duid_private_identifier[0]), (UINT)length); /* Use case of memcpy is verified. The buffer is provided by user. */
1054 *duid_private_length = (UINT)length;
1055 }
1056
1057 return NX_SUCCESS;
1058 }
1059
1060
1061 /**************************************************************************/
1062 /* */
1063 /* FUNCTION RELEASE */
1064 /* */
1065 /* _nxe_dhcpv6_add_ip_address_lease PORTABLE C */
1066 /* 6.1 */
1067 /* AUTHOR */
1068 /* */
1069 /* Yuxin Zhou, Microsoft Corporation */
1070 /* */
1071 /* DESCRIPTION */
1072 /* */
1073 /* This function performs error checking for the copy lease service. */
1074 /* */
1075 /* INPUT */
1076 /* */
1077 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
1078 /* table_index Table index to store data */
1079 /* lease_IP_address Lease IP address */
1080 /* T1 T1 lifetime (when to renew) */
1081 /* T2 T2 lifetime (when to rebind) */
1082 /* preferred_lifetime When address becomes deprecated */
1083 /* valid_lifetime When address becomes invalid */
1084 /* */
1085 /* OUTPUT */
1086 /* */
1087 /* NX_SUCCESS Successful IP address copy */
1088 /* NX_DHCPV6_PARAM_ERROR Invalid non pointer input */
1089 /* NX_PTR_ERROR Invalid pointer input */
1090 /* NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS */
1091 /* Address not onlink with Server */
1092 /* DHCPv6 network interface */
1093 /* CALLS */
1094 /* */
1095 /* _nx_dhcpv6_add_ip_address_lease Actual copy lease data service */
1096 /* */
1097 /* CALLED BY */
1098 /* */
1099 /* Application code */
1100 /* */
1101 /* RELEASE HISTORY */
1102 /* */
1103 /* DATE NAME DESCRIPTION */
1104 /* */
1105 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1106 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1107 /* resulting in version 6.1 */
1108 /* */
1109 /**************************************************************************/
_nxe_dhcpv6_add_ip_address_lease(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT table_index,NXD_ADDRESS * lease_IP_address,ULONG T1,ULONG T2,ULONG valid_lifetime,ULONG preferred_lifetime)1110 UINT _nxe_dhcpv6_add_ip_address_lease(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, NXD_ADDRESS *lease_IP_address,
1111 ULONG T1, ULONG T2, ULONG valid_lifetime, ULONG preferred_lifetime)
1112 {
1113
1114 UINT status;
1115
1116
1117 /* Check for invalid pointer input. */
1118 if ((dhcpv6_server_ptr == NX_NULL) || (lease_IP_address == NX_NULL))
1119 {
1120
1121 return NX_PTR_ERROR;
1122 }
1123
1124 /* Check for invalid non pointer input. */
1125 if (CHECK_UNSPECIFIED_ADDRESS(&(lease_IP_address -> nxd_ip_address.v6[0])))
1126 {
1127
1128 return NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS;
1129 }
1130
1131 /* Check for invalid lease time data. */
1132 if ((T1 == 0) || (T2 == 0) || (valid_lifetime == 0) || (preferred_lifetime == 0))
1133 {
1134
1135 return NX_DHCPV6_PARAM_ERROR;
1136 }
1137
1138 /* Call the actual service and return completion status. */
1139 status = _nx_dhcpv6_add_ip_address_lease(dhcpv6_server_ptr, table_index, lease_IP_address,
1140 T1, T2, valid_lifetime, preferred_lifetime);
1141
1142 return status;
1143 }
1144
1145
1146 /**************************************************************************/
1147 /* */
1148 /* FUNCTION RELEASE */
1149 /* */
1150 /* _nx_dhcpv6_add_ip_address_lease PORTABLE C */
1151 /* 6.1 */
1152 /* AUTHOR */
1153 /* */
1154 /* Yuxin Zhou, Microsoft Corporation */
1155 /* */
1156 /* DESCRIPTION */
1157 /* */
1158 /* This function copies lease data into the Server IP lease table. */
1159 /* The caller can specify which slot with a index value up to the size */
1160 /* of the lease table, (NX_DHCPV6_MAX_LEASES - 1), or the DHCPv6 server */
1161 /* will find an empty slot to store the lease data if the table index is*/
1162 /* set to 'infinity' e.g. 0xFFFFFFFF. */
1163 /* */
1164 /* This is intended to satisfy the DHCPv6 protocol requirement that a */
1165 /* DHPCv6 Server be able to store and retrieve IP lease data from */
1166 /* nonvolatile memory e..g between reboots. */
1167 /* */
1168 /* INPUT */
1169 /* */
1170 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
1171 /* table_index Table index to store data */
1172 /* lease_IP_address Lease IP address */
1173 /* T1 T1 lifetime (when to renew) */
1174 /* T2 T2 lifetime (when to rebind) */
1175 /* preferred_lifetime When address becomes deprecated */
1176 /* valid_lifetime When address becomes invalid */
1177 /* */
1178 /* OUTPUT */
1179 /* */
1180 /* NX_SUCCESS Successful IP address copy */
1181 /* NX_DHCPV6_PARAM_ERROR Invalid table index */
1182 /* NX_DHCPV6_TABLE_FULL No empty entries for lease data */
1183 /* NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS */
1184 /* Address not onlink with Server */
1185 /* DHCPv6 network interface */
1186 /* CALLS */
1187 /* */
1188 /* None */
1189 /* */
1190 /* CALLED BY */
1191 /* */
1192 /* Application code */
1193 /* */
1194 /* RELEASE HISTORY */
1195 /* */
1196 /* DATE NAME DESCRIPTION */
1197 /* */
1198 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1199 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1200 /* resulting in version 6.1 */
1201 /* */
1202 /**************************************************************************/
_nx_dhcpv6_add_ip_address_lease(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT table_index,NXD_ADDRESS * lease_IP_address,ULONG T1,ULONG T2,ULONG valid_lifetime,ULONG preferred_lifetime)1203 UINT _nx_dhcpv6_add_ip_address_lease(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, NXD_ADDRESS *lease_IP_address,
1204 ULONG T1, ULONG T2, ULONG valid_lifetime, ULONG preferred_lifetime)
1205 {
1206
1207 UINT i;
1208 NX_DHCPV6_ADDRESS_LEASE *lease_ptr;
1209 UINT ga_address_index;
1210 UINT prefix_length;
1211
1212
1213 /* Get the DHCPv6 server address interface index. */
1214 ga_address_index = dhcpv6_server_ptr -> nx_dhcpv6_server_ga_address_index;
1215
1216 prefix_length = dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address_prefix_length;
1217
1218 /* Verify the input addresses match the server interface address prefix (in IPv4 terms, the
1219 network masked addresses should be equal). */
1220
1221 if (!CHECK_IP_ADDRESSES_BY_PREFIX(&(dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address[0]),
1222 &lease_IP_address -> nxd_ip_address.v6[0], prefix_length))
1223 {
1224
1225 return NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS;
1226 }
1227
1228 /* Is there a table index specified? */
1229 if (table_index == 0xFFFFFFFF)
1230 {
1231
1232 /* No, so lets search the server table and find an available slot. */
1233 for (i = 0; i < NX_DHCPV6_MAX_LEASES; i++)
1234 {
1235
1236 /* Get a local pointer for convenience. */
1237 lease_ptr = &(dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i]);
1238
1239 /* Does this slot have an address already? */
1240 if (CHECK_UNSPECIFIED_ADDRESS(&(lease_ptr -> nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0])))
1241 {
1242
1243 /* This one looks empty. */
1244 table_index = i;
1245 break;
1246 }
1247 }
1248
1249 if (table_index == 0xFFFFFFFF)
1250 {
1251 return NX_DHCPV6_TABLE_FULL;
1252 }
1253 }
1254 else
1255 {
1256 /* Check for valid table index. */
1257 if (table_index >= NX_DHCPV6_MAX_LEASES)
1258 {
1259
1260 /* No good. Exceeds the size of the table. */
1261 return NX_DHCPV6_PARAM_ERROR;
1262 }
1263 }
1264
1265 /* Copy the supplied IP data into the lease entry. */
1266 lease_ptr = &(dhcpv6_server_ptr -> nx_dhcpv6_lease_list[table_index]);
1267
1268 COPY_NXD_ADDRESS(lease_IP_address, &(lease_ptr -> nx_dhcpv6_lease_IP_address));
1269 lease_ptr -> nx_dhcpv6_lease_T1_lifetime = T1;
1270 lease_ptr -> nx_dhcpv6_lease_T2_lifetime = T2;
1271 lease_ptr -> nx_dhcpv6_lease_valid_lifetime = valid_lifetime;
1272 lease_ptr -> nx_dhcpv6_lease_preferred_lifetime =preferred_lifetime;
1273
1274 dhcpv6_server_ptr -> nx_dhcpv6_assignable_addresses++;
1275
1276 return NX_SUCCESS;
1277 }
1278
1279
1280 /**************************************************************************/
1281 /* */
1282 /* FUNCTION RELEASE */
1283 /* */
1284 /* _nxe_dhcpv6_retrieve_ip_address_lease PORTABLE C */
1285 /* 6.1 */
1286 /* AUTHOR */
1287 /* */
1288 /* Yuxin Zhou, Microsoft Corporation */
1289 /* */
1290 /* DESCRIPTION */
1291 /* */
1292 /* This function performs error checking for the actual retrieve lease */
1293 /* service. */
1294 /* */
1295 /* This is intended to satisfy the DHCPv6 protocol requirement that a */
1296 /* DHPCv6 Server be able to store and retrieve lease data from */
1297 /* nonvolatile memory e..g between reboots. */
1298 /* */
1299 /* INPUT */
1300 /* */
1301 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
1302 /* table_index Table index to obtain data */
1303 /* lease_IP_address Lease IP address */
1304 /* T1 T1 lifetime (when to renew) */
1305 /* T2 T2 lifetime (when to rebind) */
1306 /* preferred_lifetime When address becomes deprecated */
1307 /* valid_lifetime When address becomes invalid */
1308 /* */
1309 /* OUTPUT */
1310 /* */
1311 /* NX_SUCCESS Successful IP address copy */
1312 /* NX_PTR_ERROR Invalid pointer input */
1313 /* */
1314 /* CALLS */
1315 /* */
1316 /* _nx_dhcpv6_retrieve_ip_address_lease */
1317 /* Actual retrieve data service */
1318 /* */
1319 /* CALLED BY */
1320 /* */
1321 /* Application code */
1322 /* */
1323 /* RELEASE HISTORY */
1324 /* */
1325 /* DATE NAME DESCRIPTION */
1326 /* */
1327 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1328 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1329 /* resulting in version 6.1 */
1330 /* */
1331 /**************************************************************************/
_nxe_dhcpv6_retrieve_ip_address_lease(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT table_index,NXD_ADDRESS * lease_IP_address,ULONG * T1,ULONG * T2,ULONG * valid_lifetime,ULONG * preferred_lifetime)1332 UINT _nxe_dhcpv6_retrieve_ip_address_lease(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, NXD_ADDRESS *lease_IP_address,
1333 ULONG *T1, ULONG *T2, ULONG *valid_lifetime, ULONG *preferred_lifetime)
1334 {
1335
1336 UINT status;
1337
1338
1339 /* Check for invalid pointer input. */
1340 if ((dhcpv6_server_ptr == NX_NULL) || (lease_IP_address == NX_NULL) || (T1 == NX_NULL) ||
1341 (T2 == NX_NULL) || (valid_lifetime == NX_NULL) || (preferred_lifetime == NX_NULL))
1342 {
1343
1344 return NX_PTR_ERROR;
1345 }
1346
1347 status = _nx_dhcpv6_retrieve_ip_address_lease(dhcpv6_server_ptr, table_index, lease_IP_address,
1348 T1, T2, valid_lifetime, preferred_lifetime);
1349
1350 return status;
1351 }
1352
1353
1354 /**************************************************************************/
1355 /* */
1356 /* FUNCTION RELEASE */
1357 /* */
1358 /* _nx_dhcpv6_retrieve_ip_address_lease PORTABLE C */
1359 /* 6.1 */
1360 /* AUTHOR */
1361 /* */
1362 /* Yuxin Zhou, Microsoft Corporation */
1363 /* */
1364 /* DESCRIPTION */
1365 /* */
1366 /* This function retrieves lease data from the Server IP lease table. */
1367 /* The caller must specify which slot with a index value up to the size */
1368 /* of the lease table, (NX_DHCPV6_MAX_LEASES - 1). */
1369 /* */
1370 /* This is intended to satisfy the DHCPv6 protocol requirement that a */
1371 /* DHPCv6 Server be able to store and retrieve lease data from */
1372 /* nonvolatile memory e..g between reboots. */
1373 /* */
1374 /* INPUT */
1375 /* */
1376 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
1377 /* table_index Table index to obtain data */
1378 /* lease_IP_address Lease IP address */
1379 /* T1 T1 lifetime (when to renew) */
1380 /* T2 T2 lifetime (when to rebind) */
1381 /* preferred_lifetime When address becomes deprecated */
1382 /* valid_lifetime When address becomes invalid */
1383 /* */
1384 /* OUTPUT */
1385 /* */
1386 /* NX_SUCCESS Successful IP address copy */
1387 /* NX_DHCPV6_PARAM_ERROR Invalid table index */
1388 /* */
1389 /* CALLS */
1390 /* */
1391 /* None */
1392 /* */
1393 /* CALLED BY */
1394 /* */
1395 /* Application code */
1396 /* */
1397 /* RELEASE HISTORY */
1398 /* */
1399 /* DATE NAME DESCRIPTION */
1400 /* */
1401 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1402 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1403 /* resulting in version 6.1 */
1404 /* */
1405 /**************************************************************************/
_nx_dhcpv6_retrieve_ip_address_lease(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT table_index,NXD_ADDRESS * lease_IP_address,ULONG * T1,ULONG * T2,ULONG * valid_lifetime,ULONG * preferred_lifetime)1406 UINT _nx_dhcpv6_retrieve_ip_address_lease(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, NXD_ADDRESS *lease_IP_address,
1407 ULONG *T1, ULONG *T2, ULONG *valid_lifetime, ULONG *preferred_lifetime)
1408 {
1409
1410 NX_DHCPV6_ADDRESS_LEASE *lease_ptr;
1411
1412
1413 /* Check for valid table index. */
1414 if (table_index >= NX_DHCPV6_MAX_LEASES)
1415 {
1416
1417 /* No good. Exceeds the size of the table. */
1418 return NX_DHCPV6_PARAM_ERROR;
1419 }
1420
1421 /* Get a local pointer for convenience. */
1422 lease_ptr = &(dhcpv6_server_ptr -> nx_dhcpv6_lease_list[table_index]);
1423
1424 /* Copy the lease data into the input pointer buffers. */
1425 COPY_NXD_ADDRESS(&(lease_ptr -> nx_dhcpv6_lease_IP_address), lease_IP_address);
1426 *T1 = lease_ptr -> nx_dhcpv6_lease_T1_lifetime;
1427 *T2 = lease_ptr -> nx_dhcpv6_lease_T2_lifetime;
1428 *valid_lifetime = lease_ptr -> nx_dhcpv6_lease_valid_lifetime;
1429 *preferred_lifetime = lease_ptr -> nx_dhcpv6_lease_preferred_lifetime;
1430
1431 return NX_SUCCESS;
1432 }
1433
1434
1435 /**************************************************************************/
1436 /* */
1437 /* FUNCTION RELEASE */
1438 /* */
1439 /* _nxe_dhcpv6_server_delete PORTABLE C */
1440 /* 6.1 */
1441 /* AUTHOR */
1442 /* */
1443 /* Yuxin Zhou, Microsoft Corporation */
1444 /* */
1445 /* DESCRIPTION */
1446 /* */
1447 /* This function performs error checking on the NetX delete dhcpv6 */
1448 /* server service. */
1449 /* */
1450 /* INPUT */
1451 /* */
1452 /* dhcpv6_server_ptr Pointer to DHCPV6 server */
1453 /* */
1454 /* OUTPUT */
1455 /* */
1456 /* OUTPUT */
1457 /* */
1458 /* status Completion status */
1459 /* NX_PTR_ERROR Invalid pointer input */
1460 /* */
1461 /* */
1462 /* CALLS */
1463 /* */
1464 /* _nx_dhcpv6_server_delete Actual DHCPV6 delete function */
1465 /* */
1466 /* CALLED BY */
1467 /* */
1468 /* Application Code */
1469 /* */
1470 /* RELEASE HISTORY */
1471 /* */
1472 /* DATE NAME DESCRIPTION */
1473 /* */
1474 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1475 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1476 /* resulting in version 6.1 */
1477 /* */
1478 /**************************************************************************/
_nxe_dhcpv6_server_delete(NX_DHCPV6_SERVER * dhcpv6_server_ptr)1479 UINT _nxe_dhcpv6_server_delete(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
1480 {
1481
1482 UINT status;
1483
1484
1485 /* Check for invalid input pointers. */
1486 if ((dhcpv6_server_ptr == NX_NULL) || (dhcpv6_server_ptr -> nx_dhcpv6_id != NX_DHCPV6_SERVER_ID))
1487 return(NX_PTR_ERROR);
1488
1489 /* Check for appropriate caller. */
1490 NX_THREADS_ONLY_CALLER_CHECKING
1491
1492 /* Call actual DHCPV6 server delete service. */
1493 status = _nx_dhcpv6_server_delete(dhcpv6_server_ptr);
1494
1495 /* Return commpletion status. */
1496 return(status);
1497 }
1498
1499
1500 /**************************************************************************/
1501 /* */
1502 /* FUNCTION RELEASE */
1503 /* */
1504 /* _nx_dhcpv6_client_delete PORTABLE C */
1505 /* 6.1 */
1506 /* AUTHOR */
1507 /* */
1508 /* Yuxin Zhou, Microsoft Corporation */
1509 /* */
1510 /* DESCRIPTION */
1511 /* */
1512 /* This function deletes the DHCPV6 Client instance and releases all of*/
1513 /* NetX and ThreadX resources. */
1514 /* */
1515 /* INPUT */
1516 /* */
1517 /* dhcpv6_server_ptr Pointer to Client instance */
1518 /* */
1519 /* OUTPUT */
1520 /* */
1521 /* NX_SUCCESS Successful Completion status */
1522 /* */
1523 /* CALLS */
1524 /* */
1525 /* nx_udp_socket_unbind Release DHCPV6 UDP socket port*/
1526 /* nx_udp_socket_delete Delete the DHCPV6 UDP socket */
1527 /* tx_thread_terminate Terminate DHCPV6 thread */
1528 /* tx_thread_delete Delete DHCPV6 thread */
1529 /* tx_timer_delete Delete DHCPV6 timers */
1530 /* tx_mutex_delete Delete DHCPV6 mutexes */
1531 /* tx_event_flags_delete Delete DHCPV6 flag queue */
1532 /* */
1533 /* CALLED BY */
1534 /* */
1535 /* Application Code */
1536 /* */
1537 /* RELEASE HISTORY */
1538 /* */
1539 /* DATE NAME DESCRIPTION */
1540 /* */
1541 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1542 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1543 /* resulting in version 6.1 */
1544 /* */
1545 /**************************************************************************/
_nx_dhcpv6_server_delete(NX_DHCPV6_SERVER * dhcpv6_server_ptr)1546 UINT _nx_dhcpv6_server_delete(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
1547 {
1548
1549 /* Terminate the DHCPV6 processing thread. */
1550 tx_thread_terminate(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread));
1551
1552 /* Delete the DHCPV6 processing thread. */
1553 tx_thread_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread));
1554
1555 /* Delete the flag event queue. */
1556 tx_event_flags_delete(&dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events);
1557
1558 /* Delete the timers */
1559 tx_timer_delete(&(dhcpv6_server_ptr->nx_dhcpv6_lease_timer));
1560 tx_timer_delete(&(dhcpv6_server_ptr->nx_dhcpv6_session_timer));
1561
1562 /* Delete the mutexes. */
1563 tx_mutex_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex));
1564
1565 /* Release the UDP socket port. */
1566 nx_udp_socket_unbind(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
1567
1568 /* Delete the UDP socket. */
1569 nx_udp_socket_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
1570
1571 /* Clear the dhcpv6 structure ID. */
1572 dhcpv6_server_ptr -> nx_dhcpv6_id = 0;
1573
1574 /* Return a successful status. */
1575 return(NX_SUCCESS);
1576 }
1577
1578
1579 /**************************************************************************/
1580 /* */
1581 /* FUNCTION RELEASE */
1582 /* */
1583 /* _nxe_dhcpv6_create_ip_address_range PORTABLE C */
1584 /* 6.1 */
1585 /* AUTHOR */
1586 /* */
1587 /* Yuxin Zhou, Microsoft Corporation */
1588 /* */
1589 /* DESCRIPTION */
1590 /* */
1591 /* This function performs error checking on the create address list */
1592 /* service. */
1593 /* */
1594 /* INPUT */
1595 /* */
1596 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
1597 /* start_ipv6_address Start of IP address in list. */
1598 /* end_ipv6_address End of IP address in list. */
1599 /* addresses_added Number of addresses added to list*/
1600 /* */
1601 /* OUTPUT */
1602 /* */
1603 /* NX_SUCCESS Successful IP list creation */
1604 /* */
1605 /* CALLS */
1606 /* */
1607 /* nx_dhcpv6_create_ip_address_range Actual list create service */
1608 /* */
1609 /* CALLED BY */
1610 /* */
1611 /* Application code */
1612 /* */
1613 /* RELEASE HISTORY */
1614 /* */
1615 /* DATE NAME DESCRIPTION */
1616 /* */
1617 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1618 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1619 /* resulting in version 6.1 */
1620 /* */
1621 /**************************************************************************/
_nxe_dhcpv6_create_ip_address_range(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NXD_ADDRESS * start_ipv6_address,NXD_ADDRESS * end_ipv6_address,UINT * addresses_added)1622 UINT _nxe_dhcpv6_create_ip_address_range(NX_DHCPV6_SERVER *dhcpv6_server_ptr,
1623 NXD_ADDRESS *start_ipv6_address, NXD_ADDRESS *end_ipv6_address,
1624 UINT *addresses_added)
1625 {
1626
1627 UINT status;
1628
1629
1630 /* Check for invalid input. */
1631 if ((dhcpv6_server_ptr == NX_NULL) ||
1632 (start_ipv6_address == NX_NULL)|| (end_ipv6_address == NX_NULL) ||
1633 (addresses_added == NX_NULL))
1634 {
1635 return(NX_PTR_ERROR);
1636 }
1637
1638 /* Check for invalid non pointer input. */
1639 if ((CHECK_UNSPECIFIED_ADDRESS(&start_ipv6_address -> nxd_ip_address.v6[0])) ||
1640 (CHECK_UNSPECIFIED_ADDRESS(&end_ipv6_address -> nxd_ip_address.v6[0])))
1641 {
1642
1643 return(NX_DHCPV6_INVALID_IP_ADDRESS);
1644 }
1645
1646 /* Check for an invalid address range. */
1647 if (start_ipv6_address -> nxd_ip_address.v6[3] > end_ipv6_address -> nxd_ip_address.v6[3])
1648 {
1649
1650 return(NX_DHCPV6_INVALID_IP_ADDRESS);
1651 }
1652
1653 status = _nx_dhcpv6_create_ip_address_range(dhcpv6_server_ptr, start_ipv6_address, end_ipv6_address, addresses_added);
1654
1655 return status;
1656 }
1657
1658
1659 /**************************************************************************/
1660 /* */
1661 /* FUNCTION RELEASE */
1662 /* */
1663 /* _nx_dhcpv6_create_ip_address_range PORTABLE C */
1664 /* 6.1 */
1665 /* AUTHOR */
1666 /* */
1667 /* Yuxin Zhou, Microsoft Corporation */
1668 /* */
1669 /* DESCRIPTION */
1670 /* */
1671 /* This function creates a list of IPv6 addresses the DHCPv6 server */
1672 /* may assign to clients, using a start and end address. It returns the*/
1673 /* number of addresses actually added, which may be limited by the size */
1674 /* of the server address table. */
1675 /* */
1676 /* Note: The NetX Duo DHCPv6 server accomodates up to 256 assignable */
1677 /* address ranges in the current release. */
1678 /* */
1679 /* INPUT */
1680 /* */
1681 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
1682 /* start_ipv6_address Start of IP address in list. */
1683 /* end_ipv6_address End of IP address in list. */
1684 /* addresses_added Number of addresses added to list*/
1685 /* */
1686 /* OUTPUT */
1687 /* */
1688 /* NX_SUCCESS Successful IP list creation */
1689 /* NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS */
1690 /* Supplied address not reachable */
1691 /* */
1692 /* CALLS */
1693 /* */
1694 /* */
1695 /* CALLED BY */
1696 /* */
1697 /* Application code */
1698 /* */
1699 /* RELEASE HISTORY */
1700 /* */
1701 /* DATE NAME DESCRIPTION */
1702 /* */
1703 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1704 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1705 /* resulting in version 6.1 */
1706 /* */
1707 /**************************************************************************/
_nx_dhcpv6_create_ip_address_range(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NXD_ADDRESS * start_ipv6_address,NXD_ADDRESS * end_ipv6_address,UINT * addresses_added)1708 UINT _nx_dhcpv6_create_ip_address_range(NX_DHCPV6_SERVER *dhcpv6_server_ptr,
1709 NXD_ADDRESS *start_ipv6_address, NXD_ADDRESS *end_ipv6_address,
1710 UINT *addresses_added)
1711 {
1712
1713 UINT i;
1714 NX_IP *ip_ptr;
1715 UINT prefix_length;
1716 NXD_ADDRESS next_ipv6_address;
1717 UINT ga_address_index;
1718
1719
1720 *addresses_added = 0;
1721
1722 COPY_NXD_ADDRESS(start_ipv6_address, &next_ipv6_address);
1723
1724 /* Set up a local variable for convenience. */
1725 ip_ptr = dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr;
1726 ga_address_index = dhcpv6_server_ptr -> nx_dhcpv6_server_ga_address_index;
1727 prefix_length = ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address_prefix_length;
1728
1729 /* Verify the input addresses match the server interface address prefix (in IPv4 terms, the
1730 network masked addresses should be equal). */
1731 if (!CHECK_IP_ADDRESSES_BY_PREFIX(&(ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address[0]),
1732 &start_ipv6_address -> nxd_ip_address.v6[0], prefix_length))
1733 {
1734
1735 return NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS;
1736 }
1737
1738 if (!CHECK_IP_ADDRESSES_BY_PREFIX(&(ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address[0]),
1739 &end_ipv6_address -> nxd_ip_address.v6[0], prefix_length))
1740 {
1741
1742 return NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS;
1743 }
1744
1745 /* Set the server ip address based on the specified interface. */
1746
1747 /* Clear out existing entries and start adding IP addresses at the beginning of the list. */
1748 i = 0;
1749
1750 /* Fit as many IP addresses in the specified range as will fit in the table. */
1751 while (i < NX_DHCPV6_MAX_LEASES)
1752 {
1753
1754 NX_DHCPV6_ADDRESS_LEASE *ip_lease_ptr;
1755
1756 /* Set local pointer to the next entry for convenience. */
1757 ip_lease_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i];
1758
1759 /* Initialize each entry before adding data. */
1760 memset(&dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i], 0, sizeof(NX_DHCPV6_ADDRESS_LEASE));
1761
1762 /* Add the IP address into this slot. */
1763 COPY_NXD_ADDRESS(&next_ipv6_address, &ip_lease_ptr -> nx_dhcpv6_lease_IP_address);
1764
1765 /* Update the number of addresses added. */
1766 (*addresses_added)++;
1767
1768 /* Increase the address low word by one. */
1769 next_ipv6_address.nxd_ip_address.v6[3]++;
1770
1771 /* Check if we are overflowing the last word. */
1772 if (next_ipv6_address.nxd_ip_address.v6[3] == 0xFFFFFFFF)
1773 {
1774
1775 /* We are. Let's stop here. */
1776 break;
1777 }
1778
1779 if (CHECK_IPV6_ADDRESSES_SAME(&next_ipv6_address.nxd_ip_address.v6[0], &end_ipv6_address -> nxd_ip_address.v6[0]))
1780 {
1781 break;
1782 }
1783
1784 i++;
1785 }
1786
1787 /* Indicate how many addresses were actually added to the server list. */
1788 dhcpv6_server_ptr -> nx_dhcpv6_assignable_addresses = *addresses_added;
1789
1790 return(NX_SUCCESS);
1791 }
1792
1793
1794 /**************************************************************************/
1795 /* */
1796 /* FUNCTION RELEASE */
1797 /* */
1798 /* _nxe_dhcpv6_reserve_ip_address_range PORTABLE C */
1799 /* 6.1 */
1800 /* AUTHOR */
1801 /* */
1802 /* Yuxin Zhou, Microsoft Corporation */
1803 /* */
1804 /* DESCRIPTION */
1805 /* */
1806 /* This function performs error checking on the reserve address list */
1807 /* service. */
1808 /* */
1809 /* INPUT */
1810 /* */
1811 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
1812 /* start_ipv6_address Start of IP address to reserve */
1813 /* end_ipv6_address End of IP address to reserve */
1814 /* addresses_reserved Number of addresses reserved */
1815 /* */
1816 /* OUTPUT */
1817 /* */
1818 /* NX_SUCCESS Successful IP list creation */
1819 /* NX_DHCPV6_INVALID_IP_ADDRESS Invalid address supplied */
1820 /* */
1821 /* CALLS */
1822 /* */
1823 /* nx_dhcpv6_reserve_ip_address_range Actual list create service */
1824 /* */
1825 /* CALLED BY */
1826 /* */
1827 /* Application code */
1828 /* */
1829 /* RELEASE HISTORY */
1830 /* */
1831 /* DATE NAME DESCRIPTION */
1832 /* */
1833 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1834 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1835 /* resulting in version 6.1 */
1836 /* */
1837 /**************************************************************************/
_nxe_dhcpv6_reserve_ip_address_range(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NXD_ADDRESS * start_ipv6_address,NXD_ADDRESS * end_ipv6_address,UINT * addresses_reserved)1838 UINT _nxe_dhcpv6_reserve_ip_address_range(NX_DHCPV6_SERVER *dhcpv6_server_ptr,
1839 NXD_ADDRESS *start_ipv6_address, NXD_ADDRESS *end_ipv6_address,
1840 UINT *addresses_reserved)
1841 {
1842
1843 UINT status;
1844
1845
1846 /* Check for invalid input. */
1847 if ((dhcpv6_server_ptr == NX_NULL) ||
1848 (start_ipv6_address == NX_NULL)|| (end_ipv6_address == NX_NULL) ||
1849 (addresses_reserved == NX_NULL))
1850 {
1851 return(NX_PTR_ERROR);
1852 }
1853
1854 /* Check for invalid non pointer input. */
1855 if (start_ipv6_address -> nxd_ip_address.v6[3] > end_ipv6_address -> nxd_ip_address.v6[3])
1856 {
1857
1858 return(NX_DHCPV6_INVALID_IP_ADDRESS);
1859 }
1860
1861 if ((CHECK_UNSPECIFIED_ADDRESS(&start_ipv6_address -> nxd_ip_address.v6[0])) ||
1862 (CHECK_UNSPECIFIED_ADDRESS(&end_ipv6_address -> nxd_ip_address.v6[0])))
1863 {
1864 return(NX_DHCPV6_INVALID_IP_ADDRESS);
1865 }
1866
1867 status = _nx_dhcpv6_reserve_ip_address_range(dhcpv6_server_ptr, start_ipv6_address, end_ipv6_address, addresses_reserved);
1868
1869 return status;
1870 }
1871
1872
1873 /**************************************************************************/
1874 /* */
1875 /* FUNCTION RELEASE */
1876 /* */
1877 /* _nx_dhcpv6_reserve_ip_address_range PORTABLE C */
1878 /* 6.1 */
1879 /* AUTHOR */
1880 /* */
1881 /* Yuxin Zhou, Microsoft Corporation */
1882 /* */
1883 /* DESCRIPTION */
1884 /* */
1885 /* This function reserves a range of IPv6 addresses not to assign to */
1886 /* Clients, using a start and end address. It returns the number of */
1887 /* addresses actually reserved, depending on the size of the server */
1888 /* address table. To reserve a single address, start and end address */
1889 /* are the same. */
1890 /* */
1891 /* INPUT */
1892 /* */
1893 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
1894 /* start_ipv6_address Start of IP address in list. */
1895 /* end_ipv6_address End of IP address in list. */
1896 /* addresses_reserved Number of addresses reserved */
1897 /* */
1898 /* OUTPUT */
1899 /* */
1900 /* NX_SUCCESS Successful IP address reservation*/
1901 /* NX_DHCPV6_INVALID_IP_ADDRESS Reserved addresses out of range */
1902 /* NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS */
1903 /* Supplied address is unreachable */
1904 /* */
1905 /* CALLS */
1906 /* */
1907 /* CHECK_IP_ADDRESSES_BY_PREFIX Confirm addresses match the */
1908 /* server domain by matching prefix*/
1909 /* */
1910 /* CALLED BY */
1911 /* */
1912 /* Application code */
1913 /* */
1914 /* RELEASE HISTORY */
1915 /* */
1916 /* DATE NAME DESCRIPTION */
1917 /* */
1918 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1919 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1920 /* resulting in version 6.1 */
1921 /* */
1922 /**************************************************************************/
_nx_dhcpv6_reserve_ip_address_range(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NXD_ADDRESS * start_ipv6_address,NXD_ADDRESS * end_ipv6_address,UINT * addresses_reserved)1923 UINT _nx_dhcpv6_reserve_ip_address_range(NX_DHCPV6_SERVER *dhcpv6_server_ptr,
1924 NXD_ADDRESS *start_ipv6_address, NXD_ADDRESS *end_ipv6_address,
1925 UINT *addresses_reserved)
1926 {
1927
1928 UINT i;
1929 NX_IP *ip_ptr;
1930 UINT prefix_length;
1931 NXD_ADDRESS next_ipv6_address;
1932 NX_DHCPV6_ADDRESS_LEASE *ip_lease_ptr = NX_NULL;
1933 UINT ga_address_index;
1934
1935
1936 /* Initialize local and input variables. */
1937 *addresses_reserved = 0;
1938
1939 COPY_NXD_ADDRESS(start_ipv6_address, &next_ipv6_address);
1940
1941 /* Set up a local variable for convenience. */
1942 ip_ptr = dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr;
1943 ga_address_index = dhcpv6_server_ptr -> nx_dhcpv6_server_ga_address_index;
1944 prefix_length = ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address_prefix_length;
1945
1946 /* Verify the input addresses match the server interface address prefix (in IPv4 terms, the
1947 network masked addresses should be equal). */
1948 if (!CHECK_IP_ADDRESSES_BY_PREFIX(&(ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address[0]),
1949 &start_ipv6_address -> nxd_ip_address.v6[0], prefix_length))
1950 {
1951
1952 return NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS;
1953 }
1954
1955 if (!CHECK_IP_ADDRESSES_BY_PREFIX(&(ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address[0]),
1956 &end_ipv6_address -> nxd_ip_address.v6[0], prefix_length))
1957 {
1958
1959 return NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS;
1960 }
1961
1962 /* Clear out existing entries and start adding IP addresses at the beginning of the list. */
1963 i = 0;
1964
1965 /* Match on start-end addresses for which leases to reserve. */
1966 while (i < NX_DHCPV6_MAX_LEASES)
1967 {
1968
1969 /* Set local pointer to the entry for convenience. */
1970 ip_lease_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i];
1971
1972 /* Add the IP address into this slot. */
1973 COPY_NXD_ADDRESS(&next_ipv6_address, &ip_lease_ptr -> nx_dhcpv6_lease_IP_address);
1974
1975 /* Check if we found the starting address. */
1976 if (CHECK_IPV6_ADDRESSES_SAME(&ip_lease_ptr -> nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0], &start_ipv6_address -> nxd_ip_address.v6[0]))
1977 {
1978 break;
1979 }
1980 }
1981
1982 if (i == NX_DHCPV6_MAX_LEASES)
1983 {
1984
1985 /* No starting address found in the server IP address list. */
1986 return NX_DHCPV6_INVALID_IP_ADDRESS;
1987 }
1988
1989 /* Set the lease times of this entry to infinity. */
1990 ip_lease_ptr -> nx_dhcpv6_lease_T1_lifetime = NX_DHCPV6_INFINTY_LEASE;
1991 ip_lease_ptr -> nx_dhcpv6_lease_T2_lifetime = NX_DHCPV6_INFINTY_LEASE;
1992 ip_lease_ptr -> nx_dhcpv6_lease_valid_lifetime = NX_DHCPV6_INFINTY_LEASE;
1993 ip_lease_ptr -> nx_dhcpv6_lease_preferred_lifetime = NX_DHCPV6_INFINTY_LEASE;
1994 ip_lease_ptr -> nx_dhcpv6_lease_assigned_to = (NX_DHCPV6_CLIENT *)(ALIGN_TYPE)0xFFFFFFFF;
1995
1996 /* Update the number of addresses reserved. */
1997 (*addresses_reserved)++;
1998
1999 /* Process the next entry. */
2000
2001 /* We found the starting address, so start reserving the rest of the address(es). */
2002 while ((!CHECK_IPV6_ADDRESSES_SAME(&next_ipv6_address.nxd_ip_address.v6[0], &end_ipv6_address -> nxd_ip_address.v6[0])) &&
2003 (i < NX_DHCPV6_MAX_LEASES))
2004 {
2005
2006 i++;
2007
2008 /* Set local pointer to the next entry for convenience. */
2009 ip_lease_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i];
2010
2011 /* Set the lease times of this entry to infinity. */
2012 ip_lease_ptr -> nx_dhcpv6_lease_T1_lifetime = NX_DHCPV6_INFINTY_LEASE;
2013 ip_lease_ptr -> nx_dhcpv6_lease_T2_lifetime = NX_DHCPV6_INFINTY_LEASE;
2014 ip_lease_ptr -> nx_dhcpv6_lease_valid_lifetime = NX_DHCPV6_INFINTY_LEASE;
2015 ip_lease_ptr -> nx_dhcpv6_lease_preferred_lifetime = NX_DHCPV6_INFINTY_LEASE;
2016
2017 /* Set the number of addresses actually reserved. */
2018 (*addresses_reserved)++;
2019
2020 /* Return a pointer to the beginning of non reserved addresses.*/
2021 COPY_NXD_ADDRESS(&ip_lease_ptr -> nx_dhcpv6_lease_IP_address, &next_ipv6_address);
2022 }
2023
2024 return(NX_SUCCESS);
2025 }
2026
2027
2028 /**************************************************************************/
2029 /* */
2030 /* FUNCTION RELEASE */
2031 /* */
2032 /* _nxe_dhcpv6_create_dns_address PORTABLE C */
2033 /* 6.1 */
2034 /* AUTHOR */
2035 /* */
2036 /* Yuxin Zhou, Microsoft Corporation */
2037 /* */
2038 /* DESCRIPTION */
2039 /* */
2040 /* This function does error checking for the add dns address service. */
2041 /* */
2042 /* INPUT */
2043 /* */
2044 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
2045 /* dns_ipv6_address DNS server IP address */
2046 /* */
2047 /* OUTPUT */
2048 /* */
2049 /* NX_DHCPV6_PARAM_ERROR Invalid input */
2050 /* status Actual add dns address status */
2051 /* */
2052 /* CALLS */
2053 /* */
2054 /* _nx_dhcpv6_create_dns_address */
2055 /* Add DNS server address service */
2056 /* CALLED BY */
2057 /* */
2058 /* Application code */
2059 /* */
2060 /* RELEASE HISTORY */
2061 /* */
2062 /* DATE NAME DESCRIPTION */
2063 /* */
2064 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2065 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2066 /* resulting in version 6.1 */
2067 /* */
2068 /**************************************************************************/
_nxe_dhcpv6_create_dns_address(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NXD_ADDRESS * dns_ipv6_address)2069 UINT _nxe_dhcpv6_create_dns_address(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NXD_ADDRESS *dns_ipv6_address)
2070 {
2071
2072 UINT status;
2073
2074
2075 /* Check for invalid pointer input. */
2076 if (!dhcpv6_server_ptr || !dns_ipv6_address)
2077 {
2078 return NX_PTR_ERROR;
2079 }
2080
2081 /* Check for invalid parameters and null address. */
2082 if ((dhcpv6_server_ptr -> nx_dhcpv6_id != NX_DHCPV6_SERVER_ID) ||
2083 (CHECK_UNSPECIFIED_ADDRESS(&dns_ipv6_address -> nxd_ip_address.v6[0])))
2084
2085 {
2086 return NX_DHCPV6_PARAM_ERROR;
2087 }
2088
2089 status = _nx_dhcpv6_create_dns_address(dhcpv6_server_ptr, dns_ipv6_address);
2090
2091 return status;
2092 }
2093
2094
2095 /**************************************************************************/
2096 /* */
2097 /* FUNCTION RELEASE */
2098 /* */
2099 /* _nx_dhcpv6_create_dns_address PORTABLE C */
2100 /* 6.1 */
2101 /* AUTHOR */
2102 /* */
2103 /* Yuxin Zhou, Microsoft Corporation */
2104 /* */
2105 /* DESCRIPTION */
2106 /* */
2107 /* This function the DNS server address to the DHCPv6 server for when */
2108 /* clients request the DNS server address. */
2109 /* */
2110 /* INPUT */
2111 /* */
2112 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
2113 /* dns_ipv6_address DNS server IP address */
2114 /* */
2115 /* OUTPUT */
2116 /* */
2117 /* NX_SUCCESS Successfully added dns address */
2118 /* NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS */
2119 /* DNS prefix does not match */
2120 /* DHCPv6 server interface */
2121 /* */
2122 /* CALLS */
2123 /* */
2124 /* */
2125 /* CALLED BY */
2126 /* */
2127 /* Application code */
2128 /* */
2129 /* RELEASE HISTORY */
2130 /* */
2131 /* DATE NAME DESCRIPTION */
2132 /* */
2133 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2134 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2135 /* resulting in version 6.1 */
2136 /* */
2137 /**************************************************************************/
_nx_dhcpv6_create_dns_address(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NXD_ADDRESS * dns_ipv6_address)2138 UINT _nx_dhcpv6_create_dns_address(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NXD_ADDRESS *dns_ipv6_address)
2139 {
2140
2141 NX_IP *ip_ptr;
2142 UINT prefix_length;
2143 UINT ga_address_index;
2144
2145
2146 /* Set up local variables for convenience. */
2147 ip_ptr = dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr;
2148 ga_address_index = dhcpv6_server_ptr -> nx_dhcpv6_server_ga_address_index;
2149 prefix_length = ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address_prefix_length;
2150
2151 /* Verify the input addresses match the server interface address prefix (in IPv4 terms, the
2152 network masked addresses should be equal). */
2153 if (!CHECK_IP_ADDRESSES_BY_PREFIX(&(ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address[0]),
2154 &dns_ipv6_address -> nxd_ip_address.v6[0],
2155 prefix_length))
2156 {
2157
2158 return NX_DHCPV6_INVALID_INTERFACE_IP_ADDRESS;
2159 }
2160
2161 /* Set the dns server for this interface. */
2162 COPY_NXD_ADDRESS(dns_ipv6_address, &dhcpv6_server_ptr -> nx_dhcpv6_dns_ip_address);
2163
2164 return(NX_SUCCESS);
2165 }
2166
2167
2168 /**************************************************************************/
2169 /* */
2170 /* FUNCTION RELEASE */
2171 /* */
2172 /* _nxe_dhcpv6_set_server_duid PORTABLE C */
2173 /* 6.1 */
2174 /* AUTHOR */
2175 /* */
2176 /* Yuxin Zhou, Microsoft Corporation */
2177 /* */
2178 /* DESCRIPTION */
2179 /* */
2180 /* This function performs error checking for the create server DUID */
2181 /* service. */
2182 /* */
2183 /* INPUT */
2184 /* */
2185 /* dhcpv6_server_ptr Pointer to DHCPv6 server instance */
2186 /* duid_type Type of DUID, e.g. LL or LLT */
2187 /* hardware_type Network hardware type e.g IEEE 802*/
2188 /* mac_address_msw Mac address most significant bit */
2189 /* mac_address_lsw Mac address least significant bit */
2190 /* time Time data for link layer DUIDs */
2191 /* */
2192 /* OUTPUT */
2193 /* */
2194 /* status Actual completion status */
2195 /* NX_SUCCESS Successful completion status */
2196 /* */
2197 /* CALLS */
2198 /* */
2199 /* _nx_dhcpv6_set_server_duid Actual create server duid service */
2200 /* */
2201 /* CALLED BY */
2202 /* */
2203 /* Application Code */
2204 /* */
2205 /* RELEASE HISTORY */
2206 /* */
2207 /* DATE NAME DESCRIPTION */
2208 /* */
2209 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2210 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2211 /* resulting in version 6.1 */
2212 /* */
2213 /**************************************************************************/
_nxe_dhcpv6_set_server_duid(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT duid_type,UINT hardware_type,ULONG mac_address_msw,ULONG mac_address_lsw,ULONG time)2214 UINT _nxe_dhcpv6_set_server_duid(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT duid_type, UINT hardware_type,
2215 ULONG mac_address_msw, ULONG mac_address_lsw, ULONG time)
2216 {
2217 UINT status;
2218
2219
2220 /* Check for invalid pointer input. */
2221 if (dhcpv6_server_ptr == NX_NULL)
2222 {
2223 return NX_PTR_ERROR;
2224 }
2225
2226 /* For link layer time DUIDs, the time input must be non zero. */
2227 if (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
2228 {
2229 if (time == 0)
2230 {
2231 return NX_PTR_ERROR;
2232
2233 }
2234 }
2235
2236 /* Check for invalid non pointer input. */
2237 if ((duid_type == 0) || (hardware_type == 0) || (mac_address_msw == 0) || (mac_address_lsw == 0))
2238 {
2239 return NX_INVALID_PARAMETERS;
2240 }
2241
2242 /* Call the actual service. */
2243 status = _nx_dhcpv6_set_server_duid(dhcpv6_server_ptr, duid_type, hardware_type, mac_address_msw, mac_address_lsw, time);
2244
2245 return status;
2246 }
2247
2248
2249 /**************************************************************************/
2250 /* */
2251 /* FUNCTION RELEASE */
2252 /* */
2253 /* _nx_dhcpv6_set_server_duid PORTABLE C */
2254 /* 6.1 */
2255 /* AUTHOR */
2256 /* */
2257 /* Yuxin Zhou, Microsoft Corporation */
2258 /* */
2259 /* DESCRIPTION */
2260 /* */
2261 /* This function creates the server DUID with the input data. */
2262 /* */
2263 /* INPUT */
2264 /* */
2265 /* dhcpv6_server_ptr Pointer to DHCPv6 server instance */
2266 /* duid_type Type of DUID, e.g. LL or LLT */
2267 /* hardware_type Network hardware type e.g IEEE 802*/
2268 /* mac_address_msw Mac address most significant bit */
2269 /* mac_address_lsw Mac address least significant bit */
2270 /* time Time data for link layer DUIDs */
2271 /* */
2272 /* OUTPUT */
2273 /* */
2274 /* status Actual completion status */
2275 /* NX_SUCCESS Successful completion status */
2276 /* NX_DHCPV6_BAD_SERVER_DUID Unknown or invalid DUID type */
2277 /* NX_DHCPV6_INVALID_VENDOR_DATA Invalid Vendor ID supplied */
2278 /* */
2279 /* CALLS */
2280 /* */
2281 /* memset Clear specified area of memory */
2282 /* memcpy Copy data to specified location */
2283 /* */
2284 /* CALLED BY */
2285 /* */
2286 /* Application Code */
2287 /* */
2288 /* RELEASE HISTORY */
2289 /* */
2290 /* DATE NAME DESCRIPTION */
2291 /* */
2292 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2293 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2294 /* verified memcpy use cases, */
2295 /* resulting in version 6.1 */
2296 /* */
2297 /**************************************************************************/
_nx_dhcpv6_set_server_duid(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT duid_type,UINT hardware_type,ULONG mac_address_msw,ULONG mac_address_lsw,ULONG time)2298 UINT _nx_dhcpv6_set_server_duid(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT duid_type, UINT hardware_type,
2299 ULONG mac_address_msw, ULONG mac_address_lsw, ULONG time)
2300 {
2301
2302 NX_DHCPV6_SVR_DUID *duid_ptr;
2303
2304
2305 duid_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_server_duid;
2306
2307 /* Initialize the DUID to null. */
2308 memset(duid_ptr, 0, sizeof(NX_DHCPV6_SVR_DUID));
2309
2310 /* Assign the DUID op code. */
2311 duid_ptr -> nx_op_code = NX_DHCPV6_OP_DUID_SERVER;
2312
2313 /* Set the DUID type. */
2314 duid_ptr -> nx_duid_type = (USHORT)duid_type;
2315
2316 /* Set the DUID data for a non vendor DUID. */
2317 if (duid_ptr -> nx_duid_type != NX_DHCPV6_SERVER_DUID_TYPE_VENDOR_ASSIGNED)
2318 {
2319
2320 /* Server has a valid link local address. Add this to the server DUID fields
2321 if not a vendor assigned DUID type. */
2322 duid_ptr-> nx_link_layer_address_msw = (USHORT)mac_address_msw;
2323 duid_ptr -> nx_link_layer_address_lsw = mac_address_lsw;
2324
2325 /* Set the hardware type. */
2326 duid_ptr -> nx_hardware_type = (USHORT)hardware_type;
2327 }
2328 else
2329 {
2330 /* This is a private vendor DUID with private vendor ID. */
2331 duid_ptr -> nx_duid_enterprise_number = NX_DHCPV6_SERVER_DUID_VENDOR_PRIVATE_ID;
2332
2333 /* Check that the server vendor ID size. */
2334 if (sizeof(NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_ID) > NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_LENGTH)
2335 {
2336 return NX_DHCPV6_INVALID_VENDOR_DATA;
2337 }
2338
2339 memcpy(&duid_ptr -> nx_duid_private_identifier[0], NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_ID, sizeof(NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_ID)); /* Use case of memcpy is verified. */
2340 }
2341
2342 /* Now set the server DUID length. This will depend on DUID type. */
2343 if (duid_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_ONLY)
2344 {
2345
2346 /* Set the length to include the duid type, hardware type, msw and lsw fields. */
2347 duid_ptr -> nx_option_length = 3 * sizeof(USHORT) + sizeof(ULONG);
2348 }
2349 else if (duid_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
2350 {
2351
2352 /* Set the length to include the duid type, hardware type, time, and msw and lsw fields. */
2353 duid_ptr -> nx_option_length = 3 * sizeof(USHORT) + 2 * sizeof(ULONG);
2354
2355 /* Set the DUID time. */
2356 duid_ptr -> nx_duid_time = time;
2357
2358 }
2359 else if (duid_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_VENDOR_ASSIGNED)
2360 {
2361
2362 /* Set the length to include the duid type, hardware type, enterprise number and
2363 variable length private identifier. */
2364 duid_ptr -> nx_option_length = sizeof(USHORT) + sizeof(ULONG) + sizeof(NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_ID);
2365 }
2366 else
2367 {
2368
2369 /* Undefined or unknown DUID type. Return error status. */
2370 return NX_DHCPV6_BAD_SERVER_DUID;
2371 }
2372
2373 return NX_SUCCESS;
2374 }
2375
2376
2377 /**************************************************************************/
2378 /* */
2379 /* FUNCTION RELEASE */
2380 /* */
2381 /* _nx_dhcpv6_prepare_iana_status PORTABLE C */
2382 /* 6.1 */
2383 /* AUTHOR */
2384 /* */
2385 /* Yuxin Zhou, Microsoft Corporation */
2386 /* */
2387 /* DESCRIPTION */
2388 /* */
2389 /* This function updates the IANA status option. If the flag input is */
2390 /* set, the standard server status message is added to the */
2391 /* message buffer, and the option length updated. If the flag is false,*/
2392 /* no message is sent with the status option. */
2393 /* */
2394 /* INPUT */
2395 /* */
2396 /* dhcpv6_status_ptr Pointer to IANA status to add */
2397 /* flag 0 to clear; 1 to add message */
2398 /* */
2399 /* OUTPUT */
2400 /* */
2401 /* NX_SUCCESS Successful completion status */
2402 /* */
2403 /* CALLS */
2404 /* */
2405 /* memcpy Copy specified area of memory */
2406 /* */
2407 /* CALLED BY */
2408 /* */
2409 /* _nx_dhcpv6_send_response_to_client Send server response to client */
2410 /* */
2411 /* RELEASE HISTORY */
2412 /* */
2413 /* DATE NAME DESCRIPTION */
2414 /* */
2415 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2416 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2417 /* verified memcpy use cases, */
2418 /* resulting in version 6.1 */
2419 /* */
2420 /**************************************************************************/
_nx_dhcpv6_prepare_iana_status(NX_DHCPV6_SERVER_IANA_STATUS * dhcpv6_status_ptr,UINT flag)2421 UINT _nx_dhcpv6_prepare_iana_status(NX_DHCPV6_SERVER_IANA_STATUS *dhcpv6_status_ptr, UINT flag)
2422 {
2423
2424
2425 /* Make sure the basic header fields are filled in. No need to check the status code has been set; it is
2426 part of the decision to send a response. */
2427 dhcpv6_status_ptr -> nx_op_code = NX_DHCPV6_OP_OPTION_STATUS;
2428 dhcpv6_status_ptr -> nx_option_length = sizeof(USHORT);
2429
2430 /* Check if we are adding or clearing a message. */
2431 if (flag == NX_FALSE)
2432 {
2433
2434 /* Clear the message. */
2435 memset(&dhcpv6_status_ptr -> nx_status_message[0], 0, NX_DHCPV6_STATUS_MESSAGE_MAX);
2436
2437 /*We're done! */
2438 return NX_SUCCESS;
2439 }
2440
2441 /* Flag is set so we are adding a message into the packet. */
2442
2443 /* Clear the message before adding anything into the message buffer. */
2444 memset(&dhcpv6_status_ptr -> nx_status_message[0], 0, NX_DHCPV6_STATUS_MESSAGE_MAX);
2445
2446 /* Fill in message according to status code. */
2447 switch (dhcpv6_status_ptr -> nx_status_code)
2448 {
2449
2450 case NX_DHCPV6_STATUS_SUCCESS:
2451
2452 /* Copy the standard server reply to message buffer. */
2453 memcpy(&dhcpv6_status_ptr -> nx_status_message[0], NX_DHCPV6_STATUS_MESSAGE_SUCCESS, sizeof(NX_DHCPV6_STATUS_MESSAGE_SUCCESS)); /* Use case of memcpy is verified. */
2454
2455 /* Update the option length. */
2456 dhcpv6_status_ptr -> nx_option_length = (USHORT)(dhcpv6_status_ptr -> nx_option_length + sizeof(NX_DHCPV6_STATUS_MESSAGE_SUCCESS));
2457
2458 /* We're done! */
2459 break;
2460
2461 case NX_DHCPV6_STATUS_UNSPECIFIED:
2462
2463 /* Copy the standard server reply to message buffer. */
2464 memcpy(&dhcpv6_status_ptr -> nx_status_message[0], NX_DHCPV6_STATUS_MESSAGE_UNSPECIFIED, sizeof(NX_DHCPV6_STATUS_MESSAGE_UNSPECIFIED)); /* Use case of memcpy is verified. */
2465
2466 /* Update the option length. */
2467 dhcpv6_status_ptr -> nx_option_length = (USHORT)(dhcpv6_status_ptr -> nx_option_length + sizeof(NX_DHCPV6_STATUS_MESSAGE_UNSPECIFIED));
2468
2469 /* We're done! */
2470 break;
2471
2472 case NX_DHCPV6_STATUS_NO_ADDRS_AVAILABLE:
2473
2474 /* Copy the standard server reply to message buffer. */
2475 memcpy(&dhcpv6_status_ptr -> nx_status_message[0], NX_DHCPV6_STATUS_MESSAGE_NO_ADDRS_AVAILABLE, sizeof(NX_DHCPV6_STATUS_MESSAGE_NO_ADDRS_AVAILABLE)); /* Use case of memcpy is verified. */
2476
2477 /* Update the option length. */
2478 dhcpv6_status_ptr -> nx_option_length = (USHORT)(dhcpv6_status_ptr -> nx_option_length + sizeof(NX_DHCPV6_STATUS_MESSAGE_NO_ADDRS_AVAILABLE));
2479
2480 /* We're done! */
2481 break;
2482
2483 case NX_DHCPV6_STATUS_NO_BINDING:
2484
2485 /* Copy the standard server reply to message buffer. */
2486 memcpy(&dhcpv6_status_ptr -> nx_status_message[0], NX_DHCPV6_STATUS_MESSAGE_NO_BINDING, sizeof(NX_DHCPV6_STATUS_MESSAGE_NO_BINDING)); /* Use case of memcpy is verified. */
2487
2488 /* Update the option length. */
2489 dhcpv6_status_ptr -> nx_option_length = (USHORT)(dhcpv6_status_ptr -> nx_option_length + sizeof(NX_DHCPV6_STATUS_MESSAGE_NO_BINDING));
2490
2491 /* We're done! */
2492 break;
2493
2494 case NX_DHCPV6_STATUS_NOT_ON_LINK:
2495
2496 /* Copy the standard server reply to message buffer. */
2497 memcpy(&dhcpv6_status_ptr -> nx_status_message[0], NX_DHCPV6_STATUS_MESSAGE_NOT_ON_LINK, sizeof(NX_DHCPV6_STATUS_MESSAGE_NOT_ON_LINK)); /* Use case of memcpy is verified. */
2498
2499 /* Update the option length. */
2500 dhcpv6_status_ptr -> nx_option_length = (USHORT)(dhcpv6_status_ptr -> nx_option_length + sizeof(NX_DHCPV6_STATUS_MESSAGE_NOT_ON_LINK));
2501
2502 /* We're done! */
2503 break;
2504
2505 case NX_DHCPV6_STATUS_USE_MULTICAST:
2506
2507 /* Copy the standard server reply to message buffer. */
2508 memcpy(&dhcpv6_status_ptr -> nx_status_message[0], NX_DHCPV6_STATUS_MESSAGE_USE_MULTICAST, sizeof(NX_DHCPV6_STATUS_MESSAGE_USE_MULTICAST)); /* Use case of memcpy is verified. */
2509
2510 /* Update the option length. */
2511 dhcpv6_status_ptr -> nx_option_length = (USHORT)(dhcpv6_status_ptr -> nx_option_length + sizeof(NX_DHCPV6_STATUS_MESSAGE_USE_MULTICAST));
2512
2513 /* We're done! */
2514 break;
2515
2516
2517 default:
2518 break;
2519 }
2520
2521 return NX_SUCCESS;
2522 }
2523
2524
2525 /**************************************************************************/
2526 /* */
2527 /* FUNCTION RELEASE */
2528 /* */
2529 /* _nx_dhcpv6_add_preference PORTABLE C */
2530 /* 6.1 */
2531 /* AUTHOR */
2532 /* */
2533 /* Yuxin Zhou, Microsoft Corporation */
2534 /* */
2535 /* DESCRIPTION */
2536 /* */
2537 /* This function adds a DHCPv6 preference option to the server reply. */
2538 /* */
2539 /* */
2540 /* INPUT */
2541 /* */
2542 /* dhcpv6_server_ptr Pointer to DHCPv6 Server instance */
2543 /* dhcpv6_client_ptr Pointer to DHCPv6 Client instance */
2544 /* index Location where to write the data */
2545 /* */
2546 /* OUTPUT */
2547 /* */
2548 /* NX_SUCCESS Successful completion status */
2549 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
2550 /* Data too large for packet payload */
2551 /* */
2552 /* CALLS */
2553 /* */
2554 /* memcpy Copy specified area of memory */
2555 /* */
2556 /* CALLED BY */
2557 /* */
2558 /* _nx_dhcpv6_send_response_to_client Send server response to client */
2559 /* */
2560 /* RELEASE HISTORY */
2561 /* */
2562 /* DATE NAME DESCRIPTION */
2563 /* */
2564 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2565 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2566 /* verified memcpy use cases, */
2567 /* resulting in version 6.1 */
2568 /* */
2569 /**************************************************************************/
_nx_dhcpv6_add_preference(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr,UCHAR * buffer_ptr,UINT * index)2570 UINT _nx_dhcpv6_add_preference(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr, UCHAR *buffer_ptr, UINT *index)
2571 {
2572
2573 UINT available_payload;
2574 ULONG message_word;
2575
2576
2577 /* Fill in option code and length. */
2578 dhcpv6_client_ptr -> nx_dhcpv6_preference.nx_op_code = NX_DHCPV6_OP_PREFERENCE;
2579 dhcpv6_client_ptr -> nx_dhcpv6_preference.nx_option_length = 1;
2580 dhcpv6_client_ptr -> nx_dhcpv6_preference.nx_pref_value = NX_DHCPV6_PREFERENCE_VALUE;
2581
2582 /* Compute the available payload in the packet buffer. */
2583 available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size -
2584 NX_IPv6_UDP_PACKET - *index;
2585
2586 /* Check if the DUID will fit in the packet buffer. */
2587 if (available_payload < (UINT)(dhcpv6_client_ptr -> nx_dhcpv6_preference.nx_option_length + 4))
2588 {
2589
2590 /* It won't! */
2591 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
2592 }
2593
2594 /* Create the word to write to the buffer. */
2595 message_word = (ULONG)dhcpv6_client_ptr -> nx_dhcpv6_preference.nx_op_code << 16;
2596 message_word |= dhcpv6_client_ptr -> nx_dhcpv6_preference.nx_option_length;
2597
2598 /* Adjust for endianness. */
2599 NX_CHANGE_ULONG_ENDIAN(message_word);
2600
2601 /* Copy first half of the DUID option to packet buffer. */
2602 memcpy(buffer_ptr + *index, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
2603
2604 *index += (ULONG)sizeof(ULONG);
2605
2606 /* Set the preference value. */
2607 *(buffer_ptr + *index) = (UCHAR)(dhcpv6_client_ptr -> nx_dhcpv6_preference.nx_pref_value);
2608
2609 (*index)++;
2610
2611 return NX_SUCCESS;
2612 }
2613
2614
2615 /**************************************************************************/
2616 /* */
2617 /* FUNCTION RELEASE */
2618 /* */
2619 /* _nx_dhcpv6_add_option_requests PORTABLE C */
2620 /* 6.1 */
2621 /* AUTHOR */
2622 /* */
2623 /* Yuxin Zhou, Microsoft Corporation */
2624 /* */
2625 /* DESCRIPTION */
2626 /* */
2627 /* This function adds the 'option request' option to the server reply */
2628 /* packet based on the options requested from the client, and what */
2629 /* options the DHCPv6 server is configured to supply. */
2630 /* */
2631 /* INPUT */
2632 /* */
2633 /* dhcpv6_server_ptr Pointer to DHCPV6 server instance */
2634 /* dhcpv6_client_ptr Pointer to DHCPV6 client instance */
2635 /* buffer_ptr Pointer to packet buffer */
2636 /* index Location into buffer to write data*/
2637 /* */
2638 /* OUTPUT */
2639 /* */
2640 /* NX_SUCCESS Successful completion status */
2641 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
2642 /* Not enough room for the option */
2643 /* request in the packet payload */
2644 /* CALLS */
2645 /* */
2646 /* memset Clears specified area of memory */
2647 /* memcpy Copies specified area of memory */
2648 /* */
2649 /* CALLED BY */
2650 /* */
2651 /* _nx_dhcpv6_send_request Compiles and sends the server */
2652 /* DHCPv6 response */
2653 /* */
2654 /* RELEASE HISTORY */
2655 /* */
2656 /* DATE NAME DESCRIPTION */
2657 /* */
2658 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2659 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2660 /* verified memcpy use cases, */
2661 /* resulting in version 6.1 */
2662 /* */
2663 /**************************************************************************/
_nx_dhcpv6_add_option_requests(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr,UCHAR * buffer_ptr,UINT * index)2664 UINT _nx_dhcpv6_add_option_requests(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr,
2665 UCHAR *buffer_ptr, UINT *index)
2666 {
2667
2668 USHORT i, j;
2669 ULONG message_word;
2670 UINT available_payload;
2671 NXD_ADDRESS *dns_server_address;
2672 NX_DHCPV6_SERVER_OPTIONREQUEST *dhcpv6_option_ptr;
2673
2674
2675 dhcpv6_option_ptr = &dhcpv6_client_ptr -> nx_dhcpv6_option_request;
2676
2677 /* Compute the available payload in the packet buffer. */
2678 available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size -
2679 NX_IPv6_UDP_PACKET - *index;
2680
2681 /* Process up to the maximum allowed options. */
2682 for(i = 0; i < NX_DHCPV6_MAX_OPTION_REQUEST_OPTIONS; i++)
2683 {
2684
2685 /* Check for the end of the list. */
2686 if (dhcpv6_option_ptr -> nx_op_request[i] == 0)
2687 {
2688
2689 /* No more options. */
2690 break;
2691 }
2692
2693 /* Is this the DNS server option? */
2694 if (dhcpv6_option_ptr -> nx_op_request[i] == NX_DHCPV6_RFC_DNS_SERVER_OPTION)
2695 {
2696
2697 /* Create an option containing a single DNS server address. */
2698 dhcpv6_option_ptr -> nx_option_length = 4 * sizeof(ULONG);
2699
2700 /* Check if the option request option will fit in the packet buffer. */
2701 if (available_payload < (UINT)(dhcpv6_option_ptr -> nx_option_length + 4))
2702 {
2703
2704 /* It won't. */
2705 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
2706 }
2707
2708 message_word = (ULONG)dhcpv6_option_ptr -> nx_op_request[i] << 16;
2709 message_word |= dhcpv6_option_ptr -> nx_option_length;
2710
2711 /* Adjust for endianness. */
2712 NX_CHANGE_ULONG_ENDIAN(message_word);
2713
2714 /* Copy the option request option header to the packet. */
2715 memcpy(buffer_ptr + *index, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
2716 *index += (ULONG)sizeof(ULONG);
2717
2718 dns_server_address = &dhcpv6_server_ptr -> nx_dhcpv6_dns_ip_address;
2719 for (j = 0; j < 4; j++)
2720 {
2721
2722 message_word = dns_server_address -> nxd_ip_address.v6[j];
2723
2724 NX_CHANGE_ULONG_ENDIAN(message_word);
2725
2726 memcpy(buffer_ptr + *index, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
2727
2728 *index += (ULONG)sizeof(ULONG);
2729 }
2730
2731 /* Update the available payload. */
2732 available_payload = (UINT)(available_payload - (UINT)(dhcpv6_option_ptr -> nx_option_length + 4));
2733 }
2734 /* Does the DHCPv6 server have an extended option handler? */
2735 else if (dhcpv6_server_ptr -> nx_dhcpv6_server_option_request_handler_extended)
2736 {
2737
2738 /* Yes, so call it. This handler shall fill the buffer with the requested
2739 option data (if available).
2740
2741 Note: The handler must update the index pointing to the end of data in the buffer
2742 after it inserts the data. This is done for the DNS server option above. */
2743 (dhcpv6_server_ptr -> nx_dhcpv6_server_option_request_handler_extended)(dhcpv6_server_ptr, dhcpv6_option_ptr -> nx_op_request[i], buffer_ptr, index, available_payload);
2744
2745 /* Check if exceed the payload. */
2746 if ((NX_IPv6_UDP_PACKET + *index) <= dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size)
2747 {
2748
2749 /* Update the available payload. */
2750 available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size -
2751 NX_IPv6_UDP_PACKET - *index;
2752 }
2753 else
2754 {
2755 return (NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD);
2756 }
2757 }
2758 /* Does the DHCPv6 server have an option handler? */
2759 else if (dhcpv6_server_ptr -> nx_dhcpv6_server_option_request_handler)
2760 {
2761
2762 /* Yes, so call it. This handler shall fill the buffer with the requested
2763 option data (if available).
2764
2765 Note: The handler must update the index pointing to the end of data in the buffer
2766 after it inserts the data. This is done for the DNS server option above. */
2767 (dhcpv6_server_ptr -> nx_dhcpv6_server_option_request_handler)(dhcpv6_server_ptr, dhcpv6_option_ptr -> nx_op_request[i], buffer_ptr, index);
2768
2769 /* Check if exceed the payload. */
2770 if ((NX_IPv6_UDP_PACKET + *index) <= dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size)
2771 {
2772
2773 /* Update the available payload. */
2774 available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size -
2775 NX_IPv6_UDP_PACKET - *index;
2776 }
2777 else
2778 {
2779 return (NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD);
2780 }
2781
2782 }
2783 }
2784
2785 return NX_SUCCESS;
2786 }
2787
2788
2789 /**************************************************************************/
2790 /* */
2791 /* FUNCTION RELEASE */
2792 /* */
2793 /* _nxe_dhcpv6_server_interface_set PORTABLE C */
2794 /* 6.1 */
2795 /* AUTHOR */
2796 /* */
2797 /* Yuxin Zhou, Microsoft Corporation */
2798 /* */
2799 /* DESCRIPTION */
2800 /* */
2801 /* This function performs error checking on the set interface service. */
2802 /* */
2803 /* INPUT */
2804 /* */
2805 /* dhcpv6_server_ptr Pointer to the DHCPV6 Server */
2806 /* iface_index Physical interface index for */
2807 /* DHCP communication */
2808 /* ga_address_index Global address index on DHCPv6*/
2809 /* interface */
2810 /* */
2811 /* OUTPUT */
2812 /* */
2813 /* NX_PTR_ERROR Invalid pointer input */
2814 /* NX_INVALID_INTERFACE Invalid interface index */
2815 /* NX_NO_INTERFACE_ADDRESS Invalid global address index */
2816 /* */
2817 /* CALLS */
2818 /* */
2819 /* _nx_dhcpv6_server_interface_set Actual set interfaces service */
2820 /* */
2821 /* CALLED BY */
2822 /* */
2823 /* Application Code */
2824 /* */
2825 /* RELEASE HISTORY */
2826 /* */
2827 /* DATE NAME DESCRIPTION */
2828 /* */
2829 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2830 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2831 /* resulting in version 6.1 */
2832 /* */
2833 /**************************************************************************/
_nxe_dhcpv6_server_interface_set(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT iface_index,UINT ga_address_index)2834 UINT _nxe_dhcpv6_server_interface_set(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT iface_index, UINT ga_address_index)
2835 {
2836
2837 UINT status;
2838
2839
2840 /* Check for invalid pointer input. */
2841 if (dhcpv6_server_ptr == NX_NULL)
2842 {
2843
2844 return NX_PTR_ERROR;
2845 }
2846
2847 /* Check for invalid parameters. */
2848 if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
2849 {
2850 return NX_INVALID_INTERFACE;
2851 }
2852
2853 if (ga_address_index >= NX_MAX_IPV6_ADDRESSES)
2854 {
2855 return NX_NO_INTERFACE_ADDRESS;
2856 }
2857
2858 /* Call the actual service. */
2859 status = _nx_dhcpv6_server_interface_set(dhcpv6_server_ptr, iface_index, ga_address_index);
2860
2861 return status;
2862 }
2863
2864
2865 /**************************************************************************/
2866 /* */
2867 /* FUNCTION RELEASE */
2868 /* */
2869 /* _nx_dhcpv6_server_interface_set PORTABLE C */
2870 /* 6.1 */
2871 /* AUTHOR */
2872 /* */
2873 /* Yuxin Zhou, Microsoft Corporation */
2874 /* */
2875 /* DESCRIPTION */
2876 /* */
2877 /* This function sets the physical network interface for DHCPv6 */
2878 /* communications and the address index of the IP instance for the */
2879 /* primary global address on that interface. */
2880 /* */
2881 /* INPUT */
2882 /* */
2883 /* dhcpv6_server_ptr Pointer to the DHCPV6 Server */
2884 /* iface_index Physical interface index for */
2885 /* DHCP communication */
2886 /* ga_address_index Global address index on DHCPv6*/
2887 /* interface */
2888 /* */
2889 /* OUTPUT */
2890 /* */
2891 /* NX_SUCCESS Indexes successfully set */
2892 /* */
2893 /* CALLS */
2894 /* */
2895 /* None */
2896 /* */
2897 /* CALLED BY */
2898 /* */
2899 /* */
2900 /* RELEASE HISTORY */
2901 /* */
2902 /* DATE NAME DESCRIPTION */
2903 /* */
2904 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2905 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2906 /* resulting in version 6.1 */
2907 /* */
2908 /**************************************************************************/
_nx_dhcpv6_server_interface_set(NX_DHCPV6_SERVER * dhcpv6_server_ptr,UINT iface_index,UINT ga_address_index)2909 UINT _nx_dhcpv6_server_interface_set(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT iface_index, UINT ga_address_index)
2910 {
2911
2912 dhcpv6_server_ptr -> nx_dhcpv6_server_interface_index = iface_index;
2913 dhcpv6_server_ptr -> nx_dhcpv6_server_ga_address_index = ga_address_index;
2914 return NX_SUCCESS;
2915 }
2916
2917
2918 /**************************************************************************/
2919 /* */
2920 /* FUNCTION RELEASE */
2921 /* */
2922 /* _nx_dhcpv6_server_lease_timeout_entry PORTABLE C */
2923 /* 6.1 */
2924 /* AUTHOR */
2925 /* */
2926 /* Yuxin Zhou, Microsoft Corporation */
2927 /* */
2928 /* DESCRIPTION */
2929 /* */
2930 /* This function is scheduled by the ThreadX scheduler on a user */
2931 /* configurable time interval. It sets a flag for the DHCPv6 server */
2932 /* thread task to check the lease expiration on its leased IP address. */
2933 /* */
2934 /* INPUT */
2935 /* */
2936 /* dhcpv6_server_ptr_value Pointer to the DHCPV6 Server */
2937 /* */
2938 /* OUTPUT */
2939 /* */
2940 /* None */
2941 /* */
2942 /* CALLS */
2943 /* */
2944 /* tx_event_flags_set Adds a periodic event to the */
2945 /* ThreadX event queue */
2946 /* CALLED BY */
2947 /* */
2948 /* */
2949 /* RELEASE HISTORY */
2950 /* */
2951 /* DATE NAME DESCRIPTION */
2952 /* */
2953 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2954 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2955 /* resulting in version 6.1 */
2956 /* */
2957 /**************************************************************************/
_nx_dhcpv6_server_lease_timeout_entry(ULONG dhcpv6_server_ptr_value)2958 VOID _nx_dhcpv6_server_lease_timeout_entry(ULONG dhcpv6_server_ptr_value)
2959 {
2960
2961 NX_DHCPV6_SERVER *dhcpv6_server_ptr;
2962
2963
2964 /* Setup DHCPv6 Server pointer. */
2965 NX_TIMER_EXTENSION_PTR_GET(dhcpv6_server_ptr, NX_DHCPV6_SERVER, dhcpv6_server_ptr_value)
2966
2967 /* Signal the DHCPv6 Server it is time to do check the lease time remaining on
2968 clients it has leased IP addresses to. */
2969 tx_event_flags_set(&(dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events), NX_DHCPV6_IP_LEASE_CHECK_PERIODIC_EVENT, TX_OR);
2970
2971 return;
2972 }
2973
2974
2975 /**************************************************************************/
2976 /* */
2977 /* FUNCTION RELEASE */
2978 /* */
2979 /* _nxe_dhcpv6_server_resume PORTABLE C */
2980 /* 6.1 */
2981 /* AUTHOR */
2982 /* */
2983 /* Yuxin Zhou, Microsoft Corporation */
2984 /* */
2985 /* DESCRIPTION */
2986 /* */
2987 /* This function performs error checking on the resume NetX DHCPv6 */
2988 /* server task service. */
2989 /* */
2990 /* INPUT */
2991 /* */
2992 /* dhcpv6_server_ptr Pointer to DHCPV6 Server */
2993 /* */
2994 /* OUTPUT */
2995 /* */
2996 /* OUTPUT */
2997 /* */
2998 /* status Completion status */
2999 /* NX_PTR_ERROR Invalid pointer input */
3000 /* */
3001 /* CALLS */
3002 /* */
3003 /* _nx_dhcpv6_server_resume Actual DHCPV6 resume function */
3004 /* */
3005 /* CALLED BY */
3006 /* */
3007 /* Application Code */
3008 /* */
3009 /* RELEASE HISTORY */
3010 /* */
3011 /* DATE NAME DESCRIPTION */
3012 /* */
3013 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3014 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3015 /* resulting in version 6.1 */
3016 /* */
3017 /**************************************************************************/
_nxe_dhcpv6_server_resume(NX_DHCPV6_SERVER * dhcpv6_server_ptr)3018 UINT _nxe_dhcpv6_server_resume(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
3019 {
3020
3021 UINT status;
3022
3023
3024 /* Check for invalid input pointer. */
3025 if ((dhcpv6_server_ptr == NX_NULL) || (dhcpv6_server_ptr -> nx_dhcpv6_id != NX_DHCPV6_SERVER_ID))
3026 return(NX_PTR_ERROR);
3027
3028 /* Check for appropriate caller. */
3029 NX_THREADS_ONLY_CALLER_CHECKING
3030
3031 /* Call actual DHCPV6 stop service. */
3032 status = _nx_dhcpv6_server_resume(dhcpv6_server_ptr);
3033
3034 /* Return status. */
3035 return(status);
3036 }
3037
3038
3039 /**************************************************************************/
3040 /* */
3041 /* FUNCTION RELEASE */
3042 /* */
3043 /* _nx_dhcpv6_server_resume PORTABLE C */
3044 /* 6.1 */
3045 /* AUTHOR */
3046 /* */
3047 /* Yuxin Zhou, Microsoft Corporation */
3048 /* */
3049 /* DESCRIPTION */
3050 /* */
3051 /* This function resumes DHCPV6 processing thread, activates the */
3052 /* timers, and sets the running status of the DHCPv6 Server back to */
3053 /* running. */
3054 /* */
3055 /* INPUT */
3056 /* */
3057 /* dhcpv6_server_ptr Pointer to DHCPV6 server */
3058 /* */
3059 /* OUTPUT */
3060 /* */
3061 /* status Actual completion status */
3062 /* NX_SUCCESS Successful completion status */
3063 /* NX_DHCPV6_ALREADY_STARTED DHPCv6 Server already running */
3064 /* */
3065 /* CALLS */
3066 /* */
3067 /* tx_thread_resume Resumes DHCPV6 thread task */
3068 /* tx_timer_activate Activates DHCPv6 timer */
3069 /* */
3070 /* CALLED BY */
3071 /* */
3072 /* Application Code */
3073 /* */
3074 /* RELEASE HISTORY */
3075 /* */
3076 /* DATE NAME DESCRIPTION */
3077 /* */
3078 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3079 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3080 /* resulting in version 6.1 */
3081 /* */
3082 /**************************************************************************/
_nx_dhcpv6_server_resume(NX_DHCPV6_SERVER * dhcpv6_server_ptr)3083 UINT _nx_dhcpv6_server_resume(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
3084 {
3085
3086 UINT status;
3087
3088
3089 /* Is the DHCPv6 Client already running? */
3090 if (dhcpv6_server_ptr -> nx_dhcpv6_server_running)
3091 {
3092
3093 /* Return a (benign) error status. */
3094 return NX_DHCPV6_ALREADY_STARTED;
3095 }
3096
3097 /* Set the DHCPV6 running flag to indicate DHCPV6 is running. */
3098 dhcpv6_server_ptr -> nx_dhcpv6_server_running = NX_TRUE;
3099
3100 /* Start the lease timer. */
3101 status = tx_timer_activate(&(dhcpv6_server_ptr -> nx_dhcpv6_lease_timer));
3102
3103 /* Check for invalid activate status. */
3104 if (status != TX_SUCCESS)
3105 {
3106
3107 /* Return error status. */
3108 return status;
3109 }
3110
3111 /* Start the session timer. */
3112 status = tx_timer_activate(&(dhcpv6_server_ptr -> nx_dhcpv6_session_timer));
3113
3114 /* Check for invalid activate status. */
3115 if (status != TX_SUCCESS)
3116 {
3117
3118 /* Return error status. */
3119 return status;
3120 }
3121
3122 /* Resume the Server thread as well. */
3123 status = tx_thread_resume(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread));
3124
3125 /* Check for invalid resume status. */
3126 if (status != TX_SUCCESS && status != TX_SUSPEND_LIFTED)
3127 {
3128
3129 /* Return threadx error status. */
3130 return status;
3131 }
3132 /* Return completion status. */
3133 return(NX_SUCCESS);
3134 }
3135
3136
3137 /**************************************************************************/
3138 /* */
3139 /* FUNCTION RELEASE */
3140 /* */
3141 /* _nx_dhcpv6_server_session_timeout_entry PORTABLE C */
3142 /* 6.1 */
3143 /* AUTHOR */
3144 /* */
3145 /* Yuxin Zhou, Microsoft Corporation */
3146 /* */
3147 /* DESCRIPTION */
3148 /* */
3149 /* This function is scheduled by the ThreadX scheduler on a user */
3150 /* configurable time interval. It sets a flag which the DHCPv6 server */
3151 /* thread task updates all active client session times and checks if */
3152 /* any have exceeded the session timeout without sending a response */
3153 /* back to the server. */
3154 /* */
3155 /* INPUT */
3156 /* */
3157 /* dhcpv6_server_ptr_value Pointer to the DHCPV6 server */
3158 /* */
3159 /* OUTPUT */
3160 /* */
3161 /* None */
3162 /* */
3163 /* CALLS */
3164 /* */
3165 /* tx_event_flags_set Adds a periodic event to the */
3166 /* ThreadX event queue */
3167 /* CALLED BY */
3168 /* */
3169 /* */
3170 /* RELEASE HISTORY */
3171 /* */
3172 /* DATE NAME DESCRIPTION */
3173 /* */
3174 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3175 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3176 /* resulting in version 6.1 */
3177 /* */
3178 /**************************************************************************/
_nx_dhcpv6_server_session_timeout_entry(ULONG dhcpv6_server_ptr_value)3179 VOID _nx_dhcpv6_server_session_timeout_entry(ULONG dhcpv6_server_ptr_value)
3180 {
3181
3182 NX_DHCPV6_SERVER *dhcpv6_server_ptr;
3183
3184
3185 /* Setup DHCPv6 Server pointer. */
3186 NX_TIMER_EXTENSION_PTR_GET(dhcpv6_server_ptr, NX_DHCPV6_SERVER, dhcpv6_server_ptr_value)
3187
3188 /* Signal the DHCPv6 server it's time to do more session time keeping! */
3189 tx_event_flags_set(&(dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events), NX_DHCPV6_CHECK_SESSION_PERIODIC_EVENT, TX_OR);
3190
3191 return;
3192 }
3193
3194
3195 /**************************************************************************/
3196 /* */
3197 /* FUNCTION RELEASE */
3198 /* */
3199 /* _nxe_dhcpv6_server_start PORTABLE C */
3200 /* 6.1 */
3201 /* AUTHOR */
3202 /* */
3203 /* Yuxin Zhou, Microsoft Corporation */
3204 /* */
3205 /* DESCRIPTION */
3206 /* */
3207 /* This function performs error checking on the NetX start the dhcpv6 */
3208 /* client service. */
3209 /* */
3210 /* INPUT */
3211 /* */
3212 /* dhcpv6_server_ptr Pointer to DHCPV6 Server */
3213 /* */
3214 /* OUTPUT */
3215 /* */
3216 /* status Completion status */
3217 /* NX_PTR_ERROR Invalid pointer input */
3218 /* */
3219 /* */
3220 /* CALLS */
3221 /* */
3222 /* _nx_dhcpv6_server_start Actual DHCPV6 start function */
3223 /* */
3224 /* CALLED BY */
3225 /* */
3226 /* Application Code */
3227 /* */
3228 /* RELEASE HISTORY */
3229 /* */
3230 /* DATE NAME DESCRIPTION */
3231 /* */
3232 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3233 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3234 /* resulting in version 6.1 */
3235 /* */
3236 /**************************************************************************/
_nxe_dhcpv6_server_start(NX_DHCPV6_SERVER * dhcpv6_server_ptr)3237 UINT _nxe_dhcpv6_server_start(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
3238 {
3239
3240 UINT status;
3241
3242
3243 /* Check for invalid input pointer. */
3244 if ((dhcpv6_server_ptr == NX_NULL) || (dhcpv6_server_ptr -> nx_dhcpv6_id != NX_DHCPV6_SERVER_ID))
3245 return(NX_PTR_ERROR);
3246
3247 /* Check for appropriate caller. */
3248 NX_THREADS_ONLY_CALLER_CHECKING
3249
3250 /* Call actual DHCPV6 start service. */
3251 status = _nx_dhcpv6_server_start(dhcpv6_server_ptr);
3252
3253 /* Return status. */
3254 return(status);
3255 }
3256
3257
3258 /**************************************************************************/
3259 /* */
3260 /* FUNCTION RELEASE */
3261 /* */
3262 /* _nx_dhcpv6_server_start PORTABLE C */
3263 /* 6.1 */
3264 /* AUTHOR */
3265 /* */
3266 /* Yuxin Zhou, Microsoft Corporation */
3267 /* */
3268 /* DESCRIPTION */
3269 /* */
3270 /* This function starts the DHCPV6 processing thread and prepares the */
3271 /* DHCPv6 Server to receive DHCPv6 client requests. */
3272 /* */
3273 /* INPUT */
3274 /* */
3275 /* dhcpv6_server_ptr Pointer to DHCPV6 Server */
3276 /* */
3277 /* OUTPUT */
3278 /* */
3279 /* status Completion status */
3280 /* NX_DHCPV6_ALREADY_STARTED DHCPv6 server already started */
3281 /* NX_DHCPV6_MISSING_REQUIRED_OPTIONS Server missing required options */
3282 /* NX_DHCPV6_NO_ASSIGNABLE_ADDRESSES No addresses available to assign*/
3283 /* */
3284 /* CALLS */
3285 /* */
3286 /* nxd_ipv6_linklocal_address_set Obtain MAC address for DUID */
3287 /* nx_udp_socket_create Create the Server UDP socket */
3288 /* nx_udp_socket_bind Bind the Server socket */
3289 /* nx_udp_socket_unbind Unbind the Server socket */
3290 /* tx_timer_activate Activate Server lease timer */
3291 /* tx_timer_deactivate Deactivate Server lease timer */
3292 /* tx_thread_resume Resume Server thread task */
3293 /* */
3294 /* CALLED BY */
3295 /* */
3296 /* Application Code */
3297 /* */
3298 /* RELEASE HISTORY */
3299 /* */
3300 /* DATE NAME DESCRIPTION */
3301 /* */
3302 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3303 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3304 /* resulting in version 6.1 */
3305 /* */
3306 /**************************************************************************/
_nx_dhcpv6_server_start(NX_DHCPV6_SERVER * dhcpv6_server_ptr)3307 UINT _nx_dhcpv6_server_start(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
3308 {
3309
3310 UINT status;
3311 #ifdef NETXDUO_MULTI_HOME
3312 UINT if_index;
3313 #endif
3314
3315
3316 /* Determine if the DHCPV6 server has already started. */
3317 if (dhcpv6_server_ptr -> nx_dhcpv6_server_running)
3318 {
3319
3320 /* Yes, it has. */
3321 return(NX_DHCPV6_ALREADY_STARTED);
3322 }
3323
3324 /* Check if the server has assignable addresses. */
3325 if (dhcpv6_server_ptr -> nx_dhcpv6_assignable_addresses == 0)
3326 {
3327 return NX_DHCPV6_NO_ASSIGNABLE_ADDRESSES;
3328 }
3329
3330 /* Check that the global address is valid. */
3331 if (dhcpv6_server_ptr -> nx_dhcpv6_server_ga_address_index >= NX_MAX_IPV6_ADDRESSES)
3332 {
3333 return NX_DHCPV6_INVALID_GLOBAL_INDEX;
3334 }
3335
3336 /* Create the Socket and check the status */
3337 status = nx_udp_socket_create(dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr,
3338 &(dhcpv6_server_ptr -> nx_dhcpv6_server_socket), (CHAR *)"NetX DHCPV6 Server",
3339 NX_DHCPV6_TYPE_OF_SERVICE, NX_DHCPV6_FRAGMENT_OPTION,
3340 NX_DHCPV6_TIME_TO_LIVE, NX_DHCPV6_QUEUE_DEPTH);
3341
3342 /* Was the socket creation successful? */
3343 if (status != NX_SUCCESS)
3344 {
3345
3346 /* No, return error status. */
3347 return status;
3348 }
3349
3350 /* Save the DHCP instance pointer in the socket. */
3351 dhcpv6_server_ptr -> nx_dhcpv6_server_socket.nx_udp_socket_reserved_ptr = (void *) dhcpv6_server_ptr;
3352
3353 /* Set the DHCPv6 request handler for packets received on the DHCPv6 server socket. */
3354 status = nx_udp_socket_receive_notify(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket), _nx_dhcpv6_server_socket_receive_notify);
3355
3356 /* Was the socket receive_notify set successful? */
3357 if (status != NX_SUCCESS)
3358 {
3359
3360 /* No, return error status. */
3361 return status;
3362 }
3363
3364 /* Check if the host application has created or retrieved a previously created server DUID. */
3365 if (dhcpv6_server_ptr -> nx_dhcpv6_server_duid.nx_duid_type == 0)
3366 {
3367
3368 /* No valid server DUID detected. Server cannot run yet!*/
3369 return NX_DHCPV6_NO_SERVER_DUID;
3370 }
3371
3372 /* Bind the UDP socket to the DHCPV6 Server port. */
3373 status = nx_udp_socket_bind(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket), NX_DHCPV6_SERVER_UDP_PORT, TX_WAIT_FOREVER);
3374
3375 /* Check status. */
3376 if (status != NX_SUCCESS)
3377 {
3378
3379 /* Delete the UDP socket. */
3380 nx_udp_socket_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
3381
3382 return status;
3383 }
3384
3385 /* Activate the DHCPv6 timers. */
3386 status = tx_timer_activate(&dhcpv6_server_ptr -> nx_dhcpv6_lease_timer);
3387
3388 /* Determine if the timer activate call was successful. */
3389 if ((status != TX_SUCCESS) && (status != TX_ACTIVATE_ERROR))
3390 {
3391
3392 /* No it was not; unbind the DHCPV6 socket. */
3393 nx_udp_socket_unbind(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
3394
3395 /* Delete the UDP socket. */
3396 nx_udp_socket_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
3397
3398 /* Return the error status. */
3399 return status;
3400 }
3401
3402 /* Start the session timer. */
3403 status = tx_timer_activate(&(dhcpv6_server_ptr -> nx_dhcpv6_session_timer));
3404
3405 /* Check for invalid activate status. */
3406 if ((status != TX_SUCCESS) && (status != TX_ACTIVATE_ERROR))
3407 {
3408
3409 /* No it was not; unbind the DHCPV6 socket. */
3410 nx_udp_socket_unbind(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
3411
3412 /* Delete the UDP socket. */
3413 nx_udp_socket_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
3414
3415 /* Return error status. */
3416 return status;
3417 }
3418
3419 /* Ready to resume the DHCPV6 server thread. */
3420 status = tx_thread_resume(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread));
3421
3422 /* Determine if the resume was successful. */
3423 if (status != NX_SUCCESS)
3424 {
3425
3426 /* Deactivate the timer. */
3427 tx_timer_deactivate(&dhcpv6_server_ptr -> nx_dhcpv6_lease_timer);
3428
3429 /* Unbind the DHCPV6 socket. */
3430 nx_udp_socket_unbind(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
3431
3432 /* Delete the UDP socket. */
3433 nx_udp_socket_delete(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket));
3434
3435 return status;
3436 }
3437
3438 /* Set the DHCPV6 started flag to indicate the DHCPV6 server is now running. */
3439 dhcpv6_server_ptr -> nx_dhcpv6_server_running = NX_TRUE;
3440
3441 /* Return completion status. */
3442 return(status);
3443 }
3444
3445 /**************************************************************************/
3446 /* */
3447 /* FUNCTION RELEASE */
3448 /* */
3449 /* _nx_dhcpv6_server_socket_receive_notify PORTABLE C */
3450 /* 6.1 */
3451 /* AUTHOR */
3452 /* */
3453 /* Yuxin Zhou, Microsoft Corporation */
3454 /* */
3455 /* DESCRIPTION */
3456 /* */
3457 /* This function is notified by NetX Duo when a packet arrives in the */
3458 /* server socket. It sets a flag which the DHCPv6 server thread */
3459 /* detect so it will know to process the incoming packet . */
3460 /* */
3461 /* INPUT */
3462 /* */
3463 /* socket_ptr Pointer to Server Socket */
3464 /* */
3465 /* OUTPUT */
3466 /* */
3467 /* None */
3468 /* */
3469 /* CALLS */
3470 /* */
3471 /* None */
3472 /* */
3473 /* CALLED BY */
3474 /* */
3475 /* Threads */
3476 /* */
3477 /* RELEASE HISTORY */
3478 /* */
3479 /* DATE NAME DESCRIPTION */
3480 /* */
3481 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3482 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3483 /* resulting in version 6.1 */
3484 /* */
3485 /**************************************************************************/
_nx_dhcpv6_server_socket_receive_notify(NX_UDP_SOCKET * socket_ptr)3486 VOID _nx_dhcpv6_server_socket_receive_notify(NX_UDP_SOCKET *socket_ptr)
3487 {
3488
3489 NX_DHCPV6_SERVER *dhcpv6_server_ptr;
3490
3491
3492 /* Get a pointer to the DHCPv6 server. */
3493 dhcpv6_server_ptr = (NX_DHCPV6_SERVER *) socket_ptr -> nx_udp_socket_reserved_ptr;
3494
3495 /* Signal the DHCPv6 Server it has a UDP packet on its socket receive queue. */
3496 tx_event_flags_set(&(dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events), NX_DHCPV6_SERVER_RECEIVE_EVENT, TX_OR);
3497
3498 return;
3499 }
3500
3501
3502 /**************************************************************************/
3503 /* */
3504 /* FUNCTION RELEASE */
3505 /* */
3506 /* _nxe_dhcpv6_server_suspend 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 suspend NetX DHCPv6 */
3515 /* Server task service. */
3516 /* */
3517 /* INPUT */
3518 /* */
3519 /* dhcpv6_server_ptr Pointer to DHCPV6 server */
3520 /* */
3521 /* OUTPUT */
3522 /* */
3523 /* status Completion status */
3524 /* NX_PTR_ERROR Invalid pointer input */
3525 /* */
3526 /* CALLS */
3527 /* */
3528 /* _nx_dhcpv6_server_suspend Actual DHCPV6 suspend function */
3529 /* */
3530 /* CALLED BY */
3531 /* */
3532 /* Application Code */
3533 /* */
3534 /* RELEASE HISTORY */
3535 /* */
3536 /* DATE NAME DESCRIPTION */
3537 /* */
3538 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3539 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3540 /* resulting in version 6.1 */
3541 /* */
3542 /**************************************************************************/
_nxe_dhcpv6_server_suspend(NX_DHCPV6_SERVER * dhcpv6_server_ptr)3543 UINT _nxe_dhcpv6_server_suspend(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
3544 {
3545
3546 UINT status;
3547
3548
3549 /* Check for invalid input pointer. */
3550 if ((dhcpv6_server_ptr == NX_NULL) || (dhcpv6_server_ptr -> nx_dhcpv6_id != NX_DHCPV6_SERVER_ID))
3551 return(NX_PTR_ERROR);
3552
3553 /* Check for appropriate caller. */
3554 NX_THREADS_ONLY_CALLER_CHECKING
3555
3556 /* Call actual DHCPV6 stop service. */
3557 status = _nx_dhcpv6_server_suspend(dhcpv6_server_ptr);
3558
3559 /* Return status. */
3560 return(status);
3561 }
3562
3563
3564 /**************************************************************************/
3565 /* */
3566 /* FUNCTION RELEASE */
3567 /* */
3568 /* _nx_dhcpv6_server_suspend PORTABLE C */
3569 /* 6.1 */
3570 /* AUTHOR */
3571 /* */
3572 /* Yuxin Zhou, Microsoft Corporation */
3573 /* */
3574 /* DESCRIPTION */
3575 /* */
3576 /* This function suspends DHCPV6 processing thread, deactivates the */
3577 /* timers, and sets the running status of the DHCPv6 Server to not */
3578 /* running. */
3579 /* */
3580 /* INPUT */
3581 /* */
3582 /* dhcpv6_server_ptr Pointer to DHCPV6 Server */
3583 /* */
3584 /* OUTPUT */
3585 /* */
3586 /* NX_SUCCESS Successful completion status */
3587 /* NX_DHCPV6_NOT_STARTED Task not running; can't be */
3588 /* suspended */
3589 /* */
3590 /* CALLS */
3591 /* */
3592 /* tx_thread_suspend Suspend DHCPV6 thread task */
3593 /* tx_timer_deactivate Deactivate timer */
3594 /* */
3595 /* CALLED BY */
3596 /* */
3597 /* Application Code */
3598 /* */
3599 /* RELEASE HISTORY */
3600 /* */
3601 /* DATE NAME DESCRIPTION */
3602 /* */
3603 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3604 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3605 /* resulting in version 6.1 */
3606 /* */
3607 /**************************************************************************/
_nx_dhcpv6_server_suspend(NX_DHCPV6_SERVER * dhcpv6_server_ptr)3608 UINT _nx_dhcpv6_server_suspend(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
3609 {
3610
3611
3612 /* Determine if the DHCPV6 server thread is running. */
3613 if (!dhcpv6_server_ptr -> nx_dhcpv6_server_running)
3614 {
3615
3616 /* DHCPV6 has not been started so we cannot 'suspend' it. */
3617 return(NX_DHCPV6_NOT_STARTED);
3618 }
3619
3620 /* Clear the DHCPV6 running flag to indicate DHCPV6 is not running. */
3621 dhcpv6_server_ptr -> nx_dhcpv6_server_running = NX_FALSE;
3622
3623 /* Stop the timer. */
3624 tx_timer_deactivate(&(dhcpv6_server_ptr -> nx_dhcpv6_lease_timer));
3625
3626 /* Suspend the Server thread as well. */
3627 tx_thread_suspend(&(dhcpv6_server_ptr -> nx_dhcpv6_server_thread));
3628
3629 /* Return completion status. */
3630 return(NX_SUCCESS);
3631 }
3632
3633
3634 /**************************************************************************/
3635 /* */
3636 /* FUNCTION RELEASE */
3637 /* */
3638 /* _nx_dhcpv6_server_thread_entry PORTABLE C */
3639 /* 6.1 */
3640 /* AUTHOR */
3641 /* */
3642 /* Yuxin Zhou, Microsoft Corporation */
3643 /* */
3644 /* DESCRIPTION */
3645 /* */
3646 /* This function is the background processing thread for the DHCPV6 */
3647 /* Client. It waits to be notified by ThreadX event flags when to */
3648 /* perform certain actions. These include updating the time remaining */
3649 /* on the Client IP address lease time, and maintaining the duration of*/
3650 /* the current Client Server session (if Client has made a request). */
3651 /* It will terminate if a host application handler is called and */
3652 /* indicates the Client should abort. */
3653 /* */
3654 /* INPUT */
3655 /* */
3656 /* info Pointer to DHCPV6 Client instance*/
3657 /* */
3658 /* OUTPUT */
3659 /* */
3660 /* None */
3661 /* */
3662 /* CALLS */
3663 /* */
3664 /* tx_event_flags_get Receive notice of event flags set */
3665 /* tx_mutex_get Obtain lock on Client resource */
3666 /* tx_mutex_put Release lock on Client resource */
3667 /* nx_dhcpv6_deprecated_IP_address_handler */
3668 /* Callback function for handling an */
3669 /* IP address at the end of its */
3670 /* preferred life time */
3671 /* nx_dhcpv6_expired_IP_address_handler */
3672 /* Callback function for handling an */
3673 /* IP address at the end of its */
3674 /* valid life time */
3675 /* _nx_dhcpv6_request_renew Initiate the RENEW request */
3676 /* _nx_dhcpv6_request_rebind Initiate the REBIND request */
3677 /* */
3678 /* CALLED BY */
3679 /* */
3680 /* ThreadX */
3681 /* */
3682 /* RELEASE HISTORY */
3683 /* */
3684 /* DATE NAME DESCRIPTION */
3685 /* */
3686 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3687 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3688 /* resulting in version 6.1 */
3689 /* */
3690 /**************************************************************************/
_nx_dhcpv6_server_thread_entry(ULONG info)3691 VOID _nx_dhcpv6_server_thread_entry(ULONG info)
3692 {
3693
3694 UINT i;
3695 NX_DHCPV6_SERVER *dhcpv6_server_ptr;
3696 NX_DHCPV6_CLIENT *dhcpv6_client_ptr;
3697 ULONG dhcpv6_events;
3698 NXD_ADDRESS client_address;
3699
3700
3701 /* Setup the DHCPV6 server pointer. */
3702 NX_THREAD_EXTENSION_PTR_GET(dhcpv6_server_ptr, NX_DHCPV6_SERVER, info)
3703
3704 /* Continue processing periodic tasks till this internal flag is cleared. */
3705 while (1)
3706 {
3707
3708
3709 /* Pick up IP event flags. */
3710 tx_event_flags_get(&dhcpv6_server_ptr -> nx_dhcpv6_server_timer_events, NX_DHCPV6_ALL_EVENTS,
3711 TX_OR_CLEAR, &dhcpv6_events, TX_WAIT_FOREVER);
3712
3713 if (dhcpv6_events & NX_DHCPV6_SERVER_RECEIVE_EVENT)
3714 {
3715
3716 /* Listen for new Client DHCP service request e.g. DISCOVERY messages. */
3717 _nx_dhcpv6_listen_for_messages(dhcpv6_server_ptr);
3718 }
3719
3720 if (dhcpv6_events & NX_DHCPV6_CHECK_SESSION_PERIODIC_EVENT)
3721 {
3722 /* Check the active clients whose sessions that have timed out. */
3723 for (i = 0; i < NX_DHCPV6_MAX_CLIENTS; i++)
3724 {
3725
3726 /* Set a local pointer for convenience. */
3727 dhcpv6_client_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_clients[i];
3728
3729 tx_mutex_get(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex, NX_WAIT_FOREVER);
3730
3731 /* Is this client in session with the server? */
3732 if (dhcpv6_client_ptr -> nx_dhcpv6_client_session_time)
3733 {
3734
3735 /* Update the Client session time. */
3736 dhcpv6_client_ptr -> nx_dhcpv6_client_session_time += NX_DHCPV6_SESSION_TIMER_INTERVAL;
3737
3738 if (dhcpv6_client_ptr -> nx_dhcpv6_client_session_time >= NX_DHCPV6_SESSION_TIMEOUT)
3739 {
3740
3741 /* The session has timed out without a response from the Client. Invalidate
3742 the client entry. */
3743
3744 /* First get the assigned address. */
3745 COPY_IPV6_ADDRESS(&dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0],
3746 &client_address.nxd_ip_address.v6[0]);
3747
3748 /* Clear the client record. */
3749 _nx_dhcpv6_clear_client_record(dhcpv6_server_ptr, dhcpv6_client_ptr);
3750 }
3751 }
3752
3753 tx_mutex_put(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex);
3754 }
3755 }
3756
3757 /* Check for a periodic DHCP server task. */
3758 if (dhcpv6_events & NX_DHCPV6_IP_LEASE_CHECK_PERIODIC_EVENT)
3759 {
3760
3761 /* Check the active clients for the time remaining in their leased IP address. */
3762 for (i = 0; i < NX_DHCPV6_MAX_CLIENTS; i++)
3763 {
3764
3765 /* Set a local pointer for convenience. */
3766 dhcpv6_client_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_clients[i];
3767
3768 tx_mutex_get(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex, NX_WAIT_FOREVER);
3769
3770 /* Skip those clients who do not have a lease assigned yet. */
3771 if (dhcpv6_client_ptr -> nx_dhcpv6_IP_lease_time_accrued == 0)
3772 {
3773
3774 tx_mutex_put(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex);
3775
3776 continue;
3777 }
3778
3779 /* Update the time accrued on the client's current IP address lease. */
3780 dhcpv6_client_ptr -> nx_dhcpv6_IP_lease_time_accrued += NX_DHCPV6_IP_LEASE_TIMER_INTERVAL;
3781
3782 /* Has this address become obsolete? */
3783 if (dhcpv6_client_ptr -> nx_dhcpv6_IP_lease_time_accrued >= dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime)
3784 {
3785
3786 tx_mutex_put(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex);
3787
3788 /* Clear the client record. */
3789 _nx_dhcpv6_clear_client_record(dhcpv6_server_ptr, dhcpv6_client_ptr);
3790 }
3791 else if (dhcpv6_client_ptr -> nx_dhcpv6_IP_lease_time_accrued >=
3792 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime)
3793 {
3794
3795 /* Address is deprecated! Client *should* not use it but no action taken by the server yet. */
3796 }
3797
3798 tx_mutex_put(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex);
3799 }
3800 }
3801
3802 /* Relinquish control before another cycle.*/
3803 tx_thread_sleep(1);
3804 }
3805 }
3806
3807
3808 /**************************************************************************/
3809 /* */
3810 /* FUNCTION RELEASE */
3811 /* */
3812 /* _nx_dhcpv6_server_extract_packet_information PORTABLE C */
3813 /* 6.3.0 */
3814 /* AUTHOR */
3815 /* */
3816 /* Yuxin Zhou, Microsoft Corporation */
3817 /* */
3818 /* DESCRIPTION */
3819 /* */
3820 /* This function extracts data from DHCPv6 Client request packets. A */
3821 /* request is checked for valid message type and required DHCPv6 data. */
3822 /* A client record is created if one does not exist for the client and */
3823 /* the data updated into it. */
3824 /* */
3825 /* INPUT */
3826 /* */
3827 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
3828 /* dhcpv6_client_ptr Pointer to DHCPv6 client */
3829 /* packet_ptr Pointer to received packet */
3830 /* iface_index Interface packet received on */
3831 /* */
3832 /* OUTPUT */
3833 /* */
3834 /* status Actual completion status */
3835 /* NX_SUCCESS Successful completion status */
3836 /* NX_DHCPV6_ILLEGAL_MESSAGE_TYPE Packet message type illegal */
3837 /* NX_DHCPV6_BAD_TRANSACTION_ID Message ID fails to match up */
3838 /* NX_DHCPV6_PROCESSING_ERROR Packet length is different than */
3839 /* expected */
3840 /* NX_DHCPV6_UNKNOWN_OPTION Unknown option in message */
3841 /* NX_DHCPV6_INVALID_HW_ADDRESS Missing or invalid MAC address */
3842 /* */
3843 /* CALLS */
3844 /* */
3845 /* _nx_dhcpv6_server_utility_get_data Extract data from reply packet */
3846 /* _nx_dhcpv6_server_utility_get_block_option_length */
3847 /* Extract option header data */
3848 /* _nx_dhcpv6_process_duid Extract DUID from Client message*/
3849 /* _nx_dhcpv6_process_DNS_server Extract DNS server from message */
3850 /* memcpy Copies specified area of memory */
3851 /* */
3852 /* CALLED BY */
3853 /* */
3854 /* _nx_dhcpv6_listen_for_messages Waits to receive client message*/
3855 /* */
3856 /* RELEASE HISTORY */
3857 /* */
3858 /* DATE NAME DESCRIPTION */
3859 /* */
3860 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3861 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
3862 /* packet length verification, */
3863 /* verified memcpy use cases, */
3864 /* resulting in version 6.1 */
3865 /* 10-31-2023 Haiqing Zhao Modified comment(s), and */
3866 /* updated client record on */
3867 /* each message, */
3868 /* resulting in version 6.3.0 */
3869 /* */
3870 /**************************************************************************/
_nx_dhcpv6_server_extract_packet_information(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT ** dhcpv6_client_ptr,NX_PACKET * packet_ptr,UINT iface_index,NXD_ADDRESS source_address,NXD_ADDRESS destination_address)3871 UINT _nx_dhcpv6_server_extract_packet_information(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT **dhcpv6_client_ptr, NX_PACKET *packet_ptr,
3872 UINT iface_index, NXD_ADDRESS source_address, NXD_ADDRESS destination_address)
3873 {
3874
3875 UINT status;
3876 UINT add_on;
3877 UINT record_index;
3878 ULONG option_code;
3879 ULONG option_length;
3880 UCHAR *buffer_ptr;
3881 UINT index;
3882 ULONG returned_xid;
3883 NX_DHCPV6_SVR_DUID client_duid, server_duid;
3884 UINT client_duid_received;
3885 UINT server_duid_received;
3886 NX_DHCPV6_CLIENT temp_client_rec;
3887 ULONG received_message_type;
3888 UINT matching;
3889
3890 NX_PARAMETER_NOT_USED(iface_index);
3891
3892 *dhcpv6_client_ptr = NX_NULL;
3893
3894 /* Create a scratch record for this client so we can qualify it before adding it to the server table. */
3895 memset(&temp_client_rec, 0, sizeof(NX_DHCPV6_CLIENT));
3896
3897 /* Initialize the record with the DHCPv6 Client ID. */
3898 temp_client_rec.nx_dhcpv6_id = NX_DHCPV6_CLIENT_ID;
3899
3900 /* Assume the Client is not bound to an IP address yet. */
3901 temp_client_rec.nx_dhcpv6_state = NX_DHCPV6_STATE_UNBOUND;
3902
3903 /* Check packet for message type and transaction ID. */
3904 if (packet_ptr -> nx_packet_length < 4)
3905 {
3906
3907 /* Reported length of the packet may be incorrect. */
3908 return NX_DHCPV6_PROCESSING_ERROR;
3909 }
3910
3911 /* Set a pointer to the start of DHCPv6 data. */
3912 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3913
3914 /* Initialize local variables. */
3915 index = 0;
3916 client_duid_received = NX_FALSE;
3917 server_duid_received = NX_FALSE;
3918
3919 /* Extract the message type which should be the first byte. */
3920 _nx_dhcpv6_server_utility_get_data(buffer_ptr, 1, &received_message_type);
3921
3922 /* Check for an illegal message type. */
3923 if ((received_message_type == NX_DHCPV6_MESSAGE_TYPE_ADVERTISE) ||
3924 (received_message_type == NX_DHCPV6_MESSAGE_TYPE_REPLY) ||
3925 (received_message_type == NX_DHCPV6_MESSAGE_TYPE_RECONFIGURE) ||
3926 (received_message_type > NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST))
3927 {
3928
3929 /* These should only be sent to DHCPv6 clients! The Inform Request is actually
3930 legal to receive but should NOT be used to add clients to the server table. */
3931 return NX_DHCPV6_ILLEGAL_MESSAGE_TYPE;
3932 }
3933
3934 /* Copy the source address to the Client record. */
3935 COPY_IPV6_ADDRESS(&source_address.nxd_ip_address.v6[0], &temp_client_rec.nx_dhcp_source_ip_address.nxd_ip_address.v6[0]);
3936 temp_client_rec.nx_dhcp_source_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
3937
3938 /* Copy the destination address to the Client record. */
3939 COPY_IPV6_ADDRESS(&destination_address.nxd_ip_address.v6[0], &temp_client_rec.nx_dhcp_destination_ip_address.nxd_ip_address.v6[0]);
3940 temp_client_rec.nx_dhcp_destination_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
3941
3942 /* Advance to the data pointer. */
3943 buffer_ptr++;
3944
3945 /* Parse the transaction ID. */
3946 _nx_dhcpv6_server_utility_get_data(buffer_ptr, 3, &returned_xid);
3947
3948 temp_client_rec.nx_dhcpv6_message_type = received_message_type;
3949
3950 /* Set the message ID. The server will need this to reply to the Client. */
3951 temp_client_rec.nx_dhcpv6_message_xid = returned_xid;
3952
3953 buffer_ptr += 3;
3954
3955 /* Update index for message type and transaction ID. */
3956 index += 4;
3957
3958 /* Now parse all the DHCPv6 option blocks in the packet buffer. */
3959 /* 4 bytes for option code and option length. */
3960 while (index + 4 <= packet_ptr -> nx_packet_length)
3961 {
3962
3963 /* Get the option code and length of data of the current option block. */
3964 status = _nx_dhcpv6_server_utility_get_block_option_length(buffer_ptr, &option_code, &option_length);
3965
3966 /* Check that the block data is valid. */
3967 if (status != NX_SUCCESS)
3968 {
3969
3970 /* No, return the error status. */
3971 return status;
3972 }
3973
3974 /* Keep track of how far into the packet we have parsed. */
3975 index += option_length + 4;
3976
3977 /* This is a double check to verify we haven't gone off the end of the packet buffer. */
3978 if (index > packet_ptr -> nx_packet_length)
3979 {
3980
3981 /* Reported length of the packet may be incorrect. At any rate, we don't know
3982 exactly what the end of the message is, so abort. */
3983 return NX_DHCPV6_PROCESSING_ERROR;
3984 }
3985
3986 /* Update buffer pointer to option data. */
3987 buffer_ptr += 4;
3988
3989 /* Process the option code with an option specific API. */
3990 switch (option_code)
3991 {
3992
3993 /* Note - these 'process' functions will not move the buffer pointer. */
3994
3995 case NX_DHCPV6_OP_DUID_CLIENT:
3996
3997 client_duid.nx_op_code = (USHORT)option_code;
3998 client_duid.nx_option_length = (USHORT)option_length;
3999
4000 status = _nx_dhcpv6_process_duid(&client_duid, option_code, option_length, buffer_ptr);
4001
4002 if (status != NX_SUCCESS)
4003 {
4004
4005 return status;
4006 }
4007
4008 /* Copy to the temporary client record. */
4009 memcpy(&temp_client_rec.nx_dhcpv6_client_duid, &client_duid, sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
4010
4011 /* Indicate the message contained the required Client DUID. */
4012 client_duid_received = NX_TRUE;
4013
4014 break;
4015
4016 case NX_DHCPV6_OP_DUID_SERVER:
4017
4018 server_duid.nx_op_code = (USHORT)option_code;
4019 server_duid.nx_option_length = (USHORT)option_length;
4020
4021 status = _nx_dhcpv6_process_duid(&server_duid, option_code, option_length, buffer_ptr);
4022
4023 if (status != NX_SUCCESS)
4024 {
4025
4026 return status;
4027 }
4028
4029 /* Copy to the temporary client record. */
4030 memcpy(&temp_client_rec.nx_dhcpv6_server_duid, &server_duid, sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
4031
4032 /* Indicate the message contained the required Server DUID. */
4033 server_duid_received = NX_TRUE;
4034
4035 break;
4036
4037
4038 case NX_DHCPV6_OP_IA_NA:
4039
4040 status = _nx_dhcpv6_server_process_iana(&temp_client_rec, option_code, option_length, buffer_ptr);
4041
4042 if (status != NX_SUCCESS)
4043 {
4044 return status;
4045 }
4046
4047 break;
4048
4049 /* This should not happen. The IA address option must be embedded in the IANA option. */
4050 case NX_DHCPV6_OP_IA_ADDRESS:
4051
4052 /* Don't process an IA address option outside of an address association (IANA). */
4053 status = NX_DHCPV6_IANA_OPTION_MISSING;
4054
4055 break;
4056
4057 case NX_DHCPV6_OP_OPTION_REQUEST:
4058
4059 /* Option request option contains request usually for network configuration parameters
4060 such as the DNS server. */
4061 status = _nx_dhcpv6_process_option_request(&temp_client_rec, option_code, option_length, buffer_ptr);
4062
4063 if (status != NX_SUCCESS)
4064 {
4065
4066 return status;
4067 }
4068
4069 break;
4070
4071 case NX_DHCPV6_OP_ELAPSED_TIME:
4072
4073 /* The elapsed time is time elapsed since the client initiated the IP lease request. */
4074 status = _nx_dhcpv6_process_elapsed_time(&temp_client_rec, option_code, option_length, buffer_ptr);
4075
4076 if (status != NX_SUCCESS)
4077 {
4078
4079 return status;
4080 }
4081
4082 break;
4083
4084
4085 default:
4086 break;
4087 }
4088
4089 /* Check for errors from option block processing. */
4090 if (status != NX_SUCCESS)
4091 {
4092
4093
4094 return status;
4095 }
4096
4097 /* Move to the next top level option. */
4098 buffer_ptr += option_length;
4099 }
4100
4101 /* Check for an improperly formatted packet. */
4102 if (index != packet_ptr -> nx_packet_length)
4103 {
4104
4105 /* If we get here if we are not at the expected end of the buffer. Oops */
4106 return NX_DHCPV6_PROCESSING_ERROR;
4107 }
4108
4109 /* Check if the message is missing the required DUID(s). */
4110 if ((temp_client_rec.nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT) ||
4111 (temp_client_rec.nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REBIND))
4112 {
4113
4114 if (!client_duid_received)
4115 {
4116
4117 return NX_DHCPV6_MESSAGE_DUID_MISSING;
4118 }
4119 }
4120 /* The following message types must include a client and server DUID. */
4121 else if ((temp_client_rec.nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST) ||
4122 (temp_client_rec.nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RENEW) ||
4123 (temp_client_rec.nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE))
4124 {
4125
4126 if (!server_duid_received || !client_duid_received)
4127 {
4128
4129 return NX_DHCPV6_MESSAGE_DUID_MISSING;
4130 }
4131 }
4132 /* An inform request only requires a server DUID. */
4133 else if (temp_client_rec.nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST)
4134 {
4135
4136 /* The Inform request message should NOT include an IA. */
4137 if (temp_client_rec.nx_dhcpv6_ia.nx_op_code != 0)
4138 {
4139 return NX_DHCPV6_INVALID_IA_DATA;
4140 }
4141 }
4142
4143 /* Validate the client message, and determine how (if) the server should respond to it. */
4144 status = _nx_dhcpv6_validate_client_message(dhcpv6_server_ptr, &temp_client_rec);
4145
4146 /* Check for errors. */
4147 if (status != NX_SUCCESS)
4148 {
4149
4150 /* Return all other errors as completion status. Do not send a message to the client. */
4151 return(status);
4152 }
4153
4154 if (temp_client_rec.nx_dhcpv6_response_back_from_server == NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT)
4155 {
4156
4157 /* Not responding to client. So do not assign an IP address or update
4158 the client record with invalid message. */
4159 return NX_SUCCESS;
4160 }
4161
4162 /* Look up the client record in the server table. If not found, or this is
4163 a new request e.g. a SOLICIT message, create a new client entry in the table and
4164 fill in the extracted information. */
4165 add_on = NX_FALSE;
4166
4167 if ((received_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT) ||
4168 (received_message_type == NX_DHCPV6_MESSAGE_TYPE_CONFIRM) ||
4169 (received_message_type == NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST))
4170 {
4171
4172 /* Check first if the validation process indicates we do not reply to this message. */
4173 if (temp_client_rec.nx_dhcpv6_response_back_from_server != NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT)
4174 {
4175
4176 /* Ok to update or create a new record. */
4177 add_on = NX_TRUE;
4178 }
4179 }
4180
4181 /* Check if the client is already in the server table. */
4182 status = _nx_dhcpv6_find_client_record_by_duid(dhcpv6_server_ptr, &client_duid, &record_index,
4183 add_on, temp_client_rec.nx_dhcpv6_message_xid, &matching);
4184
4185 /* Check for error during search. */
4186 if (status != NX_SUCCESS)
4187 {
4188
4189 return(status);
4190 }
4191
4192 /* Set a local pointer to the client record in the server table. */
4193 *dhcpv6_client_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_clients[record_index];
4194
4195 /* Was a match was found? */
4196 if (matching)
4197 {
4198
4199 /* This is a different message from the Client. Before updating the record check the client global address
4200 to be the same as what the server assigned or is offering to assign. */
4201 if (!CHECK_IPV6_ADDRESSES_SAME(&temp_client_rec.nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0],
4202 &(*dhcpv6_client_ptr )-> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]))
4203 {
4204
4205 /* This is a different address. Disregard this message. */
4206 (*dhcpv6_client_ptr) -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4207
4208 return NX_SUCCESS;
4209 }
4210 }
4211
4212 /* Update the client record. */
4213 status = _nx_dhcpv6_update_client_record(dhcpv6_server_ptr, &temp_client_rec, *dhcpv6_client_ptr);
4214
4215 /* Yes we're done with no processing errors detected. */
4216 return NX_SUCCESS;
4217 }
4218
4219
4220 /**************************************************************************/
4221 /* */
4222 /* FUNCTION RELEASE */
4223 /* */
4224 /* _nx_dhcpv6_validate_client_message PORTABLE C */
4225 /* 6.1 */
4226 /* AUTHOR */
4227 /* */
4228 /* Yuxin Zhou, Microsoft Corporation */
4229 /* */
4230 /* DESCRIPTION */
4231 /* */
4232 /* This function validates the client DHCPv6 request, determines if an */
4233 /* IP address need to be assigned, what state the DHCPv6 Client */
4234 /* should be advanced to, and what the server response type should be. */
4235 /* */
4236 /* INPUT */
4237 /* */
4238 /* dhcpv6_server_ptr Pointer to DHCPv6 server */
4239 /* dhcpv6_client_ptr Pointer to DHCPv6 client */
4240 /* */
4241 /* OUTPUT */
4242 /* */
4243 /* NX_SUCCESS Table searched successfully */
4244 /* */
4245 /* CALLS */
4246 /* */
4247 /* _nx_dhcp_update_assignable_ip_address Update IP address status in */
4248 /* the server database */
4249 /* */
4250 /* CALLED BY */
4251 /* */
4252 /* _nx_dhcpv6_listen_for_messages Listen for, process and respond*/
4253 /* to DHCPV6 Client messages */
4254 /* */
4255 /* RELEASE HISTORY */
4256 /* */
4257 /* DATE NAME DESCRIPTION */
4258 /* */
4259 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4260 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4261 /* resulting in version 6.1 */
4262 /* */
4263 /**************************************************************************/
_nx_dhcpv6_validate_client_message(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr)4264 UINT _nx_dhcpv6_validate_client_message(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr)
4265 {
4266
4267 UINT status;
4268 UINT matching_clients;
4269 UINT matching_server_duids;
4270 UINT record_index;
4271 UINT dest_address_type;
4272 UINT ga_address_index;
4273 UINT if_index;
4274 UINT prefix_length;
4275
4276
4277 /* Clear the Server response to the Client. We will decide that below. */
4278 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = 0;
4279
4280 ga_address_index = dhcpv6_server_ptr -> nx_dhcpv6_server_ga_address_index;
4281
4282 /* Initialize the response to the client. If the client request is invalid, ignore the request (no response
4283 from server) or indicate the problem in the IANA status option. */
4284
4285 /* Initialize the IANA status for the SOLICIT request as successfully granted. */
4286 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT)
4287 {
4288
4289 /* Respond to a valid Solicit request with an Advertise message. */
4290 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_ADVERTISE;
4291 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_SUCCESS;
4292 }
4293 else
4294 {
4295
4296 /* Respond to a valid Request request with a Reply message. */
4297 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_REPLY;
4298
4299 /* Set the expected IANA status. */
4300 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST) ||
4301 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RENEW) ||
4302 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REBIND) ||
4303 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||
4304 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE) ||
4305 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST) ||
4306 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_CONFIRM))
4307 {
4308
4309 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_SUCCESS;
4310 }
4311 }
4312
4313 /* Never accept a packet without a DHCP ID. */
4314 if (!dhcpv6_client_ptr -> nx_dhcpv6_message_xid)
4315 {
4316
4317 /* Don't respond, just discard the message. . */
4318 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4319
4320 return(NX_SUCCESS);
4321 }
4322
4323 /* Determine if destination address type (unicast or multicast). */
4324 dest_address_type = IPv6_Address_Type(&dhcpv6_client_ptr -> nx_dhcp_destination_ip_address.nxd_ip_address.v6[0]);
4325
4326 /* Do validation specific for message type. This section will also
4327 advance the DHCPv6 Client state and set the server response message type. */
4328 switch (dhcpv6_client_ptr -> nx_dhcpv6_message_type)
4329 {
4330
4331 case NX_DHCPV6_MESSAGE_TYPE_SOLICIT:
4332 {
4333
4334 /* Check for missing required fields. */
4335 if ((dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_type == 0) ||
4336 (dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_hardware_type == 0))
4337 {
4338
4339 /* Don't respond, just discard the message. . */
4340 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4341
4342 return(NX_SUCCESS);
4343 }
4344
4345 /* Check for presence of a server DUID. */
4346 if (dhcpv6_client_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw != 0)
4347 {
4348
4349 /* Don't respond, just discard the message. . */
4350 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4351
4352 /* Clear the success status. */
4353 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_UNSPECIFIED;
4354
4355 return(NX_SUCCESS);
4356 }
4357
4358 /* The Solicit message should never be unicast. Check if the destination is unicast. */
4359 if (IPV6_ADDRESS_UNICAST & dest_address_type)
4360 {
4361
4362 /* Don't respond, just discard the message. . */
4363 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4364
4365 return NX_SUCCESS;
4366 }
4367 break;
4368 }
4369
4370 case NX_DHCPV6_MESSAGE_TYPE_REQUEST:
4371 case NX_DHCPV6_MESSAGE_TYPE_RENEW:
4372 case NX_DHCPV6_MESSAGE_TYPE_REBIND:
4373 case NX_DHCPV6_MESSAGE_TYPE_RELEASE:
4374 case NX_DHCPV6_MESSAGE_TYPE_DECLINE:
4375 {
4376
4377 /* Check for missing required fields. */
4378 if ((dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_type == 0) ||
4379 (dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_hardware_type == 0))
4380 {
4381
4382 /* Don't respond, just discard the message. . */
4383 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4384
4385 return(NX_SUCCESS);
4386 }
4387
4388 /* Check for an invalid unicast destination address type. */
4389 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type != NX_DHCPV6_MESSAGE_TYPE_REBIND)
4390 {
4391
4392 /* The DHCPv6 server does not support unicast. Check for unicast client destination. */
4393 if (IPV6_ADDRESS_UNICAST & dest_address_type)
4394 {
4395
4396 /* It is unicast. Set the use multicast error status. */
4397 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_USE_MULTICAST;
4398
4399 return NX_SUCCESS;
4400 }
4401 }
4402
4403 /* This client message is not valid if an matching client record does not exist with the server. */
4404 status = _nx_dhcpv6_find_client_record_by_duid(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_client_duid,
4405 &record_index, NX_FALSE,
4406 dhcpv6_client_ptr -> nx_dhcpv6_message_xid,
4407 &matching_clients);
4408 /* Check for error. */
4409 if (status != NX_SUCCESS)
4410 {
4411
4412 return status;
4413 }
4414
4415 /* Check for matching client record. */
4416 if (!matching_clients)
4417 {
4418
4419 /* No matching client record found. */
4420
4421 /* For Release and Decline messages let the client know using the IANA status code that
4422 the server has no record of the assigned or requested address for this client. */
4423 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||
4424 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE))
4425 {
4426
4427 /* Set the non-binding error status. */
4428 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_NO_BINDING;
4429
4430 /* Set the lifetimes to zero. */
4431 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
4432 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
4433 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = 0;
4434 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0;
4435 }
4436 else
4437 {
4438
4439 /* Otherwise don't respond, just discard the message. */
4440 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4441
4442 /* Clear the success status. */
4443 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_UNSPECIFIED;
4444
4445 return(NX_SUCCESS);
4446 }
4447 }
4448
4449 /* Handle Rebind a little differently. It should not specify a server DUID. */
4450 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REBIND)
4451 {
4452 /* Is there a server DUID in the client message? */
4453 if (dhcpv6_client_ptr -> nx_dhcpv6_server_duid.nx_option_length > 0)
4454 {
4455
4456 /* Yes; don't respond, just discard the message. . */
4457 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4458
4459 /* Clear the success status. */
4460 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_UNSPECIFIED;
4461 }
4462
4463 break;
4464 }
4465 else
4466 {
4467
4468 /* With all other IA addresses the server DUID must match the server DUID. */
4469 status = _nx_dhcpv6_check_duids_same(&dhcpv6_client_ptr -> nx_dhcpv6_server_duid,
4470 &dhcpv6_server_ptr -> nx_dhcpv6_server_duid, &matching_server_duids);
4471
4472 /* Check for error. */
4473 if (status != NX_SUCCESS)
4474 {
4475
4476 /* Clear the success status. */
4477 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_UNSPECIFIED;
4478
4479 return status;
4480 }
4481
4482 /* Do the two server DUIDs match? */
4483 if (!matching_server_duids)
4484 {
4485
4486 /* No; don't respond, just discard the message. */
4487 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4488
4489 /* Clear the success status. */
4490 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_UNSPECIFIED;
4491
4492 return NX_SUCCESS;
4493 }
4494 }
4495 break;
4496 }
4497 /* The Client wished to confirm its IP address is on link. */
4498 case NX_DHCPV6_MESSAGE_TYPE_CONFIRM:
4499 {
4500
4501 /* Check for missing IA option. */
4502 if (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_option_length == 0)
4503 {
4504
4505 /* No IA option, so don't respond, just discard the message. */
4506 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4507
4508 return NX_SUCCESS;
4509 }
4510
4511 /* Verify the input addresses match the server interface address prefix (in IPv4 terms, the
4512 network masked addresses should be equal). */
4513 prefix_length = dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address_prefix_length;
4514
4515 if (!CHECK_IP_ADDRESSES_BY_PREFIX(&(dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr -> nx_ipv6_address[ga_address_index].nxd_ipv6_address[0]),
4516 &dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0],
4517 prefix_length))
4518 {
4519
4520
4521 /* Inform the client their IA address is not on link. */
4522 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_REPLY;
4523
4524 /* Set the IA-NA error status. */
4525 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_NOT_ON_LINK;
4526
4527 return(NX_SUCCESS);
4528 }
4529
4530 /* More checks will be done when the client rebind address is searched in the server
4531 address table. For now we are ok. */
4532
4533 break;
4534 }
4535
4536 case NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST:
4537 {
4538
4539 /* Verify Client's server duid matches the server DUID. Note that if the server DUID type is a
4540 link layer time type (LLT), this comparison should ignore the time field because this is an 'asynchronous' request
4541 from the client, so just match on the LL data. */
4542
4543 /* Temporarily set the server DUID type to LL if it was LLT. */
4544 if ((dhcpv6_client_ptr -> nx_dhcpv6_server_duid.nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME) ||
4545 (dhcpv6_client_ptr -> nx_dhcpv6_server_duid.nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_ONLY))
4546 {
4547
4548 /* Now verify the physical address matches what the server has for this client. */
4549 if_index = dhcpv6_server_ptr -> nx_dhcpv6_server_interface_index;
4550 if (dhcpv6_client_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_msw !=
4551 dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr -> nx_ip_interface[if_index].nx_interface_physical_address_msw)
4552 {
4553
4554 /* Inform the client their physical address is not on record. */
4555 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4556 }
4557 else if (dhcpv6_client_ptr -> nx_dhcpv6_server_duid.nx_link_layer_address_lsw !=
4558 dhcpv6_server_ptr -> nx_dhcpv6_ip_ptr -> nx_ip_interface[if_index].nx_interface_physical_address_lsw)
4559 {
4560 /* Inform the client their physical address is not on record. */
4561 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4562 }
4563 }
4564 else
4565 {
4566
4567 /* Verify the client inform request was intended for this server. If the Client did not
4568 include a server DUID, which is acceptable in DHCPv6 protocol, it will 'pass' this check. */
4569 status = _nx_dhcpv6_check_duids_same(&dhcpv6_client_ptr -> nx_dhcpv6_server_duid,
4570 &dhcpv6_client_ptr -> nx_dhcpv6_server_duid, &matching_server_duids);
4571
4572 /* Check for error. */
4573 if (status != NX_SUCCESS)
4574 {
4575
4576 /* Clear the success status. */
4577 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_UNSPECIFIED;
4578
4579 return status;
4580 }
4581
4582 /* Do the two server DUIDs match? */
4583 if (!matching_server_duids)
4584 {
4585
4586 /* Don't respond, just discard the message. */
4587 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4588
4589 /* Clear the success status. */
4590 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_UNSPECIFIED;
4591
4592 return NX_SUCCESS;
4593 }
4594 }
4595
4596 /* Check for missing options request. */
4597 if (dhcpv6_client_ptr -> nx_dhcpv6_option_request.nx_option_length == 0)
4598 {
4599
4600 /* Don't respond, just discard the message. */
4601 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4602
4603 return NX_SUCCESS;
4604 }
4605
4606 break;
4607 }
4608
4609 default:
4610 {
4611
4612 dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
4613
4614 /* Clear the success status. */
4615 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_UNSPECIFIED;
4616
4617 return(NX_SUCCESS);
4618
4619 /* No further processing to do. Leave the client state unchanged, whatever it was/is. */
4620 }
4621 }
4622
4623 return(NX_SUCCESS);
4624 }
4625
4626
4627 /**************************************************************************/
4628 /* */
4629 /* FUNCTION RELEASE */
4630 /* */
4631 /* _nx_dhcpv6_server_utility_get_block_option_length PORTABLE C */
4632 /* 6.1 */
4633 /* AUTHOR */
4634 /* */
4635 /* Yuxin Zhou, Microsoft Corporation */
4636 /* */
4637 /* DESCRIPTION */
4638 /* */
4639 /* This function parses the input buffer (assuming to be an option */
4640 /* block in a server reply) for option code and length. It assumes the */
4641 /* buffer pointer is pointed to the first byte of the option buffer. */
4642 /* */
4643 /* INPUT */
4644 /* */
4645 /* dhcpv6_ Pointer to DHCPv6 Client */
4646 /* option Option code of requested data */
4647 /* buffer_ptr Buffer to copy data to */
4648 /* length Size of buffer */
4649 /* valid */
4650 /* */
4651 /* OUTPUT */
4652 /* */
4653 /* status Completion status */
4654 /* NX_DHCPV6_OPTION_BLOCK_INCOMPLETE Unknown option specified */
4655 /* */
4656 /* CALLS */
4657 /* */
4658 /* _nx_dhcpv6_server_utility_get_data Parses a specific data from the */
4659 /* DHCPv6 option */
4660 /* */
4661 /* CALLED BY */
4662 /* */
4663 /* _nx_dhcpv6_server_utility_get_block_option_length */
4664 /* Parses option code and length */
4665 /* _nx_dhcpv6_server_extract_packet_information */
4666 /* Parses each option from server */
4667 /* reply and updates Client record */
4668 /* */
4669 /* RELEASE HISTORY */
4670 /* */
4671 /* DATE NAME DESCRIPTION */
4672 /* */
4673 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4674 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4675 /* resulting in version 6.1 */
4676 /* */
4677 /**************************************************************************/
_nx_dhcpv6_server_utility_get_block_option_length(UCHAR * buffer_ptr,ULONG * option,ULONG * length)4678 UINT _nx_dhcpv6_server_utility_get_block_option_length(UCHAR *buffer_ptr, ULONG *option, ULONG *length)
4679 {
4680
4681 /* Initialize to zero. */
4682 *option = 0;
4683 *length = 0;
4684
4685 /* First byte should be the op code. */
4686 _nx_dhcpv6_server_utility_get_data(buffer_ptr, 2, option);
4687
4688 buffer_ptr += 2;
4689
4690 /* Next byte should be the option length. */
4691 _nx_dhcpv6_server_utility_get_data(buffer_ptr, 2, length);
4692
4693 /* Buffer is now pointed at the data (past the length field). */
4694 buffer_ptr += 2;
4695
4696 /* Check for null data. */
4697 if (*option == 0 || *length == 0)
4698 {
4699
4700 return NX_DHCPV6_OPTION_BLOCK_INCOMPLETE;
4701 }
4702
4703 return(NX_SUCCESS);
4704
4705 }
4706
4707
4708 /**************************************************************************/
4709 /* */
4710 /* FUNCTION RELEASE */
4711 /* */
4712 /* _nx_dhcpv6_server_utility_get_data PORTABLE C */
4713 /* 6.1 */
4714 /* AUTHOR */
4715 /* */
4716 /* Yuxin Zhou, Microsoft Corporation */
4717 /* */
4718 /* DESCRIPTION */
4719 /* */
4720 /* This function parses the input buffer and returns numeric data */
4721 /* specified by the size argument, up to 4 bytes long. Note that if */
4722 /* caller is using this utility to extract bytes from a DHCPv6 packet */
4723 /* there is no need for byte swapping, as compared to using memcpy in */
4724 /* which case there is for little endian processors. */
4725 /* */
4726 /* INPUT */
4727 /* */
4728 /* buffer Pointer to data buffer */
4729 /* value Pointer to data parsed from buffer*/
4730 /* size Size of buffer */
4731 /* */
4732 /* OUTPUT */
4733 /* */
4734 /* NX_DHCPV6_INVALID_DATA_SIZE Requested data size too large */
4735 /* NX_SUCCESS Successful completion status */
4736 /* */
4737 /* CALLS */
4738 /* */
4739 /* None */
4740 /* */
4741 /* CALLED BY */
4742 /* _nx_dhcpv6_process_server_duid Process server duid in server reply*/
4743 /* _nx_dhcpv6_process_client_duid Process server duid in server reply*/
4744 /* _nx_dhcpv6_server_utility_get_block_option_length */
4745 /* Parses option code and length */
4746 /* _nx_dhcpv6_server_extract_packet_information */
4747 /* Parses each option from server */
4748 /* reply and updates Client record */
4749 /* */
4750 /* RELEASE HISTORY */
4751 /* */
4752 /* DATE NAME DESCRIPTION */
4753 /* */
4754 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4755 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4756 /* resulting in version 6.1 */
4757 /* */
4758 /**************************************************************************/
_nx_dhcpv6_server_utility_get_data(UCHAR * buffer,UINT size,ULONG * value)4759 UINT _nx_dhcpv6_server_utility_get_data(UCHAR *buffer, UINT size, ULONG *value)
4760 {
4761
4762
4763 /* Check that the size of the data fits in a ULONG. */
4764 if (size > sizeof(ULONG))
4765 {
4766 return NX_DHCPV6_INVALID_DATA_SIZE;
4767 }
4768
4769 *value = 0;
4770
4771 /* Process the data retrieval request. */
4772 while (size-- > 0)
4773 {
4774
4775 /* Build return value. */
4776 *value = (*value << 8) | *buffer++;
4777 }
4778
4779 /* Return value. */
4780 return NX_SUCCESS;
4781 }
4782
4783
4784 /**************************************************************************/
4785 /* */
4786 /* FUNCTION RELEASE */
4787 /* */
4788 /* _nx_dhcpv6_server_utility_time_randomize PORTABLE C */
4789 /* 6.1 */
4790 /* AUTHOR */
4791 /* */
4792 /* Yuxin Zhou, Microsoft Corporation */
4793 /* */
4794 /* DESCRIPTION */
4795 /* */
4796 /* This function returns a value of between -1 seconds and 1 second */
4797 /* in system ticks. It is used to randomize timeouts as required by */
4798 /* the RFC's so as to not overload a network server after power out. */
4799 /* */
4800 /* INPUT */
4801 /* */
4802 /* None */
4803 /* */
4804 /* OUTPUT */
4805 /* */
4806 /* ticks Number of ticks between 1 & -1*/
4807 /* */
4808 /* CALLS */
4809 /* */
4810 /* None */
4811 /* */
4812 /* CALLED BY */
4813 /* */
4814 /* _nx_dhcpv6_convert_delay_to_ticks Convert seconds to ticks */
4815 /* */
4816 /* RELEASE HISTORY */
4817 /* */
4818 /* DATE NAME DESCRIPTION */
4819 /* */
4820 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4821 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4822 /* resulting in version 6.1 */
4823 /* */
4824 /**************************************************************************/
_nx_dhcpv6_server_utility_time_randomize(void)4825 INT _nx_dhcpv6_server_utility_time_randomize(void)
4826 {
4827
4828 INT temp;
4829 UINT sign;
4830
4831
4832 temp = (INT)(NX_RAND() & 0x001F);
4833 sign = temp & 0x8;
4834
4835 /* Try for a number between 0 and 0x1F. */
4836 if (sign)
4837 {
4838 temp = -temp;
4839 }
4840
4841 return temp;
4842 }
4843
4844
4845 /**************************************************************************/
4846 /* */
4847 /* FUNCTION RELEASE */
4848 /* */
4849 /* _nx_dhcpv6_listen_for_messages PORTABLE C */
4850 /* 6.1 */
4851 /* AUTHOR */
4852 /* */
4853 /* Yuxin Zhou, Microsoft Corporation */
4854 /* */
4855 /* DESCRIPTION */
4856 /* */
4857 /* This function listens for DHCPv6 client messages. It validates and */
4858 /* extracts information for creating or updating the client record. It */
4859 /* also responds to the Client pending valid request is received, and */
4860 /* updates its client records. */
4861 /* */
4862 /* INPUT */
4863 /* */
4864 /* dhcpv6_ptr Pointer to DHCPv6 Server */
4865 /* */
4866 /* OUTPUT */
4867 /* */
4868 /* NX_SUCCESS Message handled successfully */
4869 /* NO_PACKET No packet received */
4870 /* NX_DHCP_BAD_INTERFACE_INDEX Packet interface not recognized*/
4871 /* status Actual completion outcome */
4872 /* */
4873 /* CALLS */
4874 /* */
4875 /* nx_packet_release Release DHCP packet */
4876 /* nx_udp_socket_receive Receive DHCP packet */
4877 /* _nx_dhcpv6_extract_information Extract DHCP packet info */
4878 /* _nx_dhcpv6_validate_client_message Process the Client message */
4879 /* _nx_dhcpv6_server_assign_ip_address Assign IP address to Client */
4880 /* _nx_dhcpv6_respond_to_client_message Create and send response back */
4881 /* _nx_dhcpv6_clear_client_session Clears client session data */
4882 /* */
4883 /* CALLED BY */
4884 /* */
4885 /* _nx_dhcpv6_server_thread_entry DHCPv6 Server thread task */
4886 /* */
4887 /* RELEASE HISTORY */
4888 /* */
4889 /* DATE NAME DESCRIPTION */
4890 /* */
4891 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4892 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4893 /* resulting in version 6.1 */
4894 /* */
4895 /**************************************************************************/
_nx_dhcpv6_listen_for_messages(NX_DHCPV6_SERVER * dhcpv6_server_ptr)4896 UINT _nx_dhcpv6_listen_for_messages(NX_DHCPV6_SERVER *dhcpv6_server_ptr)
4897 {
4898
4899 UINT status;
4900 UINT iface_index;
4901 NXD_ADDRESS source_address;
4902 NXD_ADDRESS destination_address;
4903 NX_IPV6_HEADER *ipv6_header_ptr;
4904 NX_PACKET *packet_ptr;
4905 NX_DHCPV6_CLIENT *dhcpv6_client_ptr;
4906 NX_DHCPV6_ADDRESS_LEASE *dhcpv6_interface_list_ptr;
4907 NX_PACKET *new_packet_ptr;
4908 ULONG bytes_copied = 0;
4909
4910
4911 /* Check for an incoming DHCPv6 packet with non blocking option. */
4912 status = nx_udp_socket_receive(&dhcpv6_server_ptr -> nx_dhcpv6_server_socket, &packet_ptr, NX_DHCPV6_PACKET_WAIT_OPTION);
4913
4914 /* Check for packet receive errors. */
4915 if (status != NX_SUCCESS)
4916 {
4917
4918 /* Return the packet receive status. */
4919 return(status);
4920 }
4921
4922 /* Check for valid packet length (message type and ID). */
4923 if (packet_ptr -> nx_packet_length < 4)
4924 {
4925
4926 /* Release the packet. */
4927 nx_packet_release(packet_ptr);
4928
4929 /* Return. */
4930 return(NX_DHCPV6_INVALID_DATA_SIZE);
4931 }
4932
4933 /* Get the interface index. */
4934 nxd_udp_packet_info_extract(packet_ptr, NX_NULL, NX_NULL, NX_NULL, &iface_index);
4935
4936 /* Does the DHCP server have a table for this packet interface? */
4937 if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
4938 {
4939
4940 /* No; Release the packet. */
4941 nx_packet_release(packet_ptr);
4942
4943 /* No, return the error status. */
4944 return(NX_DHCPV6_INVALID_INTERFACE_INDEX);
4945 }
4946
4947 /* Set a pointer to the IPv6 header to obtain source and destination address. */
4948 ipv6_header_ptr = (NX_IPV6_HEADER*)(packet_ptr -> nx_packet_ip_header);
4949
4950 /* Get the source address. */
4951 COPY_IPV6_ADDRESS(&ipv6_header_ptr -> nx_ip_header_source_ip[0], &source_address.nxd_ip_address.v6[0]);
4952 source_address.nxd_ip_version = NX_IP_VERSION_V6;
4953
4954 /* Get the destination address. */
4955 COPY_IPV6_ADDRESS(&ipv6_header_ptr -> nx_ip_header_destination_ip[0], &destination_address.nxd_ip_address.v6[0]);
4956 destination_address.nxd_ip_version = NX_IP_VERSION_V6;
4957
4958 /* We will copy the received packet (datagram) over to a packet from the DHCP Server pool and release
4959 the packet from the receive packet pool as soon as possible. */
4960 status = nx_packet_allocate(dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr, &new_packet_ptr, NX_IPv6_UDP_PACKET, NX_DHCPV6_PACKET_TIME_OUT);
4961
4962 /* Check status. */
4963 if (status != NX_SUCCESS)
4964 {
4965
4966 /* Release the original packet. */
4967 nx_packet_release(packet_ptr);
4968
4969 /* Error allocating packet, return error status. */
4970 return(status);
4971 }
4972
4973 /* Verify the incoming packet does not exceed our DHCP Server packet payload. */
4974 if ((ULONG)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr) < (packet_ptr -> nx_packet_length))
4975 {
4976
4977 /* Release the original packet. */
4978 nx_packet_release(packet_ptr);
4979
4980 /* Release the newly allocated packet and return an error. */
4981 nx_packet_release(new_packet_ptr);
4982
4983 return(NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD);
4984 }
4985
4986 /* Use a packet from the DHCP Server as a buffer to store the received packet data.
4987 Then we can release the received packet back to its packet pool. */
4988 status = nx_packet_data_extract_offset(packet_ptr, 0, (VOID *)new_packet_ptr -> nx_packet_prepend_ptr, packet_ptr -> nx_packet_length, &bytes_copied);
4989
4990 /* Check status. */
4991 if ((status != NX_SUCCESS) || (bytes_copied == 0))
4992 {
4993
4994 /* Release the original packet. */
4995 nx_packet_release(packet_ptr);
4996
4997 /* Release the allocated packet we'll never send. */
4998 nx_packet_release(new_packet_ptr);
4999
5000 /* Error extracting packet buffer, return error status. */
5001 return(status);
5002 }
5003
5004 /* Update the new packet with the bytes copied. For chained packets, this will reflect the total
5005 'datagram' length. */
5006 new_packet_ptr -> nx_packet_length = bytes_copied;
5007 new_packet_ptr -> nx_packet_append_ptr = new_packet_ptr -> nx_packet_prepend_ptr + bytes_copied;
5008
5009 /* Now we can release the original packet. */
5010 nx_packet_release(packet_ptr);
5011
5012 /* Get the DHCPv6 Server Mutex. */
5013 tx_mutex_get(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex, NX_WAIT_FOREVER);
5014
5015 /* Extract the DHCPv6 specific information from the packet. This will create new Client record or update existing
5016 client record in the server table. */
5017 status = _nx_dhcpv6_server_extract_packet_information(dhcpv6_server_ptr, &dhcpv6_client_ptr, new_packet_ptr, iface_index, source_address, destination_address);
5018
5019 /* We are done with this packet now regardless of the success of the above operations. */
5020 nx_packet_release(new_packet_ptr);
5021
5022 /* Check if we have extracted a valid client record. */
5023 if (status != NX_SUCCESS)
5024 {
5025
5026 /* Not valid; is there a client record we need to clean up? */
5027 if (dhcpv6_client_ptr)
5028 {
5029
5030 /* Yes; clear the client record completely. */
5031 _nx_dhcpv6_clear_client_record(dhcpv6_server_ptr, dhcpv6_client_ptr);
5032 }
5033 else
5034 {
5035
5036 /* No record created; return the error status and abort. */
5037 tx_mutex_put(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex);
5038
5039 /* Return the error from extracting packet data. */
5040 return(status);
5041 }
5042 }
5043
5044 /* Determine if the server will respond to the message. */
5045 if ((dhcpv6_client_ptr == NX_NULL) ||
5046 (dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server == NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT))
5047 {
5048
5049 /* Release the mutex. */
5050 tx_mutex_put(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex);
5051
5052 /* No, no further processing necessary. */
5053 return NX_SUCCESS;
5054 }
5055
5056 /* Check if the server status indicates it will grant the client request. */
5057 if (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code == NX_DHCPV6_STATUS_SUCCESS)
5058 {
5059
5060 /* Yes it will. Check if the client is requesting an IP address, or renewing or rebinding a
5061 previously assigned one. */
5062 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT) ||
5063 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST) ||
5064 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RENEW) ||
5065 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REBIND))
5066 {
5067
5068 /* Yes, it is. This will (re)assign an IP address. */
5069 status = _nx_dhcpv6_assign_ip_address(dhcpv6_server_ptr, dhcpv6_client_ptr, &dhcpv6_interface_list_ptr);
5070
5071 /* Check for errors or no address assigned. */
5072 if (status != NX_SUCCESS)
5073 {
5074
5075 /* Release the mutex. */
5076 tx_mutex_put(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex);
5077
5078 /* Return all other errors as completion status. Do not send a message to the client.
5079 The server will otherwise wait for the client to try again. Do not clear client record. */
5080 return(status);
5081 }
5082
5083 /* Check if a valid IP address is available. */
5084 if (dhcpv6_interface_list_ptr)
5085 {
5086
5087 /* There is. DHCPv6 client has been assigned an IP address. */
5088
5089 /* Now ensure we are sending valid lease time parameters with the IP address. */
5090 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST)
5091 {
5092
5093 /* Ignore invalid preferred or valid lifetimes from the client by setting to zero. */
5094 if (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime > dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime)
5095 {
5096
5097 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0;
5098 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = 0;
5099 }
5100 /* Check for invalid T1 or T2 values; if out of range, set to zero). */
5101
5102 if (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime &&
5103 (dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 > dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime))
5104 {
5105 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
5106 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
5107 }
5108 else if (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime &&
5109 (dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 > dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime))
5110 {
5111 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
5112 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
5113 }
5114 else if (dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 > dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2)
5115 {
5116 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
5117 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
5118 }
5119 }
5120 /* For a solicit message, ignore the preferred and valid lifetimes and check for
5121 valid T1 and T2 times. */
5122 else if (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT)
5123 {
5124
5125 if (dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 > dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2)
5126 {
5127 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
5128 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
5129 }
5130 }
5131
5132 /* If lifetime values are zero, or exceed the server default time, set to the default lease times. */
5133 if ((dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime == 0) ||
5134 (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime > NX_DHCPV6_DEFAULT_PREFERRED_TIME))
5135 {
5136
5137 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = NX_DHCPV6_DEFAULT_PREFERRED_TIME;
5138 }
5139 if ((dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime == 0) ||
5140 (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime > NX_DHCPV6_DEFAULT_VALID_TIME))
5141 {
5142
5143 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = NX_DHCPV6_DEFAULT_VALID_TIME;
5144 }
5145
5146 if ((dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 == 0) ||
5147 (dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 > NX_DHCPV6_DEFAULT_T1_TIME))
5148 {
5149
5150 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = NX_DHCPV6_DEFAULT_T1_TIME;
5151 }
5152
5153 if ((dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 == 0) ||
5154 (dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 > NX_DHCPV6_DEFAULT_T2_TIME))
5155 {
5156
5157 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = NX_DHCPV6_DEFAULT_T2_TIME;
5158 }
5159
5160 /* Update the lease length in the server lease table. */
5161 dhcpv6_interface_list_ptr -> nx_dhcpv6_lease_preferred_lifetime = dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime;
5162 dhcpv6_interface_list_ptr -> nx_dhcpv6_lease_valid_lifetime = dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime;
5163 dhcpv6_interface_list_ptr -> nx_dhcpv6_lease_T1_lifetime = dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1;
5164 dhcpv6_interface_list_ptr -> nx_dhcpv6_lease_T2_lifetime = dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2;
5165
5166 /* Ok to copy this address into the client record. */
5167 COPY_NXD_ADDRESS(&dhcpv6_interface_list_ptr -> nx_dhcpv6_lease_IP_address,
5168 &dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address);
5169 }
5170 }
5171 }
5172
5173 /* Send the server reply back to the client. */
5174 status = _nx_dhcpv6_send_response_to_client(dhcpv6_server_ptr, dhcpv6_client_ptr);
5175
5176 /* Check if we need to remove the client record e.g. if the Client sent a Decline message. */
5177 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||
5178 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE))
5179 {
5180
5181 /* This will clear the client record and in the case of
5182 a release message, return the IP address lease status to available. */
5183 status = _nx_dhcpv6_clear_client_record(dhcpv6_server_ptr, dhcpv6_client_ptr);
5184
5185 }
5186
5187 tx_mutex_put(&dhcpv6_server_ptr -> nx_dhcpv6_server_mutex);
5188
5189 /* Return actual outcome status. */
5190 return(status);
5191 }
5192
5193
5194 /**************************************************************************/
5195 /* */
5196 /* FUNCTION RELEASE */
5197 /* */
5198 /* _nx_dhcpv6_send_response_to_client PORTABLE C */
5199 /* 6.1.5 */
5200 /* AUTHOR */
5201 /* */
5202 /* Yuxin Zhou, Microsoft Corporation */
5203 /* */
5204 /* DESCRIPTION */
5205 /* */
5206 /* This function prepares DHCPv6 messages to send back to the Client. */
5207 /* Most of the information is obtained from the client session record. */
5208 /* */
5209 /* INPUT */
5210 /* */
5211 /* dhcpv6_server_ptr Pointer to DHCPv6 Server */
5212 /* dhcpv6_client_ptr Pointer to DHCPv6 Client */
5213 /* */
5214 /* OUTPUT */
5215 /* */
5216 /* status Completion status */
5217 /* */
5218 /* CALLS */
5219 /* */
5220 /* nx_packet_allocate Allocate a DHCPv6 packet */
5221 /* nx_packet_release Release DHCPv6 packet */
5222 /* nxd_udp_socket_send Send DHCPv6 packets */
5223 /* memcpy Copy specified area of memory */
5224 /* */
5225 /* CALLED BY */
5226 /* */
5227 /* _nx_dhcpv6_listen_for_messages Process Client DHCPv6 messages*/
5228 /* */
5229 /* RELEASE HISTORY */
5230 /* */
5231 /* DATE NAME DESCRIPTION */
5232 /* */
5233 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5234 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
5235 /* packet length verification, */
5236 /* verified memcpy use cases, */
5237 /* resulting in version 6.1 */
5238 /* 03-02-2021 Yuxin Zhou Modified comment(s), and */
5239 /* fixed compiler warnings, */
5240 /* resulting in version 6.1.5 */
5241 /* */
5242 /**************************************************************************/
_nx_dhcpv6_send_response_to_client(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr)5243 UINT _nx_dhcpv6_send_response_to_client(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr)
5244 {
5245
5246 NX_PACKET *packet_ptr;
5247 UCHAR *buffer;
5248 UINT status;
5249 UINT buffer_index;
5250 ULONG message_word;
5251
5252
5253 /* Allocate a UDP packet from the DHCPv6 server packet pool. */
5254 status = nx_packet_allocate(dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr, &packet_ptr, NX_IPv6_UDP_PACKET, NX_DHCPV6_PACKET_TIME_OUT);
5255
5256 /* Was the packet allocation successful? */
5257 if (status != NX_SUCCESS)
5258 {
5259
5260 /* Return status. */
5261 return(status);
5262 }
5263
5264 /* Verify packet payload. */
5265 if ((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 4)
5266 {
5267 nx_packet_release(packet_ptr);
5268 return(NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD);
5269 }
5270
5271 /* Indicate this is an IPv6 packet. */
5272 packet_ptr -> nx_packet_ip_version = NX_IP_VERSION_V6;
5273
5274 /* Setup the packet buffer pointer. */
5275 buffer = packet_ptr -> nx_packet_prepend_ptr;
5276
5277 /* Clear the payload and packet interface field before preparing the packet for transmission. */
5278 memset(buffer, 0, (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr));
5279
5280 /* Now reduce it to three bytes. */
5281 dhcpv6_client_ptr -> nx_dhcpv6_message_xid = dhcpv6_client_ptr -> nx_dhcpv6_message_xid & 0x0ffffff;
5282
5283 /* Clear memory to make the message header. */
5284 memset(&message_word, 0, sizeof(ULONG));
5285
5286 /* Add the server message type and matching client transaction ID as the DHCPv6 header fields. */
5287 message_word = (ULONG)((dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server << 24) |
5288 (0x0FFFFFF & dhcpv6_client_ptr -> nx_dhcpv6_message_xid));
5289
5290 /* Adjust for endianness. */
5291 NX_CHANGE_ULONG_ENDIAN(message_word);
5292
5293 /* Copy the message header to the packet buffer. */
5294 memcpy(buffer, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
5295
5296 /* Update the buffer 'pointer'. */
5297 buffer_index = sizeof(ULONG);
5298
5299 /* Handle the special case of an Inform Request which does not include a Client identifier. */
5300 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST)
5301 {
5302
5303 status = NX_SUCCESS;
5304
5305 /* Only add the Client DUID if the client included one. */
5306 if (dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_op_code != 0)
5307 {
5308
5309 /* Add the Client DUID to the packet buffer. */
5310 status = _nx_dhcpv6_add_duid(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_client_duid, buffer,
5311 &buffer_index, NX_DHCPV6_CLIENT_DUID_TYPE);
5312 }
5313 }
5314 else
5315 {
5316
5317 /* Add the Client DUID to the packet buffer. */
5318 status = _nx_dhcpv6_add_duid(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_client_duid, buffer,
5319 &buffer_index, NX_DHCPV6_CLIENT_DUID_TYPE);
5320 }
5321
5322 /* Check for error. */
5323 if (status != NX_SUCCESS)
5324 {
5325 /* Release the allocated back to the DHCPv6 Server packet pool. */
5326 nx_packet_release(packet_ptr);
5327
5328 return status;
5329 }
5330
5331 /* Now add to the server DUID to the message. */
5332 status = _nx_dhcpv6_add_duid(dhcpv6_server_ptr, &dhcpv6_server_ptr -> nx_dhcpv6_server_duid, buffer,
5333 &buffer_index, NX_DHCPV6_SERVER_DUID_TYPE);
5334
5335 /* Check for error. */
5336 if (status != NX_SUCCESS)
5337 {
5338
5339 /* Release the allocated back to the DHCPv6 Server packet pool. */
5340 nx_packet_release(packet_ptr);
5341
5342 return status;
5343 }
5344
5345 /* Handle the special case of the Confirm request where we need only
5346 send a status option. */
5347 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_CONFIRM)
5348 {
5349
5350 /* Update the IANA status message. */
5351 status = _nx_dhcpv6_prepare_iana_status(&dhcpv6_client_ptr -> nx_dhcpv6_iana_status, NX_TRUE);
5352
5353 if (status != NX_SUCCESS)
5354 {
5355 /* Release the allocated back to the DHCPv6 Server packet pool. */
5356 nx_packet_release(packet_ptr);
5357
5358 return status;
5359 }
5360
5361 /* Ok to just send a status option without the IANA option. */
5362 status = _nx_dhcpv6_add_iana_status(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_iana_status, buffer, &buffer_index);
5363
5364 /* Update the IANA status message. */
5365 status = _nx_dhcpv6_prepare_iana_status(&dhcpv6_client_ptr -> nx_dhcpv6_iana_status, NX_FALSE);
5366
5367 if (status != NX_SUCCESS)
5368 {
5369 /* Release the allocated back to the DHCPv6 Server packet pool. */
5370 nx_packet_release(packet_ptr);
5371
5372 return status;
5373 }
5374 }
5375
5376 /* Exclude IANA options from Confirm and Inform Request messages. */
5377 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type != NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST) &&
5378 (dhcpv6_client_ptr -> nx_dhcpv6_message_type != NX_DHCPV6_MESSAGE_TYPE_CONFIRM))
5379 {
5380
5381 /* Add the client IANA to the packet buffer. */
5382 status = _nx_dhcpv6_server_add_iana(dhcpv6_server_ptr, dhcpv6_client_ptr, buffer, &buffer_index);
5383
5384 /* Check for error. */
5385 if (status != NX_SUCCESS)
5386 {
5387 /* Release the allocated back to the DHCPv6 Server packet pool. */
5388 nx_packet_release(packet_ptr);
5389
5390 return status;
5391 }
5392 }
5393
5394 /* Only an Advertise response should include a preference. */
5395 if (dhcpv6_client_ptr -> nx_dhcpv6_response_back_from_server == NX_DHCPV6_MESSAGE_TYPE_ADVERTISE)
5396
5397 {
5398
5399 status = _nx_dhcpv6_add_preference(dhcpv6_server_ptr, dhcpv6_client_ptr, buffer, &buffer_index);
5400 }
5401
5402 /* Check if the message type requires the server to add option request data. */
5403 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT) ||
5404 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST) ||
5405 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST))
5406 {
5407
5408 /* It does. Did the Client ask for a requested option? Only provide information
5409 if there are no status errors from the server. */
5410 if (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code == NX_DHCPV6_STATUS_SUCCESS)
5411 {
5412
5413 /* Add the option request. */
5414 status = _nx_dhcpv6_add_option_requests(dhcpv6_server_ptr, dhcpv6_client_ptr, buffer, &buffer_index);
5415
5416 /* Check for internal error. */
5417 if (status != NX_SUCCESS)
5418 {
5419
5420 /* Release the allocated back to the DHCPv6 Server packet pool. */
5421 nx_packet_release(packet_ptr);
5422
5423 /* Return the error status and abort. */
5424 return status;
5425 }
5426 }
5427 }
5428
5429 /* Adjust the packet length for the DHCPv6 data. */
5430 packet_ptr -> nx_packet_length = buffer_index;
5431
5432 /* Update the packet pointer marking the end of the payload (DHCP) data. */
5433 packet_ptr -> nx_packet_append_ptr += buffer_index;
5434
5435 /* Send the response packet to the client. */
5436 status = nxd_udp_socket_interface_send(&(dhcpv6_server_ptr -> nx_dhcpv6_server_socket), packet_ptr,
5437 &dhcpv6_client_ptr -> nx_dhcp_source_ip_address, NX_DHCPV6_CLIENT_UDP_PORT,
5438 dhcpv6_server_ptr -> nx_dhcpv6_server_interface_index);
5439
5440 /* Check for error. */
5441 if (status != NX_SUCCESS)
5442 {
5443 /* Release the allocated back to the DHCPv6 Server packet pool. */
5444 nx_packet_release(packet_ptr);
5445 }
5446 /* Return completion status. */
5447 return(status);
5448 }
5449
5450
5451 /**************************************************************************/
5452 /* */
5453 /* FUNCTION RELEASE */
5454 /* */
5455 /* _nx_dhcpc6_server_assign_ip_address PORTABLE C */
5456 /* 6.1 */
5457 /* AUTHOR */
5458 /* */
5459 /* Yuxin Zhou, Microsoft Corporation */
5460 /* */
5461 /* DESCRIPTION */
5462 /* */
5463 /* This service finds an available IP address for the client if none is */
5464 /* provided, and updates the client's record with the new IP address. It */
5465 /* updates the server IP address lease table with the assigned lease */
5466 /* status */
5467 /* */
5468 /* INPUT */
5469 /* */
5470 /* dhcpv6_server_ptr Pointer to DHCPV6 Server */
5471 /* dhcpv6_client_ptr Pointer to DHCPV6client */
5472 /* */
5473 /* OUTPUT */
5474 /* */
5475 /* NX_SUCCESS Successful completion */
5476 /* NX_DHCPV6_NO_AVAILABLE_IP_ADDRESSES No available address to assign*/
5477 /* */
5478 /* CALLS */
5479 /* */
5480 /* _nx_dhcp_find_interface_table_ip_address */
5481 /* Look up IP address in */
5482 /* server interface table */
5483 /* _nx_dhcp_find_ip_address_owner Look up owner of an IP address*/
5484 /* in server interfce table */
5485 /* _nx_dhcp_record_ip_address_owner Set the client as IP address */
5486 /* owner in interface table */
5487 /* */
5488 /* CALLED BY */
5489 /* */
5490 /* _nx_dhcpv6_listen_for_messages Process Client DHCPv6 messages*/
5491 /* */
5492 /* RELEASE HISTORY */
5493 /* */
5494 /* DATE NAME DESCRIPTION */
5495 /* */
5496 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5497 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5498 /* resulting in version 6.1 */
5499 /* */
5500 /**************************************************************************/
_nx_dhcpv6_assign_ip_address(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr,NX_DHCPV6_ADDRESS_LEASE ** interface_address_ptr)5501 UINT _nx_dhcpv6_assign_ip_address(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr,
5502 NX_DHCPV6_ADDRESS_LEASE **interface_address_ptr)
5503 {
5504 UINT status;
5505 UINT i;
5506 NX_DHCPV6_ADDRESS_LEASE *temp_interface_address_ptr;
5507 UINT matching;
5508
5509
5510 /* Initialize outcome to no address assigned. */
5511 *interface_address_ptr = NX_NULL;
5512
5513 /* Does the Client have a IP address already assigned? */
5514 if (!CHECK_UNSPECIFIED_ADDRESS(&dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]))
5515 {
5516
5517 /* Yes; The client has an IP address. */
5518
5519 /* Check if this address exists in the Server IP address list. */
5520 status = _nx_dhcpv6_find_ip_address(dhcpv6_server_ptr, dhcpv6_client_ptr, &temp_interface_address_ptr);
5521
5522 /* Check for internal errors. */
5523 if (status != NX_SUCCESS)
5524 {
5525
5526 return status;
5527 }
5528
5529 /* Was the address found in the server table? */
5530 if (temp_interface_address_ptr)
5531 {
5532
5533 matching = NX_FALSE;
5534
5535 /* Verify the server has assigned this address. */
5536 if (temp_interface_address_ptr -> nx_dhcpv6_lease_assigned_to)
5537 {
5538 /* It has; now werify it is assigned to this client. */
5539 status = _nx_dhcpv6_check_duids_same(&dhcpv6_client_ptr -> nx_dhcpv6_client_duid,
5540 &(temp_interface_address_ptr -> nx_dhcpv6_lease_assigned_to -> nx_dhcpv6_client_duid),
5541 &matching);
5542
5543 /* Check for internal errors. */
5544 if (status != NX_SUCCESS)
5545 {
5546
5547 return status;
5548 }
5549 }
5550 else
5551 {
5552 /* It has not (so it is available). Assign it to this client. */
5553
5554 /* Set the lease address entry in the server table. */
5555 *interface_address_ptr = temp_interface_address_ptr;
5556
5557 /* Mark the owner of the lease as this client. */
5558 temp_interface_address_ptr -> nx_dhcpv6_lease_assigned_to = dhcpv6_client_ptr;
5559
5560 /* We are all done. */
5561 return NX_SUCCESS;
5562 }
5563
5564 /* Was the address assigned to this client previously? */
5565 if (matching)
5566 {
5567
5568 /* Yes, return a pointer to the IP lease in the server table. */
5569 *interface_address_ptr = temp_interface_address_ptr;
5570
5571 /* We will (re)assign this IP address to the client. */
5572 return NX_SUCCESS;
5573 }
5574 else
5575 {
5576 /* No this address is not available. */
5577
5578 /* Is it Ok to assign another IP address only if this is a Solicit request? */
5579 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type != NX_DHCPV6_MESSAGE_TYPE_SOLICIT)
5580 {
5581
5582 /* No; Reply back the client request can not be granted. */
5583 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_NO_BINDING;
5584
5585 /* Because the server can not validate the IP address to assign,
5586 set the lifetimes to zero RFC 3315 Sect 18.2.3, 18.2.4. */
5587 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
5588 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
5589 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = 0;
5590 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0;
5591
5592 dhcpv6_client_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_UNBOUND;
5593
5594 return NX_SUCCESS;
5595 }
5596 }
5597 }
5598 else
5599 {
5600
5601 /* Client address not found in table. */
5602
5603 /* Ok to assign another IP address only if this is a Solicit request? */
5604 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type != NX_DHCPV6_MESSAGE_TYPE_SOLICIT)
5605 {
5606
5607 /* No; reply backthe client request can not be granted. */
5608 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_NO_BINDING;
5609
5610 /* Because the server can not validate the IP address to assign, set the lifetimes to zero RFC 3315 Sect 18.2.3, 18.2.4. */
5611 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
5612 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
5613 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = 0;
5614 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0;
5615
5616 dhcpv6_client_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_UNBOUND;
5617
5618 return NX_SUCCESS;
5619 }
5620 }
5621 }
5622
5623 /* If we reach this point, we need to find an available address for the client. */
5624 for (i = 0; i < NX_DHCPV6_MAX_LEASES; i++)
5625 {
5626
5627 if (!dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_assigned_to)
5628 {
5629 break;
5630 }
5631 }
5632
5633 /* Check if we found anything. */
5634 if (i == NX_DHCPV6_MAX_LEASES)
5635 {
5636
5637 /* No; reply back there are no addresses available. */
5638 dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_NO_ADDRS_AVAILABLE;
5639
5640 /* Because the server can not assign the IP address, set the lifetimes to zero RFC 3315 Sect 18.2.3, 18.2.4. */
5641 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = 0;
5642 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = 0;
5643 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = 0;
5644 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0;
5645
5646 dhcpv6_client_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_UNBOUND;
5647 }
5648 else
5649 {
5650
5651 /* Found an empty slot; assign it to this client. */
5652
5653 /* Mark the owner of the lease as this client. */
5654 dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_assigned_to = dhcpv6_client_ptr;
5655
5656 /* Return the lease address entry in the server table. */
5657 *interface_address_ptr = &(dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i]);
5658 }
5659
5660 return NX_SUCCESS;
5661 }
5662
5663
5664 /**************************************************************************/
5665 /* */
5666 /* FUNCTION RELEASE */
5667 /* */
5668 /* _nx_dhcp_find_client_record_by_chaddr PORTABLE C */
5669 /* 6.1 */
5670 /* AUTHOR */
5671 /* */
5672 /* Yuxin Zhou, Microsoft Corporation */
5673 /* */
5674 /* DESCRIPTION */
5675 /* */
5676 /* This function looks up a client record by the client hardware mac */
5677 /* address. */
5678 /* */
5679 /* INPUT */
5680 /* */
5681 /* dhcpv6_server_ptr Pointer to DHCPv6 Server */
5682 /* dhcpv6_duid _ptr Pointer to client DUID */
5683 /* record_index Index of client record found */
5684 /* in server table */
5685 /* add_on Option to add if not found */
5686 /* message_xid Message transaction ID */
5687 /* matching Indicates if client existed in*/
5688 /* server records already */
5689 /* */
5690 /* OUTPUT */
5691 /* */
5692 /* NX_SUCCESS Message handled successfully */
5693 /* NX_DHCPV6_TABLE_FULL Client record table is full */
5694 /* */
5695 /* CALLS */
5696 /* _nx_dhcpv6_check_duids_same Checks if DUIDs are the same */
5697 /* */
5698 /* CALLED BY */
5699 /* */
5700 /* _nx_dhcpv6_server_extract_packet_information */
5701 /* Extract DHCPv6 info from */
5702 /* Client message */
5703 /* */
5704 /* RELEASE HISTORY */
5705 /* */
5706 /* DATE NAME DESCRIPTION */
5707 /* */
5708 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5709 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5710 /* resulting in version 6.1 */
5711 /* */
5712 /**************************************************************************/
_nx_dhcpv6_find_client_record_by_duid(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_SVR_DUID * duid_ptr,UINT * record_index,UINT add_on,ULONG message_xid,UINT * matching)5713 UINT _nx_dhcpv6_find_client_record_by_duid(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_SVR_DUID *duid_ptr,
5714 UINT *record_index, UINT add_on, ULONG message_xid, UINT *matching)
5715 {
5716
5717 UINT i;
5718 UINT status;
5719 UINT available_index;
5720 NX_DHCPV6_CLIENT *client_record_ptr;
5721
5722
5723 /* Initialize result to not found. */
5724 *matching = NX_FALSE;
5725
5726 /* Initialize an available slot in the table as outside the boundary (e.g. no slots available). */
5727 available_index = NX_DHCPV6_MAX_CLIENTS;
5728
5729 /* Records are not necessarily added and deleted sequentially,
5730 so search the whole table until a match is found. */
5731 i = 0;
5732 status = NX_SUCCESS;
5733
5734 while (i < NX_DHCPV6_MAX_CLIENTS)
5735 {
5736
5737 /* Set local pointer for convenience. */
5738 client_record_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_clients[i];
5739
5740 /* Skip empty records. */
5741 if (!client_record_ptr -> nx_dhcpv6_id)
5742 {
5743
5744 /* Flag the first empty record in case we need to add the current client to the table. */
5745 if (i < available_index)
5746 available_index = i;
5747
5748 i++;
5749
5750 continue;
5751 }
5752
5753 status = _nx_dhcpv6_check_duids_same(&client_record_ptr -> nx_dhcpv6_client_duid, duid_ptr, matching);
5754
5755 /* Check the DUID in the received client request against the server record. */
5756 if ((status == NX_SUCCESS) && *matching)
5757 {
5758
5759 client_record_ptr -> nx_dhcpv6_message_xid = message_xid;
5760
5761
5762 /* Reset the client session time every time we hear from a client. */
5763 client_record_ptr -> nx_dhcpv6_client_session_time = 1;
5764
5765 /* Got a match! Return the client record location. */
5766 *record_index = i;
5767
5768 /* Set the result to client located. */
5769 *matching = NX_TRUE;
5770
5771 return(NX_SUCCESS);
5772 }
5773
5774 /* No match. Check the next client in the server table. */
5775 i++;
5776 }
5777
5778 /* Not found. Create a record for this client? */
5779 if (!add_on)
5780 {
5781
5782 /* Do not create a record and handle as an error. */
5783 return(NX_DHCPV6_CLIENT_RECORD_NOT_FOUND);
5784 }
5785
5786 /* Check if there is available room in the table for a new client. */
5787 if (available_index >= NX_DHCPV6_MAX_CLIENTS)
5788 {
5789
5790 /* No, we cannot add this client so the server's table. */
5791 return(NX_DHCPV6_TABLE_FULL);
5792 }
5793
5794 /* Set local pointer to an available slot. */
5795 client_record_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_clients[available_index];
5796
5797 /* Return the location of the newly created client record. */
5798 *record_index = available_index;
5799
5800 return(NX_SUCCESS);
5801 }
5802
5803
5804 /**************************************************************************/
5805 /* */
5806 /* FUNCTION RELEASE */
5807 /* */
5808 /* _nx_dhcpv6_find_ip_address PORTABLE C */
5809 /* 6.1 */
5810 /* AUTHOR */
5811 /* */
5812 /* Yuxin Zhou, Microsoft Corporation */
5813 /* */
5814 /* DESCRIPTION */
5815 /* */
5816 /* This function looks up a client DHCPv6 message IP address in the */
5817 /* appropriate server IP address table, based on the client network */
5818 /* interface index. For single homed hosts, this defaults to zero. */
5819 /* */
5820 /* INPUT */
5821 /* */
5822 /* dhcpv6_server_ptr Pointer to DHCPv6 Server */
5823 /* dhcpv6_client_ptr Pointer to DHCPv6 client */
5824 /* interface_address_ptr Pointer to matching entry */
5825 /* */
5826 /* OUTPUT */
5827 /* */
5828 /* NX_SUCCESS Search completes successfully */
5829 /* */
5830 /* CALLS */
5831 /* */
5832 /* _nx_dhcp_clear_client_record Removes client record from */
5833 /* server table */
5834 /* */
5835 /* CALLED BY */
5836 /* */
5837 /* CHECK_IPV6_ADDRESSES_SAME Does IPv6 address comparison */
5838 /* */
5839 /* RELEASE HISTORY */
5840 /* */
5841 /* DATE NAME DESCRIPTION */
5842 /* */
5843 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5844 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5845 /* resulting in version 6.1 */
5846 /* */
5847 /**************************************************************************/
_nx_dhcpv6_find_ip_address(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr,NX_DHCPV6_ADDRESS_LEASE ** interface_address_ptr)5848 UINT _nx_dhcpv6_find_ip_address(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr,
5849 NX_DHCPV6_ADDRESS_LEASE **interface_address_ptr)
5850 {
5851
5852 UINT i;
5853 NXD_ADDRESS server_table_address;
5854
5855
5856 /* Initialize to not found. */
5857 *interface_address_ptr = NX_NULL;
5858
5859 /* Search through the interface specific address table. For single homed hosts, there is only one address table. */
5860 for (i = 0; i < NX_DHCPV6_MAX_LEASES; i++)
5861 {
5862
5863 /* Get a pointer to the address, using the client's interface index to access the correct IP address table. */
5864 server_table_address = dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_IP_address;
5865
5866 /* Check for a match. */
5867 if (CHECK_IPV6_ADDRESSES_SAME(&server_table_address.nxd_ip_address.v6[0],
5868 &dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]))
5869 {
5870
5871 /* Set the location of the matching server entry, to indicate we found a match. */
5872 *interface_address_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i];
5873 break;
5874 }
5875 }
5876
5877 return NX_SUCCESS;
5878 }
5879
5880
5881 /**************************************************************************/
5882 /* */
5883 /* FUNCTION RELEASE */
5884 /* */
5885 /* _nx_dhcpv6_clear_client_record PORTABLE C */
5886 /* 6.1 */
5887 /* AUTHOR */
5888 /* */
5889 /* Yuxin Zhou, Microsoft Corporation */
5890 /* */
5891 /* DESCRIPTION */
5892 /* */
5893 /* This function clears the entire client record from the server table.*/
5894 /* It also frees up the client's IP address in the server IP address */
5895 /* table. */
5896 /* */
5897 /* INPUT */
5898 /* */
5899 /* dhcpv6_ptr Pointer to DHCPV6 Server */
5900 /* dhcpv6_client_ptr Pointer to DHCPV6 Client */
5901 /* */
5902 /* OUTPUT */
5903 /* */
5904 /* NX_SUCCESS Successful outcome */
5905 /* NX_DHCP_BAD_INTERFACE_INDEX Invalid client interface index */
5906 /* CALLS */
5907 /* */
5908 /* tx_mutex_get Get server protection mutex */
5909 /* tx_mutex_put Release server protection mutex*/
5910 /* */
5911 /* CALLED BY */
5912 /* */
5913 /* _nx_dhcpv6_listen_for_messages Listen for client requests */
5914 /* _nx_dhcpv6_find_client_record_by_chaddr */
5915 /* Find client in server table */
5916 /* */
5917 /* RELEASE HISTORY */
5918 /* */
5919 /* DATE NAME DESCRIPTION */
5920 /* */
5921 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5922 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5923 /* resulting in version 6.1 */
5924 /* */
5925 /**************************************************************************/
_nx_dhcpv6_clear_client_record(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr)5926 UINT _nx_dhcpv6_clear_client_record(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr)
5927 {
5928
5929 UINT i;
5930
5931
5932 if (!dhcpv6_client_ptr)
5933 {
5934
5935 /* Benign error. Return success. */
5936 return(NX_SUCCESS);
5937 }
5938
5939 i = 0;
5940
5941 /* Does the client have an assigned IP address? */
5942 if (!CHECK_UNSPECIFIED_ADDRESS(&dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]))
5943 {
5944
5945 /* Yes, We need to free up the Client's assigned IP address in the server database. */
5946 while (i < NX_DHCPV6_MAX_LEASES)
5947 {
5948
5949 tx_mutex_get(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex), NX_WAIT_FOREVER);
5950
5951 /* Find the interface table entry by matching IP address. */
5952 if (CHECK_IPV6_ADDRESSES_SAME(&dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0],
5953 &dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]))
5954 {
5955
5956 /* Clear the IP address list item properties. */
5957 if (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE)
5958 {
5959
5960 /* Apparently another client has this address so do not clear the assignment status. */
5961 dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_assigned_to = (NX_DHCPV6_CLIENT *)(ALIGN_TYPE)0xFFFFFFFF;
5962 }
5963 else
5964 {
5965
5966 /* Restore availability by clearing the owner. */
5967 dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_assigned_to = NX_NULL;
5968 }
5969
5970 dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_T1_lifetime = 0;
5971 dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_T2_lifetime = 0;
5972 dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_valid_lifetime = 0;
5973 dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_preferred_lifetime = 0;
5974
5975 tx_mutex_put(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex));
5976
5977 /* Address now available for DHCP client. */
5978 break;
5979 }
5980 i++;
5981
5982 tx_mutex_put(&(dhcpv6_server_ptr -> nx_dhcpv6_server_mutex));
5983
5984 }
5985 }
5986
5987 /* Ok to clear the Client record. */
5988 memset(dhcpv6_client_ptr, 0, sizeof(NX_DHCPV6_CLIENT));
5989
5990 return(NX_SUCCESS);
5991 }
5992
5993
5994 /**************************************************************************/
5995 /* */
5996 /* FUNCTION RELEASE */
5997 /* */
5998 /* _nx_dhcpv6_update_client_record PORTABLE C */
5999 /* 6.1 */
6000 /* AUTHOR */
6001 /* */
6002 /* Yuxin Zhou, Microsoft Corporation */
6003 /* */
6004 /* DESCRIPTION */
6005 /* */
6006 /* This function updates the client record based on the most recent */
6007 /* message received from the client. A typical example is after a */
6008 /* Solicit message is received the server gets a Request message which */
6009 /* it will add to the client record it has in its table. */
6010 /* */
6011 /* INPUT */
6012 /* */
6013 /* dhcpv6_server_ptr Pointer to DHCPV6 Server */
6014 /* to_server_ptr Pointer to client to update */
6015 /* from_client_ptr Pointer to client updated from */
6016 /* */
6017 /* OUTPUT */
6018 /* */
6019 /* NX_SUCCESS Successful outcome */
6020 /* */
6021 /* CALLS */
6022 /* */
6023 /* memcpy Copy specified area of memory */
6024 /* */
6025 /* CALLED BY */
6026 /* */
6027 /* _nx_dhcpv6_server_extract_packet_information */
6028 /* Process DHCPv6 data in packet */
6029 /* */
6030 /* RELEASE HISTORY */
6031 /* */
6032 /* DATE NAME DESCRIPTION */
6033 /* */
6034 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6035 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
6036 /* verified memcpy use cases, */
6037 /* resulting in version 6.1 */
6038 /* */
6039 /**************************************************************************/
_nx_dhcpv6_update_client_record(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * from_extracted_client_data_ptr,NX_DHCPV6_CLIENT * to_client_data_on_record_ptr)6040 UINT _nx_dhcpv6_update_client_record(NX_DHCPV6_SERVER *dhcpv6_server_ptr,
6041 NX_DHCPV6_CLIENT *from_extracted_client_data_ptr,
6042 NX_DHCPV6_CLIENT *to_client_data_on_record_ptr)
6043 {
6044
6045 NX_PARAMETER_NOT_USED(dhcpv6_server_ptr);
6046
6047 /* If this is a solicit message update the entire copy into the specified record. */
6048 if (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT)
6049 {
6050
6051 /* Ok to copy the whole record over. */
6052 memcpy(to_client_data_on_record_ptr, from_extracted_client_data_ptr, sizeof(NX_DHCPV6_CLIENT)); /* Use case of memcpy is verified. */
6053
6054 /* Update various fields now that the client is in a DHCPv6 session with the server. */
6055 to_client_data_on_record_ptr -> nx_dhcpv6_client_session_time = 1;
6056 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_client_duid, &from_extracted_client_data_ptr -> nx_dhcpv6_client_duid, sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
6057 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_server_duid, &from_extracted_client_data_ptr -> nx_dhcpv6_server_duid, sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
6058 }
6059 else if (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST)
6060 {
6061
6062 /* Update selected fields for an INFORM REQUEST. */
6063 to_client_data_on_record_ptr -> nx_dhcpv6_id = from_extracted_client_data_ptr -> nx_dhcpv6_id;
6064 to_client_data_on_record_ptr -> nx_dhcpv6_message_xid = from_extracted_client_data_ptr -> nx_dhcpv6_message_xid;
6065 to_client_data_on_record_ptr -> nx_dhcpv6_message_type = from_extracted_client_data_ptr -> nx_dhcpv6_message_type;
6066 to_client_data_on_record_ptr -> nx_dhcpv6_response_back_from_server = from_extracted_client_data_ptr -> nx_dhcpv6_response_back_from_server;
6067
6068 COPY_IPV6_ADDRESS(&from_extracted_client_data_ptr -> nx_dhcp_source_ip_address.nxd_ip_address.v6[0],
6069 &to_client_data_on_record_ptr -> nx_dhcp_source_ip_address.nxd_ip_address.v6[0]);
6070 to_client_data_on_record_ptr -> nx_dhcp_source_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
6071
6072 COPY_IPV6_ADDRESS(&from_extracted_client_data_ptr -> nx_dhcp_destination_ip_address.nxd_ip_address.v6[0],
6073 &to_client_data_on_record_ptr -> nx_dhcp_destination_ip_address.nxd_ip_address.v6[0]);
6074 to_client_data_on_record_ptr -> nx_dhcp_destination_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
6075
6076 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_option_request, &from_extracted_client_data_ptr -> nx_dhcpv6_option_request, sizeof(NX_DHCPV6_SERVER_OPTIONREQUEST)); /* Use case of memcpy is verified. */
6077 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_client_duid, &from_extracted_client_data_ptr -> nx_dhcpv6_client_duid, sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
6078 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_server_duid, &from_extracted_client_data_ptr -> nx_dhcpv6_server_duid, sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
6079
6080 }
6081 /* If this is not a solicit message, update the selected fields into the specified record. */
6082 else if ((from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST) ||
6083 (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RENEW) ||
6084 (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REBIND) ||
6085 (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||
6086 (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE) ||
6087 (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_CONFIRM))
6088 {
6089
6090
6091 /* Ok to update the existing client record.
6092
6093 Note: if this is a duplicate client request we update the client record just
6094 the same. */
6095 to_client_data_on_record_ptr -> nx_dhcpv6_id = from_extracted_client_data_ptr -> nx_dhcpv6_id;
6096 to_client_data_on_record_ptr -> nx_dhcpv6_message_xid = from_extracted_client_data_ptr -> nx_dhcpv6_message_xid;
6097 to_client_data_on_record_ptr -> nx_dhcpv6_message_type = from_extracted_client_data_ptr -> nx_dhcpv6_message_type;
6098 to_client_data_on_record_ptr -> nx_dhcpv6_response_back_from_server = from_extracted_client_data_ptr -> nx_dhcpv6_response_back_from_server;
6099
6100 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_client_duid, &from_extracted_client_data_ptr -> nx_dhcpv6_client_duid, sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
6101 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_server_duid, &from_extracted_client_data_ptr -> nx_dhcpv6_server_duid, sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */
6102 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_elapsed_time, &from_extracted_client_data_ptr -> nx_dhcpv6_elapsed_time, sizeof(NX_DHCPV6_SERVER_ELAPSED_TIME)); /* Use case of memcpy is verified. */
6103 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_iana, &from_extracted_client_data_ptr -> nx_dhcpv6_iana, sizeof(NX_DHCPV6_SERVER_IA_NA)); /* Use case of memcpy is verified. */
6104 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_ia, &from_extracted_client_data_ptr -> nx_dhcpv6_ia, sizeof(NX_DHCPV6_SERVER_IA_ADDRESS)); /* Use case of memcpy is verified. */
6105
6106 /* Update the IANA status option code, length and status message. The DHCPv6 server
6107 will figure out the actual lenght with the status message text added in later. */
6108 to_client_data_on_record_ptr -> nx_dhcpv6_iana_status.nx_status_code = from_extracted_client_data_ptr -> nx_dhcpv6_iana_status.nx_status_code;
6109 to_client_data_on_record_ptr -> nx_dhcpv6_iana_status.nx_option_length = sizeof(USHORT);
6110
6111 COPY_IPV6_ADDRESS(&from_extracted_client_data_ptr -> nx_dhcp_source_ip_address.nxd_ip_address.v6[0],
6112 &to_client_data_on_record_ptr -> nx_dhcp_source_ip_address.nxd_ip_address.v6[0]);
6113
6114 to_client_data_on_record_ptr -> nx_dhcp_source_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
6115
6116 COPY_IPV6_ADDRESS(&from_extracted_client_data_ptr -> nx_dhcp_destination_ip_address.nxd_ip_address.v6[0],
6117 &to_client_data_on_record_ptr -> nx_dhcp_destination_ip_address.nxd_ip_address.v6[0]);
6118
6119 to_client_data_on_record_ptr -> nx_dhcp_destination_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
6120
6121 memcpy(&to_client_data_on_record_ptr -> nx_dhcpv6_option_request, &from_extracted_client_data_ptr -> nx_dhcpv6_option_request, sizeof(NX_DHCPV6_SERVER_OPTIONREQUEST)); /* Use case of memcpy is verified. */
6122
6123 /* Update fields based on the state of the client. At this point the client is bound to a
6124 valid IP address to the session is 'over'. Set timeout fields to stop the session timer
6125 and begin the lease life timer. */
6126 to_client_data_on_record_ptr -> nx_dhcpv6_client_session_time = 0;
6127
6128 /* Start the lease timer if we have just (re)assigned an IP lease. */
6129 if ((from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST) ||
6130 (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RENEW) ||
6131 (from_extracted_client_data_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_REBIND))
6132 {
6133
6134 to_client_data_on_record_ptr -> nx_dhcpv6_IP_lease_time_accrued = 1;
6135 to_client_data_on_record_ptr -> nx_dhcpv6_state = NX_DHCPV6_STATE_BOUND;
6136 }
6137
6138 /* No need to set the client state to unbound. We will remove the client record and restore the
6139 IP address status back to available after sending the server reply. */
6140 }
6141 /* else
6142 Confirm, Inform Request and other messages should not change the client record. */
6143
6144 return NX_SUCCESS;
6145 }
6146
6147
6148 /**************************************************************************/
6149 /* */
6150 /* FUNCTION RELEASE */
6151 /* */
6152 /* _nx_dhcpv6_server_process_iana PORTABLE C */
6153 /* 6.1 */
6154 /* AUTHOR */
6155 /* */
6156 /* Yuxin Zhou, Microsoft Corporation */
6157 /* */
6158 /* DESCRIPTION */
6159 /* */
6160 /* This function extracts the IANA option from a client DHCPv6 message.*/
6161 /* */
6162 /* INPUT */
6163 /* */
6164 /* dhcpv6_client_ptr Pointer to DHCPV6 Client instance */
6165 /* option_code Option code */
6166 /* option_length Size of option data */
6167 /* option_data Pointer to option data */
6168 /* */
6169 /* OUTPUT */
6170 /* */
6171 /* status Actual completion status */
6172 /* NX_DHCPV6_INVALID_IANA_DATA IANA option is missing data or */
6173 /* improperly formatted */
6174 /* CALLS */
6175 /* */
6176 /* _nx_dhcpv6_server_utility_get_data */
6177 /* Parses data from packet buffer */
6178 /* _nx_dhcpv6_server_utility_get_block_option_length */
6179 /* Parses option header from buffer */
6180 /* */
6181 /* CALLED BY */
6182 /* */
6183 /* _nx_dhcpv6_server_extract_packet_information */
6184 /* Extracts DHCPV6 data from packet */
6185 /* */
6186 /* RELEASE HISTORY */
6187 /* */
6188 /* DATE NAME DESCRIPTION */
6189 /* */
6190 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6191 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6192 /* packet length verification, */
6193 /* resulting in version 6.1 */
6194 /* */
6195 /**************************************************************************/
_nx_dhcpv6_server_process_iana(NX_DHCPV6_CLIENT * dhcpv6_client_ptr,ULONG option_code,UINT option_length,UCHAR * option_data)6196 UINT _nx_dhcpv6_server_process_iana(NX_DHCPV6_CLIENT *dhcpv6_client_ptr, ULONG option_code, UINT option_length, UCHAR *option_data)
6197 {
6198
6199 UINT status;
6200 ULONG data;
6201 UINT index;
6202 ULONG iana_option_code, iana_option_length;
6203 UINT process_ia_option;
6204
6205
6206 /* Initialize local variables. */
6207 process_ia_option = NX_TRUE;
6208 index = 0;
6209
6210 /* Set option code and length. */
6211 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_op_code = (USHORT)option_code;
6212 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_option_length = (USHORT)option_length;
6213
6214 /* Check option length for IANA ID. */
6215 if (option_length < 4)
6216 {
6217 return(NX_DHCPV6_INVALID_IANA_DATA);
6218 }
6219
6220 /* The first word should contain the IANA ID. */
6221 _nx_dhcpv6_server_utility_get_data(option_data + index, sizeof(ULONG), &data);
6222
6223 /* Process the IANA ID. */
6224 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_IA_NA_id = data;
6225
6226 /* Update the write location index. */
6227 index += 4;
6228
6229 /* Check option length for T1 and T2. */
6230 if (index + 8 > option_length)
6231 {
6232 return(NX_DHCPV6_INVALID_IANA_DATA);
6233 }
6234
6235 /* Copy T1 and T2 from the buffer into IANA. */
6236 _nx_dhcpv6_server_utility_get_data(option_data + index, sizeof(ULONG), &data);
6237 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 = data;
6238 index += (ULONG)sizeof(ULONG);
6239
6240 _nx_dhcpv6_server_utility_get_data(option_data + index, sizeof(ULONG), &data);
6241 dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2 = data;
6242 index += (ULONG)sizeof(ULONG);
6243
6244 /* Check for invalid T1/T2 lifetimes. */
6245 if (dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T1 > dhcpv6_client_ptr -> nx_dhcpv6_iana.nx_T2)
6246 {
6247
6248 /* Reject the server DHCPv6 response. */
6249 return NX_DHCPV6_INVALID_IANA_TIME;
6250 }
6251
6252 /* Check if we're at the end of option data yet. */
6253 if (index == option_length)
6254 {
6255
6256 /* Yes, all done. */
6257 return NX_SUCCESS;
6258 }
6259
6260 /* Now we recurse into the options embedded in the IANA option. We do it here
6261 because this is part of the IANA option data length. */
6262 while (index + 4 <= option_length)
6263 {
6264
6265 /* Get the next option code and length. */
6266 status = _nx_dhcpv6_server_utility_get_block_option_length(option_data + index, &iana_option_code, &iana_option_length);
6267
6268 /* Check that the block data is valid. */
6269 if (status != NX_SUCCESS)
6270 {
6271
6272 /* No, return the error status. */
6273 return status;
6274 }
6275
6276 /* Skip IA option code and length. */
6277 index += 4;
6278
6279 /* This is a double check to verify we haven't gone off the end of the packet buffer. */
6280 if (index + iana_option_length > option_length)
6281 {
6282 return (NX_DHCPV6_INVALID_IANA_DATA);
6283 }
6284
6285 /* Check if this is an IA address option request, and if we have already
6286 processed an IA in this message (the DHCPv6 server is limited to
6287 one IA per client message). */
6288 if (iana_option_code == NX_DHCPV6_OP_IA_ADDRESS)
6289 {
6290
6291 /* Yes it is, so process it. */
6292 status = _nx_dhcpv6_server_process_ia(dhcpv6_client_ptr, iana_option_code, iana_option_length, (option_data + index), process_ia_option);
6293
6294 /* Check for errors processing the DHCPv6 message. */
6295 if (status != NX_SUCCESS)
6296 {
6297
6298 /* Abort further processing. Return error status. */
6299 return status;
6300 }
6301
6302 /* Indicate we already have an IA option if the client request contains multiple IAs. */
6303 process_ia_option = NX_FALSE;
6304 }
6305
6306 /* Keep track of how far into the packet we have parsed. */
6307 index += iana_option_length;
6308 }
6309
6310 /* Check if we went past the reported size of IA-NA data. */
6311 if (index != option_length)
6312 {
6313
6314 /* Yes return an error status. */
6315 return NX_DHCPV6_INVALID_IANA_DATA;
6316 }
6317
6318 return NX_SUCCESS;
6319 }
6320
6321
6322 /**************************************************************************/
6323 /* */
6324 /* FUNCTION RELEASE */
6325 /* */
6326 /* _nx_dhcpv6_process_option_request PORTABLE C */
6327 /* 6.1 */
6328 /* AUTHOR */
6329 /* */
6330 /* Yuxin Zhou, Microsoft Corporation */
6331 /* */
6332 /* DESCRIPTION */
6333 /* */
6334 /* This function extracts the option request from the client packet. */
6335 /* */
6336 /* INPUT */
6337 /* */
6338 /* dhcpv6_client_ptr Pointer to DHCPV6 client instance */
6339 /* option_code Option code */
6340 /* option_length Size of option data */
6341 /* option_data Pointer to option data */
6342 /* */
6343 /* OUTPUT */
6344 /* */
6345 /* NX_SUCCESS Successful completion status */
6346 /* */
6347 /* CALLS */
6348 /* */
6349 /* _nx_dhcpv6_server_utility_get_data */
6350 /* Parses data from specified buffer */
6351 /* */
6352 /* CALLED BY */
6353 /* */
6354 /* _nx_dhcpv6_server_extract_packet_information */
6355 /* Extracts DHCPv6 data from packet */
6356 /* */
6357 /* RELEASE HISTORY */
6358 /* */
6359 /* DATE NAME DESCRIPTION */
6360 /* */
6361 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6362 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6363 /* packet length verification, */
6364 /* resulting in version 6.1 */
6365 /* */
6366 /**************************************************************************/
_nx_dhcpv6_process_option_request(NX_DHCPV6_CLIENT * dhcpv6_client_ptr,ULONG option_code,UINT option_length,UCHAR * option_data)6367 UINT _nx_dhcpv6_process_option_request(NX_DHCPV6_CLIENT *dhcpv6_client_ptr, ULONG option_code, UINT option_length, UCHAR *option_data)
6368 {
6369
6370 ULONG data;
6371 UINT i = 0;
6372 UINT index = 0;
6373
6374
6375 /* Set option code and length. */
6376 dhcpv6_client_ptr -> nx_dhcpv6_option_request.nx_op_code = (USHORT)option_code;
6377 dhcpv6_client_ptr -> nx_dhcpv6_option_request.nx_option_length = (USHORT)option_length;
6378
6379 /* Loop to process requested option. */
6380 while ((index + 2 <= option_length) && (i < NX_DHCPV6_MAX_OPTION_REQUEST_OPTIONS))
6381 {
6382
6383 /* Extract the option request which should be the next 2 bytes. */
6384 _nx_dhcpv6_server_utility_get_data(option_data + index, 2, &data);
6385
6386 dhcpv6_client_ptr -> nx_dhcpv6_option_request.nx_op_request[i] = (USHORT)data;
6387
6388 /* Update all the length and index counters.*/
6389 index += 2;
6390 i++;
6391 }
6392
6393 return NX_SUCCESS;
6394 }
6395
6396
6397 /**************************************************************************/
6398 /* */
6399 /* FUNCTION RELEASE */
6400 /* */
6401 /* _nx_dhcpv6_process_elapsed_time PORTABLE C */
6402 /* 6.1 */
6403 /* AUTHOR */
6404 /* */
6405 /* Yuxin Zhou, Microsoft Corporation */
6406 /* */
6407 /* DESCRIPTION */
6408 /* */
6409 /* This function extracts the elapsed time option in the client packet.*/
6410 /* */
6411 /* INPUT */
6412 /* */
6413 /* dhcpv6_client_ptr Pointer to DHCPV6 client instance */
6414 /* option_code Option code */
6415 /* option_length Size of option data */
6416 /* option_data Pointer to option data */
6417 /* */
6418 /* OUTPUT */
6419 /* */
6420 /* NX_SUCCESS Successful completion status */
6421 /* NX_DHCPV6_INVALID_OPTION_DATA Elapsed time is missing data */
6422 /* CALLS */
6423 /* */
6424 /* _nx_dhcpv6_server_utility_get_data */
6425 /* Parses data from specified buffer */
6426 /* */
6427 /* CALLED BY */
6428 /* */
6429 /* _nx_dhcpv6_server_extract_packet_information */
6430 /* Extracts DHCPv6 data from packet */
6431 /* */
6432 /* RELEASE HISTORY */
6433 /* */
6434 /* DATE NAME DESCRIPTION */
6435 /* */
6436 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6437 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6438 /* packet length verification, */
6439 /* resulting in version 6.1 */
6440 /* */
6441 /**************************************************************************/
_nx_dhcpv6_process_elapsed_time(NX_DHCPV6_CLIENT * dhcpv6_client_ptr,ULONG option_code,UINT option_length,UCHAR * option_data)6442 UINT _nx_dhcpv6_process_elapsed_time(NX_DHCPV6_CLIENT *dhcpv6_client_ptr, ULONG option_code, UINT option_length, UCHAR *option_data)
6443 {
6444
6445 ULONG data;
6446
6447
6448 /* Set option code and length. */
6449 dhcpv6_client_ptr -> nx_dhcpv6_elapsed_time.nx_op_code = (USHORT)option_code;
6450 dhcpv6_client_ptr -> nx_dhcpv6_elapsed_time.nx_option_length = (USHORT)option_length;
6451
6452 /* Check option length for elapsed-time. */
6453 if (option_length != 2)
6454 {
6455 return(NX_DHCPV6_INVALID_OPTION_DATA);
6456 }
6457
6458 /* Extract the elapsed session time which should be the next 2 bytes. */
6459 _nx_dhcpv6_server_utility_get_data(option_data, 2, &data);
6460 dhcpv6_client_ptr -> nx_dhcpv6_elapsed_time.nx_session_time = (USHORT)data;
6461
6462 return NX_SUCCESS;
6463 }
6464
6465
6466 /**************************************************************************/
6467 /* */
6468 /* FUNCTION RELEASE */
6469 /* */
6470 /* _nx_dhcpv6_server_process_ia PORTABLE C */
6471 /* 6.3.0 */
6472 /* AUTHOR */
6473 /* */
6474 /* Yuxin Zhou, Microsoft Corporation */
6475 /* */
6476 /* DESCRIPTION */
6477 /* */
6478 /* This function extracts the IA address option from the client packet.*/
6479 /* */
6480 /* INPUT */
6481 /* */
6482 /* dhcpv6_client_ptr Pointer to DHCPV6 Client instance */
6483 /* option_code Option code */
6484 /* option_length Size of option data */
6485 /* option_data Pointer to option data */
6486 /* process_ia If true, write IA to client record*/
6487 /* */
6488 /* OUTPUT */
6489 /* */
6490 /* NX_SUCCESS Successful completion status */
6491 /* NX_DHCPV6_INVALID_IA_DATA IA option is missing data or */
6492 /* improperly formatted */
6493 /* NX_DHCPV6_INVALID_IA_TIME IA option lifetime data is invalid*/
6494 /* */
6495 /* CALLS */
6496 /* */
6497 /* _nx_dhcpv6_server_utility_get_data */
6498 /* Extract bytes from a DHCPv6 packet*/
6499 /* */
6500 /* CALLED BY */
6501 /* */
6502 /* _nx_dhcpv6_server_process_iana Processes IANA in client request */
6503 /* */
6504 /* RELEASE HISTORY */
6505 /* */
6506 /* DATE NAME DESCRIPTION */
6507 /* */
6508 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6509 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6510 /* packet length verification, */
6511 /* resulting in version 6.1 */
6512 /* 10-31-2023 Haiqing Zhao Modified comment(s), and */
6513 /* improved to ignore valid */
6514 /* lifetime and preferred life */
6515 /* time in client message, */
6516 /* resulting in version 6.3.0 */
6517 /* */
6518 /**************************************************************************/
_nx_dhcpv6_server_process_ia(NX_DHCPV6_CLIENT * dhcpv6_client_ptr,ULONG option_code,UINT option_length,UCHAR * option_data,UINT process_ia)6519 UINT _nx_dhcpv6_server_process_ia(NX_DHCPV6_CLIENT *dhcpv6_client_ptr, ULONG option_code, UINT option_length, UCHAR *option_data, UINT process_ia)
6520 {
6521
6522 UINT k;
6523 ULONG data;
6524
6525
6526 /* Fill in the IA address code and length. Client might already have one on
6527 record, but use the server's data instead. */
6528 if (process_ia)
6529 {
6530 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code = (USHORT)option_code;
6531 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_option_length = (USHORT)option_length;
6532 }
6533
6534 /* Check option length for Ipv6 address (16 bytes), preferred-lifetime (4 bytes) and valid-lifetime (4 bytes). */
6535 if (option_length != 24)
6536 {
6537 return(NX_DHCPV6_INVALID_IA_DATA);
6538 }
6539
6540 /* Process IPv6 address. */
6541 for (k = 0; k < 4; k++)
6542 {
6543
6544 /* Copy each IPv6 address word into the IA address. */
6545 _nx_dhcpv6_server_utility_get_data(option_data + (k * 4), sizeof(ULONG), &data);
6546
6547 if (process_ia)
6548 {
6549 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[k] = data;
6550 }
6551 }
6552
6553 /* Skip 4 bytes preferred lifetime data and 4 bytes valid lifetime data from the client buffer to IA.
6554 This is because in RFC 8415, page 105, it requires that the server MUST ignore any received
6555 preferred-lifetime and valid-lifetime values in a message sent by a client to a server. */
6556
6557 return(NX_SUCCESS);
6558 }
6559
6560
6561 /**************************************************************************/
6562 /* */
6563 /* FUNCTION RELEASE */
6564 /* */
6565 /* _nx_dhcpv6_process_duid PORTABLE C */
6566 /* 6.1 */
6567 /* AUTHOR */
6568 /* */
6569 /* Yuxin Zhou, Microsoft Corporation */
6570 /* */
6571 /* DESCRIPTION */
6572 /* */
6573 /* This function extracts the DUID from the client packet. */
6574 /* */
6575 /* INPUT */
6576 /* */
6577 /* duid_ptr Pointer to DHCPV6 DUID instance */
6578 /* option_code Option code */
6579 /* option_length Size of option data */
6580 /* option_data Pointer to option data */
6581 /* */
6582 /* OUTPUT */
6583 /* */
6584 /* NX_SUCCESS Successful completion status */
6585 /* NX_DHCPV6_INVALID_DUID DUID is missing data or does not */
6586 /* match the DUID on record */
6587 /* CALLS */
6588 /* */
6589 /* _nx_dhcpv6_server_utility_get_data */
6590 /* Parses data from specified buffer */
6591 /* */
6592 /* CALLED BY */
6593 /* */
6594 /* _nx_dhcpv6_server_extract_packet_information */
6595 /* Extracts DHCPv6 data from packet */
6596 /* */
6597 /* RELEASE HISTORY */
6598 /* */
6599 /* DATE NAME DESCRIPTION */
6600 /* */
6601 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6602 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6603 /* packet length verification, */
6604 /* corrected the logic of */
6605 /* processing DUID type, */
6606 /* resulting in version 6.1 */
6607 /* */
6608 /**************************************************************************/
_nx_dhcpv6_process_duid(NX_DHCPV6_SVR_DUID * duid_ptr,ULONG option_code,UINT option_length,UCHAR * option_data)6609 UINT _nx_dhcpv6_process_duid(NX_DHCPV6_SVR_DUID *duid_ptr, ULONG option_code, UINT option_length, UCHAR *option_data)
6610 {
6611
6612 ULONG data;
6613 UINT index = 0;
6614
6615 NX_PARAMETER_NOT_USED(option_code);
6616
6617 /* Check option length for DUID type. */
6618 if (option_length < 2)
6619 {
6620 return(NX_DHCPV6_INVALID_OPTION_DATA);
6621 }
6622
6623 /* Extract the DUID type which should be the next 2 bytes. */
6624 _nx_dhcpv6_server_utility_get_data(option_data + index, 2, &data);
6625 duid_ptr -> nx_duid_type = (USHORT)data;
6626 index += 2;
6627
6628 /* Check the duid type. */
6629 if ((duid_ptr -> nx_duid_type < NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME) ||
6630 (duid_ptr -> nx_duid_type > NX_DHCPV6_SERVER_DUID_TYPE_LINK_ONLY))
6631 {
6632 return(NX_DHCPV6_INVALID_DUID);
6633 }
6634
6635 /* Check if it is a link layer duid. */
6636 if ((duid_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME) ||
6637 (duid_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_ONLY))
6638 {
6639
6640 /* Check option length for hardware type. */
6641 if (index + 2 > option_length)
6642 {
6643 return(NX_DHCPV6_INVALID_OPTION_DATA);
6644 }
6645
6646 /* Extract the hardware type which should be the next 2 bytes. */
6647 _nx_dhcpv6_server_utility_get_data(option_data + index, 2, &data);
6648 duid_ptr -> nx_hardware_type = (USHORT)data;
6649 index += 2;
6650
6651 /* IS this a link layer plus time DUID type? */
6652 if (duid_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
6653 {
6654
6655 /* Check option length for time. */
6656 if (index + 4 > option_length)
6657 {
6658 return(NX_DHCPV6_INVALID_OPTION_DATA);
6659 }
6660
6661 /* Yes; Extract the time which should be the next 4 bytes. */
6662 _nx_dhcpv6_server_utility_get_data(option_data + index, 4, &data);
6663 duid_ptr -> nx_duid_time = data;
6664 index += 4;
6665 }
6666
6667 /* Check option length mac address. */
6668 if (index + 6 > option_length)
6669 {
6670 return(NX_DHCPV6_INVALID_OPTION_DATA);
6671 }
6672
6673 /* Extract the link local address msw which should be the next 2 bytes. */
6674 _nx_dhcpv6_server_utility_get_data(option_data + index, 2, &data);
6675 duid_ptr -> nx_link_layer_address_msw = (USHORT)data;
6676 index += 2;
6677
6678 /* Extract the link local address lsw which should be the next 4 bytes. */
6679 _nx_dhcpv6_server_utility_get_data(option_data + index, 4, &data);
6680 duid_ptr -> nx_link_layer_address_lsw = data;
6681 index += 4;
6682 }
6683 else
6684 {
6685
6686 /* DUID Assigned by Vendor Based on Enterprise Number. */
6687
6688 /* Check option length for enterprise-number. */
6689 if (index + 4 > option_length)
6690 {
6691 return(NX_DHCPV6_INVALID_DUID);
6692 }
6693
6694 /* Extract the enterprise-number which should be the next 4 bytes. */
6695 _nx_dhcpv6_server_utility_get_data(option_data + index, 4, &data);
6696 duid_ptr -> nx_duid_enterprise_number = data;
6697 index += 4;
6698
6699 /* Check the size of identifier. */
6700 if (option_length - 6 <= NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_LENGTH)
6701 {
6702
6703 /* Set the identifier. */
6704 memcpy(duid_ptr -> nx_duid_private_identifier, option_data + index, option_length - 6); /* Use case of memcpy is verified. */
6705 index = option_length;
6706 }
6707 else
6708 {
6709 return(NX_DHCPV6_INVALID_DUID);
6710 }
6711 }
6712
6713 /* Are we past the end of the buffer, subtracting for the toplevel opcode and
6714 length of the IANA option? */
6715 if (index != option_length)
6716 {
6717
6718 /* Yes, return the error status to reject this packet. */
6719 return NX_DHCPV6_INVALID_OPTION_DATA;
6720 }
6721
6722 return NX_SUCCESS;
6723 }
6724
6725
6726 /**************************************************************************/
6727 /* */
6728 /* FUNCTION RELEASE */
6729 /* */
6730 /* _nx_dhcpv6_check_duids_same PORTABLE C */
6731 /* 6.1 */
6732 /* AUTHOR */
6733 /* */
6734 /* Yuxin Zhou, Microsoft Corporation */
6735 /* */
6736 /* DESCRIPTION */
6737 /* */
6738 /* This function compares the two input DUIDs to match field by field. */
6739 /* if they match, the match status is returned NX_TRUE. */
6740 /* */
6741 /* INPUT */
6742 /* */
6743 /* dhcpv6_duid1_ptr Pointer to first DHCPV6 DUID */
6744 /* dhcpv6_duid1_ptr Pointer to 2nd DHCPV6 DUID */
6745 /* matching Flag indicating if DUIDs match */
6746 /* */
6747 /* OUTPUT */
6748 /* */
6749 /* NX_SUCCESS No errors doing comparison */
6750 /* NX_PTR_ERROR Invalid pointer input */
6751 /* */
6752 /* CALLS */
6753 /* */
6754 /* tx_mutex_get Get server protection mutex */
6755 /* tx_mutex_put Release server protection mutex*/
6756 /* */
6757 /* CALLED BY */
6758 /* */
6759 /* _nx_dhcpv6_listen_for_messages Listen for client requests */
6760 /* _nx_dhcpv6_find_client_record_by_chaddr */
6761 /* Find client in server table */
6762 /* */
6763 /* RELEASE HISTORY */
6764 /* */
6765 /* DATE NAME DESCRIPTION */
6766 /* */
6767 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6768 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6769 /* resulting in version 6.1 */
6770 /* */
6771 /**************************************************************************/
_nx_dhcpv6_check_duids_same(NX_DHCPV6_SVR_DUID * dhcpv6_duid1_ptr,NX_DHCPV6_SVR_DUID * dhcpv6_duid2_ptr,UINT * matching)6772 UINT _nx_dhcpv6_check_duids_same(NX_DHCPV6_SVR_DUID *dhcpv6_duid1_ptr, NX_DHCPV6_SVR_DUID *dhcpv6_duid2_ptr, UINT *matching)
6773 {
6774
6775
6776 /* Check for invalid input. */
6777 if (!dhcpv6_duid1_ptr || !dhcpv6_duid2_ptr || !matching)
6778 {
6779
6780 /* Return invalid input. */
6781 return(NX_PTR_ERROR);
6782 }
6783
6784 /* Initialize result to no match. */
6785 *matching = NX_FALSE;
6786
6787 /* CHeck field by field starting with the ones most likely to miss. */
6788 if (dhcpv6_duid1_ptr -> nx_link_layer_address_msw != dhcpv6_duid2_ptr -> nx_link_layer_address_msw)
6789 {
6790 return NX_SUCCESS;
6791 }
6792 else if (dhcpv6_duid1_ptr -> nx_link_layer_address_lsw != dhcpv6_duid2_ptr -> nx_link_layer_address_lsw)
6793 {
6794 return NX_SUCCESS;
6795 }
6796 else if (dhcpv6_duid1_ptr -> nx_duid_type != dhcpv6_duid2_ptr -> nx_duid_type)
6797 {
6798 return NX_SUCCESS;
6799 }
6800 else if (dhcpv6_duid1_ptr -> nx_hardware_type != dhcpv6_duid2_ptr -> nx_hardware_type)
6801 {
6802 return NX_SUCCESS;
6803 }
6804 else if (dhcpv6_duid1_ptr -> nx_op_code != dhcpv6_duid2_ptr -> nx_op_code)
6805 {
6806 return NX_SUCCESS;
6807 }
6808 else if (dhcpv6_duid1_ptr -> nx_option_length != dhcpv6_duid2_ptr -> nx_option_length)
6809 {
6810 return NX_SUCCESS;
6811 }
6812 else if (dhcpv6_duid1_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
6813 {
6814
6815 if (dhcpv6_duid1_ptr -> nx_duid_time != dhcpv6_duid2_ptr -> nx_duid_time)
6816 {
6817 return NX_SUCCESS;
6818 }
6819 }
6820 else if (dhcpv6_duid1_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_VENDOR_ASSIGNED)
6821 {
6822
6823 /* First compare the enterprise ID. */
6824 if (dhcpv6_duid1_ptr -> nx_duid_enterprise_number != dhcpv6_duid2_ptr -> nx_duid_enterprise_number)
6825 {
6826 return NX_SUCCESS;
6827 }
6828
6829 /* Then compare the private ID. */
6830 if (memcmp(dhcpv6_duid1_ptr -> nx_duid_private_identifier, dhcpv6_duid2_ptr -> nx_duid_private_identifier,
6831 dhcpv6_duid1_ptr -> nx_option_length - sizeof(ULONG)))
6832 {
6833
6834 /* No match. */
6835 return NX_SUCCESS;
6836 }
6837 }
6838
6839 /* It's match! */
6840 *matching = NX_TRUE;
6841
6842 return(NX_SUCCESS);
6843 }
6844
6845
6846 /**************************************************************************/
6847 /* */
6848 /* FUNCTION RELEASE */
6849 /* */
6850 /* _nx_dhcpv6_add_duid PORTABLE C */
6851 /* 6.1 */
6852 /* AUTHOR */
6853 /* */
6854 /* Yuxin Zhou, Microsoft Corporation */
6855 /* */
6856 /* DESCRIPTION */
6857 /* */
6858 /* This function adds a DHCPv6 DUID to the server response packet */
6859 /* based on the input DUID and the DUID type (client or server). */
6860 /* */
6861 /* INPUT */
6862 /* */
6863 /* dhcpv6_server_ptr Pointer to DHCPV6 server instance */
6864 /* dhcpv6_duid_ptr Pointer to DHCPV6 DUID instance */
6865 /* buffer Pointer to packet buffer */
6866 /* index Location where to add DUID */
6867 /* duid_type Indicate client or serve DUID */
6868 /* */
6869 /* OUTPUT */
6870 /* */
6871 /* NX_SUCCESS Successful completion status */
6872 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
6873 /* Packet buffer too small for DUID */
6874 /* CALLS */
6875 /* */
6876 /* memset Clears specified area of memory */
6877 /* memcpy Copies specified area of memory */
6878 /* */
6879 /* CALLED BY */
6880 /* */
6881 /* _nx_dhcpv6_send_request Compiles and sends the Server */
6882 /* DHCPv6 response */
6883 /* */
6884 /* RELEASE HISTORY */
6885 /* */
6886 /* DATE NAME DESCRIPTION */
6887 /* */
6888 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6889 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
6890 /* verified memcpy use cases, */
6891 /* resulting in version 6.1 */
6892 /* */
6893 /**************************************************************************/
_nx_dhcpv6_add_duid(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_SVR_DUID * dhcpv6_duid_ptr,UCHAR * buffer_ptr,UINT * index,UINT duid_type)6894 UINT _nx_dhcpv6_add_duid(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_SVR_DUID *dhcpv6_duid_ptr, UCHAR *buffer_ptr, UINT *index, UINT duid_type)
6895 {
6896
6897 ULONG message_word;
6898 UINT available_payload;
6899
6900 NX_PARAMETER_NOT_USED(duid_type);
6901
6902 /* Clear memory to make the message header. */
6903 memset(&message_word, 0, sizeof(ULONG));
6904
6905 /* Compile the header from the DUID. */
6906 message_word = (ULONG)(dhcpv6_duid_ptr -> nx_op_code << 16);
6907 message_word |= (dhcpv6_duid_ptr -> nx_option_length);
6908
6909 /* Compute the available payload in the packet buffer. */
6910 available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size -
6911 NX_IPv6_UDP_PACKET - *index;
6912
6913 /* Check if the DUID will fit in the packet buffer. */
6914 if (available_payload < (UINT)(dhcpv6_duid_ptr -> nx_option_length + 4))
6915 {
6916
6917 /* Hmmm... not enough! Can't do it. */
6918 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
6919 }
6920
6921 /* Adjust for endianness. */
6922 NX_CHANGE_ULONG_ENDIAN(message_word);
6923
6924 /* Copy first half of the DUID option to packet buffer. */
6925 memcpy(buffer_ptr + *index, &message_word, sizeof(UINT)); /* Use case of memcpy is verified. */
6926 *index += (ULONG)sizeof(UINT);
6927
6928 memset(&message_word, 0, sizeof(ULONG));
6929
6930 /* Set up the rest of the Client DUID header. */
6931 message_word = (ULONG)(dhcpv6_duid_ptr -> nx_duid_type << 16);
6932 message_word |= dhcpv6_duid_ptr -> nx_hardware_type;
6933
6934 /* Adjust for endianness. */
6935 NX_CHANGE_ULONG_ENDIAN(message_word);
6936
6937 /* Set up the DUID option. */
6938 memcpy(buffer_ptr + *index, &message_word, sizeof(UINT)); /* Use case of memcpy is verified. */
6939 *index += (ULONG)sizeof(UINT);
6940
6941 /* Adjust for endianness. */
6942 NX_CHANGE_ULONG_ENDIAN(dhcpv6_duid_ptr -> nx_duid_time);
6943 NX_CHANGE_USHORT_ENDIAN(dhcpv6_duid_ptr -> nx_link_layer_address_msw);
6944 NX_CHANGE_ULONG_ENDIAN(dhcpv6_duid_ptr -> nx_link_layer_address_lsw);
6945
6946 /* Include the 'time' field if this is a Link layer time DUID type. */
6947 if (dhcpv6_duid_ptr -> nx_duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
6948 {
6949
6950 memcpy(buffer_ptr + *index, &(dhcpv6_duid_ptr -> nx_duid_time), sizeof(ULONG)); /* Use case of memcpy is verified. */
6951 *index += (ULONG)sizeof(ULONG);
6952 }
6953
6954 /* Copy the rest of the DUID header. */
6955 memcpy(buffer_ptr + *index, &(dhcpv6_duid_ptr -> nx_link_layer_address_msw), sizeof(USHORT)); /* Use case of memcpy is verified. */
6956 *index += (ULONG)sizeof(USHORT);
6957
6958 memcpy(buffer_ptr + *index, &(dhcpv6_duid_ptr -> nx_link_layer_address_lsw), sizeof(ULONG)); /* Use case of memcpy is verified. */
6959 *index += (ULONG)sizeof(ULONG);
6960
6961 /* Swap bytes back to original endianness. */
6962 NX_CHANGE_ULONG_ENDIAN(dhcpv6_duid_ptr -> nx_link_layer_address_lsw);
6963 NX_CHANGE_USHORT_ENDIAN(dhcpv6_duid_ptr -> nx_link_layer_address_msw);
6964 NX_CHANGE_ULONG_ENDIAN(dhcpv6_duid_ptr -> nx_duid_time);
6965
6966 return NX_SUCCESS;
6967 }
6968
6969
6970 /**************************************************************************/
6971 /* */
6972 /* FUNCTION RELEASE */
6973 /* */
6974 /* _nx_dhcpv6_server_add_iana PORTABLE C */
6975 /* 6.1 */
6976 /* AUTHOR */
6977 /* */
6978 /* Yuxin Zhou, Microsoft Corporation */
6979 /* */
6980 /* DESCRIPTION */
6981 /* */
6982 /* This function adds the IANA option to the server response packet */
6983 /* using the Client IANA on record. It will also add any 'nested' */
6984 /* options such as the Client IA(s) and IANA status option. */
6985 /* */
6986 /* INPUT */
6987 /* */
6988 /* dhcpv6_server_ptr Pointer to DHCPV6 server instance */
6989 /* dhcpv6_client_ptr Pointer to DHCPV6 client instance */
6990 /* buffer_ptr Pointer to response packet buffer */
6991 /* index Location into buffer to write data*/
6992 /* */
6993 /* OUTPUT */
6994 /* */
6995 /* status Actual completion status */
6996 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
6997 /* Buffer too small for IANA option */
6998 /* CALLS */
6999 /* */
7000 /* _nx_dhcpv6_add_ia Adds the IA option to buffer */
7001 /* memset Clears specified area of memory */
7002 /* memcpy Copies specified area of memory */
7003 /* */
7004 /* CALLED BY */
7005 /* */
7006 /* _nx_dhcpv6_send_request Sends server DHCPv6 response */
7007 /* */
7008 /* RELEASE HISTORY */
7009 /* */
7010 /* DATE NAME DESCRIPTION */
7011 /* */
7012 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7013 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
7014 /* verified memcpy use cases, */
7015 /* resulting in version 6.1 */
7016 /* */
7017 /**************************************************************************/
_nx_dhcpv6_server_add_iana(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_CLIENT * dhcpv6_client_ptr,UCHAR * buffer_ptr,UINT * index)7018 UINT _nx_dhcpv6_server_add_iana(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr, UCHAR *buffer_ptr, UINT *index)
7019 {
7020
7021 UINT status;
7022 UINT add_ia;
7023 UINT temp;
7024 UINT temp_index;
7025 ULONG message_word;
7026 UINT available_payload;
7027 NX_DHCPV6_SERVER_IA_NA *iana_ptr;
7028
7029
7030 /* Initialize the completion status variable. */
7031 status = NX_SUCCESS;
7032
7033 /* Compute the available payload in the packet buffer. */
7034 available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size -
7035 NX_IPv6_UDP_PACKET - *index;
7036
7037 iana_ptr = &dhcpv6_client_ptr -> nx_dhcpv6_iana;
7038
7039 /* Check if the client IANA will fit in the packet buffer. */
7040 if (available_payload < (UINT)(iana_ptr -> nx_option_length + 4))
7041 {
7042
7043 /* Hmmm... not enough! Can't do it. */
7044 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
7045 }
7046
7047 /* For release or decline messages, or a server status indicating no IP address can be
7048 assigned yet, set the IANA IP lease times to expired. */
7049 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||
7050 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE) ||
7051 (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code != NX_DHCPV6_STATUS_SUCCESS))
7052 {
7053
7054 iana_ptr -> nx_T1 = 0;
7055 iana_ptr -> nx_T2 = 0;
7056
7057 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0;
7058 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = 0;
7059 }
7060
7061 /* Clear memory to make the first word of the IA-NA header. */
7062 memset(&message_word, 0, sizeof(ULONG));
7063
7064 /* Save this location in the buffer. */
7065 temp_index = *index;
7066
7067 /* Write the IANA opcode and data length into one word. */
7068 message_word = (ULONG)((iana_ptr -> nx_op_code) << 16);
7069
7070 /* Reset the IANA length to just the IANA option fields, (not IA or status options). */
7071 iana_ptr -> nx_option_length = 3 * sizeof(ULONG);
7072
7073 message_word |= iana_ptr -> nx_option_length;
7074
7075 /* Adjust for endianness. */
7076 NX_CHANGE_ULONG_ENDIAN(message_word);
7077
7078 /* Copy the word into the packet buffer going to the server. */
7079 memcpy(buffer_ptr + *index, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
7080
7081 /* Update the buffer pointer. */
7082 *index += (ULONG)sizeof(ULONG);
7083
7084 /* Adjust for endianness. */
7085 NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_IA_NA_id);
7086 NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T1);
7087 NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T2);
7088
7089 memcpy(buffer_ptr + *index, &(iana_ptr -> nx_IA_NA_id), sizeof(ULONG)); /* Use case of memcpy is verified. */
7090 *index += (ULONG)sizeof(ULONG);
7091
7092 memcpy(buffer_ptr + *index, &(iana_ptr -> nx_T1), sizeof(ULONG)); /* Use case of memcpy is verified. */
7093 *index += (ULONG)sizeof(ULONG);
7094
7095 memcpy(buffer_ptr + *index, &(iana_ptr -> nx_T2), sizeof(ULONG)); /* Use case of memcpy is verified. */
7096 *index += (ULONG)sizeof(ULONG);
7097
7098 /* Swap bytes back. */
7099 NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_IA_NA_id);
7100 NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T1);
7101 NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T2);
7102
7103 /* Determine if we include an IA address option. This requires a successful IANA status
7104 and applies only if the client is requesting or confirming an address including renew/rebinding one. */
7105 add_ia = NX_FALSE;
7106
7107 /* We include an IA if we intend to assign or confirm an IP address. */
7108 if (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code == NX_DHCPV6_STATUS_SUCCESS)
7109 {
7110 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type >= NX_DHCPV6_MESSAGE_TYPE_SOLICIT) &&
7111 (dhcpv6_client_ptr -> nx_dhcpv6_message_type <= NX_DHCPV6_MESSAGE_TYPE_DECLINE))
7112 {
7113
7114 add_ia = NX_TRUE;
7115 }
7116 }
7117
7118 /* Or if we are confirming the IP address a client is releasing or declining, regardless
7119 if our records show this IP address is bound to this client. Sect 18.2.6-7 RFC 3315. */
7120 if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||
7121 (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE))
7122 {
7123 add_ia = NX_TRUE;
7124 }
7125
7126 if (add_ia)
7127 {
7128
7129 temp = *index;
7130
7131 /* Check for a missing IA option (as in the Solicit message did not have one). */
7132 if (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code == 0)
7133 {
7134
7135 NX_DHCPV6_ADDRESS_LEASE *client_address_lease;
7136
7137 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code = NX_DHCPV6_OP_IA_ADDRESS;
7138
7139 /* Set the length to include option code, lenght (one word), IPv6 address (4 words), and lifetime data (2 words). */
7140 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_option_length = (2 * sizeof(ULONG))+ (4 * sizeof(ULONG));
7141
7142 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = NX_DHCPV6_DEFAULT_PREFERRED_TIME;
7143
7144 dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime= NX_DHCPV6_DEFAULT_VALID_TIME;
7145
7146 /* Find the Client's tentatively assigned address in the Server IP address list. */
7147 _nx_dhcpv6_find_ip_address(dhcpv6_server_ptr, dhcpv6_client_ptr, &client_address_lease);
7148
7149 if ((status != NX_SUCCESS) || (client_address_lease == NX_NULL))
7150 {
7151
7152 return status;
7153 }
7154
7155 COPY_IPV6_ADDRESS(&client_address_lease -> nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0],
7156 &dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]);
7157 }
7158
7159 status = _nx_dhcpv6_add_ia(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_ia, buffer_ptr, &temp);
7160
7161 if (status != NX_SUCCESS)
7162 {
7163
7164 return status;
7165 }
7166
7167
7168 /* Add the size of the IA(s) to the client IANA. Note that we include the option code
7169 and length field of any nested options. */
7170 iana_ptr -> nx_option_length = (USHORT)(iana_ptr -> nx_option_length + dhcpv6_client_ptr-> nx_dhcpv6_ia.nx_option_length + 4);
7171
7172 /* Update the index into packet buffer from our temporary variable. */
7173 *index = temp;
7174 }
7175
7176 /* Update the IANA status message. */
7177 status = _nx_dhcpv6_prepare_iana_status(&dhcpv6_client_ptr -> nx_dhcpv6_iana_status, NX_TRUE);
7178
7179 if (status != NX_SUCCESS)
7180 {
7181
7182 return status;
7183 }
7184
7185 temp = *index;
7186
7187 /* Ok to add one to server reply.*/
7188 status = _nx_dhcpv6_add_iana_status(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_iana_status, buffer_ptr, &temp);
7189
7190 if (status != NX_SUCCESS)
7191 {
7192
7193 return status;
7194 }
7195
7196 /* Update the index into packet buffer from our temporary variable. */
7197 *index = temp;
7198
7199 /* Update the IANA option length with the iana status option size. */
7200 iana_ptr -> nx_option_length = (USHORT)(iana_ptr -> nx_option_length + dhcpv6_client_ptr->nx_dhcpv6_iana_status.nx_option_length + 4);
7201
7202 /* Rewrite the IANA opcode and update the changed IANA data length with the additional IA address option. */
7203 message_word = (ULONG)((iana_ptr -> nx_op_code) << 16);
7204 message_word |= (ULONG)(iana_ptr -> nx_option_length);
7205
7206 /* Adjust for endianness. */
7207 NX_CHANGE_ULONG_ENDIAN(message_word);
7208
7209 /* Copy the updated word into the packet buffer at the saved location. */
7210 memcpy(buffer_ptr + temp_index, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
7211
7212 /* Erase the IANA status message. We will add another message on the next (if any) IANA option for the client. */
7213 status = _nx_dhcpv6_prepare_iana_status(&dhcpv6_client_ptr -> nx_dhcpv6_iana_status, NX_FALSE);
7214
7215 return status;
7216 }
7217
7218
7219 /**************************************************************************/
7220 /* */
7221 /* FUNCTION RELEASE */
7222 /* */
7223 /* _nx_dhcpv6_add_ia PORTABLE C */
7224 /* 6.1 */
7225 /* AUTHOR */
7226 /* */
7227 /* Yuxin Zhou, Microsoft Corporation */
7228 /* */
7229 /* DESCRIPTION */
7230 /* */
7231 /* This function adds the IA address option to the server response */
7232 /* packet using the input IA option. */
7233 /* */
7234 /* INPUT */
7235 /* */
7236 /* dhcpv6_server_ptr Pointer to DHCPV6 server instance */
7237 /* dhcpv6_ia_ptr Pointer to IA to add */
7238 /* buffer_ptr Pointer to response packet buffer */
7239 /* index Location into buffer to write data*/
7240 /* */
7241 /* OUTPUT */
7242 /* */
7243 /* NX_SUCCESS Successful completion status */
7244 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
7245 /* Buffer to small for IA option */
7246 /* CALLS */
7247 /* */
7248 /* memset Clears specified area of memory */
7249 /* memcpy Copies specified area of memory */
7250 /* */
7251 /* CALLED BY */
7252 /* */
7253 /* _nx_dhcpv6_server_add_iana Adds the IANA to server response */
7254 /* */
7255 /* RELEASE HISTORY */
7256 /* */
7257 /* DATE NAME DESCRIPTION */
7258 /* */
7259 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7260 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
7261 /* verified memcpy use cases, */
7262 /* resulting in version 6.1 */
7263 /* */
7264 /**************************************************************************/
_nx_dhcpv6_add_ia(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_SERVER_IA_ADDRESS * dhcpv6_ia_ptr,UCHAR * buffer_ptr,UINT * index)7265 UINT _nx_dhcpv6_add_ia(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_SERVER_IA_ADDRESS *dhcpv6_ia_ptr, UCHAR *buffer_ptr, UINT *index)
7266 {
7267
7268 ULONG message_word;
7269 UINT available_payload;
7270
7271
7272 /* Compute the available payload in the packet buffer. */
7273 available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size -
7274 NX_IPv6_UDP_PACKET - *index;
7275
7276 /* Check if the client IA address option will fit in the packet buffer. */
7277 if (available_payload < (UINT)(dhcpv6_ia_ptr -> nx_option_length + 4))
7278 {
7279
7280 /* Hmmm... not enough! Can't do it. */
7281 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
7282 }
7283
7284 /* If the client has created an address option, apply it to the message. */
7285
7286 /* Clear memory to make the first word of the IA-Address header. */
7287 memset(&message_word, 0, sizeof(ULONG));
7288
7289 /* Compile the header from the IA option on the client record. */
7290 message_word = (ULONG)(dhcpv6_ia_ptr -> nx_op_code << 16);
7291 message_word |= dhcpv6_ia_ptr -> nx_option_length;
7292
7293 /* Adjust for endianness. */
7294 NX_CHANGE_ULONG_ENDIAN(message_word);
7295
7296 /* Copy option header into the packet and update the index into the buffer. */
7297 memcpy(buffer_ptr + *index, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */
7298 *index += (ULONG)sizeof(ULONG);
7299
7300 /* Adjust for endianness. */
7301 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[0]);
7302 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[1]);
7303 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[2]);
7304 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[3]);
7305 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_preferred_lifetime);
7306 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_valid_lifetime);
7307
7308 /* Copy the IPv6 address to the packet. */
7309 memcpy(buffer_ptr + *index, &(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[0]), sizeof(ULONG)); /* Use case of memcpy is verified. */
7310 *index += (ULONG)sizeof(ULONG);
7311
7312 memcpy(buffer_ptr + *index, &(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[1]), sizeof(ULONG)); /* Use case of memcpy is verified. */
7313 *index += (ULONG)sizeof(ULONG);
7314
7315 memcpy(buffer_ptr + *index, &(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[2]), sizeof(ULONG)); /* Use case of memcpy is verified. */
7316 *index += (ULONG)sizeof(ULONG);
7317
7318 memcpy(buffer_ptr + *index, &(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[3]), sizeof(ULONG)); /* Use case of memcpy is verified. */
7319 *index += (ULONG)sizeof(ULONG);
7320
7321 /* Copy the Client's preference for lifetimes to packet. */
7322 memcpy(buffer_ptr + *index, &(dhcpv6_ia_ptr -> nx_preferred_lifetime), sizeof(ULONG)); /* Use case of memcpy is verified. */
7323 *index += (ULONG)sizeof(ULONG);
7324
7325 memcpy(buffer_ptr + *index, &(dhcpv6_ia_ptr -> nx_valid_lifetime), sizeof(ULONG)); /* Use case of memcpy is verified. */
7326 *index += (ULONG)sizeof(ULONG);
7327
7328 /* Swap bytes back. */
7329 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[0]);
7330 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[1]);
7331 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[2]);
7332 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_global_address.nxd_ip_address.v6[3]);
7333 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_preferred_lifetime);
7334 NX_CHANGE_ULONG_ENDIAN(dhcpv6_ia_ptr -> nx_valid_lifetime);
7335
7336 return NX_SUCCESS;
7337 }
7338
7339
7340 /**************************************************************************/
7341 /* */
7342 /* FUNCTION RELEASE */
7343 /* */
7344 /* _nx_dhcpv6_add_iana_status PORTABLE C */
7345 /* 6.1 */
7346 /* AUTHOR */
7347 /* */
7348 /* Yuxin Zhou, Microsoft Corporation */
7349 /* */
7350 /* DESCRIPTION */
7351 /* */
7352 /* This function adds the IANA status option to the server response */
7353 /* packet using the input IANA status option. */
7354 /* */
7355 /* INPUT */
7356 /* */
7357 /* dhcpv6_server_ptr Pointer to DHCPV6 server instance */
7358 /* iana_status_ptr Pointer to IANA status option */
7359 /* buffer_ptr Pointer to response packet buffer */
7360 /* index Location into buffer to write data*/
7361 /* */
7362 /* OUTPUT */
7363 /* */
7364 /* NX_SUCCESS Successful completion status */
7365 /* NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD */
7366 /* Buffer to small for IA option */
7367 /* CALLS */
7368 /* */
7369 /* memset Clears specified area of memory */
7370 /* memcpy Copies specified area of memory */
7371 /* */
7372 /* CALLED BY */
7373 /* */
7374 /* _nx_dhcpv6_server_add_iana Add IANA status to server response*/
7375 /* */
7376 /* RELEASE HISTORY */
7377 /* */
7378 /* DATE NAME DESCRIPTION */
7379 /* */
7380 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7381 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
7382 /* verified memcpy use cases, */
7383 /* resulting in version 6.1 */
7384 /* */
7385 /**************************************************************************/
_nx_dhcpv6_add_iana_status(NX_DHCPV6_SERVER * dhcpv6_server_ptr,NX_DHCPV6_SERVER_IANA_STATUS * iana_status_ptr,UCHAR * buffer_ptr,UINT * index)7386 UINT _nx_dhcpv6_add_iana_status(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_SERVER_IANA_STATUS *iana_status_ptr, UCHAR *buffer_ptr, UINT *index)
7387 {
7388
7389 ULONG message_word;
7390 USHORT message_short;
7391 UINT available_payload;
7392 UINT message_length;
7393
7394
7395 /* Compute the available payload in the packet buffer. */
7396 available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size -
7397 NX_IPv6_UDP_PACKET - *index;
7398
7399 /* Check if the status option will fit in the packet buffer. */
7400 if (available_payload < (UINT)(iana_status_ptr -> nx_option_length + 4))
7401 {
7402
7403 /* Hmmm... not enough! Can't do it. */
7404 return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
7405 }
7406
7407 /* Clear memory to make the message header. */
7408 memset(&message_word, 0, sizeof(ULONG));
7409
7410 /* Compile the header for the status option. */
7411 message_word = (ULONG)(iana_status_ptr -> nx_op_code << 16);
7412 message_word |= (iana_status_ptr -> nx_option_length);
7413
7414 /* Adjust for endianness. */
7415 NX_CHANGE_ULONG_ENDIAN(message_word);
7416
7417 /* Copy the word to packet buffer. */
7418 memcpy(buffer_ptr + *index, &message_word, sizeof(UINT)); /* Use case of memcpy is verified. */
7419 *index += (ULONG)sizeof(UINT);
7420
7421 memset(&message_word, 0, sizeof(ULONG));
7422
7423 /* Set up the status option code. */
7424 message_short = iana_status_ptr -> nx_status_code;
7425
7426 /* Adjust for endianness. */
7427 NX_CHANGE_USHORT_ENDIAN(message_short);
7428
7429 /* Set up the DUID option. */
7430 memcpy(buffer_ptr + *index, &message_short, sizeof(USHORT)); /* Use case of memcpy is verified. */
7431 *index += (ULONG)sizeof(USHORT);
7432
7433 message_length = iana_status_ptr -> nx_option_length - (ULONG)(sizeof(USHORT));
7434 memcpy(buffer_ptr + *index, &iana_status_ptr -> nx_status_message[0], message_length); /* Use case of memcpy is verified. */
7435
7436 *index += message_length;
7437
7438 /* No need to swap the last byte. */
7439 return NX_SUCCESS;
7440 }
7441 #endif /* FEATURE_NX_IPV6 */
7442