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