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