1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Component                                                        */
16 /**                                                                       */
17 /**   Dynamic Host Configuration Protocol (DHCP) Server                   */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_DHCP_SERVER_SOURCE_CODE
23 
24 
25 /* Force error checking to be disabled in this module */
26 
27 #ifndef NX_DISABLE_ERROR_CHECKING
28 #define NX_DISABLE_ERROR_CHECKING
29 #endif
30 
31 /* Include necessary system files.  */
32 
33 #include    "nx_api.h"
34 #ifndef NX_DISABLE_IPV4
35 #include    "nx_ip.h"
36 #include    "nx_udp.h"
37 #include    "nxd_dhcp_server.h"
38 #include    "tx_timer.h"
39 #include    "nx_packet.h"
40 #include    "nx_system.h"
41 
42 /* Bring in externs for caller checking code.  */
43 
44 NX_CALLER_CHECKING_EXTERNS
45 
46 #ifdef EL_PRINTF_ENABLE
47 #define EL_PRINTF      printf
48 #endif
49 
50 /* Define the DHCP Internal Function.  */
51 static VOID        _nx_dhcp_server_thread_entry(ULONG ip_instance);
52 static VOID        _nx_dhcp_slow_periodic_timer_entry(ULONG info);
53 static VOID        _nx_dhcp_fast_periodic_timer_entry(ULONG info);
54 static UINT        _nx_dhcp_server_packet_process(NX_DHCP_SERVER *dhcp_ptr, NX_PACKET *packet_ptr);
55 static UINT        _nx_dhcp_respond_to_client_message(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr);
56 static UINT        _nx_dhcp_server_extract_information(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT **dhcp_client_ptr, NX_PACKET *packet_ptr, UINT iface_index);
57 static UINT        _nx_dhcp_process_option_data(NX_DHCP_CLIENT *dhcp_ptr, CHAR *buffer, UCHAR value, UINT get_option_data, UINT size);
58 static UINT        _nx_dhcp_add_option(UCHAR *bootp_message, UINT option, UINT size, ULONG value, UINT *index);
59 static UINT        _nx_dhcp_add_requested_option(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index, UCHAR *buffer, UINT option, UINT *index);
60 static UINT        _nx_dhcp_set_server_options(NX_DHCP_SERVER *dhcp_ptr, CHAR *buffer, UINT buffer_length);
61 static UINT        _nx_dhcp_load_server_options(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr, UCHAR *buffer, UINT option_type, UINT *index);
62 static UINT        _nx_dhcp_parse_next_option(CHAR **buffer, UINT *digit, UINT length);
63 static UINT        _nx_dhcp_server_get_data(UCHAR *data, UINT size, ULONG *value);
64 static VOID        _nx_dhcp_server_store_data(UCHAR *data, UINT size, ULONG value);
65 static UINT        _nx_dhcp_clear_client_session(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr);
66 static UINT        _nx_dhcp_validate_client_message(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr);
67 static UINT        _nx_dhcp_find_client_record_by_chaddr(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index, ULONG client_mac_msw, ULONG client_mac_lsw,NX_DHCP_CLIENT **dhcp_client_ptr, UINT add_on);
68 static UINT        _nx_dhcp_find_client_record_by_ip_address(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT **dhcp_client_ptr, UINT iface_index, ULONG assigned_ip_address);
69 static UINT        _nx_dhcp_server_assign_ip_address(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr);
70 static UINT        _nx_dhcp_find_interface_table_ip_address(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index, ULONG ip_address, NX_DHCP_INTERFACE_IP_ADDRESS **return_interface_address);
71 static UINT        _nx_dhcp_update_assignable_ip_address(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr, ULONG ip_address, UINT assign_status);
72 static UINT        _nx_dhcp_find_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS *iface_owner, NX_DHCP_CLIENT *client_record_ptr, UINT *assigned_to_client);
73 static UINT        _nx_dhcp_record_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS *iface_owner, NX_DHCP_CLIENT *client_record_ptr, UINT lease_time);
74 static UINT        _nx_dhcp_clear_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS *iface_owner);
75 static VOID        _nx_dhcp_server_socket_receive_notify(NX_UDP_SOCKET *socket_ptr);
76 
77 
78 /* To enable dhcp server output, define TESTOUTPUT. */
79 /* #define     TESTOUTPUT          1  */
80 
81 /* To enable packet dump, define PACKET_DUMP. */
82 /* #define     PACKET_DUMP         1  */
83 
84 #ifdef      TESTOUTPUT
85 
86 static int  add_client = 0;
87 
88 /* Define how often to print the server table of current clients.
89    For no output set to zero.  For low volume, set to 1;
90    for very high volume, set higher so as not to overwelm the processor. */
91 
92 #define     TRACE_NTH_CLIENT_PACKET    1
93 
94 #endif
95 
96 
97 /**************************************************************************/
98 /*                                                                        */
99 /*  FUNCTION                                               RELEASE        */
100 /*                                                                        */
101 /*    _nxe_dhcp_server_create                             PORTABLE C      */
102 /*                                                           6.1          */
103 /*  AUTHOR                                                                */
104 /*                                                                        */
105 /*    Yuxin Zhou, Microsoft Corporation                                   */
106 /*                                                                        */
107 /*  DESCRIPTION                                                           */
108 /*                                                                        */
109 /*    This function checks for errors in the DHCP create function call.   */
110 /*                                                                        */
111 /*  INPUT                                                                 */
112 /*                                                                        */
113 /*    dhcp_ptr                              Pointer to DHCP Server        */
114 /*    ip_ptr                                Pointer to IP instance        */
115 /*    stack_ptr                             Pointer to free memory        */
116 /*    stack_size                            Size of DHCP server stack     */
117 /*    name_ptr                              DHCP name pointer             */
118 /*    packet_pool                           Server packet pool for sending*/
119 /*                                                                        */
120 /*  OUTPUT                                                                */
121 /*                                                                        */
122 /*    status                                Completion status             */
123 /*                                                                        */
124 /*  CALLS                                                                 */
125 /*                                                                        */
126 /*    _nx_dhcp_server_create                Actual DHCP create function   */
127 /*                                                                        */
128 /*  CALLED BY                                                             */
129 /*                                                                        */
130 /*    Application Code                                                    */
131 /*                                                                        */
132 /*  RELEASE HISTORY                                                       */
133 /*                                                                        */
134 /*    DATE              NAME                      DESCRIPTION             */
135 /*                                                                        */
136 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
137 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
138 /*                                            resulting in version 6.1    */
139 /*                                                                        */
140 /**************************************************************************/
141 
_nxe_dhcp_server_create(NX_DHCP_SERVER * dhcp_ptr,NX_IP * ip_ptr,VOID * stack_ptr,ULONG stack_size,CHAR * name_ptr,NX_PACKET_POOL * packet_pool)142 UINT  _nxe_dhcp_server_create(NX_DHCP_SERVER *dhcp_ptr, NX_IP *ip_ptr, VOID *stack_ptr, ULONG stack_size,
143                               CHAR *name_ptr, NX_PACKET_POOL *packet_pool)
144 {
145 
146 UINT    status;
147 
148 
149     /* Check for pointer invalid input.  */
150     if ((dhcp_ptr == NX_NULL) || (packet_pool == NX_NULL) ||(stack_ptr == NX_NULL) ||(ip_ptr == NX_NULL))
151     {
152         return(NX_PTR_ERROR);
153     }
154 
155     if (stack_size == 0)
156     {
157         return(NX_DHCP_PARAMETER_ERROR);
158     }
159 
160     /* Check for appropriate caller.  */
161     NX_INIT_AND_THREADS_CALLER_CHECKING
162 
163     /* Call actual DHCP create service.  */
164     status =  _nx_dhcp_server_create(dhcp_ptr, ip_ptr, stack_ptr, stack_size, name_ptr, packet_pool);
165 
166     /* Return status.  */
167     return(status);
168 }
169 
170 
171 /**************************************************************************/
172 /*                                                                        */
173 /*  FUNCTION                                               RELEASE        */
174 /*                                                                        */
175 /*    _nx_dhcp_server_create                              PORTABLE C      */
176 /*                                                           6.1          */
177 /*  AUTHOR                                                                */
178 /*                                                                        */
179 /*    Yuxin Zhou, Microsoft Corporation                                   */
180 /*                                                                        */
181 /*  DESCRIPTION                                                           */
182 /*                                                                        */
183 /*    This function initializes the DHCP Server with necessary components.*/
184 /*    It creates a packet pool for sending Server DHCP messages and a     */
185 /*    thread task for the DHCP server operation. It also sets the standard*/
186 /*    DHCP options (e.g. lease time etc) for granting IP addresses.       */
187 /*                                                                        */
188 /*  INPUT                                                                 */
189 /*                                                                        */
190 /*    dhcp_ptr                              Pointer to DHCP Server        */
191 /*    ip_ptr                                Pointer to IP instance        */
192 /*    stack_ptr                             Pointer to server thread on   */
193 /*                                                    the stack           */
194 /*    stack_size                            Size of DHCP server stack     */
195 /*    name_ptr                              DHCP name pointer             */
196 /*    packet_pool                           Server packet pool for sending*/
197 /*                                            DHCP replies to client      */
198 /*                                                                        */
199 /*  OUTPUT                                                                */
200 /*    NX_SUCCESS                            Successful completion status  */
201 /*    NX_DHCP_INADEQUATE_PACKET_POOL_PAYLOAD                              */
202 /*                                          Packet payload too small error*/
203 /*    NX_DHCP_NO_SERVER_OPTION_LIST         Missing option list error     */
204 /*                                                                        */
205 /*    status                                Completion status of socket   */
206 /*                                               and thread create calls  */
207 /*                                                                        */
208 /*  CALLS                                                                 */
209 /*                                                                        */
210 /*    nx_udp_socket_create                  Create the DHCP UDP socket    */
211 /*    nx_udp_socket_delete                  Delete the DHCP UDP socket    */
212 /*    tx_thread_create                      Create DHCP processing thread */
213 /*                                                                        */
214 /*  CALLED BY                                                             */
215 /*                                                                        */
216 /*    Application Code                                                    */
217 /*                                                                        */
218 /*  RELEASE HISTORY                                                       */
219 /*                                                                        */
220 /*    DATE              NAME                      DESCRIPTION             */
221 /*                                                                        */
222 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
223 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
224 /*                                            buffer length verification, */
225 /*                                            resulting in version 6.1    */
226 /*                                                                        */
227 /**************************************************************************/
_nx_dhcp_server_create(NX_DHCP_SERVER * dhcp_ptr,NX_IP * ip_ptr,VOID * stack_ptr,ULONG stack_size,CHAR * name_ptr,NX_PACKET_POOL * packet_pool_ptr)228 UINT  _nx_dhcp_server_create(NX_DHCP_SERVER *dhcp_ptr, NX_IP *ip_ptr, VOID *stack_ptr, ULONG stack_size,
229                              CHAR *name_ptr, NX_PACKET_POOL *packet_pool_ptr)
230 {
231 
232 UINT  status;
233 UINT  timer_ticks;
234 UINT  i, j;
235 
236 
237     /* Initialize the DHCP control block to zero.  */
238     memset((void *) dhcp_ptr, 0, sizeof(NX_DHCP_SERVER));
239 
240     /* Check the Server packet pool is at least large enough for a full sized DHCP message as per
241        RFC 2131, plus header data. */
242     if (packet_pool_ptr -> nx_packet_pool_payload_size < NX_DHCP_MINIMUM_PACKET_PAYLOAD)
243     {
244 
245         /* Return the error status. */
246         return(NX_DHCP_INADEQUATE_PACKET_POOL_PAYLOAD);
247     }
248 
249     /* Set the packet pool pointer.  */
250     dhcp_ptr -> nx_dhcp_packet_pool_ptr = packet_pool_ptr;
251 
252     /* Save the DHCP name.  */
253     dhcp_ptr -> nx_dhcp_name = name_ptr;
254 
255     /* Set the DHCP Server attributes.  */
256     dhcp_ptr -> nx_dhcp_ip_ptr = ip_ptr;
257 
258     /* Loop through all the interface tables and clear table memory. */
259     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
260     {
261 
262         /* Clear all the table's IP address entries. */
263         for (j = 0; j < NX_DHCP_IP_ADDRESS_MAX_LIST_SIZE; j++)
264         {
265 
266             memset(&dhcp_ptr -> nx_dhcp_interface_table[i].nx_dhcp_ip_address_list[j],
267                    0, sizeof(NX_DHCP_INTERFACE_IP_ADDRESS));
268         }
269 
270         /* Clear the DHCP interface itself. */
271         memset(&dhcp_ptr -> nx_dhcp_interface_table[i], 0, sizeof(NX_DHCP_INTERFACE_TABLE));
272     }
273 
274     /* Loop through the entire client record table. */
275     for (i = 0; i < NX_DHCP_CLIENT_RECORD_TABLE_SIZE; i++)
276     {
277 
278         /* Clear the client record. */
279         memset(&dhcp_ptr -> client_records[i], 0, sizeof(NX_DHCP_CLIENT));
280     }
281 
282     /* Verify the application has defined a server option list. */
283     if (sizeof(NX_DHCP_SERVER_OPTION_LIST) == 1)
284     {
285 
286         /* No, return the error status. */
287         return(NX_DHCP_NO_SERVER_OPTION_LIST);
288     }
289 
290     /* Create the list of DHCP options the server can provide for the client. */
291     status = _nx_dhcp_set_server_options(dhcp_ptr, (CHAR *)NX_DHCP_SERVER_OPTION_LIST, sizeof(NX_DHCP_SERVER_OPTION_LIST) - 1);
292 
293     /* Was the option list set successful?  */
294     if (status != NX_SUCCESS)
295     {
296 
297         /* No, return error status.  */
298         return(status);
299     }
300 
301     /* Update the dhcp structure ID.  */
302     dhcp_ptr -> nx_dhcp_id =  NX_DHCP_SERVER_ID;
303 
304     /* Create the Socket and check the status */
305     status = nx_udp_socket_create(ip_ptr, &(dhcp_ptr -> nx_dhcp_socket), "NetX DHCP Server Socket",
306                        NX_DHCP_TYPE_OF_SERVICE, NX_DHCP_FRAGMENT_OPTION, NX_DHCP_TIME_TO_LIVE, NX_DHCP_QUEUE_DEPTH);
307 
308     /* Was the socket creation successful?  */
309     if (status != NX_SUCCESS)
310     {
311 
312         /* No, return error status.  */
313         return(status);
314     }
315 
316     /* Save the DHCP instance pointer in the socket. */
317     dhcp_ptr -> nx_dhcp_socket.nx_udp_socket_reserved_ptr =  (void *) dhcp_ptr;
318 
319     /* Set the DHCP request handler for packets received on the DHCP server socket. */
320     status = nx_udp_socket_receive_notify(&(dhcp_ptr -> nx_dhcp_socket), _nx_dhcp_server_socket_receive_notify);
321 
322     /* Was the socket receive_notify set successful?  */
323     if (status != NX_SUCCESS)
324     {
325 
326         /* Delete the UDP socket.  */
327         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
328 
329         /* No, return error status.  */
330         return status;
331     }
332 
333     /* Create the DHCP processing thread.  */
334     status =  tx_thread_create(&(dhcp_ptr -> nx_dhcp_server_thread), "NetX DHCP Server Thread",
335                                _nx_dhcp_server_thread_entry, (ULONG)(ALIGN_TYPE)dhcp_ptr,
336                                stack_ptr, stack_size, NX_DHCP_SERVER_THREAD_PRIORITY,
337                                NX_DHCP_SERVER_THREAD_PRIORITY, 1, TX_DONT_START);
338 
339     NX_THREAD_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_server_thread), dhcp_ptr)
340 
341     /* Determine if the thread creation was successful.  */
342     if (status != NX_SUCCESS)
343     {
344 
345         /* Delete the UDP socket.  */
346         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
347 
348         /* No, return error status.  */
349         return(status);
350     }
351 
352     /* Create the DHCP mutex.  */
353     status = tx_mutex_create(&dhcp_ptr -> nx_dhcp_mutex, "DHCP Server Mutex", TX_NO_INHERIT);
354 
355     /* Determine if the thread creation was successful.  */
356     if (status != NX_SUCCESS)
357     {
358 
359         /* Delete the UDP socket.  */
360         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
361 
362         /* Delete DHCP thead.  */
363         tx_thread_delete(&(dhcp_ptr -> nx_dhcp_server_thread));
364 
365         /* No, return error status.  */
366         return(status);
367     }
368 
369     /* Convert seconds to timer ticks. */
370     timer_ticks = NX_DHCP_SLOW_PERIODIC_TIME_INTERVAL * NX_IP_PERIODIC_RATE;
371 
372     /* Create the timer for Client DHCP session. This will keep track of when leases expire
373        and when a client session has timed out. */
374     status = tx_timer_create(&(dhcp_ptr -> nx_dhcp_slow_periodic_timer), "DHCP Server IP Lease Timer",
375                              _nx_dhcp_slow_periodic_timer_entry, (ULONG)(ALIGN_TYPE)dhcp_ptr,
376                              timer_ticks, timer_ticks, TX_NO_ACTIVATE);
377 
378     NX_TIMER_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_slow_periodic_timer), dhcp_ptr)
379 
380     /* Convert seconds to timer ticks. */
381     timer_ticks = NX_DHCP_FAST_PERIODIC_TIME_INTERVAL * NX_IP_PERIODIC_RATE;
382 
383     /* Create the timer for Client DHCP session. This will keep track of when leases expire
384        and when a client session has timed out. */
385     status += tx_timer_create(&(dhcp_ptr -> nx_dhcp_fast_periodic_timer), "DHCP Server Session Timer",
386                               _nx_dhcp_fast_periodic_timer_entry, (ULONG)(ALIGN_TYPE)dhcp_ptr,
387                               timer_ticks, timer_ticks, TX_NO_ACTIVATE);
388 
389     NX_TIMER_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_fast_periodic_timer), dhcp_ptr)
390 
391     /* Check for error. */
392     if (status != NX_SUCCESS)
393     {
394 
395         /* Delete the UDP socket.  */
396         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
397 
398         /* Delete DHCP thead.  */
399         tx_thread_delete(&(dhcp_ptr -> nx_dhcp_server_thread));
400 
401         /* Delete ThreadX resources. */
402         tx_mutex_delete(&(dhcp_ptr -> nx_dhcp_mutex));
403 
404         /* Delete DHCP timer.  */
405         tx_timer_delete(&(dhcp_ptr -> nx_dhcp_slow_periodic_timer));
406         tx_timer_delete(&(dhcp_ptr -> nx_dhcp_fast_periodic_timer));
407 
408         /* Return the error status. */
409         return(status);
410     }
411 
412     /* Create the DHCP event flag instance.  */
413     status = tx_event_flags_create(&dhcp_ptr -> nx_dhcp_server_events, "DHCP Server Events");
414 
415     /* Check for error. */
416     if (status != TX_SUCCESS)
417     {
418 
419         /* Delete the UDP socket.  */
420         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
421 
422         /* Delete DHCP thread.  */
423         tx_thread_delete(&(dhcp_ptr -> nx_dhcp_server_thread));
424 
425         /* Delete ThreadX resources. */
426         tx_mutex_delete(&(dhcp_ptr -> nx_dhcp_mutex));
427 
428         /* Delete DHCP Timer.  */
429         tx_timer_delete(&(dhcp_ptr -> nx_dhcp_slow_periodic_timer));
430 
431         tx_timer_delete(&(dhcp_ptr -> nx_dhcp_fast_periodic_timer));
432 
433         /* Return the error status. */
434         return(status);
435     }
436 
437     /* Return a successful status.  */
438     return(NX_SUCCESS);
439 }
440 
441 
442 /**************************************************************************/
443 /*                                                                        */
444 /*  FUNCTION                                               RELEASE        */
445 /*                                                                        */
446 /*    _nx_dhcp_fast_periodic_timer_entry                  PORTABLE C      */
447 /*                                                           6.1          */
448 /*  AUTHOR                                                                */
449 /*                                                                        */
450 /*    Yuxin Zhou, Microsoft Corporation                                   */
451 /*                                                                        */
452 /*  DESCRIPTION                                                           */
453 /*                                                                        */
454 /*    This function watches the session timeout on each active client     */
455 /*    session. WHen it does it clears session data from the client record */
456 /*    and resets the client state to INIT. If a iP address had been       */
457 /*    assigned, it is returned back to the server pool.                   */
458 /*                                                                        */
459 /*  INPUT                                                                 */
460 /*                                                                        */
461 /*    info                                 Generic pointer to DHCP server */
462 /*                                                                        */
463 /*  OUTPUT                                                                */
464 /*                                                                        */
465 /*    None                                                                */
466 /*                                                                        */
467 /*  CALLS                                                                 */
468 /*                                                                        */
469 /*     tx_event_flags_set                   Adds a fast periodic event    */
470 /*                                                                        */
471 /*  CALLED BY                                                             */
472 /*                                                                        */
473 /*    Application code                                                    */
474 /*                                                                        */
475 /*  RELEASE HISTORY                                                       */
476 /*                                                                        */
477 /*    DATE              NAME                      DESCRIPTION             */
478 /*                                                                        */
479 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
480 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
481 /*                                            resulting in version 6.1    */
482 /*                                                                        */
483 /**************************************************************************/
_nx_dhcp_fast_periodic_timer_entry(ULONG info)484 static VOID  _nx_dhcp_fast_periodic_timer_entry(ULONG info)
485 {
486 
487 NX_DHCP_SERVER   *dhcp_ptr;
488 
489 
490     /* Setup DHCP pointer.  */
491     NX_TIMER_EXTENSION_PTR_GET(dhcp_ptr, NX_DHCP_SERVER, info)
492 
493     /* Signal the DHCP Server fast periodic event.  */
494     tx_event_flags_set(&(dhcp_ptr -> nx_dhcp_server_events), NX_DHCP_SERVER_FAST_PERIODIC_EVENT, TX_OR);
495 
496     return;
497 }
498 
499 
500 /**************************************************************************/
501 /*                                                                        */
502 /*  FUNCTION                                               RELEASE        */
503 /*                                                                        */
504 /*    _nx_dhcp_slow_periodic_timer_entry                  PORTABLE C      */
505 /*                                                           6.1          */
506 /*  AUTHOR                                                                */
507 /*                                                                        */
508 /*    Yuxin Zhou, Microsoft Corporation                                   */
509 /*                                                                        */
510 /*  DESCRIPTION                                                           */
511 /*                                                                        */
512 /*    This function watches lease timeout on assigned IP address in the   */
513 /*    server database.  When one has expired, the address is returned to  */
514 /*    the available pool and the Client is reset to the INIT state.       */
515 /*                                                                        */
516 /*  INPUT                                                                 */
517 /*                                                                        */
518 /*    info                                 Generic pointer to DHCP server */
519 /*                                                                        */
520 /*  OUTPUT                                                                */
521 /*                                                                        */
522 /*    None                                                                */
523 /*                                                                        */
524 /*  CALLS                                                                 */
525 /*                                                                        */
526 /*     tx_event_flags_set                   Adds a slow periodic event    */
527 /*                                                                        */
528 /*  CALLED BY                                                             */
529 /*                                                                        */
530 /*    ThreadX system timer thread                                         */
531 /*                                                                        */
532 /*  RELEASE HISTORY                                                       */
533 /*                                                                        */
534 /*    DATE              NAME                      DESCRIPTION             */
535 /*                                                                        */
536 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
537 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
538 /*                                            resulting in version 6.1    */
539 /*                                                                        */
540 /**************************************************************************/
_nx_dhcp_slow_periodic_timer_entry(ULONG info)541 static VOID  _nx_dhcp_slow_periodic_timer_entry(ULONG info)
542 {
543 
544 NX_DHCP_SERVER                  *dhcp_ptr;
545 
546 
547     /* Setup DHCP pointer.  */
548     NX_TIMER_EXTENSION_PTR_GET(dhcp_ptr, NX_DHCP_SERVER, info)
549 
550     /* Signal the DHCP Server slow periodic event.  */
551     tx_event_flags_set(&(dhcp_ptr -> nx_dhcp_server_events), NX_DHCP_SERVER_SLOW_PERIODIC_EVENT, TX_OR);
552 
553     return;
554 }
555 
556 
557 /**************************************************************************/
558 /*                                                                        */
559 /*  FUNCTION                                               RELEASE        */
560 /*                                                                        */
561 /*    _nx_dhcp_server_socket_receive_notify               PORTABLE C      */
562 /*                                                           6.1          */
563 /*  AUTHOR                                                                */
564 /*                                                                        */
565 /*    Yuxin Zhou, Microsoft Corporation                                   */
566 /*                                                                        */
567 /*  DESCRIPTION                                                           */
568 /*                                                                        */
569 /*    This function is notified by NetX Duo when a packet arrives in the  */
570 /*    server socket. It sets a flag which the DHCP server thread          */
571 /*    detect so it will know to process the incoming packet .             */
572 /*                                                                        */
573 /*  INPUT                                                                 */
574 /*                                                                        */
575 /*    socket_ptr                            Pointer to Server Socket      */
576 /*                                                                        */
577 /*  OUTPUT                                                                */
578 /*                                                                        */
579 /*    None                                                                */
580 /*                                                                        */
581 /*  CALLS                                                                 */
582 /*                                                                        */
583 /*    None                                                                */
584 /*     tx_event_flags_set                   Adds a packet receive event   */
585 /*  CALLED BY                                                             */
586 /*                                                                        */
587 /*    Threads                                                             */
588 /*                                                                        */
589 /*  RELEASE HISTORY                                                       */
590 /*                                                                        */
591 /*    DATE              NAME                      DESCRIPTION             */
592 /*                                                                        */
593 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
594 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
595 /*                                            resulting in version 6.1    */
596 /*                                                                        */
597 /**************************************************************************/
_nx_dhcp_server_socket_receive_notify(NX_UDP_SOCKET * socket_ptr)598 VOID  _nx_dhcp_server_socket_receive_notify(NX_UDP_SOCKET *socket_ptr)
599 {
600 
601 NX_DHCP_SERVER  *dhcp_server_ptr;
602 
603 
604     /* Get a pointer to the DHCP server.  */
605     dhcp_server_ptr =  (NX_DHCP_SERVER *) socket_ptr -> nx_udp_socket_reserved_ptr;
606 
607     /* Signal the DHCP Server it has a UDP packet on its socket receive queue.  */
608     tx_event_flags_set(&(dhcp_server_ptr -> nx_dhcp_server_events), NX_DHCP_SERVER_RECEIVE_EVENT, TX_OR);
609 
610     return;
611 }
612 
613 
614 /**************************************************************************/
615 /*                                                                        */
616 /*  FUNCTION                                               RELEASE        */
617 /*                                                                        */
618 /*    _nxe_dhcp_server_delete                             PORTABLE C      */
619 /*                                                           6.1          */
620 /*  AUTHOR                                                                */
621 /*                                                                        */
622 /*    Yuxin Zhou, Microsoft Corporation                                   */
623 /*                                                                        */
624 /*  DESCRIPTION                                                           */
625 /*                                                                        */
626 /*    This function checks for errors in the DHCP delete function call.   */
627 /*                                                                        */
628 /*  INPUT                                                                 */
629 /*                                                                        */
630 /*    dhcp_ptr                              Pointer to DHCP Server        */
631 /*                                                                        */
632 /*  OUTPUT                                                                */
633 /*                                                                        */
634 /*    status                                Completion status             */
635 /*                                                                        */
636 /*  CALLS                                                                 */
637 /*                                                                        */
638 /*    _nx_dhcp_server_delete                Actual DHCP delete function   */
639 /*                                                                        */
640 /*  CALLED BY                                                             */
641 /*                                                                        */
642 /*    Application Code                                                    */
643 /*                                                                        */
644 /*  RELEASE HISTORY                                                       */
645 /*                                                                        */
646 /*    DATE              NAME                      DESCRIPTION             */
647 /*                                                                        */
648 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
649 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
650 /*                                            resulting in version 6.1    */
651 /*                                                                        */
652 /**************************************************************************/
_nxe_dhcp_server_delete(NX_DHCP_SERVER * dhcp_ptr)653 UINT  _nxe_dhcp_server_delete(NX_DHCP_SERVER *dhcp_ptr)
654 {
655 
656 UINT    status;
657 
658 
659     /* Check for invalid input pointers.  */
660     if (dhcp_ptr == NX_NULL)
661         return(NX_PTR_ERROR);
662 
663     if (dhcp_ptr -> nx_dhcp_id != NX_DHCP_SERVER_ID)
664     {
665         return(NX_DHCP_PARAMETER_ERROR);
666     }
667 
668     /* Check for appropriate caller.  */
669     NX_THREADS_ONLY_CALLER_CHECKING
670 
671     /* Call actual DHCP delete service.  */
672     status =  _nx_dhcp_server_delete(dhcp_ptr);
673 
674     /* Return status.  */
675     return(status);
676 }
677 
678 
679 /**************************************************************************/
680 /*                                                                        */
681 /*  FUNCTION                                               RELEASE        */
682 /*                                                                        */
683 /*    _nx_dhcp_server_delete                              PORTABLE C      */
684 /*                                                           6.1          */
685 /*  AUTHOR                                                                */
686 /*                                                                        */
687 /*    Yuxin Zhou, Microsoft Corporation                                   */
688 /*                                                                        */
689 /*  DESCRIPTION                                                           */
690 /*                                                                        */
691 /*    This function deletes the DHCP server   and releases all of its     */
692 /*    resources.                                                          */
693 /*                                                                        */
694 /*  INPUT                                                                 */
695 /*                                                                        */
696 /*    dhcp_ptr                              Pointer to DHCP Server        */
697 /*                                                                        */
698 /*  OUTPUT                                                                */
699 /*                                                                        */
700 /*    status                                Completion status             */
701 /*                                                                        */
702 /*  CALLS                                                                 */
703 /*                                                                        */
704 /*    nx_udp_socket_unbind                  Free the UDP socket port      */
705 /*    nx_udp_socket_delete                  Delete the DHCP UDP socket    */
706 /*    tx_thread_terminate                   Terminate DHCP thread         */
707 /*    tx_thread_terminate                   Terminate DHCP thread         */
708 /*    tx_thread_delete                      Delete DHCP thread            */
709 /*    tx_timer_delete                       Delete DHCP timer             */
710 /*                                                                        */
711 /*  CALLED BY                                                             */
712 /*                                                                        */
713 /*    Application Code                                                    */
714 /*                                                                        */
715 /*  RELEASE HISTORY                                                       */
716 /*                                                                        */
717 /*    DATE              NAME                      DESCRIPTION             */
718 /*                                                                        */
719 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
720 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
721 /*                                            resulting in version 6.1    */
722 /*                                                                        */
723 /**************************************************************************/
_nx_dhcp_server_delete(NX_DHCP_SERVER * dhcp_ptr)724 UINT  _nx_dhcp_server_delete(NX_DHCP_SERVER *dhcp_ptr)
725 {
726 
727 
728     /* Determine if DHCP is stopped.  */
729     if (dhcp_ptr -> nx_dhcp_started != NX_FALSE)
730     {
731 
732         /* Stop the DHCP server.  */
733         _nx_dhcp_server_stop(dhcp_ptr);
734     }
735 
736     /* Delete the UDP socket.  */
737     nx_udp_socket_delete(&(dhcp_ptr  -> nx_dhcp_socket));
738 
739     /* Delete the session ("fast") timer. */
740     tx_timer_delete(&(dhcp_ptr -> nx_dhcp_fast_periodic_timer));
741 
742     /* Delete the IP lease ("slow") timer. */
743     tx_timer_delete(&(dhcp_ptr -> nx_dhcp_slow_periodic_timer));
744 
745     /* Suspend the DHCP processing thread.  */
746     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_server_thread));
747 
748     /* Terminate the DHCP processing thread.  */
749     tx_thread_terminate(&(dhcp_ptr -> nx_dhcp_server_thread));
750 
751     /* Delete the DHCP processing thread.  */
752     tx_thread_delete(&(dhcp_ptr -> nx_dhcp_server_thread));
753 
754     /* Delete the mutexes.  */
755     tx_mutex_delete(&(dhcp_ptr -> nx_dhcp_mutex));
756 
757     /* Delete the flag event.  */
758     tx_event_flags_delete(&(dhcp_ptr -> nx_dhcp_server_events));
759 
760     /* Clear the dhcp structure ID. */
761     dhcp_ptr -> nx_dhcp_id =  0;
762 
763     /* Return a successful status.  */
764     return(NX_SUCCESS);
765 }
766 
767 
768 /**************************************************************************/
769 /*                                                                        */
770 /*  FUNCTION                                               RELEASE        */
771 /*                                                                        */
772 /*    _nxe_dhcp_create_server_ip_address_list             PORTABLE C      */
773 /*                                                           6.1          */
774 /*  AUTHOR                                                                */
775 /*                                                                        */
776 /*    Yuxin Zhou, Microsoft Corporation                                   */
777 /*                                                                        */
778 /*  DESCRIPTION                                                           */
779 /*                                                                        */
780 /*    This function performs error checking for the IP address list create*/
781 /*    service.                                                            */
782 /*                                                                        */
783 /*   INPUT                                                                */
784 /*                                                                        */
785 /*    dhcp_ptr                        Pointer to DHCP Server              */
786 /*    iface_index                     IP interface index to specify the   */
787 /*                                       DHCP server interface to use     */
788 /*    start_ip_address                Starting IP address                 */
789 /*    end_ip_address                  Ending IP address                   */
790 /*    addresses_added                 Pointer to addresses added counter  */
791 /*                                                                        */
792 /*  OUTPUT                                                                */
793 /*                                                                        */
794 /*    NX_SUCCESS                      Successful completion status        */
795 /*    NX_PTR_ERROR                    Invalid pointer input               */
796 /*                                                                        */
797 /*  CALLS                                                                 */
798 /*                                                                        */
799 /*    _nx_dhcp_create_server_ip_address_list                              */
800 /*                                    Actual IP address create service    */
801 /*                                                                        */
802 /*  CALLED BY                                                             */
803 /*                                                                        */
804 /*     Application code                                                   */
805 /*                                                                        */
806 /*  RELEASE HISTORY                                                       */
807 /*                                                                        */
808 /*    DATE              NAME                      DESCRIPTION             */
809 /*                                                                        */
810 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
811 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
812 /*                                            resulting in version 6.1    */
813 /*                                                                        */
814 /**************************************************************************/
_nxe_dhcp_create_server_ip_address_list(NX_DHCP_SERVER * dhcp_ptr,UINT iface_index,ULONG start_ip_address,ULONG end_ip_address,UINT * addresses_added)815 UINT _nxe_dhcp_create_server_ip_address_list(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index,
816                                              ULONG start_ip_address, ULONG end_ip_address, UINT *addresses_added)
817 {
818 
819 UINT            status;
820 
821 
822     /* Check for invalid input.  */
823     if ((dhcp_ptr == NX_NULL) || (addresses_added == NX_NULL))
824     {
825         return(NX_PTR_ERROR);
826     }
827 
828     /* Check for invalid non pointer input. */
829     if ((start_ip_address > end_ip_address) ||
830         (iface_index >= NX_MAX_PHYSICAL_INTERFACES) ||
831         (start_ip_address == NX_DHCP_NO_ADDRESS))
832     {
833 
834         return(NX_DHCP_INVALID_IP_ADDRESS);
835     }
836 
837     status = _nx_dhcp_create_server_ip_address_list(dhcp_ptr, iface_index, start_ip_address, end_ip_address, addresses_added);
838 
839     return(status);
840 }
841 
842 
843 /**************************************************************************/
844 /*                                                                        */
845 /*  FUNCTION                                               RELEASE        */
846 /*                                                                        */
847 /*    _nx_dhcp_create_server_ip_address_list              PORTABLE C      */
848 /*                                                           6.1          */
849 /*  AUTHOR                                                                */
850 /*                                                                        */
851 /*    Yuxin Zhou, Microsoft Corporation                                   */
852 /*                                                                        */
853 /*  DESCRIPTION                                                           */
854 /*                                                                        */
855 /*   This function creates a list of available IP addresses for DHCP      */
856 /*   clients on the specified interface. The caller supplies a start and  */
857 /*   end IP address and all addresses in between are flagged as available.*/
858 /*   The start ip address is assumed to be the first entry in the list,   */
859 /*   not appended to a previously started list. All the IP addresses  may */
860 /*   not fit in the server interface table; the number actually added is  */
861 /*   written to the 'addresses added' variable. The caller should check   */
862 /*   this output.                                                         */
863 /*                                                                        */
864 /*   If some addresses within the specified range need to be reserved or  */
865 /*   statically assigned the host application needs to set their lease to */
866 /*   infinity (0xffffffff) and assigned status is set. This function also */
867 /*   add the interface subnet, router, dns server for specified index.    */
868 /*                                                                        */
869 /*  INPUT                                                                 */
870 /*                                                                        */
871 /*    dhcp_ptr                           Pointer to DHCP server           */
872 /*    iface_index                        Index specifying server interface*/
873 /*    start_ip_address                   Beginning IP address in list.    */
874 /*    end_ip_address                     Ending IP address in list.       */
875 /*    addresses_added                    Number of addresses added to list*/
876 /*                                                                        */
877 /*  OUTPUT                                                                */
878 /*                                                                        */
879 /*    NX_SUCCESS                         Successful IP list creation      */
880 /*    NX_DHCP_SERVER_BAD_INTERFACE_INDEX Invalid interface index input    */
881 /*    NX_DHCP_INVALID_IP_ADDRESS_LIST    Invalid IP list parameter input  */
882 /*                                                                        */
883 /*  CALLS                                                                 */
884 /*                                                                        */
885 /*     _nx_dhcp_update_assignable_ip_address                              */
886 /*                                        Updates interface table entry   */
887 /*                                        with IP address status and owner*/
888 /*     _nx_dhcp_clear_client_session      Clears client record of session */
889 /*                                           data from most recent client */
890 /*                                                                        */
891 /*  CALLED BY                                                             */
892 /*                                                                        */
893 /*    Application code                                                    */
894 /*                                                                        */
895 /*  RELEASE HISTORY                                                       */
896 /*                                                                        */
897 /*    DATE              NAME                      DESCRIPTION             */
898 /*                                                                        */
899 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
900 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
901 /*                                            resulting in version 6.1    */
902 /*                                                                        */
903 /**************************************************************************/
_nx_dhcp_create_server_ip_address_list(NX_DHCP_SERVER * dhcp_ptr,UINT iface_index,ULONG start_ip_address,ULONG end_ip_address,UINT * addresses_added)904 UINT  _nx_dhcp_create_server_ip_address_list(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index,
905                                             ULONG start_ip_address, ULONG end_ip_address,
906                                             UINT *addresses_added)
907 {
908 
909 UINT                         i;
910 ULONG                        next_ip_address;
911 NX_IP                        *ip_ptr;
912 NX_DHCP_INTERFACE_IP_ADDRESS *ip_address_entry_ptr;
913 NX_DHCP_INTERFACE_TABLE      *dhcp_interface_table_ptr;
914 
915 
916     /* Check for an invalid interface index. */
917     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
918     {
919         return NX_DHCP_SERVER_BAD_INTERFACE_INDEX;
920     }
921 
922     /* Obtain DHCP Server mutex protection,. */
923     tx_mutex_get(&dhcp_ptr -> nx_dhcp_mutex, NX_WAIT_FOREVER);
924 
925     *addresses_added = 0;
926     next_ip_address = start_ip_address;
927 
928     /* Set local pointer to the list being created for convenience. */
929     dhcp_interface_table_ptr = &dhcp_ptr -> nx_dhcp_interface_table[iface_index];
930 
931     /* Fill in the interface table with DHCP attributes for the specified interface. */
932 
933     /* Set up a local variable for convenience. */
934     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
935 
936     /* Assign the IP interface specified by the IP interface index to the DHCP interface. */
937     dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_incoming_interface = &(ip_ptr -> nx_ip_interface[iface_index]);
938 
939     /* Set the server ip address based on the specified interface. */
940     dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_server_ip_address = ip_ptr -> nx_ip_interface[iface_index].nx_interface_ip_address;
941 
942     /* Set the dns server, subnet mask, and router (default gateway) for this interface. */
943     dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_dns_ip_address = ip_ptr -> nx_ip_interface[iface_index].nx_interface_ip_address;
944     dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_subnet_mask = ip_ptr -> nx_ip_interface[iface_index].nx_interface_ip_network_mask;
945     dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_router_ip_address = ip_ptr -> nx_ip_gateway_address;
946 
947 
948     /* Make sure the start/end address subnet match the interface subnet. */
949     if ((dhcp_interface_table_ptr -> nx_dhcp_subnet_mask & start_ip_address) !=
950         (dhcp_interface_table_ptr -> nx_dhcp_subnet_mask & dhcp_interface_table_ptr -> nx_dhcp_server_ip_address))
951     {
952 
953         /* Release DHCP Server mutex.  */
954         tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
955 
956         return(NX_DHCP_SERVER_BAD_INTERFACE_INDEX);
957     }
958     if ((dhcp_interface_table_ptr -> nx_dhcp_subnet_mask & end_ip_address) !=
959         (dhcp_interface_table_ptr -> nx_dhcp_subnet_mask & dhcp_interface_table_ptr -> nx_dhcp_server_ip_address))
960     {
961 
962         /* Release DHCP Server mutex.  */
963         tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
964 
965         return(NX_DHCP_SERVER_BAD_INTERFACE_INDEX);
966     }
967 
968     /* Zero out the list size. */
969     dhcp_interface_table_ptr -> nx_dhcp_address_list_size = 0;
970 
971     /* Check for invalid list parameters. */
972     if ((start_ip_address > end_ip_address) || !start_ip_address || !end_ip_address)
973     {
974 
975         /* Release DHCP Server mutex.  */
976         tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
977 
978         return(NX_DHCP_INVALID_IP_ADDRESS_LIST);
979     }
980 
981     /* Clear out existing entries and start adding IP addresses at the beginning of the list. */
982     i = 0;
983 
984     /* Fit as many IP addresses in the specified range as will fit in the table. */
985     while (i < NX_DHCP_IP_ADDRESS_MAX_LIST_SIZE && next_ip_address <= end_ip_address)
986     {
987 
988         /* Set local pointer to the next entry for convenience. */
989         ip_address_entry_ptr = &dhcp_interface_table_ptr -> nx_dhcp_ip_address_list[i];
990 
991         /* Clear existing entry; client identifier and available status
992            must be initialized to NULL and not assigned respectively.  */
993         memset(ip_address_entry_ptr, 0, sizeof(NX_DHCP_INTERFACE_IP_ADDRESS));
994 
995         /* Add the next IP address to the list. */
996         ip_address_entry_ptr -> nx_assignable_ip_address = next_ip_address;
997 
998         /* Increase the list size. */
999         dhcp_interface_table_ptr -> nx_dhcp_address_list_size++;
1000 
1001         next_ip_address++;
1002         i++;
1003     }
1004 
1005     /* Set the actual number of available addresses added to the table. */
1006     *addresses_added = dhcp_interface_table_ptr -> nx_dhcp_address_list_size;
1007 
1008     /* Release DHCP Server mutex.  */
1009     tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
1010 
1011     return(NX_SUCCESS);
1012 }
1013 
1014 
1015 /**************************************************************************/
1016 /*                                                                        */
1017 /*  FUNCTION                                               RELEASE        */
1018 /*                                                                        */
1019 /*    _nxe_dhcp_set_interface_network_parameters          PORTABLE C      */
1020 /*                                                           6.1          */
1021 /*  AUTHOR                                                                */
1022 /*                                                                        */
1023 /*    Yuxin Zhou, Microsoft Corporation                                   */
1024 /*                                                                        */
1025 /*  DESCRIPTION                                                           */
1026 /*                                                                        */
1027 /*   This function performs error checking services for the set interface */
1028 /*   network parameters service.                                          */
1029 /*                                                                        */
1030 /*  INPUT                                                                 */
1031 /*                                                                        */
1032 /*    dhcp_ptr                           Pointer to DHCP server           */
1033 /*    iface_index                        Index specifying server interface*/
1034 /*    subnet_mask                        Network mask for DHCP clients    */
1035 /*    default_gateway_address            Router/default gateway for client*/
1036 /*    dns_server_address                 DNS server for DHCP clients      */
1037 /*                                                                        */
1038 /*  OUTPUT                                                                */
1039 /*                                                                        */
1040 /*    status                             Actual completion status         */
1041 /*    NX_PTR_ERROR                       Invalid interface index input    */
1042 /*    NX_DHCP_INVALID_NETWORK_PARAMETERS Invalid network parameter input  */
1043 /*                                                                        */
1044 /*  CALLS                                                                 */
1045 /*                                                                        */
1046 /*     _nx_dhcp_update_assignable_ip_address                              */
1047 /*                                        Updates interface table entry   */
1048 /*                                        with IP address status and owner*/
1049 /*     _nx_dhcp_clear_client_session      Clears client record of session */
1050 /*                                           data from most recent client */
1051 /*                                                                        */
1052 /*  CALLED BY                                                             */
1053 /*                                                                        */
1054 /*    Application code                                                    */
1055 /*                                                                        */
1056 /*  RELEASE HISTORY                                                       */
1057 /*                                                                        */
1058 /*    DATE              NAME                      DESCRIPTION             */
1059 /*                                                                        */
1060 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1061 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1062 /*                                            resulting in version 6.1    */
1063 /*                                                                        */
1064 /**************************************************************************/
_nxe_dhcp_set_interface_network_parameters(NX_DHCP_SERVER * dhcp_ptr,UINT iface_index,ULONG subnet_mask,ULONG default_gateway_address,ULONG dns_server_address)1065 UINT  _nxe_dhcp_set_interface_network_parameters(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index,
1066                                             ULONG subnet_mask, ULONG default_gateway_address,
1067                                             ULONG dns_server_address)
1068 {
1069 UINT status;
1070 
1071     /* Check for invalid pointer input. */
1072     if (dhcp_ptr == NX_NULL)
1073     {
1074         return(NX_PTR_ERROR);
1075     }
1076 
1077     /* Check for non pointer input. */
1078     if ((subnet_mask == 0) || (default_gateway_address == 0) || (dns_server_address == 0))
1079     {
1080         return(NX_DHCP_INVALID_NETWORK_PARAMETERS);
1081     }
1082 
1083     /* Call the actual service. */
1084     status = _nx_dhcp_set_interface_network_parameters(dhcp_ptr, iface_index,
1085                                             subnet_mask, default_gateway_address,
1086                                             dns_server_address);
1087     /* Return completion status. */
1088     return(status);
1089 }
1090 
1091 
1092 /**************************************************************************/
1093 /*                                                                        */
1094 /*  FUNCTION                                               RELEASE        */
1095 /*                                                                        */
1096 /*    _nx_dhcp_set_interface_network_parameters           PORTABLE C      */
1097 /*                                                           6.1          */
1098 /*  AUTHOR                                                                */
1099 /*                                                                        */
1100 /*    Yuxin Zhou, Microsoft Corporation                                   */
1101 /*                                                                        */
1102 /*  DESCRIPTION                                                           */
1103 /*                                                                        */
1104 /*   This function sets the DHCP server default options for 'network      */
1105 /*   critical parameters:' gateway, dns server and network mask for the   */
1106 /*   specified interface.                                                 */
1107 /*                                                                        */
1108 /*  INPUT                                                                 */
1109 /*                                                                        */
1110 /*    dhcp_ptr                           Pointer to DHCP server           */
1111 /*    iface_index                        Index specifying server interface*/
1112 /*    subnet_mask                        Network mask for DHCP clients    */
1113 /*    default_gateway_address            Router/default gateway for client*/
1114 /*    dns_server_address                 DNS server for DHCP clients      */
1115 /*                                                                        */
1116 /*  OUTPUT                                                                */
1117 /*                                                                        */
1118 /*    NX_SUCCESS                         Valid parameters received        */
1119 /*    NX_DHCP_SERVER_BAD_INTERFACE_INDEX Invalid interface index input    */
1120 /*    NX_DHCP_INVALID_NETWORK_PARAMETERS Invalid network parameter input  */
1121 /*                                                                        */
1122 /*  CALLS                                                                 */
1123 /*                                                                        */
1124 /*     None                                                               */
1125 /*                                                                        */
1126 /*  CALLED BY                                                             */
1127 /*                                                                        */
1128 /*    Application code                                                    */
1129 /*                                                                        */
1130 /*  RELEASE HISTORY                                                       */
1131 /*                                                                        */
1132 /*    DATE              NAME                      DESCRIPTION             */
1133 /*                                                                        */
1134 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1135 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1136 /*                                            resulting in version 6.1    */
1137 /*                                                                        */
1138 /**************************************************************************/
_nx_dhcp_set_interface_network_parameters(NX_DHCP_SERVER * dhcp_ptr,UINT iface_index,ULONG subnet_mask,ULONG default_gateway_address,ULONG dns_server_address)1139 UINT  _nx_dhcp_set_interface_network_parameters(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index,
1140                                             ULONG subnet_mask, ULONG default_gateway_address,
1141                                             ULONG dns_server_address)
1142 {
1143 
1144     /* Check for invalid non pointer input. */
1145     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
1146     {
1147 
1148         return(NX_DHCP_SERVER_BAD_INTERFACE_INDEX);
1149     }
1150 
1151     /* The default gateway should be on the same network as the dhcp server interface. */
1152     if ((default_gateway_address & subnet_mask) !=
1153         (dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_server_ip_address &
1154                         dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_subnet_mask))
1155     {
1156         return(NX_DHCP_INVALID_NETWORK_PARAMETERS);
1157     }
1158 
1159     /* Obtain DHCP Server mutex protection,. */
1160     tx_mutex_get(&dhcp_ptr -> nx_dhcp_mutex, NX_WAIT_FOREVER);
1161 
1162     /* Set the subnet, dns server, and router address for this interface. */
1163     dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_dns_ip_address = dns_server_address;
1164 
1165     dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_subnet_mask = subnet_mask;
1166 
1167     dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_router_ip_address = default_gateway_address;
1168 
1169     /* Release DHCP Server mutex.  */
1170     tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
1171 
1172     return(NX_SUCCESS);
1173 }
1174 
1175 
1176 /**************************************************************************/
1177 /*                                                                        */
1178 /*  FUNCTION                                               RELEASE        */
1179 /*                                                                        */
1180 /*    _nxe_dhcp_server_start                              PORTABLE C      */
1181 /*                                                           6.1          */
1182 /*  AUTHOR                                                                */
1183 /*                                                                        */
1184 /*    Yuxin Zhou, Microsoft Corporation                                   */
1185 /*                                                                        */
1186 /*  DESCRIPTION                                                           */
1187 /*                                                                        */
1188 /*    This function checks for errors in the DHCP start function call.    */
1189 /*                                                                        */
1190 /*  INPUT                                                                 */
1191 /*                                                                        */
1192 /*    dhcp_ptr                              Pointer to DHCP Server        */
1193 /*                                                                        */
1194 /*  OUTPUT                                                                */
1195 /*                                                                        */
1196 /*    status                                Completion status             */
1197 /*                                                                        */
1198 /*  CALLS                                                                 */
1199 /*                                                                        */
1200 /*    _nx_dhcp_start                        Actual DHCP start function    */
1201 /*    nx_udp_socket_bind                    Bind the DHCP UDP socket      */
1202 /*                                                                        */
1203 /*  CALLED BY                                                             */
1204 /*                                                                        */
1205 /*    Application Code                                                    */
1206 /*                                                                        */
1207 /*  RELEASE HISTORY                                                       */
1208 /*                                                                        */
1209 /*    DATE              NAME                      DESCRIPTION             */
1210 /*                                                                        */
1211 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1212 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1213 /*                                            resulting in version 6.1    */
1214 /*                                                                        */
1215 /**************************************************************************/
_nxe_dhcp_server_start(NX_DHCP_SERVER * dhcp_ptr)1216 UINT  _nxe_dhcp_server_start(NX_DHCP_SERVER *dhcp_ptr)
1217 {
1218 
1219 UINT    status;
1220 
1221 
1222     /* Check for invalid input pointer.  */
1223     if (dhcp_ptr == NX_NULL)
1224         return(NX_PTR_ERROR);
1225 
1226     if (dhcp_ptr -> nx_dhcp_id != NX_DHCP_SERVER_ID)
1227     {
1228         return(NX_DHCP_PARAMETER_ERROR);
1229     }
1230 
1231     /* Check for appropriate caller.  */
1232     NX_INIT_AND_THREADS_CALLER_CHECKING
1233 
1234     /* Call actual DHCP start service.  */
1235     status =  _nx_dhcp_server_start(dhcp_ptr);
1236 
1237     /* Return status.  */
1238     return(status);
1239 }
1240 
1241 
1242 /**************************************************************************/
1243 /*                                                                        */
1244 /*  FUNCTION                                               RELEASE        */
1245 /*                                                                        */
1246 /*    _nx_dhcp_server_start                               PORTABLE C      */
1247 /*                                                           6.1          */
1248 /*  AUTHOR                                                                */
1249 /*                                                                        */
1250 /*    Yuxin Zhou, Microsoft Corporation                                   */
1251 /*                                                                        */
1252 /*  DESCRIPTION                                                           */
1253 /*                                                                        */
1254 /*    This function initiates the DHCP processing thread.                 */
1255 /*                                                                        */
1256 /*  INPUT                                                                 */
1257 /*                                                                        */
1258 /*    dhcp_ptr                              Pointer to DHCP Server        */
1259 /*                                                                        */
1260 /*  OUTPUT                                                                */
1261 /*                                                                        */
1262 /*    status                                Completion status             */
1263 /*                                                                        */
1264 /*  CALLS                                                                 */
1265 /*                                                                        */
1266 /*    nx_udp_socket_bind                    Bind DHCP socket              */
1267 /*    nx_udp_socket_unbind                  Unbind DHCP socket            */
1268 /*    tx_thread_resume                      Initiate DHCP processing      */
1269 /*    tx_mutex_get                          Get the DHCP mutex            */
1270 /*    tx_mutex_put                          Release the DHCP mutex        */
1271 /*                                                                        */
1272 /*  CALLED BY                                                             */
1273 /*                                                                        */
1274 /*    Application Code                                                    */
1275 /*                                                                        */
1276 /*  RELEASE HISTORY                                                       */
1277 /*                                                                        */
1278 /*    DATE              NAME                      DESCRIPTION             */
1279 /*                                                                        */
1280 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1281 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1282 /*                                            resulting in version 6.1    */
1283 /*                                                                        */
1284 /**************************************************************************/
_nx_dhcp_server_start(NX_DHCP_SERVER * dhcp_ptr)1285 UINT  _nx_dhcp_server_start(NX_DHCP_SERVER *dhcp_ptr)
1286 {
1287 
1288 UINT  status;
1289 
1290 
1291     /* Determine if DHCP has already been started.  */
1292     if (dhcp_ptr -> nx_dhcp_started)
1293     {
1294 
1295         /* Error DHCP has already been started.  */
1296 
1297         /* Return completion status.  */
1298         return(NX_DHCP_SERVER_ALREADY_STARTED);
1299     }
1300 
1301     dhcp_ptr -> nx_dhcp_started = NX_TRUE;
1302 
1303     /* Bind the UDP socket to the DHCP Socket port.  */
1304     status =  nx_udp_socket_bind(&(dhcp_ptr -> nx_dhcp_socket), NX_DHCP_SERVER_UDP_PORT, TX_WAIT_FOREVER);
1305 
1306     /* Check status.  */
1307     if (status != NX_SUCCESS)
1308     {
1309 
1310         /* Error, unbind the DHCP socket.  */
1311         nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
1312 
1313         /* Set status to DHCP error code.  */
1314         return(status);
1315     }
1316 
1317     /* Start the session ("fast") timer. */
1318     tx_timer_activate(&(dhcp_ptr -> nx_dhcp_fast_periodic_timer));
1319 
1320     /* Start the IP lease ("slow") timer. */
1321     tx_timer_activate(&(dhcp_ptr -> nx_dhcp_slow_periodic_timer));
1322 
1323     /* Start the DHCP server thread.  */
1324     tx_thread_resume(&(dhcp_ptr -> nx_dhcp_server_thread));
1325 
1326 
1327     /* Return completion status.  */
1328     return(NX_SUCCESS);
1329 }
1330 
1331 
1332 /**************************************************************************/
1333 /*                                                                        */
1334 /*  FUNCTION                                               RELEASE        */
1335 /*                                                                        */
1336 /*    _nxe_dhcp_server_stop                               PORTABLE C      */
1337 /*                                                           6.1          */
1338 /*  AUTHOR                                                                */
1339 /*                                                                        */
1340 /*    Yuxin Zhou, Microsoft Corporation                                   */
1341 /*                                                                        */
1342 /*  DESCRIPTION                                                           */
1343 /*                                                                        */
1344 /*    This function checks for errors in the DHCP stop function call.     */
1345 /*                                                                        */
1346 /*  INPUT                                                                 */
1347 /*                                                                        */
1348 /*    dhcp_ptr                              Pointer to DHCP Server        */
1349 /*                                                                        */
1350 /*  OUTPUT                                                                */
1351 /*                                                                        */
1352 /*    status                                Completion status             */
1353 /*                                                                        */
1354 /*  CALLS                                                                 */
1355 /*                                                                        */
1356 /*    _nx_dhcp_stop                         Actual DHCP stop function     */
1357 /*                                                                        */
1358 /*  CALLED BY                                                             */
1359 /*                                                                        */
1360 /*    Application Code                                                    */
1361 /*                                                                        */
1362 /*  RELEASE HISTORY                                                       */
1363 /*                                                                        */
1364 /*    DATE              NAME                      DESCRIPTION             */
1365 /*                                                                        */
1366 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1367 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1368 /*                                            resulting in version 6.1    */
1369 /*                                                                        */
1370 /**************************************************************************/
_nxe_dhcp_server_stop(NX_DHCP_SERVER * dhcp_ptr)1371 UINT  _nxe_dhcp_server_stop(NX_DHCP_SERVER *dhcp_ptr)
1372 {
1373 
1374 UINT    status;
1375 
1376 
1377     /* Check for invalid input pointer.  */
1378     if (dhcp_ptr == NX_NULL)
1379         return(NX_PTR_ERROR);
1380 
1381     if (dhcp_ptr -> nx_dhcp_id != NX_DHCP_SERVER_ID)
1382     {
1383         return(NX_DHCP_PARAMETER_ERROR);
1384     }
1385 
1386     /* Check for appropriate caller.  */
1387     NX_THREADS_ONLY_CALLER_CHECKING
1388 
1389     /* Call actual DHCP stop service.  */
1390     status =  _nx_dhcp_server_stop(dhcp_ptr);
1391 
1392     /* Return status.  */
1393     return(status);
1394 }
1395 
1396 
1397 /**************************************************************************/
1398 /*                                                                        */
1399 /*  FUNCTION                                               RELEASE        */
1400 /*                                                                        */
1401 /*    _nx_dhcp_server_stop                                PORTABLE C      */
1402 /*                                                           6.1          */
1403 /*  AUTHOR                                                                */
1404 /*                                                                        */
1405 /*    Yuxin Zhou, Microsoft Corporation                                   */
1406 /*                                                                        */
1407 /*  DESCRIPTION                                                           */
1408 /*                                                                        */
1409 /*    This function halts the DHCP processing thread.                     */
1410 /*                                                                        */
1411 /*  INPUT                                                                 */
1412 /*                                                                        */
1413 /*    dhcp_ptr                              Pointer to DHCP Server        */
1414 /*                                                                        */
1415 /*  OUTPUT                                                                */
1416 /*                                                                        */
1417 /*    status                                Completion status             */
1418 /*                                                                        */
1419 /*  CALLS                                                                 */
1420 /*                                                                        */
1421 /*    nx_udp_socket_unbind                  Unbind the DHCP UDP socket    */
1422 /*    tx_thread_preemption_change           Change the thread preemption  */
1423 /*    tx_thread_suspend                     Suspend DHCP processing       */
1424 /*    tx_thread_wait_abort                  Remove any thread suspension  */
1425 /*    tx_timer_deactivate                   Deactivate timer              */
1426 /*                                                                        */
1427 /*  CALLED BY                                                             */
1428 /*                                                                        */
1429 /*    Application Code                                                    */
1430 /*                                                                        */
1431 /*  RELEASE HISTORY                                                       */
1432 /*                                                                        */
1433 /*    DATE              NAME                      DESCRIPTION             */
1434 /*                                                                        */
1435 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1436 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1437 /*                                            resulting in version 6.1    */
1438 /*                                                                        */
1439 /**************************************************************************/
_nx_dhcp_server_stop(NX_DHCP_SERVER * dhcp_ptr)1440 UINT  _nx_dhcp_server_stop(NX_DHCP_SERVER *dhcp_ptr)
1441 {
1442 
1443 UINT    current_preemption;
1444 
1445 
1446     /* Determine if DHCP is started.  */
1447     if (dhcp_ptr -> nx_dhcp_started == NX_FALSE)
1448     {
1449 
1450         /* DHCP is not started so it can't be stopped.  */
1451         return(NX_DHCP_SERVER_NOT_STARTED);
1452     }
1453 
1454     /* Obtain mutex protection, which is to say don't interrupt a DHCP server
1455        if it is processing a packet from a DHCP client. */
1456     tx_mutex_get(&dhcp_ptr -> nx_dhcp_mutex, NX_WAIT_FOREVER);
1457 
1458     /* Stop the session ("fast") timer. */
1459     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_fast_periodic_timer));
1460 
1461     /* Stop the IP lease ("slow") timer. */
1462     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_slow_periodic_timer));
1463 
1464     /* Clear the started flag here to ensure other threads can't issue a stop while
1465        this stop is in progress.  */
1466     dhcp_ptr -> nx_dhcp_started =  NX_FALSE;
1467 
1468     /* Disable preemption for critical section.  */
1469     tx_thread_preemption_change(tx_thread_identify(), 0, &current_preemption);
1470 
1471     /* Suspend the DHCP thread.  */
1472     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_server_thread));
1473 
1474     /* Unbind the port.  */
1475     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
1476 
1477     /* Restore preemption.  */
1478     tx_thread_preemption_change(tx_thread_identify(), current_preemption, &current_preemption);
1479 
1480     tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
1481 
1482 
1483     /* Return completion status.  */
1484     return(NX_SUCCESS);
1485 }
1486 
1487 
1488 /**************************************************************************/
1489 /*                                                                        */
1490 /*  FUNCTION                                               RELEASE        */
1491 /*                                                                        */
1492 /*    _nx_dhcp_server_thread_entry                        PORTABLE C      */
1493 /*                                                           6.1          */
1494 /*  AUTHOR                                                                */
1495 /*                                                                        */
1496 /*    Yuxin Zhou, Microsoft Corporation                                   */
1497 /*                                                                        */
1498 /*  DESCRIPTION                                                           */
1499 /*                                                                        */
1500 /*    This function is top level server processing thread for the DHCP    */
1501 /*    service. It listens for and processes client requests in an infinite*/
1502 /*    loop.                                                               */
1503 /*                                                                        */
1504 /*    Note that the current implementation expects a Client to  initiate  */
1505 /*    a session with DISCOVER message rather than using the option of     */
1506 /*    skipping to the REQUEST message.                                    */
1507 /*                                                                        */
1508 /*  INPUT                                                                 */
1509 /*                                                                        */
1510 /*    dhcp_instance                         Pointer to the DHCP server    */
1511 /*                                                                        */
1512 /*  OUTPUT                                                                */
1513 /*                                                                        */
1514 /*    status                                Completion status             */
1515 /*                                                                        */
1516 /*  CALLS                                                                 */
1517 /*                                                                        */
1518 /*    _nx_dhcp_process                      Main DHCP processing function */
1519 /*                                                                        */
1520 /*  CALLED BY                                                             */
1521 /*                                                                        */
1522 /*    ThreadX                                                             */
1523 /*                                                                        */
1524 /*  RELEASE HISTORY                                                       */
1525 /*                                                                        */
1526 /*    DATE              NAME                      DESCRIPTION             */
1527 /*                                                                        */
1528 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1529 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1530 /*                                            resulting in version 6.1    */
1531 /*                                                                        */
1532 /**************************************************************************/
_nx_dhcp_server_thread_entry(ULONG info)1533 static VOID  _nx_dhcp_server_thread_entry(ULONG info)
1534 {
1535 
1536 NX_DHCP_SERVER                  *dhcp_ptr;
1537 ULONG                           dhcp_events;
1538 NX_DHCP_INTERFACE_TABLE         *iface_table_ptr;
1539 NX_DHCP_INTERFACE_IP_ADDRESS    *iface_address_ptr;
1540 NX_DHCP_CLIENT                  *dhcp_client_ptr;
1541 UINT                            iface_index, i;
1542 UINT                            status;
1543 NX_PACKET                       *packet_ptr;
1544 
1545 
1546     /* Setup the DHCP pointer.  */
1547     NX_THREAD_EXTENSION_PTR_GET(dhcp_ptr, NX_DHCP_SERVER, info)
1548 
1549     /* Enter while loop.  */
1550     while(1)
1551     {
1552 
1553         /* Release the DHCP mutex.  */
1554         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1555 
1556         /* Pick up IP event flags.  */
1557         tx_event_flags_get(&dhcp_ptr -> nx_dhcp_server_events, NX_DHCP_SERVER_ALL_EVENTS,
1558                            TX_OR_CLEAR, &dhcp_events, TX_WAIT_FOREVER);
1559 
1560         /* Obtain the DHCP mutex before processing the DHCP event.  */
1561         tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
1562 
1563         /* Check events.  */
1564 
1565         /* Packet receive event.  */
1566         if (dhcp_events & NX_DHCP_SERVER_RECEIVE_EVENT)
1567         {
1568 
1569             /* Loop to receive DHCP message.  */
1570             while(1)
1571             {
1572 
1573                 /* Check for an incoming DHCP packet with non blocking option. */
1574                 status = _nx_udp_socket_receive(&dhcp_ptr -> nx_dhcp_socket, &packet_ptr, NX_NO_WAIT);
1575 
1576                 /* Check for packet receive errors. */
1577                 if (status != NX_SUCCESS)
1578                 {
1579 
1580 #ifdef EL_PRINTF_ENABLE
1581                     EL_PRINTF("DHCPserv: Error receiving DHCP packet 0x%x\n", status);
1582 #endif
1583                     break;
1584                 }
1585 
1586                 /* Process DHCP packet.  */
1587                 _nx_dhcp_server_packet_process(dhcp_ptr, packet_ptr);
1588             }
1589         }
1590 
1591         /* FAST periodic event.  */
1592         if (dhcp_events & NX_DHCP_SERVER_FAST_PERIODIC_EVENT)
1593         {
1594 
1595             /* Check the clients in active session with the server. */
1596             for (i = 0; i < NX_DHCP_CLIENT_RECORD_TABLE_SIZE; i++)
1597             {
1598 
1599                 /* Create a local pointer for convenience. */
1600                 dhcp_client_ptr = &dhcp_ptr -> client_records[i];
1601 
1602                 /* Skip empty records. */
1603                 if ((dhcp_client_ptr -> nx_dhcp_client_mac_lsw == 0) && (dhcp_client_ptr -> nx_dhcp_client_mac_msw == 0))
1604                     continue;
1605 
1606                 /* Skip clients not in active session with the Server, static members,
1607                 or client in the bound state. */
1608                 if (dhcp_client_ptr -> nx_dhcp_session_timeout == TX_WAIT_FOREVER)
1609                     continue;
1610                 if (dhcp_client_ptr -> nx_dhcp_client_state == NX_DHCP_STATE_BOUND)
1611                     continue;
1612 
1613                 /* Skip clients whose session timeout is not set e.g. previous session
1614                    failed and no longer configured with this server. */
1615                 if (dhcp_client_ptr -> nx_dhcp_session_timeout == 0)
1616                     continue;
1617                 if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address == NX_DHCP_NO_ADDRESS)
1618                     continue;
1619 
1620                 /* Check how much time is left before decreasing the time remaining on the session timeout. */
1621                 if (dhcp_client_ptr -> nx_dhcp_session_timeout >= NX_DHCP_FAST_PERIODIC_TIME_INTERVAL)
1622                 {
1623                     /* Ok to decrement the full amount. */
1624                     dhcp_client_ptr -> nx_dhcp_session_timeout -= NX_DHCP_FAST_PERIODIC_TIME_INTERVAL;
1625                 }
1626                 else
1627                 {
1628 
1629                     /* Set to zero. Time's up! */
1630                     dhcp_client_ptr -> nx_dhcp_session_timeout = 0;
1631                 }
1632 
1633                 /* Has time expired on this session? */
1634                 if (dhcp_client_ptr -> nx_dhcp_session_timeout == 0)
1635                 {
1636 
1637                     /* Yes, the client has bailed on the session, intentionally or otherwise. If it wants to
1638                        get an IP address it must start again. Reset status to 'INIT'. */
1639                     dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
1640 
1641 #ifdef EL_PRINTF_ENABLE
1642                     EL_PRINTF("DHCPserv: client session has timed out. Clear session data\n");
1643 #endif
1644 
1645                     /* Does the client have an assigned IP address? */
1646                     if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address)
1647                     {
1648 
1649                         /* Yes, return it back to the available pool. */
1650                         _nx_dhcp_update_assignable_ip_address(dhcp_ptr, dhcp_client_ptr,
1651                                                               dhcp_client_ptr -> nx_dhcp_assigned_ip_address,
1652                                                               NX_DHCP_ADDRESS_STATUS_MARK_AVAILABLE);
1653 
1654                         /* The assigned address must be removed. */
1655                         dhcp_client_ptr -> nx_dhcp_assigned_ip_address = NX_DHCP_NO_ADDRESS;
1656 
1657                         /* Clear the session data, including any data read from last client DHCP message. */
1658                         _nx_dhcp_clear_client_session(dhcp_ptr, dhcp_client_ptr);
1659                     }
1660                 }
1661             }
1662         }
1663 
1664         /* Slow periodic event.  */
1665         if (dhcp_events & NX_DHCP_SERVER_SLOW_PERIODIC_EVENT)
1666         {
1667 
1668             for (iface_index = 0; iface_index < NX_MAX_PHYSICAL_INTERFACES; iface_index++)
1669             {
1670 
1671                 /* Set a local pointer for convenience. */
1672                 iface_table_ptr = &dhcp_ptr -> nx_dhcp_interface_table[iface_index];
1673 
1674                 /* Check the interface addresses in the table for lease expiration. */
1675                 for (i = 0; i < iface_table_ptr -> nx_dhcp_address_list_size; i++)
1676                 {
1677 
1678                     iface_address_ptr = &iface_table_ptr -> nx_dhcp_ip_address_list[i];
1679 
1680                     /* Skip all the entries who are not assigned or assigned indefinately (static). */
1681                     if(iface_address_ptr -> assigned == NX_FALSE)
1682                         continue;
1683                     if(iface_address_ptr -> lease_time == TX_WAIT_FOREVER)
1684                         continue;
1685 
1686                     /* Check how much time is left before decreasing the time remaining on the lease timeout. */
1687                     if (iface_address_ptr -> lease_time >= NX_DHCP_SLOW_PERIODIC_TIME_INTERVAL)
1688                     {
1689 
1690                         /* Ok to decrement the full amount. */
1691                         iface_address_ptr -> lease_time -= NX_DHCP_SLOW_PERIODIC_TIME_INTERVAL;
1692                     }
1693                     else
1694                     {
1695 
1696                         /* Set to zero. Time's up! */
1697                         iface_address_ptr -> lease_time = 0;
1698                     }
1699 
1700                     /* Has time expired on this lease? */
1701                     if (iface_address_ptr -> lease_time == 0)
1702                     {
1703 
1704                         /* Yes, make this address available. */
1705 
1706                         /* Clear the 'owner' field. */
1707                         _nx_dhcp_clear_ip_address_owner(iface_address_ptr);
1708 
1709                         /* Look up the client in the server database by its assigned address. */
1710                         _nx_dhcp_find_client_record_by_ip_address(dhcp_ptr, &dhcp_client_ptr, iface_index,
1711                                                                   iface_address_ptr -> nx_assignable_ip_address);
1712 
1713                         /* Did we find it? */
1714                         if (dhcp_client_ptr != NX_NULL)
1715                         {
1716 
1717                             /* Remove the assigned IP address and reset the Client to the INIT state. */
1718                             dhcp_client_ptr -> nx_dhcp_assigned_ip_address = NX_DHCP_NO_ADDRESS;
1719                             dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
1720 
1721 #ifdef EL_PRINTF_ENABLE
1722                             EL_PRINTF("DHCPserv: client IP lease expired. Clear client data, release IP address\n");
1723 #endif
1724 
1725                             /* Clear all session data if there is any for this client. */
1726                             _nx_dhcp_clear_client_session(dhcp_ptr, dhcp_client_ptr);
1727 
1728                             /* No, we should have this client in the server client records table but we don't.
1729                             That's all we can do right now. */
1730                         }
1731                     }
1732                 }
1733             }
1734         }
1735     };
1736 
1737     /* We only break out of this loop in the event of the server stopping
1738        or a fatal error occurring.*/
1739 }
1740 
1741 
1742 /**************************************************************************/
1743 /*                                                                        */
1744 /*  FUNCTION                                               RELEASE        */
1745 /*                                                                        */
1746 /*    _nx_dhcp_respond_to_client_message                  PORTABLE C      */
1747 /*                                                           6.1          */
1748 /*  AUTHOR                                                                */
1749 /*                                                                        */
1750 /*    Yuxin Zhou, Microsoft Corporation                                   */
1751 /*                                                                        */
1752 /*  DESCRIPTION                                                           */
1753 /*                                                                        */
1754 /*    This function prepares a DHCP message response and sends it back to */
1755 /*    the  Client.  Most of the information is obtained from specified    */
1756 /*    input or from client session record.                                */
1757 /*                                                                        */
1758 /*  INPUT                                                                 */
1759 /*                                                                        */
1760 /*    dhcp_ptr                             Pointer to DHCP Server         */
1761 /*    dhcp_client_ptr                      Pointer to client to respond to*/
1762 /*                                                                        */
1763 /*  OUTPUT                                                                */
1764 /*                                                                        */
1765 /*    status                                Completion status from various*/
1766 /*                                              NetX calls                */
1767 /*                                                                        */
1768 /*  CALLS                                                                 */
1769 /*                                                                        */
1770 /*    nx_packet_allocate                    Allocate a DHCP packet        */
1771 /*    nx_packet_release                     Release DHCP packet           */
1772 /*    nx_udp_socket_send                    Send DHCP packet              */
1773 /*    _nx_dhcp_add_option                   Add an option to the request  */
1774 /*    _nx_dhcp_add_requested_option         Adds non standard option to   */
1775 /*                                                 server reply to client */
1776 /*    _nx_dhcp_load_server_options          Load option data from server  */
1777 /*                                             option list                */
1778 /*    _nx_dhcp_server_store_data            Store data into buffer        */
1779 /*                                                                        */
1780 /*  CALLED BY                                                             */
1781 /*                                                                        */
1782 /*   _nx_dhcp_listen_for_messages           Service Client DHCP messages  */
1783 /*                                                                        */
1784 /*  RELEASE HISTORY                                                       */
1785 /*                                                                        */
1786 /*    DATE              NAME                      DESCRIPTION             */
1787 /*                                                                        */
1788 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1789 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1790 /*                                            resulting in version 6.1    */
1791 /*                                                                        */
1792 /**************************************************************************/
_nx_dhcp_respond_to_client_message(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT * dhcp_client_ptr)1793 static UINT  _nx_dhcp_respond_to_client_message(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr)
1794 {
1795 
1796 NX_PACKET               *packet_ptr;
1797 UCHAR                   *buffer;
1798 UINT                     status;
1799 UINT                     destination_ip_address;
1800 UINT                     destination_port;
1801 UINT                     index = 0;
1802 
1803 
1804 #ifdef EL_PRINTF_ENABLE
1805     /* Set local variables for convenience. */
1806     EL_PRINTF("DHCPserv: respond to client message on interface %d\n", dhcp_client_ptr -> nx_dhcp_client_iface_index);
1807 #endif
1808 
1809     /* Allocate a DHCP packet.  */
1810     status =  nx_packet_allocate(dhcp_ptr -> nx_dhcp_packet_pool_ptr, &packet_ptr, NX_IPv4_UDP_PACKET, NX_DHCP_PACKET_ALLOCATE_TIMEOUT);
1811 
1812     /* Was the packet allocation successful?  */
1813     if (status != NX_SUCCESS)
1814     {
1815 
1816         /* Return status.  */
1817         return(status);
1818     }
1819 
1820     /* Setup the packet buffer pointer.  */
1821     buffer =  packet_ptr -> nx_packet_prepend_ptr;
1822 
1823     /* Clear the buffer memory.  */
1824     memset((void *) buffer, 0, NX_DHCP_OFFSET_END);
1825 
1826     /* Setup the standard DHCP fields.  */
1827     buffer[NX_DHCP_OFFSET_OP] =        NX_DHCP_OP_REPLY;
1828     buffer[NX_DHCP_OFFSET_HTYPE] =     (UCHAR)dhcp_client_ptr -> nx_dhcp_client_hwtype;
1829     buffer[NX_DHCP_OFFSET_HLEN] =      (UCHAR)dhcp_client_ptr -> nx_dhcp_client_hwlen;
1830     buffer[NX_DHCP_OFFSET_HOPS] =      0;
1831     buffer[NX_DHCP_OFFSET_BOOT_FILE] = 0;
1832 
1833     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_XID, 4, dhcp_client_ptr -> nx_dhcp_xid);
1834     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_SECS, 2, 0);
1835     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_CLIENT_IP, 4, NX_DHCP_NO_ADDRESS);
1836     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_SERVER_IP, 4, NX_DHCP_NO_ADDRESS);
1837     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_RELAY_IP, 4, NX_DHCP_NO_ADDRESS);
1838     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_FLAGS, 1, dhcp_client_ptr -> nx_dhcp_broadcast_flag_set);
1839     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_CLIENT_HW, 2, dhcp_client_ptr -> nx_dhcp_client_mac_msw);
1840     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_CLIENT_HW + 2, 4, dhcp_client_ptr -> nx_dhcp_client_mac_lsw);
1841     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_VENDOR, 4, NX_DHCP_MAGIC_COOKIE);
1842 
1843     /* Update the index.  */
1844     index = NX_DHCP_OFFSET_OPTIONS;
1845 
1846     /* Add the list of options that go out with ALL server messages. */
1847     status = _nx_dhcp_load_server_options(dhcp_ptr, dhcp_client_ptr, buffer, NX_DHCP_OPTIONS_FOR_ALL_REPLIES, &index);
1848 
1849     /* Unless the server is sending a NACK, there are more options to add for the server reply. */
1850     if (dhcp_client_ptr -> nx_dhcp_response_type_to_client != NX_DHCP_TYPE_DHCPNACK)
1851     {
1852 
1853         /* Add the list of options that go out with server ACK replies (standard network parameters). */
1854         _nx_dhcp_load_server_options(dhcp_ptr, dhcp_client_ptr, buffer, NX_DHCP_OPTIONS_FOR_GENERIC_ACK, &index);
1855 
1856         /* Determine if there are any message specific options to add. */
1857         switch (dhcp_client_ptr -> nx_dhcp_message_type)
1858         {
1859 
1860             case NX_DHCP_TYPE_DHCPDISCOVER:
1861 
1862                 /* Are we returning an OFFER to the Client? */
1863                 if (dhcp_client_ptr -> nx_dhcp_response_type_to_client == NX_DHCP_TYPE_DHCPOFFER)
1864                 {
1865 
1866                     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_YOUR_IP, 4, dhcp_client_ptr -> nx_dhcp_your_ip_address);
1867 
1868                     /* Add the list of options that go out with server OFFER replies. */
1869                     _nx_dhcp_load_server_options(dhcp_ptr, dhcp_client_ptr, buffer, NX_DHCP_OPTIONS_FOR_REPLY_TO_OFFER, &index);
1870                 }
1871 
1872                 /* Increment the number of Discovery messages received.  */
1873                 dhcp_ptr -> nx_dhcp_discoveries_received++;
1874                 break;
1875 
1876 
1877             case NX_DHCP_TYPE_DHCPREQUEST:
1878 
1879                 /* Are we returning an ACK to the Client? */
1880                 if (dhcp_client_ptr -> nx_dhcp_response_type_to_client == NX_DHCP_TYPE_DHCPACK)
1881                 {
1882 
1883                     _nx_dhcp_server_store_data(buffer + NX_DHCP_OFFSET_YOUR_IP, 4, dhcp_client_ptr -> nx_dhcp_assigned_ip_address);
1884 
1885                     /* Add the list of options that go out with server ACKs replies. */
1886                     _nx_dhcp_load_server_options(dhcp_ptr, dhcp_client_ptr, buffer, NX_DHCP_OPTIONS_FOR_REPLY_TO_REQUEST, &index);
1887                 }
1888 
1889                 /* Increment the number of Request messages received.  */
1890                 dhcp_ptr -> nx_dhcp_requests_received++;
1891                 break;
1892 
1893             /* Note: DHCP Servers should not reply to NX_DHCP_REPLY_TO_RELEASE or NX_DHCP_REPLY_TO_DECLINE messages. */
1894             case NX_DHCP_TYPE_DHCPRELEASE:
1895                 dhcp_ptr -> nx_dhcp_releases_received++;
1896                 break;
1897 
1898             case NX_DHCP_TYPE_DHCPDECLINE:
1899                 dhcp_ptr -> nx_dhcp_declines_received++;
1900                 break;
1901 
1902             case NX_DHCP_TYPE_DHCPINFORM:
1903 
1904                 /* At this time the server sends just standard network parameters to INFORM requests.
1905                    so no additional options to add. */
1906 
1907                 /* Increment the number of Inform messages received.  */
1908                 dhcp_ptr -> nx_dhcp_informs_received++;
1909                 break;
1910 
1911             /* No other DHCP messages are supported by NetX DHCP Server at this time. */
1912             default:
1913                 break;
1914         }
1915 
1916         /* Determine which of the remaining client requested options the server has information for. */
1917         _nx_dhcp_load_server_options(dhcp_ptr, dhcp_client_ptr, buffer, NX_DHCP_OPTIONS_REQUESTED_BY_CLIENT, &index);
1918     }
1919 
1920     /* Setup the packet pointers.  */
1921     /* Added the END option.  */
1922     *(buffer + index) = NX_DHCP_SERVER_OPTION_END;
1923     index ++;
1924 
1925     /* Check the option length.  */
1926     if (index > NX_DHCP_OFFSET_END)
1927     {
1928         packet_ptr -> nx_packet_length = index;
1929         packet_ptr -> nx_packet_append_ptr =  packet_ptr -> nx_packet_prepend_ptr + index;
1930     }
1931     else
1932     {
1933         packet_ptr -> nx_packet_length = NX_DHCP_OFFSET_END;
1934         packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_END;
1935     }
1936 
1937     /* DHCP Server set the correct destination address and port to send resposne. RFC2131, Section4.1, Page23.
1938        1. If the 'giaddr' field in a DHCP message from a client is non-zero, the server sends any return messages to the 'DHCP server' port on the
1939           BOOTP relay agent whose address appears in 'giaddr'.
1940        2. If the 'giaddr'field is zero and the 'ciaddr' field is nonzero, then the server unicasts DHCPOFFER and DHCPACK messages to the address in 'ciaddr'.
1941        3. If 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is set, then the server broadcasts DHCPOFFER and DHCPACK messages to 0xffffffff.
1942        4. If the broadcast bit is not set and 'giaddr' is zero and 'ciaddr' is zero, then the server unicasts DHCPOFFER and DHCPACK messages to the client's hardware address and 'yiaddr' address.
1943        5. In all cases, when 'giaddr' is zero, the server broadcasts any DHCPNAK messages to 0xffffffff.  */
1944 
1945     /* Check the 'giaddr' field. */
1946     if (dhcp_client_ptr -> nx_dhcp_relay_ip_address)
1947     {
1948 
1949         /* Set the destination address and port. */
1950         destination_ip_address = dhcp_client_ptr -> nx_dhcp_relay_ip_address;
1951         destination_port = NX_DHCP_SERVER_UDP_PORT;
1952     }
1953     else
1954     {
1955         /* Check the DHCP response message type.  */
1956         if (dhcp_client_ptr -> nx_dhcp_response_type_to_client != NX_DHCP_TYPE_DHCPNACK)
1957         {
1958 
1959             /* Check the 'ciaddr' field*/
1960             if (dhcp_client_ptr -> nx_dhcp_clientip_address)
1961             {
1962                 destination_ip_address = dhcp_client_ptr -> nx_dhcp_clientip_address;
1963             }
1964             /* Check the broadcast bit.  */
1965             else if (dhcp_client_ptr -> nx_dhcp_broadcast_flag_set & NX_DHCP_FLAGS_BROADCAST)
1966             {
1967                 destination_ip_address = NX_DHCP_BC_ADDRESS;
1968             }
1969             else
1970             {
1971                 destination_ip_address = dhcp_client_ptr -> nx_dhcp_your_ip_address;
1972 
1973                 /* Add the dynamic arp entry.  */
1974                 status = nx_arp_dynamic_entry_set(dhcp_ptr -> nx_dhcp_ip_ptr, destination_ip_address, dhcp_client_ptr -> nx_dhcp_client_mac_msw, dhcp_client_ptr -> nx_dhcp_client_mac_lsw);
1975 
1976                 /* Check the status.  */
1977                 if (status)
1978                 {
1979                     nx_packet_release(packet_ptr);
1980 
1981                     return(status);
1982                 }
1983             }
1984         }
1985         else
1986         {
1987             destination_ip_address = NX_DHCP_BC_ADDRESS;
1988         }
1989 
1990         /* Set the destination port.  */
1991         destination_port = NX_DHCP_CLIENT_UDP_PORT;
1992     }
1993 
1994 #ifdef EL_PRINTF_ENABLE
1995     EL_PRINTF("DHCPserv: DHCP reply packet destination 0x%x\n", destination_ip_address);
1996     EL_PRINTF("DHCPserv: DHCP reply buffer size (bytes) %d\n", packet_ptr -> nx_packet_length);
1997     EL_PRINTF("DHCPserv: DHCP reply packet payload size (bytes) %d\n\n", packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_payload_size);
1998 #endif
1999 
2000 #ifdef PACKET_DUMP
2001 {
2002 
2003     ULONG *work_ptr;
2004     ULONG  uword;
2005     UINT i = 0;
2006     UINT index = 0;
2007     UINT length;
2008 
2009 #ifdef EL_PRINTF_ENABLE
2010     EL_PRINTF("DHCPserv: server reply to client - packet dump:\n");
2011 #endif
2012 
2013     work_ptr = (ULONG *)packet_ptr -> nx_packet_prepend_ptr;
2014     length = ((packet_ptr -> nx_packet_length + sizeof(ULONG) - 1)/sizeof(ULONG));
2015 
2016     while(i < length)
2017     {
2018         uword = *work_ptr;
2019 
2020         if (index == 10)
2021         {
2022 
2023 #ifdef EL_PRINTF_ENABLE
2024             EL_PRINTF("\n");
2025 #endif
2026             index = 0;
2027         }
2028 
2029 #ifdef EL_PRINTF_ENABLE
2030         EL_PRINTF(" %08x", uword);
2031 #endif
2032         work_ptr++;
2033         index++;
2034         i++;
2035     }
2036 #ifdef EL_PRINTF_ENABLE
2037     EL_PRINTF("\n\n");
2038 #endif
2039 }
2040 #endif  /* #ifdef PACKET_DUMP */
2041 
2042     /* Send the packet.  */
2043     status =  nx_udp_socket_interface_send(&(dhcp_ptr -> nx_dhcp_socket), packet_ptr, destination_ip_address, destination_port, dhcp_client_ptr -> nx_dhcp_client_iface_index);
2044 
2045     if (status != NX_SUCCESS)
2046     {
2047         nx_packet_release(packet_ptr);
2048     }
2049 
2050     /* Return completion status.  */
2051     return(status);
2052 }
2053 
2054 
2055 /**************************************************************************/
2056 /*                                                                        */
2057 /*  FUNCTION                                               RELEASE        */
2058 /*                                                                        */
2059 /*    _nx_dhcp_clear_client_session                       PORTABLE C      */
2060 /*                                                           6.1          */
2061 /*  AUTHOR                                                                */
2062 /*                                                                        */
2063 /*    Yuxin Zhou, Microsoft Corporation                                   */
2064 /*                                                                        */
2065 /*  DESCRIPTION                                                           */
2066 /*                                                                        */
2067 /*    This function clears data from the current client session (e.g. read*/
2068 /*    from the most recent client message. It does remove anything in the */
2069 /*    interface table associated with this client's subnet, nor change the*/
2070 /*    client state.                                                       */
2071 /*                                                                        */
2072 /*    Permanent client info such as client host name, client mac address  */
2073 /*    assigned IP address, or lease time is not cleared (left to the      */
2074 /*    caller).                                                            */
2075 /*                                                                        */
2076 /*  INPUT                                                                 */
2077 /*                                                                        */
2078 /*    dhcp_ptr                              Pointer to DHCP Server        */
2079 /*    dhcp_client_ptr                       Pointer to DHCP Client        */
2080 /*                                                                        */
2081 /*  OUTPUT                                                                */
2082 /*                                                                        */
2083 /*    NX_SUCCESS                            Successful outcome            */
2084 /*                                                                        */
2085 /*  CALLS                                                                 */
2086 /*                                                                        */
2087 /*    None                                                                */
2088 /*                                                                        */
2089 /*  CALLED BY                                                             */
2090 /*                                                                        */
2091 /*   _nx_dhcp_listen_for_messages           Handle Client DHCP messages   */
2092 /*   _nx_dhcp_fast_periodic_timer_entry     Session timer entry function  */
2093 /*                                                                        */
2094 /*  RELEASE HISTORY                                                       */
2095 /*                                                                        */
2096 /*    DATE              NAME                      DESCRIPTION             */
2097 /*                                                                        */
2098 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2099 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2100 /*                                            resulting in version 6.1    */
2101 /*                                                                        */
2102 /**************************************************************************/
_nx_dhcp_clear_client_session(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT * dhcp_client_ptr)2103 static UINT  _nx_dhcp_clear_client_session(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr)
2104 {
2105 
2106 UINT i;
2107 
2108     NX_PARAMETER_NOT_USED(dhcp_ptr);
2109 
2110     dhcp_client_ptr -> nx_dhcp_message_type = 0;
2111     dhcp_client_ptr -> nx_dhcp_response_type_to_client = 0;
2112     dhcp_client_ptr -> nx_dhcp_xid = 0;
2113     dhcp_client_ptr -> nx_dhcp_requested_ip_address = 0x0;
2114     dhcp_client_ptr -> nx_dhcp_requested_lease_time = 0x0;
2115     dhcp_client_ptr -> nx_dhcp_your_ip_address = 0x0;
2116     dhcp_client_ptr -> nx_dhcp_clientip_address = 0x0;
2117     dhcp_client_ptr -> nx_dhcp_server_id = 0x0;
2118     dhcp_client_ptr -> nx_dhcp_clientrec_server_ip = 0x0;
2119     dhcp_client_ptr -> nx_dhcp_broadcast_flag_set = NX_DHCP_FLAGS_BROADCAST;
2120     dhcp_client_ptr -> nx_dhcp_session_timeout = 0;
2121     dhcp_client_ptr -> nx_dhcp_destination_ip_address = 0;
2122     dhcp_client_ptr -> nx_dhcp_source_ip_address = 0;
2123 
2124     /* Clear out the option data. */
2125     dhcp_client_ptr -> nx_dhcp_client_option_count = 0;
2126     for (i = 0; i < NX_DHCP_CLIENT_OPTIONS_MAX; i++)
2127     {
2128          dhcp_client_ptr -> nx_dhcp_user_options[0] = 0;
2129     }
2130 
2131     return(NX_SUCCESS);
2132 }
2133 
2134 
2135 /**************************************************************************/
2136 /*                                                                        */
2137 /*  FUNCTION                                               RELEASE        */
2138 /*                                                                        */
2139 /*    _nxe_dhcp_clear_client_record                       PORTABLE C      */
2140 /*                                                           6.1          */
2141 /*  AUTHOR                                                                */
2142 /*                                                                        */
2143 /*    Yuxin Zhou, Microsoft Corporation                                   */
2144 /*                                                                        */
2145 /*  DESCRIPTION                                                           */
2146 /*                                                                        */
2147 /*    This function performs error checking for the clear client record   */
2148 /*    service.                                                            */
2149 /*                                                                        */
2150 /*  INPUT                                                                 */
2151 /*                                                                        */
2152 /*    dhcp_ptr                              Pointer to DHCP Server        */
2153 /*    dhcp_client_ptr                       Pointer to DHCP Client        */
2154 /*                                                                        */
2155 /*  OUTPUT                                                                */
2156 /*                                                                        */
2157 /*    NX_SUCCESS                            Successful outcome            */
2158 /*                                                                        */
2159 /*  CALLS                                                                 */
2160 /*                                                                        */
2161 /*    _nx_dhcp_clear_client_record     Actual clear client record service */
2162 /*                                                                        */
2163 /*  CALLED BY                                                             */
2164 /*                                                                        */
2165 /*   Host Application                                                     */
2166 /*                                                                        */
2167 /*  RELEASE HISTORY                                                       */
2168 /*                                                                        */
2169 /*    DATE              NAME                      DESCRIPTION             */
2170 /*                                                                        */
2171 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2172 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2173 /*                                            resulting in version 6.1    */
2174 /*                                                                        */
2175 /**************************************************************************/
_nxe_dhcp_clear_client_record(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT * dhcp_client_ptr)2176 UINT  _nxe_dhcp_clear_client_record(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr)
2177 {
2178 
2179 UINT status;
2180 
2181 
2182     /* Check for invalid input.  */
2183     if ((dhcp_ptr == NX_NULL) || (dhcp_client_ptr == NX_NULL))
2184     {
2185         return(NX_PTR_ERROR);
2186     }
2187 
2188     /* Check for appropriate caller.  */
2189     NX_THREADS_ONLY_CALLER_CHECKING
2190 
2191     /* Call actual DHCP clear client record service.  */
2192     status =  _nx_dhcp_clear_client_record(dhcp_ptr, dhcp_client_ptr);
2193 
2194     /* Return status.  */
2195     return(status);
2196 }
2197 
2198 
2199 /**************************************************************************/
2200 /*                                                                        */
2201 /*  FUNCTION                                               RELEASE        */
2202 /*                                                                        */
2203 /*    _nx_dhcp_clear_client_record                        PORTABLE C      */
2204 /*                                                           6.1          */
2205 /*  AUTHOR                                                                */
2206 /*                                                                        */
2207 /*    Yuxin Zhou, Microsoft Corporation                                   */
2208 /*                                                                        */
2209 /*  DESCRIPTION                                                           */
2210 /*                                                                        */
2211 /*    This function clears the entire client record from the server table.*/
2212 /*    It also frees up the client's IP address in the server IP address   */
2213 /*    table.                                                              */
2214 /*                                                                        */
2215 /*    The DHCP server does not use this function, it is strictly for the  */
2216 /*    host application to remove clients from the table (e.g. to free up  */
2217 /*    room for new clients by removing old 'stale' client entries no      */
2218 /*    longer configured with the server.                                  */
2219 /*                                                                        */
2220 /*  INPUT                                                                 */
2221 /*                                                                        */
2222 /*    dhcp_ptr                              Pointer to DHCP Server        */
2223 /*    dhcp_client_ptr                       Pointer to DHCP Client        */
2224 /*                                                                        */
2225 /*  OUTPUT                                                                */
2226 /*                                                                        */
2227 /*    NX_SUCCESS                            Successful outcome            */
2228 /*                                                                        */
2229 /*  CALLS                                                                 */
2230 /*                                                                        */
2231 /*    _nx_dhcp_clear_ip_address_owner     Clear IP address owner          */
2232 /*                                                                        */
2233 /*  CALLED BY                                                             */
2234 /*                                                                        */
2235 /*   Host Application                                                     */
2236 /*                                                                        */
2237 /*  RELEASE HISTORY                                                       */
2238 /*                                                                        */
2239 /*    DATE              NAME                      DESCRIPTION             */
2240 /*                                                                        */
2241 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2242 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2243 /*                                            resulting in version 6.1    */
2244 /*                                                                        */
2245 /**************************************************************************/
_nx_dhcp_clear_client_record(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT * dhcp_client_ptr)2246 UINT  _nx_dhcp_clear_client_record(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr)
2247 {
2248 
2249 UINT                     i;
2250 NX_DHCP_INTERFACE_TABLE  *iface_table_ptr;
2251 
2252 
2253     if (dhcp_client_ptr == 0x0)
2254     {
2255         /* Benign error. Return success. */
2256         return(NX_SUCCESS);
2257     }
2258 
2259     /* Obtain DHCP Server mutex protection,. */
2260     tx_mutex_get(&dhcp_ptr -> nx_dhcp_mutex, NX_WAIT_FOREVER);
2261 
2262     /* Set local pointer for convenience. */
2263     iface_table_ptr = &dhcp_ptr -> nx_dhcp_interface_table[dhcp_client_ptr -> nx_dhcp_client_iface_index];
2264 
2265     i = 0;
2266 
2267     /* Does the client have an assigned IP address? */
2268     if (iface_table_ptr -> nx_dhcp_ip_address_list[i].nx_assignable_ip_address)
2269     {
2270 
2271         /* Yes, We need to free up the Client's assigned IP address in the server database. */
2272         while (i < iface_table_ptr -> nx_dhcp_address_list_size)
2273         {
2274 
2275             /* Find the interface table entry by matching IP address. */
2276             if (iface_table_ptr -> nx_dhcp_ip_address_list[i].nx_assignable_ip_address ==
2277                 dhcp_client_ptr -> nx_dhcp_assigned_ip_address)
2278             {
2279 
2280                 /* Clear the owner information.  */
2281                 _nx_dhcp_clear_ip_address_owner(&(iface_table_ptr -> nx_dhcp_ip_address_list[i]));
2282 
2283                 /* Address now available for DHCP client. */
2284                 break;
2285             }
2286             i++;
2287         }
2288     }
2289 
2290     /* Ok to clear the Client record. */
2291     memset(dhcp_client_ptr, 0, sizeof(NX_DHCP_CLIENT));
2292 
2293     /* Update the total number of dhcp clients. */
2294     if (dhcp_ptr -> nx_dhcp_number_clients > 0)
2295     {
2296 
2297         dhcp_ptr -> nx_dhcp_number_clients--;
2298     }
2299 
2300     /* Release DHCP Server mutex.  */
2301     tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
2302 
2303     return(NX_SUCCESS);
2304 }
2305 
2306 
2307 /**************************************************************************/
2308 /*                                                                        */
2309 /*  FUNCTION                                               RELEASE        */
2310 /*                                                                        */
2311 /*    _nx_dhcp_load_server_options                        PORTABLE C      */
2312 /*                                                           6.1          */
2313 /*  AUTHOR                                                                */
2314 /*                                                                        */
2315 /*    Yuxin Zhou, Microsoft Corporation                                   */
2316 /*                                                                        */
2317 /*  DESCRIPTION                                                           */
2318 /*                                                                        */
2319 /*  This function adds the specified options in the server's DHCP option  */
2320 /*  list to the DHCP server response to the Client message. There is a    */
2321 /*  required set of options that go out with all server messages, as well */
2322 /*  as a standard (user configurable) set of options for all 'ACK'        */
2323 /*  messages.  Lastly, there are certain options that are specific to the */
2324 /*  client message request e.g. RENEW vs OFFER etc                        */
2325 /*                                                                        */
2326 /*  There is no support for responding to specific client options in this */
2327 /*  revision.                                                             */
2328 /*                                                                        */
2329 /*  INPUT                                                                 */
2330 /*                                                                        */
2331 /*    dhcp_ptr                            Pointer to DHCP Server          */
2332 /*    dhcp_client_ptr                     Pointer to client session record*/
2333 /*    buffer                              Packet buffer to load options to*/
2334 /*    option_type                         Category of options to load     */
2335 /*                                                                        */
2336 /*  OUTPUT                                                                */
2337 /*                                                                        */
2338 /*    NX_SUCCESS                           Successful completion status   */
2339 /*                                                                        */
2340 /*  CALLS                                                                 */
2341 /*                                                                        */
2342 /*    _nx_dhcp_add_option                 Add option to response (specify */
2343 /*                                                 option and data to add)*/
2344 /*    _nx_dhcp_add_requested_option       Add option to response          */
2345 /*                                            (specify option and client  */
2346 /*                                            interface)                  */
2347 /*                                                                        */
2348 /*  CALLED BY                                                             */
2349 /*                                                                        */
2350 /*    _nx_dhcp_respond_to_dhcp_message      Create and send response back */
2351 /*                                               DHCP Client              */
2352 /*                                                                        */
2353 /*  RELEASE HISTORY                                                       */
2354 /*                                                                        */
2355 /*    DATE              NAME                      DESCRIPTION             */
2356 /*                                                                        */
2357 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2358 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2359 /*                                            resulting in version 6.1    */
2360 /*                                                                        */
2361 /**************************************************************************/
_nx_dhcp_load_server_options(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT * dhcp_client_ptr,UCHAR * buffer,UINT option_type,UINT * index)2362 static UINT  _nx_dhcp_load_server_options(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr, UCHAR *buffer, UINT option_type, UINT *index)
2363 {
2364 
2365 UINT i;
2366 UINT iface_index;
2367 UINT renew_time;
2368 UINT rebind_time;
2369 UINT lease_time;
2370 
2371 
2372     /* Compute default lease, renew and rebind times to offer the client. */
2373     lease_time = dhcp_client_ptr -> nx_dhcp_requested_lease_time;
2374 
2375 #if (NX_DHCP_DEFAULT_LEASE_TIME >= 0xFFFFFFFF)
2376     if (lease_time == 0)
2377 #else
2378     if ((lease_time == 0) || (lease_time > NX_DHCP_DEFAULT_LEASE_TIME))
2379 #endif
2380     {
2381         lease_time = NX_DHCP_DEFAULT_LEASE_TIME;
2382     }
2383 
2384     renew_time = lease_time/2;
2385     rebind_time = 7 * (lease_time/8);
2386 
2387     /* Set a local pointer for convenience. */
2388     iface_index = dhcp_client_ptr -> nx_dhcp_client_iface_index;
2389 
2390     /* Determine what set of options to apply based on caller input. */
2391     if (option_type == NX_DHCP_OPTIONS_FOR_ALL_REPLIES)
2392     {
2393 
2394         /* This is the generic set of options for ALL server replies. */
2395 
2396         /* Set the DHCP message type the server is sending back to client.  */
2397         _nx_dhcp_add_option(buffer, NX_DHCP_SERVER_OPTION_DHCP_TYPE, NX_DHCP_SERVER_OPTION_DHCP_TYPE_SIZE,
2398                             dhcp_client_ptr -> nx_dhcp_response_type_to_client, index);
2399 
2400         /* Add the server identifier to all messages to the client. */
2401         _nx_dhcp_add_option(buffer, NX_DHCP_SERVER_OPTION_DHCP_SERVER_ID, NX_DHCP_SERVER_OPTION_DHCP_SERVER_SIZE,
2402                             dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_server_ip_address, index);
2403 
2404         return(NX_SUCCESS);
2405     }
2406     else if (option_type == NX_DHCP_OPTIONS_FOR_REPLY_TO_OFFER)
2407     {
2408 
2409         /* Offer an IP lease. */
2410         _nx_dhcp_add_option(buffer, NX_DHCP_SERVER_OPTION_DHCP_LEASE, NX_DHCP_SERVER_OPTION_DHCP_LEASE_SIZE, lease_time, index);
2411         /* With the computed renew time. */
2412         _nx_dhcp_add_option(buffer, NX_DHCP_SERVER_OPTION_RENEWAL, NX_DHCP_SERVER_OPTION_RENEWAL_SIZE, renew_time, index);
2413         /* And rebind time. */
2414         _nx_dhcp_add_option(buffer, NX_DHCP_SERVER_OPTION_REBIND, NX_DHCP_SERVER_OPTION_REBIND_SIZE, rebind_time, index);
2415     }
2416     else if (option_type == NX_DHCP_OPTIONS_FOR_REPLY_TO_REQUEST)
2417     {
2418 
2419         /* Confirm the assigned IP lease, renew and rebind times. */
2420         _nx_dhcp_add_option(buffer, NX_DHCP_SERVER_OPTION_DHCP_LEASE, NX_DHCP_SERVER_OPTION_DHCP_LEASE_SIZE, lease_time, index);
2421         _nx_dhcp_add_option(buffer, NX_DHCP_SERVER_OPTION_RENEWAL, NX_DHCP_SERVER_OPTION_RENEWAL_SIZE, renew_time, index);
2422         _nx_dhcp_add_option(buffer, NX_DHCP_SERVER_OPTION_REBIND, NX_DHCP_SERVER_OPTION_REBIND_SIZE, rebind_time, index);
2423     }
2424     else if (option_type == NX_DHCP_OPTIONS_FOR_REPLY_TO_INFORM)
2425     {
2426 
2427         /* The NetX DHCP Server reply to Inform messages includes the standard server option
2428            list which is automatically included. */
2429     }
2430     else if (option_type == NX_DHCP_OPTIONS_FOR_GENERIC_ACK)
2431     {
2432 
2433         /* Add the standard DHCP server information (e.g. subnet, router IP etc) which are
2434            appended to the required server options. */
2435         for (i= NX_DHCP_REQUIRED_SERVER_OPTION_SIZE; i < dhcp_ptr -> nx_dhcp_server_option_count; i++)
2436         {
2437 
2438             /* Append this DHCP option to the client message. */
2439             _nx_dhcp_add_requested_option(dhcp_ptr,  dhcp_client_ptr -> nx_dhcp_client_iface_index,
2440                                                    buffer, dhcp_ptr -> nx_dhcp_server_options[i], index);
2441         }
2442     }
2443     else if (option_type == NX_DHCP_OPTIONS_REQUESTED_BY_CLIENT)
2444     {
2445 
2446         /* The NetX DHSP Server does not (yet) support this feature in the current release. */
2447 
2448         /* Clear the current DHCP Client's requested option list. */
2449         for (i = 0; i < dhcp_client_ptr -> nx_dhcp_client_option_count; i++)
2450         {
2451 
2452             dhcp_client_ptr -> nx_dhcp_user_options[i] = 0;
2453         }
2454 
2455         dhcp_client_ptr -> nx_dhcp_client_option_count = 0;
2456     }
2457 
2458     return(NX_SUCCESS);
2459 }
2460 
2461 
2462 /**************************************************************************/
2463 /*                                                                        */
2464 /*  FUNCTION                                               RELEASE        */
2465 /*                                                                        */
2466 /*    _nx_dhcp_set_default_server_options                 PORTABLE C      */
2467 /*                                                           6.1          */
2468 /*  AUTHOR                                                                */
2469 /*                                                                        */
2470 /*    Yuxin Zhou, Microsoft Corporation                                   */
2471 /*                                                                        */
2472 /*  DESCRIPTION                                                           */
2473 /*                                                                        */
2474 /*  This function parses a set of options from the supplied buffer into   */
2475 /*  the server's list of options to supply data to the DHCP Client. If the*/
2476 /*  server is configured to use default option data, it will use this list*/
2477 /*  of options to compose the response to the Client.                     */
2478 /*                                                                        */
2479 /*  INPUT                                                                 */
2480 /*                                                                        */
2481 /*    dhcp_ptr                             Pointer to DHCP Server         */
2482 /*    buffer                               Pointer to option list         */
2483 /*    size                                 Size of option list buffer     */
2484 /*                                                                        */
2485 /*  OUTPUT                                                                */
2486 /*                                                                        */
2487 /*    NX_SUCCESS                            Successful completion status  */
2488 /*    status                                Actual error status           */
2489 /*                                                                        */
2490 /*  CALLS                                                                 */
2491 /*                                                                        */
2492 /*    None                                                                */
2493 /*                                                                        */
2494 /*  CALLED BY                                                             */
2495 /*                                                                        */
2496 /*    _nx_dhcp_server_create               Create the DHCP Server instance*/
2497 /*                                                                        */
2498 /*  RELEASE HISTORY                                                       */
2499 /*                                                                        */
2500 /*    DATE              NAME                      DESCRIPTION             */
2501 /*                                                                        */
2502 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2503 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2504 /*                                            resulting in version 6.1    */
2505 /*                                                                        */
2506 /**************************************************************************/
_nx_dhcp_set_server_options(NX_DHCP_SERVER * dhcp_ptr,CHAR * buffer,UINT buffer_size)2507 static UINT  _nx_dhcp_set_server_options(NX_DHCP_SERVER *dhcp_ptr, CHAR *buffer, UINT buffer_size)
2508 {
2509 
2510 UINT j;
2511 UINT digit;
2512 UINT status;
2513 CHAR *work_ptr;
2514 
2515 
2516     j = 0;
2517     /* Search through the text for all options to load. */
2518     while(buffer_size && (j < NX_DHCP_SERVER_OPTION_LIST_SIZE))
2519     {
2520 
2521         /* Check if we're off the end of the buffer. */
2522         if (buffer == 0x0)
2523         {
2524             break;
2525         }
2526 
2527         work_ptr = buffer;
2528 
2529         /* This should advance the buffer past the digit.*/
2530         status = _nx_dhcp_parse_next_option(&buffer, &digit, buffer_size);
2531         if (status)
2532         {
2533 
2534 #ifdef EL_PRINTF_ENABLE
2535             EL_PRINTF("DHCPserv: Unable to set server DHCP option data list. Status 0x%x\n", status);
2536 #endif
2537 
2538             return(status);
2539         }
2540 
2541         buffer_size -= (UINT)(buffer - work_ptr);
2542 
2543         /* Load the parsed option into the server 'option list.' */
2544         dhcp_ptr -> nx_dhcp_server_options[j] = digit;
2545         j++;
2546     }
2547 
2548     /* Update the number of server options in the list. */
2549     dhcp_ptr -> nx_dhcp_server_option_count = j;
2550 
2551     return(NX_SUCCESS);
2552 }
2553 
2554 
2555 /**************************************************************************/
2556 /*                                                                        */
2557 /*  FUNCTION                                               RELEASE        */
2558 /*                                                                        */
2559 /*    _nx_dhcp_parse_next_option                          PORTABLE C      */
2560 /*                                                           6.1.3        */
2561 /*  AUTHOR                                                                */
2562 /*                                                                        */
2563 /*    Yuxin Zhou, Microsoft Corporation                                   */
2564 /*                                                                        */
2565 /*  DESCRIPTION                                                           */
2566 /*                                                                        */
2567 /*  This function parses space or comma separated numeric data from the   */
2568 /*  supplied buffer, for example, the server option list.                 */
2569 /*                                                                        */
2570 /*  INPUT                                                                 */
2571 /*                                                                        */
2572 /*    option_list                           Pointer to buffer to parse    */
2573 /*    option                                Data parsed from buffer       */
2574 /*    length                                Size of option list buffer    */
2575 /*                                                                        */
2576 /*  OUTPUT                                                                */
2577 /*                                                                        */
2578 /*    NX_SUCCESS                            Successful completion status  */
2579 /*    NX_DHCP_INTERNAL_OPTION_PARSE_ERROR   Parsing error status          */
2580 /*                                                                        */
2581 /*  CALLS                                                                 */
2582 /*                                                                        */
2583 /*    _nx_utility_string_to_uint           Convert ascii number to integer*/
2584 /*                                                                        */
2585 /*  CALLED BY                                                             */
2586 /*                                                                        */
2587 /*    _nx_dhcp_set_default_server_options  Creates the server option list */
2588 /*                                                                        */
2589 /*  RELEASE HISTORY                                                       */
2590 /*                                                                        */
2591 /*    DATE              NAME                      DESCRIPTION             */
2592 /*                                                                        */
2593 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2594 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2595 /*                                            resulting in version 6.1    */
2596 /*  12-31-2020     Yuxin Zhou               Modified comment(s), fixed    */
2597 /*                                            obsolescent functions,      */
2598 /*                                            resulting in version 6.1.3  */
2599 /*                                                                        */
2600 /**************************************************************************/
_nx_dhcp_parse_next_option(CHAR ** option_list,UINT * option,UINT length)2601 static UINT  _nx_dhcp_parse_next_option(CHAR **option_list, UINT *option, UINT length)
2602 {
2603 
2604 CHAR c;
2605 UINT j;
2606 UINT buffer_index;
2607 CHAR num_string[3];
2608 CHAR *buffer;
2609 
2610 
2611     /* Check for invalid input. */
2612     if ((option_list == 0x0) || (option == 0) || (length == 0))
2613     {
2614         return(NX_DHCP_INTERNAL_OPTION_PARSE_ERROR);
2615     }
2616 
2617     buffer = *option_list;
2618     memset(&num_string[0], 0, 3);
2619 
2620     /* Initialize parsed option to undefined option (sorry, zero is taken by the PAD option
2621        which I personally think was a bad programming decision). */
2622     *option = 999;
2623     j = 0;
2624     buffer_index = 0;
2625 
2626     /* Get the first character in the buffer. */
2627     c = *buffer++;
2628 
2629     /* Get the first digit (non separator character)*/
2630     while ((c == ' ') || (c == ','))
2631     {
2632 
2633         c = *buffer++;
2634         j++;
2635     }
2636 
2637     /* Now parse the next characters until the end of the buffer or next separator character. */
2638     while ((j < length) && (buffer_index < 3))
2639     {
2640 
2641         /* Check for separator marking the end of the option string. */
2642         if ((c == ' ') || (c == ',') || (c == 0x0))
2643             break;
2644 
2645         /* Check for an invalid digit or out of range option. */
2646         if (c < 0x30 || c > 0x39 || buffer_index > 2)
2647         {
2648             return(NX_DHCP_BAD_OPTION_LIST_ERROR);
2649         }
2650 
2651         num_string[buffer_index] = c;
2652         j++;
2653 
2654         /* Append the character ('digit') into a number buffer. */
2655         c = *buffer++;
2656         buffer_index++;
2657     }
2658 
2659     *option_list += j;
2660 
2661     /* Convert the number string to an actual unsigned integer. */
2662     return(_nx_utility_string_to_uint(num_string, buffer_index, option));
2663 }
2664 
2665 
2666 /**************************************************************************/
2667 /*                                                                        */
2668 /*  FUNCTION                                               RELEASE        */
2669 /*                                                                        */
2670 /*    _nx_dhcp_server_packet_process                      PORTABLE C      */
2671 /*                                                           6.3.0        */
2672 /*  AUTHOR                                                                */
2673 /*                                                                        */
2674 /*    Yuxin Zhou, Microsoft Corporation                                   */
2675 /*                                                                        */
2676 /*  DESCRIPTION                                                           */
2677 /*                                                                        */
2678 /*    This function processes a Client DHCP message and extracts          */
2679 /*    information from a client DHCP message to create or update the      */
2680 /*    client record.  It handles the DHCP message based on type, sets     */
2681 /*    a timer on the client record if a response is expected from the     */
2682 /*    client, and waits for another DHCP packet.                          */
2683 /*                                                                        */
2684 /*  INPUT                                                                 */
2685 /*                                                                        */
2686 /*    dhcp_ptr                              Pointer to DHCP Server        */
2687 /*                                                                        */
2688 /*  OUTPUT                                                                */
2689 /*                                                                        */
2690 /*    NX_SUCCESS                           Message handled successfully   */
2691 /*    NO_PACKET                            No packet received             */
2692 /*    NX_DHCP_SERVER_BAD_INTERFACE_INDEX   Packet interface not recognized*/
2693 /*    status                               Actual completion outcome      */
2694 /*                                                                        */
2695 /*  CALLS                                                                 */
2696 /*                                                                        */
2697 /*    nx_packet_release                     Release DHCP packet           */
2698 /*    nx_udp_socket_receive                 Receive DHCP packet           */
2699 /*    _nx_dhcp_server_extract_information   Extract DHCP packet info      */
2700 /*    _nx_dhcp_validate_client_message      Process the Client message    */
2701 /*    _nx_dhcp_server_assign_ip_address     Assign IP address to Client   */
2702 /*    _nx_dhcp_respond_to_client_message    Create and send response back */
2703 /*    _nx_dhcp_clear_client_session         Clears client session data    */
2704 /*                                                                        */
2705 /*  CALLED BY                                                             */
2706 /*                                                                        */
2707 /*    _nx_dhcp_server_thread_entry          DHCP Server thread task       */
2708 /*                                                                        */
2709 /*  RELEASE HISTORY                                                       */
2710 /*                                                                        */
2711 /*    DATE              NAME                      DESCRIPTION             */
2712 /*                                                                        */
2713 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2714 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2715 /*                                            resulting in version 6.1    */
2716 /*  10-31-2023     Bo Chen                  Modified comment(s), corrected*/
2717 /*                                            the logic of verifying the  */
2718 /*                                            incoming packet length,     */
2719 /*                                            resulting in version 6.3.0  */
2720 /*                                                                        */
2721 /**************************************************************************/
_nx_dhcp_server_packet_process(NX_DHCP_SERVER * dhcp_ptr,NX_PACKET * packet_ptr)2722 static UINT  _nx_dhcp_server_packet_process(NX_DHCP_SERVER *dhcp_ptr, NX_PACKET *packet_ptr)
2723 {
2724 
2725 UINT            status;
2726 UINT            iface_index;
2727 NX_DHCP_CLIENT  *dhcp_client_ptr = NX_NULL;
2728 NX_PACKET       *new_packet_ptr;
2729 ULONG           bytes_copied = 0;
2730 ULONG           offset;
2731 
2732 #ifdef EL_PRINTF_ENABLE
2733     EL_PRINTF("\n");
2734     EL_PRINTF("DHCPserv: Waiting to receive next packet\n");
2735 #endif
2736 
2737     /* Check for minimum sized DHCP packet (e.g. just the DHCP header and 0 bytes of option data). */
2738     if (packet_ptr -> nx_packet_length <  NX_DHCP_HEADER_SIZE)
2739     {
2740 #ifdef EL_PRINTF_ENABLE
2741         EL_PRINTF("DHCPserv: Client DHCP packet is malformed or empty. Invalid DHCP packet.\n");
2742 #endif
2743 
2744         /* No; Release the original packet. */
2745         nx_packet_release(packet_ptr);
2746 
2747         /* Return successful completion status. */
2748         return(NX_DHCP_MALFORMED_DHCP_PACKET);
2749     }
2750 
2751     /* Get the interface index.  */
2752      nx_udp_packet_info_extract(packet_ptr, NX_NULL, NX_NULL, NX_NULL, &iface_index);
2753 
2754     /* Does the DHCP server have a table for this packet interface? */
2755     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
2756     {
2757 
2758 #ifdef EL_PRINTF_ENABLE
2759         EL_PRINTF("DHCPserv: No interface found for DHCP packet\n");
2760 #endif
2761 
2762         /* Release the original packet. */
2763         nx_packet_release(packet_ptr);
2764 
2765         /* No, return the error status. */
2766         return(NX_DHCP_SERVER_BAD_INTERFACE_INDEX);
2767     }
2768 
2769     /* We will copy the received packet (datagram) over to a packet from the DHCP Server pool and release
2770        the packet from the receive packet pool as soon as possible. */
2771     status =  nx_packet_allocate(dhcp_ptr -> nx_dhcp_packet_pool_ptr, &new_packet_ptr, NX_IPv4_UDP_PACKET, NX_DHCP_PACKET_ALLOCATE_TIMEOUT);
2772 
2773     /* Check status.  */
2774     if (status != NX_SUCCESS)
2775     {
2776 
2777         /* Release the original packet. */
2778         nx_packet_release(packet_ptr);
2779 
2780         /* Error allocating packet, return error status.  */
2781         return(status);
2782     }
2783 
2784     /* Update the prepend pointer to make sure that the IP header and UDP header also are copied into new packet. */
2785     packet_ptr -> nx_packet_prepend_ptr -= 28;
2786     packet_ptr -> nx_packet_length += 28;
2787 
2788     /* Verify the incoming packet does not exceed our DHCP Server packet payload. */
2789     if ((ULONG)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr) < (packet_ptr -> nx_packet_length))
2790     {
2791 
2792         /* Release the original packet. */
2793         nx_packet_release(packet_ptr);
2794 
2795         /* Release the newly allocated packet and return an error. */
2796         nx_packet_release(new_packet_ptr);
2797 
2798         return(NX_DHCP_INADEQUATE_PACKET_POOL_PAYLOAD);
2799     }
2800 
2801     /* Initialize the offset to the beginning of the packet buffer. */
2802     offset = 0;
2803     status = nx_packet_data_extract_offset(packet_ptr, offset, (VOID *)new_packet_ptr -> nx_packet_prepend_ptr, packet_ptr -> nx_packet_length, &bytes_copied);
2804 
2805     /* Check status.  */
2806     if ((status != NX_SUCCESS) || (bytes_copied != packet_ptr -> nx_packet_length))
2807     {
2808 
2809         /* Release the original packet. */
2810         nx_packet_release(packet_ptr);
2811 
2812         /* Release the allocated packet we'll never send. */
2813         nx_packet_release(new_packet_ptr);
2814 
2815         /* Error extracting packet buffer, return error status.  */
2816         return(status);
2817     }
2818 
2819     /* Update the new packet with the bytes copied, and removed.
2820        For chained packets, this will reflect the total 'datagram' length. */
2821     new_packet_ptr -> nx_packet_prepend_ptr += 28;
2822     new_packet_ptr -> nx_packet_length = bytes_copied - 28;
2823     new_packet_ptr -> nx_packet_append_ptr = new_packet_ptr -> nx_packet_prepend_ptr + new_packet_ptr -> nx_packet_length;
2824 
2825     /* Now we can release the original packet. */
2826     nx_packet_release(packet_ptr);
2827 
2828     /* Extract the DHCP specific information from the packet. This will create new record or update existing
2829        client record in the server database. */
2830     status = _nx_dhcp_server_extract_information(dhcp_ptr, &dhcp_client_ptr, new_packet_ptr, iface_index);
2831 
2832 #ifdef PACKET_DUMP
2833 {
2834 
2835     ULONG *work_ptr;
2836     ULONG  uword;
2837     UINT i = 0;
2838     UINT index = 0;
2839     UINT length;
2840 
2841 #ifdef EL_PRINTF_ENABLE
2842     EL_PRINTF("DHCPserv: received client packet dump:\n");
2843 #endif
2844 
2845     /* Get a pointer to the IP header and adjust the packet length for IP and UDP header size. */
2846     work_ptr = (ULONG *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER) - sizeof(NX_IPV4_HEADER));
2847     length = ((packet_ptr -> nx_packet_length + sizeof(ULONG) - 1)/sizeof(ULONG)) + sizeof(NX_UDP_HEADER) + sizeof(NX_IPV4_HEADER);
2848 
2849     while(i < length)
2850     {
2851         uword = *work_ptr;
2852 
2853         if (index == 10)
2854         {
2855 
2856 #ifdef EL_PRINTF_ENABLE
2857             EL_PRINTF("\n");
2858 #endif
2859             index = 0;
2860         }
2861 #ifdef EL_PRINTF_ENABLE
2862         EL_PRINTF(" %08x", uword);
2863 #endif
2864         work_ptr++;
2865         index++;
2866         i++;
2867     }
2868 #ifdef EL_PRINTF_ENABLE
2869     EL_PRINTF("\n\n");
2870 #endif
2871 }
2872 #endif  /* #ifdef PACKET_DUMP */
2873 
2874     /* We are done with this packet now regardless of the success of the above operations. */
2875     nx_packet_release(new_packet_ptr);
2876 
2877     /* Check if we have an invalid client record. */
2878     if ((status != NX_SUCCESS) && dhcp_client_ptr)
2879     {
2880 
2881 #ifdef EL_PRINTF_ENABLE
2882         EL_PRINTF("DHCPserv: Error extracting DHCP packet (invalid): 0x%x\n", status);
2883 #endif
2884 
2885        /* Client record was created but there was a problem with the packet
2886          or client message. Since we're not sure what got written to the Client record,
2887          remove packet data out completely. */
2888         _nx_dhcp_clear_client_record(dhcp_ptr, dhcp_client_ptr);
2889     }
2890 
2891     /* Check for general errors or failure to produce a client record. */
2892     if ((status != NX_SUCCESS) || !dhcp_client_ptr)
2893     {
2894 
2895 #ifdef EL_PRINTF_ENABLE
2896         EL_PRINTF("DHCPserv: Internal error extracting DHCP packet: 0x%x\n", status);
2897 #endif
2898 
2899         /* Return the error from extracting packet data. */
2900         return(status);
2901     }
2902 
2903     /* Clear any previous response type in the client record. */
2904     dhcp_client_ptr -> nx_dhcp_response_type_to_client = 0;
2905 
2906     /* Validate the client message including how the server should respond to it. */
2907     status = _nx_dhcp_validate_client_message(dhcp_ptr, dhcp_client_ptr);
2908 
2909     /* Check for errors. */
2910     if (status != NX_SUCCESS)
2911     {
2912 
2913 #ifdef EL_PRINTF_ENABLE
2914         EL_PRINTF("DHCPserv: DHCP packet failed validation: 0x%x\n", status);
2915 #endif
2916 
2917         /* Return all other errors as completion status. Do not send a message to the client. */
2918         return(status);
2919     }
2920 
2921     /* Assign/confirm the assigned IP address of the Client if the server is not returning
2922        a NACK, responding to an INFORM message, or not responding at all. */
2923     if ((dhcp_client_ptr -> nx_dhcp_response_type_to_client != NX_DHCP_TYPE_DHCPNACK) &&
2924         (dhcp_client_ptr -> nx_dhcp_response_type_to_client != NX_DHCP_TYPE_DHCPSILENT) &&
2925         (dhcp_client_ptr -> nx_dhcp_message_type != NX_DHCP_TYPE_DHCPINFORM))
2926     {
2927 
2928 #ifdef EL_PRINTF_ENABLE
2929         EL_PRINTF("DHCPserv: assigning IP address to DHCP client...\n");
2930 #endif
2931 
2932         /* Assign/confirm an IP address to the client. If the client is renewing or rebinding
2933            this will verify they sent the correct IP address and reset the lease time. */
2934         status = _nx_dhcp_server_assign_ip_address(dhcp_ptr, dhcp_client_ptr);
2935 
2936         /* Has the server run out of available addresses? Handle this 'error'
2937           condition separately.  */
2938         if (status == NX_DHCP_NO_AVAILABLE_IP_ADDRESSES)
2939         {
2940 
2941 #ifdef EL_PRINTF_ENABLE
2942             EL_PRINTF("DHCPserv: Unable to assign IP address; none available\n");
2943 #endif
2944 
2945             /* Actually as yet, there is no callback to the host application
2946                for handling this situation.
2947 
2948                The server should still send a NACK to the Client that it cannot
2949                provide what it requests. */
2950         }
2951         /* Check for errors other than running out of available IP addresses. */
2952         else if (status != NX_SUCCESS)
2953         {
2954 
2955 #ifdef EL_PRINTF_ENABLE
2956             EL_PRINTF("DHCPserv: Unable to assign IP address. Status: 0x%x\n", status);
2957 #endif
2958 
2959             /* Return all other errors as completion status. Do not send a message to the client. */
2960             return(status);
2961         }
2962     }
2963 
2964 #ifdef EL_PRINTF_ENABLE
2965     if (dhcp_client_ptr -> nx_dhcp_response_type_to_client == NX_DHCP_TYPE_DHCPOFFER)
2966         EL_PRINTF("DHCPserv: response to client: OFFER\n");
2967     else if (dhcp_client_ptr -> nx_dhcp_response_type_to_client == NX_DHCP_TYPE_DHCPACK)
2968         EL_PRINTF("DHCPserv: response to client: ACK\n");
2969     else if (dhcp_client_ptr -> nx_dhcp_response_type_to_client == NX_DHCP_TYPE_DHCPNACK)
2970         EL_PRINTF("DHCPserv: response to client: NACK\n");
2971     else if (dhcp_client_ptr -> nx_dhcp_response_type_to_client == NX_DHCP_TYPE_DHCPSILENT)
2972         EL_PRINTF("DHCPserv: response to client: SILENT (no response)\n");
2973 #endif
2974 
2975 
2976     /* Is there a response to send to the Client? */
2977     if (dhcp_client_ptr -> nx_dhcp_response_type_to_client != NX_DHCP_TYPE_DHCPSILENT)
2978     {
2979 
2980         /* Yes; use the session data in the client record to compose the server reply. */
2981         status = _nx_dhcp_respond_to_client_message(dhcp_ptr, dhcp_client_ptr);
2982 
2983         /* Check for error. */
2984         if (status != NX_SUCCESS)
2985         {
2986 
2987 #ifdef EL_PRINTF_ENABLE
2988             EL_PRINTF("DHCPserv: Error sending response to DHCP client. Status: 0x%x\n", status);
2989 #endif
2990 
2991             /* Return error completion status. Error sending a message to client. */
2992             return(status);
2993         }
2994 
2995         /* Update the client state if an ACK was sent successfully. */
2996         if (dhcp_client_ptr -> nx_dhcp_response_type_to_client == NX_DHCP_TYPE_DHCPACK)
2997         {
2998 
2999             /* Was the client was in a requesting, renewing or rebinding state? */
3000             if ((dhcp_client_ptr -> nx_dhcp_client_state == NX_DHCP_STATE_RENEWING)   ||
3001                 (dhcp_client_ptr -> nx_dhcp_client_state == NX_DHCP_STATE_REBINDING)  ||
3002                 (dhcp_client_ptr -> nx_dhcp_client_state == NX_DHCP_STATE_REQUESTING))
3003             {
3004 
3005                 /* Yes, the client should now be bound to an IP address. */
3006                 dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_BOUND;
3007             }
3008         }
3009     }
3010 
3011     /*
3012        If the Client is BOUND, the session is over. Clear the session including
3013        the sesison timeout.
3014 
3015        If the Client is still in the BOOT or INIT state something was wrong with their
3016        message or else the server had a problem.  Clear the record and they
3017        can start a new session with a retransmission of their request.
3018     */
3019 
3020     /* Do we need to clear the session data depending? */
3021     if (dhcp_client_ptr -> nx_dhcp_client_state == NX_DHCP_STATE_BOOT ||
3022         dhcp_client_ptr -> nx_dhcp_client_state == NX_DHCP_STATE_INIT ||
3023         dhcp_client_ptr -> nx_dhcp_client_state == NX_DHCP_STATE_BOUND)
3024     {
3025 
3026 #ifdef EL_PRINTF_ENABLE
3027         EL_PRINTF("DHCPserv: client session completed. Clear session data.\n");
3028 #endif
3029 
3030         /* Yes, clear all data from the session. Client assigned IP address
3031            and hardware address are not cleared.*/
3032         _nx_dhcp_clear_client_session(dhcp_ptr,dhcp_client_ptr);
3033     }
3034     else
3035     {
3036 
3037 #ifdef EL_PRINTF_ENABLE
3038         EL_PRINTF("DHCPserv: Waiting for DHCP client response...\n");
3039 #endif
3040 
3041        /* No; assume the Client is Renewing, rebinding, or selecting,
3042           to set the session timeout to await the next Client response;
3043           (not finished with this DHCP session yet). */
3044 
3045         /* Assume we have received at least one message from the Client, so
3046            reset the timer on the client session timeout. */
3047         dhcp_client_ptr -> nx_dhcp_session_timeout = NX_DHCP_CLIENT_SESSION_TIMEOUT;
3048     }
3049 
3050 
3051 /* Output Server session data if enabled.  */
3052 #ifdef TESTOUTPUT
3053     add_client++;
3054 
3055     /* Only print out the session table depending on trace interval. */
3056     if ((TRACE_NTH_CLIENT_PACKET > 0) && (add_client % TRACE_NTH_CLIENT_PACKET == 0))
3057     {
3058 
3059         UINT i;
3060 
3061 #ifdef EL_PRINTF_ENABLE
3062         EL_PRINTF("\nClient\t\tAssigned\tLease\t\tSession\tState\n");
3063 #endif
3064         for (i = 0; i < dhcp_ptr -> nx_dhcp_number_clients; i++)
3065         {
3066             NX_DHCP_CLIENT *client_ptr;
3067 
3068             client_ptr = &(dhcp_ptr -> client_records[i]);
3069 
3070 #ifdef EL_PRINTF_ENABLE
3071             EL_PRINTF("0x%x 0x%x\t0x%08x\t0x%08x\t%d\t%d\n",
3072                    client_ptr -> nx_dhcp_client_mac_msw,
3073                    client_ptr -> nx_dhcp_client_mac_lsw,
3074                    client_ptr -> nx_dhcp_assigned_ip_address,
3075                    client_ptr -> nx_dhcp_requested_lease_time,
3076                    client_ptr -> nx_dhcp_session_timeout,
3077                    client_ptr -> nx_dhcp_client_state);
3078 #endif
3079         }
3080 
3081 #ifdef EL_PRINTF_ENABLE
3082         EL_PRINTF("\nHost\tIP address\tAssigned?  Lease\n");
3083         EL_PRINTF("Interface 0\n");
3084         for (i = 0; i < dhcp_ptr -> nx_dhcp_interface_table[0].nx_dhcp_address_list_size; i++)
3085         {
3086             NX_DHCP_INTERFACE_IP_ADDRESS *interface_address_ptr;
3087 
3088             interface_address_ptr = &(dhcp_ptr -> nx_dhcp_interface_table[0].nx_dhcp_ip_address_list[i]);
3089             EL_PRINTF("0x%x 0x%x\t0x%x\t%d\t  0x%x\n",
3090                    interface_address_ptr -> owner_mac_msw,
3091                    interface_address_ptr -> owner_mac_lsw,
3092                    interface_address_ptr -> nx_assignable_ip_address,
3093                    interface_address_ptr -> assigned,
3094                    interface_address_ptr -> lease_time);
3095         }
3096 
3097         EL_PRINTF("\nInterface 1\n");
3098         for (i = 0; i < dhcp_ptr -> nx_dhcp_interface_table[1].nx_dhcp_address_list_size; i++)
3099         {
3100             NX_DHCP_INTERFACE_IP_ADDRESS *interface_address_ptr;
3101 
3102             interface_address_ptr = &(dhcp_ptr -> nx_dhcp_interface_table[1].nx_dhcp_ip_address_list[i]);
3103             EL_PRINTF("0x%x 0x%x\t0x%x\t%d\t  0x%x\n",
3104                    interface_address_ptr -> owner_mac_msw,
3105                    interface_address_ptr -> owner_mac_lsw,
3106                    interface_address_ptr -> nx_assignable_ip_address,
3107                    interface_address_ptr -> assigned,
3108                    interface_address_ptr -> lease_time);
3109         }
3110 #endif
3111     }
3112 #endif
3113 
3114     /* Return actual outcome status.  */
3115     return(status);
3116 }
3117 
3118 
3119 /**************************************************************************/
3120 /*                                                                        */
3121 /*  FUNCTION                                               RELEASE        */
3122 /*                                                                        */
3123 /*    _nx_dhcp_find_client_record_by_ip_address           PORTABLE C      */
3124 /*                                                           6.1          */
3125 /*  AUTHOR                                                                */
3126 /*                                                                        */
3127 /*    Yuxin Zhou, Microsoft Corporation                                   */
3128 /*                                                                        */
3129 /*  DESCRIPTION                                                           */
3130 /*                                                                        */
3131 /*    This function looks up a client record using the client's last known*/
3132 /*    assigned IP address.                                                */
3133 /*                                                                        */
3134 /*  INPUT                                                                 */
3135 /*                                                                        */
3136 /*    dhcp_ptr                              Pointer to DHCP server        */
3137 /*    dhcp_client_ptr                       Pointer to DHCP client        */
3138 /*    iface_index                           Client network interface index*/
3139 /*    assigned_ip_address                   Client's assigned IP address  */
3140 /*                                                                        */
3141 /*  OUTPUT                                                                */
3142 /*                                                                        */
3143 /*    NX_SUCCESS                           Successful completion          */
3144 /*    NX_DHCP_CLIENT_RECORD_NOT_FOUND      Client record not found in     */
3145 /*                                             Server database            */
3146 /*                                                                        */
3147 /*  CALLS                                                                 */
3148 /*                                                                        */
3149 /*    _nx_dhcp_clear_client_record         Remove Client record from      */
3150 /*                                             Server database            */
3151 /*                                                                        */
3152 /*  CALLED BY                                                             */
3153 /*                                                                        */
3154 /*    _nx_dhcp_slow_periodic_timer_entry    Update IP lease time outs     */
3155 /*                                                                        */
3156 /*  RELEASE HISTORY                                                       */
3157 /*                                                                        */
3158 /*    DATE              NAME                      DESCRIPTION             */
3159 /*                                                                        */
3160 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3161 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3162 /*                                            resulting in version 6.1    */
3163 /*                                                                        */
3164 /**************************************************************************/
_nx_dhcp_find_client_record_by_ip_address(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT ** dhcp_client_ptr,UINT iface_index,ULONG assigned_ip_address)3165 UINT  _nx_dhcp_find_client_record_by_ip_address(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT **dhcp_client_ptr,
3166                                                UINT iface_index, ULONG assigned_ip_address)
3167 {
3168 
3169 UINT            i;
3170 NX_DHCP_CLIENT  *client_record_ptr;
3171 
3172 
3173     /* Initialize the search results to unsuccessful. */
3174     *dhcp_client_ptr = NX_NULL;
3175 
3176     i = 0;
3177 
3178     /* Records are not necessarily added and deleted sequentially,
3179        so search the whole table until a match is found. */
3180     while (i < NX_DHCP_CLIENT_RECORD_TABLE_SIZE)
3181     {
3182         /* Set local pointer for convenience. */
3183         client_record_ptr = &dhcp_ptr -> client_records[i];
3184 
3185         /* Check the mac address for a match. */
3186         if (client_record_ptr -> nx_dhcp_assigned_ip_address == assigned_ip_address)
3187         {
3188 
3189             /* Verify the client packet interface matches the interface on record. */
3190             if (client_record_ptr -> nx_dhcp_client_iface_index == iface_index)
3191             {
3192                 /* Return the client record location. */
3193                 *dhcp_client_ptr = client_record_ptr;
3194 
3195                 return(NX_SUCCESS);
3196             }
3197             else
3198             {
3199 
3200                 /* It appears the client has changed its subnet location but not hardware type e.g.
3201                    same mac address/hardware type but not interface. Clear the old record. */
3202 
3203                 /* This will remove the client record both in the
3204                    server's client table and in the IP address database. */
3205                 _nx_dhcp_clear_client_record(dhcp_ptr, client_record_ptr);
3206 
3207                 /* Search through the rest of the server records for
3208                    another instance of this client. Either way, if not found
3209                    with the expected interface a null pointer is returned,
3210                    or new record created depending on the caller. */
3211             }
3212         }
3213         i++;
3214     }
3215 
3216     return(NX_DHCP_CLIENT_RECORD_NOT_FOUND);
3217 }
3218 
3219 
3220 /**************************************************************************/
3221 /*                                                                        */
3222 /*  FUNCTION                                               RELEASE        */
3223 /*                                                                        */
3224 /*    _nx_dhcp_find_client_record_by_chaddr               PORTABLE C      */
3225 /*                                                           6.1          */
3226 /*  AUTHOR                                                                */
3227 /*                                                                        */
3228 /*    Yuxin Zhou, Microsoft Corporation                                   */
3229 /*                                                                        */
3230 /*  DESCRIPTION                                                           */
3231 /*                                                                        */
3232 /*    This function looks up a client record by the client hardware mac   */
3233 /*    address.                                                            */
3234 /*                                                                        */
3235 /*  INPUT                                                                 */
3236 /*                                                                        */
3237 /*    dhcp_ptr                              Pointer to DHCP Server        */
3238 /*    iface_index                           Client interface index        */
3239 /*    client_mac_msw                        MSB of client hardware address*/
3240 /*    client_mac_lsw                        LSB of client hardware address*/
3241 /*    dhcp_client_ptr                       Pointer to client record entry*/
3242 /*    add_on                                Option to add if not found    */
3243 /*                                                                        */
3244 /*  OUTPUT                                                                */
3245 /*                                                                        */
3246 /*    NX_SUCCESS                           Message handled successfully   */
3247 /*    NX_DHCP_CLIENT_TABLE_FULL            No more room in Client table   */
3248 /*                                                                        */
3249 /*  CALLS                                                                 */
3250 /*                                                                        */
3251 /*    _nx_dhcp_clear_client_record          Removes client record from    */
3252 /*                                              server table              */
3253 /*                                                                        */
3254 /*  CALLED BY                                                             */
3255 /*                                                                        */
3256 /*    _nx_dhcp_server_extract_information    Extract DHCP info from Client */
3257 /*                                             message                    */
3258 /*                                                                        */
3259 /*  RELEASE HISTORY                                                       */
3260 /*                                                                        */
3261 /*    DATE              NAME                      DESCRIPTION             */
3262 /*                                                                        */
3263 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3264 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3265 /*                                            resulting in version 6.1    */
3266 /*                                                                        */
3267 /**************************************************************************/
_nx_dhcp_find_client_record_by_chaddr(NX_DHCP_SERVER * dhcp_ptr,UINT iface_index,ULONG client_mac_msw,ULONG client_mac_lsw,NX_DHCP_CLIENT ** dhcp_client_ptr,UINT add_on)3268 static UINT  _nx_dhcp_find_client_record_by_chaddr(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index, ULONG client_mac_msw,
3269                                  ULONG client_mac_lsw, NX_DHCP_CLIENT **dhcp_client_ptr, UINT add_on)
3270 {
3271 
3272 UINT            i;
3273 UINT            available_index;
3274 NX_DHCP_CLIENT  *client_record_ptr;
3275 
3276 
3277     /* Initialize the search results to unsuccessful. */
3278     *dhcp_client_ptr = NX_NULL;
3279 
3280     /* Initialize an available slot in the table as outside the boundary (e.g. no slots available). */
3281     available_index = NX_DHCP_CLIENT_RECORD_TABLE_SIZE;
3282 
3283     /* Records are not necessarily added and deleted sequentially,
3284        so search the whole table until a match is found. */
3285     i = 0;
3286     while (i < NX_DHCP_CLIENT_RECORD_TABLE_SIZE)
3287     {
3288 
3289         /* Set local pointer for convenience. */
3290         client_record_ptr = &dhcp_ptr -> client_records[i];
3291 
3292         /* Skip empty records. Assume a client with no mac address is empty. */
3293         if ((client_record_ptr -> nx_dhcp_client_mac_msw == 0) && (client_record_ptr -> nx_dhcp_client_mac_lsw == 0))
3294         {
3295 
3296             /* Flag the first empty record in case we need to add the current client to the table. */
3297             if (i < available_index)
3298                 available_index = i;
3299 
3300             i++;
3301             continue;
3302         }
3303 
3304         /* Check the mac address of each record for a match. */
3305         if ((client_record_ptr -> nx_dhcp_client_mac_msw == client_mac_msw) &&
3306             (client_record_ptr -> nx_dhcp_client_mac_lsw == client_mac_lsw))
3307         {
3308 
3309             /* Verify the client packet interface matches the interface on record. */
3310             if (client_record_ptr -> nx_dhcp_client_iface_index == iface_index)
3311             {
3312                 /* Return the client record location. */
3313                 *dhcp_client_ptr = client_record_ptr;
3314 
3315                 return(NX_SUCCESS);
3316             }
3317             else
3318             {
3319 
3320                 /* It appears the client has changed its location (subnet) but not hardware type e.g. same mac
3321                    address/hware type but not interface. Remove the client record entirely and
3322                    free up any assigned IP address in the server database. */
3323                 _nx_dhcp_clear_client_record(dhcp_ptr, client_record_ptr);
3324 
3325                 /* Continue searching through the rest of the server records for
3326                    another instance of this client. Either way, if not found
3327                    with the expected interface a null pointer is returned,
3328                    or new record created depending on the caller. */
3329             }
3330         }
3331 
3332         i++;
3333     }
3334 
3335     /* Not found. Create a record for this client? */
3336     if (add_on == NX_FALSE)
3337     {
3338 
3339 #ifdef EL_PRINTF_ENABLE
3340         EL_PRINTF("DHCPserv: Client HW address not found. Do not add to server database\n");
3341 #endif
3342 
3343         /* No, we're done then. */
3344         return(NX_SUCCESS);
3345     }
3346 
3347     /* Check if there is available room in the table for a new client. */
3348     if (available_index >= NX_DHCP_CLIENT_RECORD_TABLE_SIZE)
3349     {
3350 
3351         /* No, we cannot add this client so the server's table. */
3352         return(NX_DHCP_CLIENT_TABLE_FULL);
3353     }
3354 
3355     /* Set local pointer to an available slot. */
3356     client_record_ptr = &dhcp_ptr -> client_records[available_index];
3357 
3358     /* Add this client to the server's total number of clients. */
3359     dhcp_ptr -> nx_dhcp_number_clients++;
3360 
3361     /* Add the supplied information to the new client record. */
3362     client_record_ptr -> nx_dhcp_client_mac_msw = client_mac_msw;
3363     client_record_ptr -> nx_dhcp_client_mac_lsw = client_mac_lsw;
3364     client_record_ptr -> nx_dhcp_client_iface_index = iface_index;
3365 
3366     /* Initialize the client state as the init state. */
3367     client_record_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
3368 
3369     /* Return the location of the newly created client record. */
3370     *dhcp_client_ptr = client_record_ptr;
3371 
3372     return(NX_SUCCESS);
3373 }
3374 
3375 
3376 /**************************************************************************/
3377 /*                                                                        */
3378 /*  FUNCTION                                               RELEASE        */
3379 /*                                                                        */
3380 /*    _nx_dhcp_find_interface_table_ip_address            PORTABLE C      */
3381 /*                                                           6.1          */
3382 /*  AUTHOR                                                                */
3383 /*                                                                        */
3384 /*    Yuxin Zhou, Microsoft Corporation                                   */
3385 /*                                                                        */
3386 /*  DESCRIPTION                                                           */
3387 /*                                                                        */
3388 /*    This function looks up a table entry by IP address in the specified */
3389 /*    server interface table. If not found, a NULL entry pointer is       */
3390 /*    returned but successful search completion.                          */
3391 /*                                                                        */
3392 /*  INPUT                                                                 */
3393 /*                                                                        */
3394 /*    dhcp_ptr                              Pointer to DHCP Server        */
3395 /*    iface_index                           Network interface index       */
3396 /*    ip_address                            IP address to look up         */
3397 /*    return_interface_address              Pointer to table entry        */
3398 /*                                                                        */
3399 /*  OUTPUT                                                                */
3400 /*                                                                        */
3401 /*    NX_SUCCESS                           Message handled successfully   */
3402 /*                                                                        */
3403 /*  CALLS                                                                 */
3404 /*                                                                        */
3405 /*    _nx_dhcp_clear_client_record          Removes client record from    */
3406 /*                                              server table              */
3407 /*                                                                        */
3408 /*  CALLED BY                                                             */
3409 /*                                                                        */
3410 /*    _nx_dhcp_server_extract_information   Extract DHCP info from Client */
3411 /*                                             message                    */
3412 /*                                                                        */
3413 /*  RELEASE HISTORY                                                       */
3414 /*                                                                        */
3415 /*    DATE              NAME                      DESCRIPTION             */
3416 /*                                                                        */
3417 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3418 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3419 /*                                            resulting in version 6.1    */
3420 /*                                                                        */
3421 /**************************************************************************/
_nx_dhcp_find_interface_table_ip_address(NX_DHCP_SERVER * dhcp_ptr,UINT iface_index,ULONG ip_address,NX_DHCP_INTERFACE_IP_ADDRESS ** return_interface_address)3422 static UINT  _nx_dhcp_find_interface_table_ip_address(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index, ULONG ip_address,
3423                                               NX_DHCP_INTERFACE_IP_ADDRESS **return_interface_address)
3424 {
3425 
3426 UINT i;
3427 NX_DHCP_INTERFACE_TABLE *dhcp_interface_table_ptr;
3428 
3429 
3430     /* Initialize search results to NULL (not found). */
3431     *return_interface_address = NX_NULL;
3432 
3433     /* Set a local varible to the IP address list for this client. */
3434     dhcp_interface_table_ptr = &(dhcp_ptr -> nx_dhcp_interface_table[iface_index]);
3435 
3436     /* Yes, search for an available ip address in the IP list for this interface */
3437     for(i = 0; i < dhcp_interface_table_ptr -> nx_dhcp_address_list_size; i++)
3438     {
3439 
3440         /* Is this address a match? */
3441         if (dhcp_interface_table_ptr -> nx_dhcp_ip_address_list[i].nx_assignable_ip_address == ip_address)
3442         {
3443             /* Yes, set a pointer to the location and return. */
3444             *return_interface_address =  &dhcp_interface_table_ptr -> nx_dhcp_ip_address_list[i];
3445 
3446             /* And we're done! */
3447             return(NX_SUCCESS);
3448         }
3449     }
3450 
3451     /* Not found, so return null pointer and successful search status. */
3452     return(NX_SUCCESS);
3453 }
3454 
3455 
3456 /**************************************************************************/
3457 /*                                                                        */
3458 /*  FUNCTION                                               RELEASE        */
3459 /*                                                                        */
3460 /*    _nx_dhcp_update_assignable_ip_address               PORTABLE C      */
3461 /*                                                           6.1          */
3462 /*  AUTHOR                                                                */
3463 /*                                                                        */
3464 /*    Yuxin Zhou, Microsoft Corporation                                   */
3465 /*                                                                        */
3466 /*  DESCRIPTION                                                           */
3467 /*                                                                        */
3468 /*    This function updates the IP address status in the server interface */
3469 /*    table address for the current client. This will return an error     */
3470 /*    status if the IP address being updated is not owned by the client.  */
3471 /*                                                                        */
3472 /*    Note: No changes are made to the associated client record.          */
3473 /*                                                                        */
3474 /*  INPUT                                                                 */
3475 /*                                                                        */
3476 /*    dhcp_ptr                              Pointer to DHCP Server        */
3477 /*    dhcp_client_ptr                       Pointer to DHCP client        */
3478 /*    ip_address                            IP address to update          */
3479 /*    assign_status                         Status to assign              */
3480 /*                                                                        */
3481 /*  OUTPUT                                                                */
3482 /*                                                                        */
3483 /*    NX_SUCCESS                           Entry updated successfully     */
3484 /*    NX_DHCP_IP_ADDRESS_NOT_FOUND         IP address not found           */
3485 /*    NX_DHCP_IP_ADDRESS_ASSIGNED_TO_OTHER IP address not assigned to     */
3486 /*                                                  current client        */
3487 /*    NX_DHCP_INVALID_UPDATE_ADDRESS_CMD   Unknown status input           */
3488 /*                                                                        */
3489 /*  CALLS                                                                 */
3490 /*                                                                        */
3491 /*    _nx_dhcp_find_interface_table_ip_address                            */
3492 /*                                        Find IP address in server       */
3493 /*                                              interface table           */
3494 /*    _nx_dhcp_find_ip_address_owner      Verify Client is address owner  */
3495 /*    _nx_dhcp_clear_ip_address_owner     Clear IP address owner          */
3496 /*    _nx_dhcp_record_ip_address_owner    Sets Client as IP address owner */
3497 /*                                                                        */
3498 /*  CALLED BY                                                             */
3499 /*                                                                        */
3500 /*    _nx_dhcp_validate_client_message         Process DHCP Client message*/
3501 /*    _nx_dhcp_fast_periodic_timer_entry       Timer on client sessions   */
3502 /*    _nx_dhcp_slow_periodic_timer_entry       Timer on IP address leases */
3503 /*                                             message                    */
3504 /*                                                                        */
3505 /*  RELEASE HISTORY                                                       */
3506 /*                                                                        */
3507 /*    DATE              NAME                      DESCRIPTION             */
3508 /*                                                                        */
3509 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3510 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3511 /*                                            resulting in version 6.1    */
3512 /*                                                                        */
3513 /**************************************************************************/
_nx_dhcp_update_assignable_ip_address(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT * dhcp_client_ptr,ULONG ip_address,UINT assign_status)3514 static UINT  _nx_dhcp_update_assignable_ip_address(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr,
3515                                            ULONG ip_address, UINT assign_status)
3516 {
3517 
3518 UINT iface_index;
3519 UINT assigned_to_client;
3520 UINT lease_time;
3521 NX_DHCP_INTERFACE_IP_ADDRESS    *interface_address_ptr;
3522 
3523 
3524     /* Create a local variable for convenience. */
3525     iface_index = dhcp_client_ptr -> nx_dhcp_client_iface_index;
3526 
3527     /* Look up the IP address in the server interface IP address table. */
3528     _nx_dhcp_find_interface_table_ip_address(dhcp_ptr, iface_index, ip_address, &interface_address_ptr);
3529 
3530     /* Was it found? */
3531     if (interface_address_ptr == 0x0)
3532     {
3533 
3534         /* No, return an error status address not found. */
3535         return(NX_DHCP_IP_ADDRESS_NOT_FOUND);
3536     }
3537 
3538     /* Is the Client releasing IP address?  */
3539     if (assign_status == NX_DHCP_ADDRESS_STATUS_MARK_AVAILABLE)
3540     {
3541 
3542         /* Check if owner of this IP address matches with this client's record.  */
3543         _nx_dhcp_find_ip_address_owner(interface_address_ptr, dhcp_client_ptr, &assigned_to_client);
3544 
3545         /* Is the IP address owned (leased) to this client? */
3546         if (assigned_to_client == NX_FALSE)
3547         {
3548 
3549             /* No, this IP address is assigned to another host. We cannot change
3550                the IP address status. */
3551             return(NX_DHCP_IP_ADDRESS_ASSIGNED_TO_OTHER);
3552         }
3553 
3554         /* Yes, clear the owner information.  */
3555         _nx_dhcp_clear_ip_address_owner(interface_address_ptr);
3556     }
3557 
3558     /* Was the IP address assigned externally from the DHCP process?  */
3559     else if (assign_status == NX_DHCP_ADDRESS_STATUS_ASSIGNED_EXT)
3560     {
3561 
3562         /* Check the lease time.  */
3563         if (interface_address_ptr -> lease_time)
3564         {
3565             /* If this already has a lease time (because we assigned it most likely) don't change it. */
3566             lease_time = interface_address_ptr -> lease_time;
3567         }
3568         else
3569         {
3570             /* Otherwise, make this lease time infinity e.g. the time out will not expire on it.*/
3571              lease_time = NX_WAIT_FOREVER;
3572         }
3573 
3574         /*  Set the current client as the owner.  */
3575         _nx_dhcp_record_ip_address_owner(interface_address_ptr, dhcp_client_ptr, lease_time);
3576     }
3577 
3578     /* Is the client informing us the IP address is already in use (e.g. it has
3579        sent the server a DECLINE message) or accepting another DHCP server's offer? */
3580     else if (assign_status == NX_DHCP_ADDRESS_STATUS_ASSIGNED_OTHER)
3581     {
3582 
3583         /* Yes; Is the client is declining the IP address? */
3584         if (dhcp_client_ptr -> nx_dhcp_message_type == NX_DHCP_TYPE_DHCPDECLINE)
3585         {
3586 
3587             /* Yes, remove the Client as owner of this IP lease.
3588                Record owner information with null 'owner' ID since we don't know who the owner is.  */
3589             _nx_dhcp_record_ip_address_owner(interface_address_ptr, NX_NULL, NX_WAIT_FOREVER);
3590         }
3591         else
3592         {
3593 
3594             /* Record owner information.  */
3595             _nx_dhcp_record_ip_address_owner(interface_address_ptr, dhcp_client_ptr, NX_WAIT_FOREVER);
3596         }
3597     }
3598     else
3599     {
3600 
3601         /* Received an invalid update address command. */
3602         return(NX_DHCP_INVALID_UPDATE_ADDRESS_CMD);
3603     }
3604 
3605     /* Successful completion! */
3606     return(NX_SUCCESS);
3607 }
3608 
3609 
3610 /**************************************************************************/
3611 /*                                                                        */
3612 /*  FUNCTION                                               RELEASE        */
3613 /*                                                                        */
3614 /*    _nx_dhcp_find_ip_address_owner                      PORTABLE C      */
3615 /*                                                           6.1          */
3616 /*  AUTHOR                                                                */
3617 /*                                                                        */
3618 /*    Yuxin Zhou, Microsoft Corporation                                   */
3619 /*                                                                        */
3620 /*  DESCRIPTION                                                           */
3621 /*                                                                        */
3622 /*    This function finds the owner of the specified IP address and checks*/
3623 /*    it against the specified client record to insure the client is the  */
3624 /*    owner of the IP address. The result of the search is updated in the */
3625 /*    assigned_to_client pointer.                                         */
3626 /*                                                                        */
3627 /*  INPUT                                                                 */
3628 /*                                                                        */
3629 /*    iface_owner                           Pointer to table entry        */
3630 /*    dhcp_client_ptr                       Pointer to DHCP client        */
3631 /*    assign_status                         Status to assign              */
3632 /*                                                                        */
3633 /*  OUTPUT                                                                */
3634 /*                                                                        */
3635 /*    NX_SUCCESS                            Table searched successfully   */
3636 /*                                                                        */
3637 /*  CALLS                                                                 */
3638 /*                                                                        */
3639 /*    None                                                                */
3640 /*                                                                        */
3641 /*  CALLED BY                                                             */
3642 /*                                                                        */
3643 /*    _nx_dhcp_update_assignable_ip_address Update IP address status in   */
3644 /*                                            the server database         */
3645 /*    _nx_dhcp_server_assign_ip_address     Assign an IP address to the   */
3646 /*                                            current client              */
3647 /*                                                                        */
3648 /*  RELEASE HISTORY                                                       */
3649 /*                                                                        */
3650 /*    DATE              NAME                      DESCRIPTION             */
3651 /*                                                                        */
3652 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3653 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3654 /*                                            resulting in version 6.1    */
3655 /*                                                                        */
3656 /**************************************************************************/
_nx_dhcp_find_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS * iface_owner,NX_DHCP_CLIENT * client_record_ptr,UINT * assigned_to_client)3657 static UINT  _nx_dhcp_find_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS *iface_owner, NX_DHCP_CLIENT *client_record_ptr, UINT *assigned_to_client)
3658 {
3659 
3660 
3661     /* Initialize the value.  */
3662     *assigned_to_client = NX_FALSE;
3663 
3664     /* Compare the owner in the interface table entry with the client record mac address. */
3665     if ((iface_owner -> owner_hwtype == client_record_ptr -> nx_dhcp_client_hwtype) &&
3666         (iface_owner -> owner_mac_msw == client_record_ptr -> nx_dhcp_client_mac_msw) &&
3667         (iface_owner -> owner_mac_lsw == client_record_ptr -> nx_dhcp_client_mac_lsw))
3668     {
3669 
3670         /* They match; This verifies the IP address is assigned to this client. */
3671         *assigned_to_client = NX_TRUE;
3672     }
3673 
3674     return(NX_SUCCESS);
3675 }
3676 
3677 
3678 /**************************************************************************/
3679 /*                                                                        */
3680 /*  FUNCTION                                               RELEASE        */
3681 /*                                                                        */
3682 /*    _nx_dhcp_record_ip_address_owner                    PORTABLE C      */
3683 /*                                                           6.1          */
3684 /*  AUTHOR                                                                */
3685 /*                                                                        */
3686 /*    Yuxin Zhou, Microsoft Corporation                                   */
3687 /*                                                                        */
3688 /*  DESCRIPTION                                                           */
3689 /*                                                                        */
3690 /*    This function fills in the address owner in the interface table from*/
3691 /*    the specified client record.                                        */
3692 /*                                                                        */
3693 /*  INPUT                                                                 */
3694 /*                                                                        */
3695 /*    iface_owner                           Pointer to table entry        */
3696 /*    client_record_ptr                     Pointer to DHCP client        */
3697 /*    lease_time                            Lease duration in secs        */
3698 /*                                                                        */
3699 /*  OUTPUT                                                                */
3700 /*                                                                        */
3701 /*    NX_SUCCESS                            Table searched successfully   */
3702 /*                                                                        */
3703 /*  CALLS                                                                 */
3704 /*                                                                        */
3705 /*    None                                                                */
3706 /*                                                                        */
3707 /*  CALLED BY                                                             */
3708 /*                                                                        */
3709 /*    _nx_dhcp_update_assignable_ip_address Update IP address status in   */
3710 /*                                            the server database         */
3711 /*    _nx_dhcp_server_assign_ip_address     Assign an IP address to the   */
3712 /*                                            current client              */
3713 /*                                                                        */
3714 /*  RELEASE HISTORY                                                       */
3715 /*                                                                        */
3716 /*    DATE              NAME                      DESCRIPTION             */
3717 /*                                                                        */
3718 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3719 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3720 /*                                            resulting in version 6.1    */
3721 /*                                                                        */
3722 /**************************************************************************/
_nx_dhcp_record_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS * iface_owner,NX_DHCP_CLIENT * client_record_ptr,UINT lease_time)3723 static UINT  _nx_dhcp_record_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS *iface_owner, NX_DHCP_CLIENT *client_record_ptr, UINT lease_time)
3724 {
3725 
3726     /* Check the client_record_ptr.  */
3727     if (client_record_ptr)
3728     {
3729 
3730         /* Parse the mac address and hardware type from the client record. */
3731         iface_owner -> owner_hwtype = client_record_ptr -> nx_dhcp_client_hwtype;
3732         iface_owner -> owner_mac_msw = client_record_ptr -> nx_dhcp_client_mac_msw;
3733         iface_owner -> owner_mac_lsw = client_record_ptr -> nx_dhcp_client_mac_lsw;
3734     }
3735     else
3736     {
3737 
3738         /* We don't know who the owner is, set the owner information as zero.  */
3739         iface_owner -> owner_hwtype = 0;
3740         iface_owner -> owner_mac_msw = 0;
3741         iface_owner -> owner_mac_lsw = 0;;
3742     }
3743 
3744     /* Record the lease time.  */
3745     iface_owner -> lease_time = lease_time;
3746 
3747     /* Set the assigned status.  */
3748     iface_owner -> assigned = NX_TRUE;
3749 
3750     /* Return.  */
3751     return(NX_SUCCESS);
3752 }
3753 
3754 
3755 /**************************************************************************/
3756 /*                                                                        */
3757 /*  FUNCTION                                               RELEASE        */
3758 /*                                                                        */
3759 /*    _nx_dhcp_clear_ip_address_owner                     PORTABLE C      */
3760 /*                                                           6.1          */
3761 /*  AUTHOR                                                                */
3762 /*                                                                        */
3763 /*    Yuxin Zhou, Microsoft Corporation                                   */
3764 /*                                                                        */
3765 /*  DESCRIPTION                                                           */
3766 /*                                                                        */
3767 /*    This function clears the address owner information.                 */
3768 /*                                                                        */
3769 /*  INPUT                                                                 */
3770 /*                                                                        */
3771 /*    iface_owner                           Pointer to table entry        */
3772 /*                                                                        */
3773 /*  OUTPUT                                                                */
3774 /*                                                                        */
3775 /*    NX_SUCCESS                                                          */
3776 /*                                                                        */
3777 /*  CALLS                                                                 */
3778 /*                                                                        */
3779 /*    None                                                                */
3780 /*                                                                        */
3781 /*  CALLED BY                                                             */
3782 /*                                                                        */
3783 /*    _nx_dhcp_slow_periodic_timer_entry    Update IP lease time outs     */
3784 /*    _nx_dhcp_clear_client_record          Clear Client record           */
3785 /*    _nx_dhcp_update_assignable_ip_address Update IP address status in   */
3786 /*                                                 the server database    */
3787 /*    _nx_dhcp_server_assign_ip_address     Assign an IP address to the   */
3788 /*                                                  current client        */
3789 /*                                                                        */
3790 /*  RELEASE HISTORY                                                       */
3791 /*                                                                        */
3792 /*    DATE              NAME                      DESCRIPTION             */
3793 /*                                                                        */
3794 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3795 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3796 /*                                            resulting in version 6.1    */
3797 /*                                                                        */
3798 /**************************************************************************/
_nx_dhcp_clear_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS * iface_owner)3799 static UINT  _nx_dhcp_clear_ip_address_owner(NX_DHCP_INTERFACE_IP_ADDRESS *iface_owner)
3800 {
3801 
3802     /* Clear the owner information.  */
3803     iface_owner -> owner_hwtype = 0;
3804     iface_owner -> owner_mac_msw = 0;
3805     iface_owner -> owner_mac_lsw = 0;
3806 
3807     /* Clear the lease time.  */
3808     iface_owner -> lease_time = 0;
3809 
3810     /* Clear the assigned status.  */
3811     iface_owner -> assigned = NX_FALSE;
3812 
3813     /* Return.  */
3814     return(NX_SUCCESS);
3815 }
3816 
3817 
3818 /**************************************************************************/
3819 /*                                                                        */
3820 /*  FUNCTION                                               RELEASE        */
3821 /*                                                                        */
3822 /*    _nx_dhcp_validate_client_message                    PORTABLE C      */
3823 /*                                                           6.1          */
3824 /*  AUTHOR                                                                */
3825 /*                                                                        */
3826 /*    Yuxin Zhou, Microsoft Corporation                                   */
3827 /*                                                                        */
3828 /*  DESCRIPTION                                                           */
3829 /*                                                                        */
3830 /*    This function verifies the client message is a valid DHCP request,  */
3831 /*    determines if an IP address need to be assigned, what state the DHCP*/
3832 /*    Client should be advanced to, and what the server DHCP response type*/
3833 /*    should be.  in the client record the specified client record.       */
3834 /*                                                                        */
3835 /*  INPUT                                                                 */
3836 /*                                                                        */
3837 /*    dhcp_ptr                              Pointer to DHCP Server        */
3838 /*    client_record_ptr                     Pointer to DHCP client        */
3839 /*                                                                        */
3840 /*  OUTPUT                                                                */
3841 /*                                                                        */
3842 /*    NX_SUCCESS                           Table searched successfully    */
3843 /*                                                                        */
3844 /*  CALLS                                                                 */
3845 /*                                                                        */
3846 /*   _nx_dhcp_update_assignable_ip_address Update IP address status in    */
3847 /*                                              the server database       */
3848 /*                                                                        */
3849 /*  CALLED BY                                                             */
3850 /*                                                                        */
3851 /*    _nx_dhcp_listen_for_messages         Listen for, process and respond*/
3852 /*                                            to DHCP Client messages     */
3853 /*                                                                        */
3854 /*  RELEASE HISTORY                                                       */
3855 /*                                                                        */
3856 /*    DATE              NAME                      DESCRIPTION             */
3857 /*                                                                        */
3858 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3859 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3860 /*                                            resulting in version 6.1    */
3861 /*                                                                        */
3862 /**************************************************************************/
_nx_dhcp_validate_client_message(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT * dhcp_client_ptr)3863 static UINT  _nx_dhcp_validate_client_message(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr)
3864 {
3865 
3866 ULONG                   server_ip_address;
3867 UINT                    iface_index;
3868 NX_DHCP_INTERFACE_TABLE *dhcp_interface_table_ptr;
3869 
3870 
3871     /* Create a local variable for the client's interface for convenience. */
3872     iface_index = dhcp_client_ptr -> nx_dhcp_client_iface_index;
3873     dhcp_interface_table_ptr = &dhcp_ptr -> nx_dhcp_interface_table[iface_index];
3874 
3875     if (dhcp_client_ptr -> nx_dhcp_xid == 0x0)
3876     {
3877 
3878 #ifdef EL_PRINTF_ENABLE
3879         EL_PRINTF("DHCPserv: DHCP packet missing transaction ID. Reject the packet silently. \n");
3880 #endif
3881 
3882         /* Return the request denied message to clients and return. */
3883         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPSILENT;
3884         return(NX_SUCCESS);
3885     }
3886 
3887     /* Client messages should never fill in the "Your (Client) IP" or "Next Server IP" fields. */
3888     else if ((dhcp_client_ptr -> nx_dhcp_your_ip_address !=  NX_DHCP_NO_ADDRESS) ||
3889         (dhcp_client_ptr -> nx_dhcp_clientrec_server_ip !=  NX_DHCP_NO_ADDRESS))
3890     {
3891 
3892 #ifdef EL_PRINTF_ENABLE
3893         EL_PRINTF("DHCPserv: NACK! 'Your IP'/'Server IP' fields should not be filled in.\n");
3894 #endif
3895 
3896         /* Return the 'request denied' message to the client. */
3897         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
3898     }
3899 
3900     /* Check for missing required fields. */
3901     else if ((dhcp_client_ptr -> nx_dhcp_client_hwtype == 0) ||
3902              (dhcp_client_ptr -> nx_dhcp_client_hwlen == 0))
3903     {
3904 
3905 #ifdef EL_PRINTF_ENABLE
3906         EL_PRINTF("DHCPserv: NACK! DHCP packet missing MAC and/or hardware type\n");
3907 #endif
3908 
3909         /* Return the request denied message to clients and return. */
3910         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
3911     }
3912 
3913     else
3914     {
3915 
3916         /* Do validation specific the for message type. This section will also
3917            advance the Client DHCP state and set the server response message type.
3918         */
3919         switch (dhcp_client_ptr -> nx_dhcp_message_type)
3920         {
3921 
3922 
3923             case NX_DHCP_TYPE_DHCPDISCOVER:
3924             {
3925 
3926 #ifdef EL_PRINTF_ENABLE
3927                 EL_PRINTF("DHCPserv: Received DISCOVER message\n");
3928 #endif
3929 
3930                 /* Determine if server needs to assign an IP address based on assigned IP address.
3931                    e.g. If this appears to be a retransmission of a previous IP address DISOVERY request,
3932                    only assign another IP address if the client appears not to have been assigned one already.*/
3933                 /* Initialize response back to be an offer pending validation check. */
3934                 dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPOFFER;
3935 
3936                 /* Check for invalid IP address field(s). */
3937                 if (dhcp_client_ptr -> nx_dhcp_clientip_address != NX_DHCP_NO_ADDRESS)
3938                 {
3939 
3940 #ifdef EL_PRINTF_ENABLE
3941                     EL_PRINTF("DHCPserv: NACK! Client IP address field must not be filled in.\n");
3942 #endif
3943 
3944                     /* Let the client know it has an invalid request. */
3945                     dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
3946                 }
3947                 else
3948                 {
3949 
3950                     /* DHCP client state advances to SElECTING state. */
3951                     dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_SELECTING;
3952                 }
3953 
3954                 break;
3955             }
3956 
3957             case NX_DHCP_TYPE_DHCPREQUEST:
3958             {
3959 
3960 
3961                /* This is a more complex message since a client request can be generated from
3962                   4 different states: boot, selecting, renew, rebind. This requires that
3963                   we determine the Client state based on what's previously known about
3964                   the client and which fields are filled in the Request message. */
3965 
3966                 /* Get the DHCP server IP address for the client package interface. */
3967                 server_ip_address = dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_server_ip_address;
3968 
3969                 /* Get the index of the client packet interface. */
3970                 iface_index = dhcp_client_ptr -> nx_dhcp_client_iface_index;
3971 
3972                 /* If the client does not specify a server id but is requesting an IP address...  */
3973                 if ((dhcp_client_ptr -> nx_dhcp_server_id == 0) &&
3974                     (dhcp_client_ptr -> nx_dhcp_requested_ip_address != NX_DHCP_NO_ADDRESS))
3975                 {
3976 
3977 #ifdef EL_PRINTF_ENABLE
3978                     EL_PRINTF("DHCPserv: Received REQUEST (BOOT state) message\n");
3979 #endif
3980                     /* ...Then it is in the boot state as per RFC 2131 4.3.2 (requests
3981                        an IP address but is skipping the DISCO message). */
3982 
3983                     /* This client may NOT specify a Client IP address e.g. that field must
3984                        be left blank. */
3985                     if (dhcp_client_ptr -> nx_dhcp_clientip_address != NX_DHCP_NO_ADDRESS)
3986                     {
3987 
3988 #ifdef EL_PRINTF_ENABLE
3989                         EL_PRINTF("DHCPserv: NACK! REQUEST message may not specify Client IP address.\n");
3990 #endif
3991 
3992                         /* Let the client know it has an invalid request. */
3993                         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
3994                         break;
3995                     }
3996 
3997                     /* Server SHOULD send a DHCPNAK message to the client if the 'requested IP address' is incorrect, or is on the wrong network.
3998                        RFC 2131, Section 4.3.2, Page31.  */
3999                     if ((dhcp_client_ptr -> nx_dhcp_assigned_ip_address != 0) &&
4000                         (dhcp_client_ptr -> nx_dhcp_assigned_ip_address != dhcp_client_ptr -> nx_dhcp_requested_ip_address))
4001                     {
4002 
4003                         ULONG ip_address_assigned = dhcp_client_ptr -> nx_dhcp_assigned_ip_address;
4004 
4005 #ifdef EL_PRINTF_ENABLE
4006                         EL_PRINTF("DHCPserv: NACK! REQUEST message contains incorrect requested IP address. \n");
4007 #endif
4008 
4009                         /* No; invalid request. Return the IP address tentatively assigned to
4010                           the client back to the available IP address pool. */
4011 
4012                         _nx_dhcp_update_assignable_ip_address(dhcp_ptr, dhcp_client_ptr, ip_address_assigned,
4013                                                        NX_DHCP_ADDRESS_STATUS_MARK_AVAILABLE);
4014 
4015                         /* Clear requested IP lease time because the client is not granted an IP address lease. */
4016                         dhcp_client_ptr -> nx_dhcp_requested_lease_time = 0;
4017 
4018                         /* Let the client know it made an invalid request. */
4019                         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4020                         break;
4021                     }
4022 
4023                     /* Set the client state to the BOOT state */
4024                     dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_BOOT;
4025 
4026                     /* Indicate the server will grant the IP lease. */
4027                     dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPACK;
4028 
4029                     /* Advance the client state to requesting (waiting for an ACK). */
4030                     dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_REQUESTING;
4031                     break;
4032                 }
4033                 /* Else if the client is specifying a server id, and a requested IP address... */
4034                 else if (dhcp_client_ptr -> nx_dhcp_server_id &&
4035                         (dhcp_client_ptr -> nx_dhcp_requested_ip_address != NX_DHCP_NO_ADDRESS))
4036                 {
4037 
4038 #ifdef EL_PRINTF_ENABLE
4039                     EL_PRINTF("DHCPserv: Received REQUEST (SELECT state) message\n");
4040 #endif
4041 
4042                     /* ...Then the client is in the SELECT state as per RFC 2131 4.3.2 (sent a
4043                       DISCOVERY message and is responding to a server OFFER message). */
4044 
4045                     /* Client may NOT specify a Client IP address. */
4046                     if (dhcp_client_ptr -> nx_dhcp_clientip_address != NX_DHCP_NO_ADDRESS)
4047                     {
4048 
4049 #ifdef EL_PRINTF_ENABLE
4050                         EL_PRINTF("DHCPserv: NACK! REQUEST message may not specify Client IP address.\n");
4051 #endif
4052 
4053                         /* Let the client know it has an invalid request. */
4054                         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4055                         break;
4056                     }
4057 
4058                     /* Check if the Client has chosen this server's offer (e.g.server ID option in the
4059                        REQUEST message). */
4060                     if (dhcp_client_ptr -> nx_dhcp_server_id != server_ip_address)
4061                     {
4062 
4063                         ULONG  ip_address_assigned;
4064 
4065                         /* We are not. */
4066 
4067                         /* Is the Client accepting the same IP address this server offered? */
4068                         if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address == dhcp_client_ptr -> nx_dhcp_requested_ip_address)
4069                         {
4070 
4071                             /* Yes, so do not change the client record IP address and IP address
4072                                status in the server interface table as assigned.  */
4073                             ip_address_assigned = dhcp_client_ptr -> nx_dhcp_assigned_ip_address;
4074                         }
4075                         else
4076                         {
4077 
4078                             /* No, it is accepting a different IP address from another server. */
4079                             ip_address_assigned = dhcp_client_ptr -> nx_dhcp_requested_ip_address;
4080 
4081                             /* So update the client record's assigned address to the one it is accepting
4082                                from another server. */
4083                             dhcp_client_ptr -> nx_dhcp_assigned_ip_address = dhcp_client_ptr -> nx_dhcp_requested_ip_address;
4084                         }
4085 
4086                         /* Update the server interface table with the information.  */
4087                         _nx_dhcp_update_assignable_ip_address(dhcp_ptr, dhcp_client_ptr, ip_address_assigned,
4088                                                                        NX_DHCP_ADDRESS_STATUS_ASSIGNED_OTHER);
4089 
4090 #ifdef EL_PRINTF_ENABLE
4091                         EL_PRINTF("DHCPserv: SILENCE! REQUEST message indicates Client accepting another server IP.\n");
4092 #endif
4093 
4094                         /* If this client wants an IP address from this server it must start
4095                            over at the init state. */
4096                         dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
4097 
4098                         /* No need to respond. */
4099                         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPSILENT;
4100 
4101                         return(NX_SUCCESS);
4102                     }
4103 
4104                     /* Make sure the Client did in fact receive an OFFER from this server (e.g. has
4105                        been tentatively assigned an IP address from us). */
4106                     if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address == NX_DHCP_NO_ADDRESS)
4107                     {
4108 
4109 #ifdef EL_PRINTF_ENABLE
4110                         EL_PRINTF("DHCPserv: NACK! REQUEST message does not indicate valid assigned IP address.\n");
4111 #endif
4112 
4113                         /* It did not.  This is an invalid request. Let the client know. */
4114                         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4115 
4116                         /* Clear requested IP lease times because the client was not assigned an IP address. */
4117                         dhcp_client_ptr -> nx_dhcp_requested_lease_time = 0;
4118 
4119                         /* Nothing more to do! */
4120                         break;
4121                     }
4122 
4123                     /* Does the Client's requested IP address match the "Your IP" field in the server OFFER
4124                        previously sent to this client (e.g. Client's assigned IP address)? */
4125                     else if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address != dhcp_client_ptr -> nx_dhcp_requested_ip_address)
4126                     {
4127 
4128                         ULONG ip_address_assigned = dhcp_client_ptr -> nx_dhcp_assigned_ip_address;
4129 
4130 #ifdef EL_PRINTF_ENABLE
4131                         EL_PRINTF("DHCPserv: NACK! REQUEST message contains requested IP address. \n");
4132 #endif
4133 
4134                         /* No; invalid request. Return the IP address tentatively assigned to
4135                           the client back to the available IP address pool. */
4136 
4137                         _nx_dhcp_update_assignable_ip_address(dhcp_ptr, dhcp_client_ptr, ip_address_assigned,
4138                                                        NX_DHCP_ADDRESS_STATUS_MARK_AVAILABLE);
4139 
4140                         /* Clear requested IP lease time because the client is not granted an IP address lease. */
4141                         dhcp_client_ptr -> nx_dhcp_requested_lease_time = 0;
4142 
4143                         /* Let the client know it made an invalid request. */
4144                         dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4145                         break;
4146                     }
4147 
4148                     /* The Client accepts this Server's offer. We will grant the client the IP lease now. */
4149                     dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPACK;
4150 
4151                     /* UPdate the client state to REQUESTING (waiting on an ACK). */
4152                     dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_REQUESTING;
4153                 }
4154 
4155                /* Is this a RENEW or REBIND request? If so the server ID and requested IP options must
4156                   NOT be filled in as per RFC 2131 4.3.2. */
4157                else if ((dhcp_client_ptr -> nx_dhcp_server_id == NX_DHCP_NO_ADDRESS) &&
4158                        (dhcp_client_ptr -> nx_dhcp_requested_ip_address == NX_DHCP_NO_ADDRESS))
4159                {
4160 
4161 #ifdef EL_PRINTF_ENABLE
4162                    EL_PRINTF("DHCPserv: Received REQUEST (RENEW/REBIND state) message\n");
4163 #endif
4164 
4165                    /* Yes, this is a renew/rebind request! */
4166 
4167                    /* Extending an IP lease is a administration decision vs RFC mandate. The
4168                       NetX DHCP Server automatically extends IP leases. */
4169 
4170                    /* Go ahead and ACK the renew request pending any DHCP violations. */
4171                    dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPACK;
4172 
4173                    /* The "Client IP" address field MUST be filled in. */
4174                    if (dhcp_client_ptr -> nx_dhcp_clientip_address == NX_DHCP_NO_ADDRESS)
4175                    {
4176 
4177 #ifdef EL_PRINTF_ENABLE
4178                        EL_PRINTF("DHCPserv: NACK! REQUEST message no 'Client IP' address specified. \n");
4179 #endif
4180 
4181                        /* This is an invalid renew/rebind request. Reject the request but
4182                           do not change or advance the Client state (SHOULD be bound). */
4183                        dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4184 
4185                        break;
4186                    }
4187 
4188                    /* The "Client IP" address subnet should match the Client packet source IP address subnet. */
4189                    if ((dhcp_interface_table_ptr -> nx_dhcp_subnet_mask & dhcp_client_ptr -> nx_dhcp_clientip_address) !=
4190                            (dhcp_interface_table_ptr -> nx_dhcp_subnet_mask & dhcp_interface_table_ptr -> nx_dhcp_server_ip_address))
4191                    {
4192 #ifdef EL_PRINTF_ENABLE
4193                        EL_PRINTF("DHCPserv: NACK! REQUEST message; the 'Client IP' address subnet does not match the DHCP server subnet. \n");
4194 #endif
4195 
4196                        /* This is an invalid renew/rebind request. Reject the request but
4197                           do not change or advance the Client state (SHOULD be bound). */
4198                        dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4199                        break;
4200                    }
4201 
4202                    /* Is there an assigned IP address in the Client record?  */
4203                    if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address == NX_DHCP_NO_ADDRESS)
4204                    {
4205 
4206 #ifdef EL_PRINTF_ENABLE
4207                        EL_PRINTF("DHCPserv: NACK! REQUEST message; server has no record of assigned IP address.\n");
4208 #endif
4209 
4210                        /* No; possibly assigned by another DHCP server or outside of DHCP protocol.
4211                           Reject the renewal request. */
4212                        dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4213 
4214                        /* This client needs to start the configuration process with this
4215                           server from the INIT start if it wants an IP address from it. */
4216                        dhcp_client_ptr -> nx_dhcp_client_state  = NX_DHCP_STATE_INIT;
4217                        break;
4218                    }
4219 
4220                    /* Determine if this is a renew or a rebind request. */
4221                    if (dhcp_client_ptr -> nx_dhcp_destination_ip_address != NX_DHCP_BC_ADDRESS)
4222                    {
4223 
4224 #ifdef EL_PRINTF_ENABLE
4225                        EL_PRINTF("DHCPserv: Received REQUEST (renewing) message\n");
4226 #endif
4227 
4228                        /* Renewing: DHCP clients' renew requests must be unicast. */
4229                        dhcp_client_ptr -> nx_dhcp_client_state  = NX_DHCP_STATE_RENEWING;
4230                    }
4231                    else
4232                    {
4233 
4234 #ifdef EL_PRINTF_ENABLE
4235                        EL_PRINTF("DHCPserv: Received REQUEST (rebinding) message\n");
4236 #endif
4237 
4238                       /* Rebinding DHCP clients' rebind request must be broadcast. */
4239                        dhcp_client_ptr -> nx_dhcp_client_state  = NX_DHCP_STATE_REBINDING;
4240                    }
4241                 }
4242                 else
4243                 {
4244 
4245 #ifdef EL_PRINTF_ENABLE
4246                     EL_PRINTF("DHCPserv: NACK! Received unknown REQUEST message type.\n");
4247 #endif
4248 
4249                     /* Do not respond to unknown requests. This is kind of a dealer's choice
4250                        because it is not specified in the RFC 2132 how to handle undefined
4251                        request IDs or message types. */
4252                     dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPSILENT;
4253                     return(NX_SUCCESS);
4254                 }
4255 
4256                 break;
4257             }
4258 
4259             case NX_DHCP_TYPE_DHCPRELEASE:
4260             {
4261 
4262 #ifdef EL_PRINTF_ENABLE
4263                 EL_PRINTF("DHCPserv: Received RELEASE response type.\n");
4264 #endif
4265 
4266 
4267                 /* The Client is releasing it's IP address back to the server. A client is not
4268                    required to do this; usually it indicates the client may have moved on the
4269                    network.
4270 
4271                    Clear the client record and mark the IP address as available. If the request proves
4272                    invalid, this server will ignore it and let the Client's assigned IP lease expire.  */
4273 
4274                 /* Regardless what happens the server does not send a reply to a RELEASE message. */
4275                 dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPSILENT;
4276 
4277                 /* Was an address previously assigned? */
4278                 if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address == NX_DHCP_NO_ADDRESS)
4279                 {
4280 
4281                     /* No; nothing to do here. */
4282                     return(NX_SUCCESS);
4283                 }
4284 
4285                 /* The client IP field must be filled in for RELEASE requests. Was it? */
4286                 if (dhcp_client_ptr -> nx_dhcp_clientip_address == NX_DHCP_NO_ADDRESS)
4287                 {
4288 
4289                     /* No; This is an invalid release request.  */
4290                     return(NX_SUCCESS);
4291                 }
4292 
4293                 /* Does client IP field match what this Server assigned the Client? */
4294                 if (dhcp_client_ptr -> nx_dhcp_clientip_address != dhcp_client_ptr -> nx_dhcp_assigned_ip_address)
4295                 {
4296 
4297                     /* No; Not sure how this happened but let the existing assigned
4298                        IP address lease expire. Ignore this message. */
4299                     return(NX_SUCCESS);
4300                 }
4301 
4302                 /* A RELEASE request must be unicasted to the server. Was this a broadcast
4303                    message? */
4304                 if (dhcp_client_ptr -> nx_dhcp_destination_ip_address == NX_DHCP_BC_ADDRESS)
4305                 {
4306 
4307                     /* Yes, so not a valid RELEASE request. */
4308                     return(NX_SUCCESS);
4309                 }
4310                 else
4311                 {
4312 
4313                     UINT index = dhcp_client_ptr -> nx_dhcp_client_iface_index;
4314                     ULONG server_ip = (&dhcp_ptr -> nx_dhcp_interface_table[index]) ->nx_dhcp_server_ip_address;
4315 
4316                     /* Check that we are the intended server. */
4317                     if (dhcp_client_ptr -> nx_dhcp_destination_ip_address != server_ip)
4318                     {
4319 
4320                         /* We are not. Not a valid Release request. */
4321                         return(NX_SUCCESS);
4322                      }
4323                 }
4324 
4325                 /* Legitimate release request: return the IP address to the available pool,
4326                    and clear the client session. */
4327 
4328                 /* Release the client's assigned IP address (in the "CI-ADDR" field). */
4329                 _nx_dhcp_update_assignable_ip_address(dhcp_ptr, dhcp_client_ptr,
4330                                                       dhcp_client_ptr -> nx_dhcp_assigned_ip_address,
4331                                                       NX_DHCP_ADDRESS_STATUS_MARK_AVAILABLE);
4332 
4333                 /* Clear the Client's assigned IP address. */
4334                 dhcp_client_ptr -> nx_dhcp_assigned_ip_address = NX_DHCP_NO_ADDRESS;
4335 
4336                 /* If this client wants to configure its network parameters with us it
4337                    must start at the INIT state. */
4338                 dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
4339 
4340 
4341                 break;
4342             }
4343 
4344             case NX_DHCP_TYPE_DHCPDECLINE:
4345             {
4346 
4347 #ifdef EL_PRINTF_ENABLE
4348                 EL_PRINTF("DHCPserv: Received DECLINE response type.\n");
4349 #endif
4350 
4351                 /* The Client is informing us an IP address we assigned to it is apparently already
4352                    in use by another host.  It needs to restart in the INIT/BOOT state for this
4353                    server to assign it another IP address. */
4354                 dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
4355 
4356                 /* Regardless what happens do not send a reply. */
4357                 dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPSILENT;
4358 
4359                 /* If no address previously assigned, silently ignore this message. */
4360                 if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address == NX_DHCP_NO_ADDRESS)
4361                 {
4362 
4363                     /* This client never had an address assigned by this server. Do nothing. */
4364                     return(NX_SUCCESS);
4365                 }
4366 
4367                 /* A DECLINE message must specify the requested address. */
4368                 if (dhcp_client_ptr -> nx_dhcp_requested_ip_address == NX_DHCP_NO_ADDRESS)
4369                 {
4370 
4371                     /* This is an invalid decline request. Reject it silently. */
4372                     return(NX_SUCCESS);
4373                 }
4374 
4375                 /* A Decline request is supposed to be unicasted to the server. If it is not,
4376                    ignore it. */
4377                 if (dhcp_client_ptr -> nx_dhcp_destination_ip_address != NX_DHCP_BC_ADDRESS)
4378                 {
4379 
4380                     return(NX_SUCCESS);
4381                 }
4382                 else
4383                 {
4384 
4385                     UINT index = dhcp_client_ptr -> nx_dhcp_client_iface_index;
4386                     ULONG server_ip = (&dhcp_ptr -> nx_dhcp_interface_table[index]) ->nx_dhcp_server_ip_address;
4387 
4388                     /* Check that we are the intended server. */
4389                     if (dhcp_client_ptr -> nx_dhcp_server_id != server_ip)
4390                     {
4391 
4392                         /* We are not. Ignore the request. */
4393                         return(NX_SUCCESS);
4394                      }
4395                 }
4396 
4397                 /* Release the client's assigned IP address. */
4398                 _nx_dhcp_update_assignable_ip_address(dhcp_ptr, dhcp_client_ptr,
4399                                                                dhcp_client_ptr -> nx_dhcp_assigned_ip_address,
4400                                                                NX_DHCP_ADDRESS_STATUS_ASSIGNED_OTHER);
4401 
4402                 /* Clear the Client's assigned IP address. */
4403                 dhcp_client_ptr -> nx_dhcp_assigned_ip_address = NX_DHCP_NO_ADDRESS;
4404 
4405                 break;
4406             }
4407 
4408             case NX_DHCP_TYPE_DHCPINFORM:
4409             {
4410 
4411 #ifdef EL_PRINTF_ENABLE
4412                   EL_PRINTF("DHCPserv: Received INFORM response type.\n");
4413 #endif
4414 
4415 
4416                 /* A DHCP client sends an INFORM message when it has been assigned an IP address
4417                    with another server or outside DHCP but still needs local configuration data.
4418                    The DHCP server must update its database with their address (specified in the "CI-ADDR" field)
4419                    as no longer available. When the server forms a reply ACK, it must leave the
4420                    'Your IP' and lease time fields blank as per RFC 2131 3.4. */
4421 
4422 
4423                 /* A DHCP server must respond (ACK) to INFORM messages unless the message
4424                    is invalid. */
4425                 dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPACK;
4426 
4427                 /* The INFORM message must have the Client IP address filled in to be valid. */
4428                 if (dhcp_client_ptr -> nx_dhcp_clientip_address == NX_DHCP_NO_ADDRESS)
4429                 {
4430 
4431                     /* Invalid message. */
4432                     dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4433                 }
4434 
4435                 /* It cannot have a requested IP option in the options. */
4436                 if (dhcp_client_ptr -> nx_dhcp_requested_ip_address != NX_DHCP_NO_ADDRESS)
4437                 {
4438 
4439                     /* Invalid message. */
4440                     dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4441                 }
4442 
4443                 /* Make sure the server interface table is up to date for this IP address. */
4444                 _nx_dhcp_update_assignable_ip_address(dhcp_ptr, dhcp_client_ptr, dhcp_client_ptr -> nx_dhcp_clientip_address,
4445                                                       NX_DHCP_ADDRESS_STATUS_ASSIGNED_EXT);
4446 
4447                 /* And update the client record assigned IP address in case it is not set yet. */
4448                 dhcp_client_ptr -> nx_dhcp_assigned_ip_address = dhcp_client_ptr -> nx_dhcp_clientip_address;
4449 
4450                 /* Has client IP address leased (bound) from this server? */
4451                 if (dhcp_client_ptr -> nx_dhcp_client_state != NX_DHCP_STATE_BOUND)
4452                 {
4453 
4454                     /* No, so if this client needs to configure an IP address assigned
4455                        with this server it must start at the INIT state. */
4456                     dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
4457                 }
4458 
4459                 break;
4460             }
4461             default:
4462             {
4463 
4464 #ifdef EL_PRINTF_ENABLE
4465                  EL_PRINTF("DHCPserv: NACK! Received unknown response type.\n");
4466  #endif
4467 
4468                  dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPSILENT;
4469 
4470                  return(NX_SUCCESS);
4471 
4472                 /* No further processing to do. Leave the client state unchanged, whatever it was/is. */
4473             }
4474 
4475         } /* switch case on client message*/
4476     }
4477 
4478     /* Were there were any conditions requiring a NACK response? */
4479     if (dhcp_client_ptr -> nx_dhcp_response_type_to_client == NX_DHCP_TYPE_DHCPNACK)
4480     {
4481         /* Yes, the caller knows to send the NACK message. No processing to do. */
4482         return NX_SUCCESS;
4483     }
4484 
4485     /* If this is not a DISCOVERY or REQUEST message, we are done! */
4486     if ((dhcp_client_ptr -> nx_dhcp_message_type != NX_DHCP_TYPE_DHCPDISCOVER) &&
4487         (dhcp_client_ptr -> nx_dhcp_message_type != NX_DHCP_TYPE_DHCPREQUEST))
4488     {
4489 
4490         return(NX_SUCCESS);
4491     }
4492 
4493     /* If the boot/init state client did not request an address, we are done. */
4494     if (dhcp_client_ptr -> nx_dhcp_requested_ip_address == NX_DHCP_NO_ADDRESS)
4495     {
4496 
4497         return(NX_SUCCESS);
4498     }
4499 
4500     /* Check if the Client has requested a valid IP address. This is only permitted
4501        with a DISCO or REQUEST messages while the Client is in either the BOOT/INIT
4502        or SELECT states.
4503 
4504         As per RFC 2131 4.3.1, the DHCP server should assign an IP address in order of preference as follows:
4505         1) the client currently is bound to
4506         2) client ip address in client records (e.g. previously assigned to)
4507         3) the currently requested IP
4508         4) the server will assign one. */
4509 
4510     /* Find the currently binding source address in the server's database. */
4511     if (dhcp_client_ptr -> nx_dhcp_source_ip_address != NX_DHCP_NO_ADDRESS)
4512     {
4513 
4514         /* Assign this as the Client's IP address. */
4515         dhcp_client_ptr -> nx_dhcp_assigned_ip_address = dhcp_client_ptr -> nx_dhcp_source_ip_address;
4516     }
4517 
4518     /* Next best option: Has the client previously been assigned an IP address? */
4519     else if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address)
4520     {
4521 
4522         /* Yes, let's leave it assigned to it. */
4523         return(NX_SUCCESS);
4524     }
4525     else
4526     {
4527 
4528         /* Last option: Set the client's requested IP address as the one to assign. */
4529         dhcp_client_ptr -> nx_dhcp_assigned_ip_address = dhcp_client_ptr -> nx_dhcp_requested_ip_address;
4530     }
4531 
4532     return(NX_SUCCESS);
4533 }
4534 
4535 
4536 /**************************************************************************/
4537 /*                                                                        */
4538 /*  FUNCTION                                               RELEASE        */
4539 /*                                                                        */
4540 /*    _nx_dhcp_server_assign_ip_address                   PORTABLE C      */
4541 /*                                                           6.1          */
4542 /*  AUTHOR                                                                */
4543 /*                                                                        */
4544 /*    Yuxin Zhou, Microsoft Corporation                                   */
4545 /*                                                                        */
4546 /*  DESCRIPTION                                                           */
4547 /*                                                                        */
4548 /*  This service finds an available IP address for the client if none is  */
4549 /*  provided, and updates the client's record with the new IP address. It */
4550 /*  updates the interface table entry with current client data (lease     */
4551 /*  time, owner).                                                         */
4552 /*                                                                        */
4553 /*  If there already is an assigned IP address on the client record, this */
4554 /*  function will verify the IP address has not been assigned to another  */
4555 /*  client before setting the current client as owner.  If it has, this   */
4556 /*  function will look for another available IP address for  the client.  */
4557 /*                                                                        */
4558 /*  Once an address is assigned, this function updates the fields in the  */
4559 /*  interface pointer entry, and the "Your IP address" in its message back*/
4560 /*  to the client.                                                        */
4561 /*                                                                        */
4562 /*  INPUT                                                                 */
4563 /*                                                                        */
4564 /*    dhcp_cptr                             Pointer to DHCP Server        */
4565 /*    dhcp_client_ptr                       Pointer to client record      */
4566 /*                                                                        */
4567 /*  OUTPUT                                                                */
4568 /*                                                                        */
4569 /*    NX_SUCCESS                            Successful completion         */
4570 /*    NX_DHCP_NO_AVAILABLE_IP_ADDRESSES     No available address to assign*/
4571 /*                                                                        */
4572 /*  CALLS                                                                 */
4573 /*                                                                        */
4574 /*    _nx_dhcp_find_interface_table_ip_address                            */
4575 /*                                          Look up IP address in         */
4576 /*                                             server interface table     */
4577 /*    _nx_dhcp_find_ip_address_owner        Look up owner of an IP address*/
4578 /*                                             in server interfce table   */
4579 /*    _nx_dhcp_record_ip_address_owner      Set the client as IP address  */
4580 /*                                              owner in interface table  */
4581 /*                                                                        */
4582 /*  CALLED BY                                                             */
4583 /*                                                                        */
4584 /*    _nx_dhcp_validate_client_message      Check Client DHCP messages for*/
4585 /*                                              proper data and determine */
4586 /*                                              server response           */
4587 /*                                                                        */
4588 /*  RELEASE HISTORY                                                       */
4589 /*                                                                        */
4590 /*    DATE              NAME                      DESCRIPTION             */
4591 /*                                                                        */
4592 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4593 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4594 /*                                            resulting in version 6.1    */
4595 /*                                                                        */
4596 /**************************************************************************/
_nx_dhcp_server_assign_ip_address(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT * dhcp_client_ptr)4597 static UINT  _nx_dhcp_server_assign_ip_address(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT *dhcp_client_ptr)
4598 {
4599 
4600 NX_DHCP_INTERFACE_TABLE         *dhcp_interface_table_ptr;
4601 NX_DHCP_INTERFACE_IP_ADDRESS    *interface_address_ptr;
4602 UINT                            assigned_to_client;
4603 UINT                            assigned_ip;
4604 UINT                            lease_time;
4605 
4606 
4607     /* Set a flag on the outcome of finding an available address. */
4608     assigned_ip = NX_FALSE;
4609 
4610     /* Compute the client lease time based on client's requested
4611        lease time and server default lease time. */
4612     lease_time = dhcp_client_ptr -> nx_dhcp_requested_lease_time;
4613 
4614 
4615 #if (NX_DHCP_DEFAULT_LEASE_TIME >= 0xFFFFFFFF)
4616     if (lease_time == 0)
4617 #else
4618     if ((lease_time == 0) || (lease_time > NX_DHCP_DEFAULT_LEASE_TIME))
4619 #endif
4620     {
4621         lease_time = NX_DHCP_DEFAULT_LEASE_TIME;
4622     }
4623 
4624 
4625     interface_address_ptr = (NX_DHCP_INTERFACE_IP_ADDRESS *)NX_NULL;
4626 
4627     /* Does the Client have a candidate already assigned? */
4628     if (dhcp_client_ptr -> nx_dhcp_assigned_ip_address)
4629     {
4630 
4631         /* The client does have one assigned, but we need to verify it is available
4632            or already assigned to the client. */
4633 
4634         /* Look for this IP address in the specified interface IP address list (table). */
4635         _nx_dhcp_find_interface_table_ip_address(dhcp_ptr, dhcp_client_ptr -> nx_dhcp_client_iface_index,
4636                                  dhcp_client_ptr -> nx_dhcp_assigned_ip_address, &interface_address_ptr);
4637 
4638         /* Was the ip address found? */
4639         if (interface_address_ptr)
4640         {
4641 
4642             /* Yes; Is it assigned to anyone yet? */
4643             if (interface_address_ptr -> assigned == NX_FALSE)
4644             {
4645                 /* No, We will assign this one further below. */
4646             }
4647             else
4648             {
4649 
4650                 /* Determine who if is assigned to.  */
4651                 _nx_dhcp_find_ip_address_owner(interface_address_ptr, dhcp_client_ptr, &assigned_to_client);
4652 
4653                 /* Assigned to this client? */
4654                 if (assigned_to_client)
4655                 {
4656 
4657 
4658                     /* Yes, so we're done here, except for checking a few fields. */
4659 
4660                     /* Renew the lease time. */
4661                     interface_address_ptr -> lease_time = lease_time;
4662 
4663                     /* Set the Your IP address field for the server response message. */
4664                     dhcp_client_ptr -> nx_dhcp_your_ip_address = interface_address_ptr -> nx_assignable_ip_address;
4665 
4666                     return(NX_SUCCESS);
4667                 }
4668 
4669 #ifdef EL_PRINTF_ENABLE
4670                 EL_PRINTF("DHCPserv: NACK! Cannot assign requested IP address (already assigned)\n");
4671 #endif
4672 
4673                 /* No, assigned to someone else.  We cannot provide this so return a NACK. */
4674                 dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4675                 dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
4676 
4677                 /* Clear the client's assigned IP address since it is assigned to someone else. */
4678                 dhcp_client_ptr -> nx_dhcp_assigned_ip_address = NX_DHCP_NO_ADDRESS;
4679 
4680                 return(NX_SUCCESS);
4681             }
4682         }
4683         else
4684         {
4685 
4686             /* If this is a NOT discovery message, the server can not very well
4687                 assign a different IP address becaause an ACK reply cannot contain
4688                 different information. */
4689             if (dhcp_client_ptr -> nx_dhcp_message_type != NX_DHCP_TYPE_DHCPDISCOVER)
4690             {
4691 
4692 #ifdef EL_PRINTF_ENABLE
4693                 EL_PRINTF("DHCPserv: NACK! Cannot assign requested IP address (not owned by server)\n");
4694 #endif
4695 
4696                 /* Apparently the client has asked for an IP address either not
4697                    in the server database or on another network.  We cannot provide this
4698                    so return a NACK. */
4699                 dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4700                 dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
4701 
4702                 /* Clear the client record's 'assigned' IP address since none was assigned. */
4703                 dhcp_client_ptr -> nx_dhcp_assigned_ip_address = NX_DHCP_NO_ADDRESS;
4704 
4705                 /* Since the client did not get assigned an IP address
4706                    make sure the requested lease time is reset to zero. */
4707                 dhcp_client_ptr -> nx_dhcp_requested_lease_time = 0;
4708 
4709                 return(NX_SUCCESS);
4710             }
4711 
4712             /* For a Discovery request, the server will go ahead and find an
4713                available IP address to offer the client. */
4714         }
4715     }
4716 
4717     /* If the client doesn't have an address assigned yet, find one in the server table not
4718        yet assigned. */
4719     if (interface_address_ptr == 0x0)
4720     {
4721 
4722         UINT i;
4723 
4724         /* Set a local varible to the IP address list for this client. */
4725         dhcp_interface_table_ptr = &(dhcp_ptr -> nx_dhcp_interface_table[dhcp_client_ptr -> nx_dhcp_client_iface_index]);
4726 
4727         /* Yes, search for an available ip address in the IP list for this interface */
4728         for(i = 0; i < dhcp_interface_table_ptr -> nx_dhcp_address_list_size; i++)
4729         {
4730 
4731             /* Set a local pointer variable to the next address. */
4732             interface_address_ptr = &dhcp_interface_table_ptr -> nx_dhcp_ip_address_list[i];
4733 
4734             /* Is this address assigned already? */
4735             if (interface_address_ptr -> assigned == NX_FALSE)
4736             {
4737 
4738                 /* No, but it is now! */
4739 
4740                 /* Indicate the search was successful. */
4741                 assigned_ip = NX_TRUE;
4742 
4743                 break;
4744             }
4745         }
4746 
4747         /* Check if we were able to find an available IP address. */
4748         if (assigned_ip == NX_FALSE)
4749         {
4750 
4751 #ifdef EL_PRINTF_ENABLE
4752             EL_PRINTF("DHCPserv: NACK! Cannot assign requested IP address (not found in server IP list)\n");
4753 #endif
4754 
4755 
4756             /* The server is not obliged to respond, but it should let the client
4757                know if it cannot provide what it requests. */
4758             dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
4759             dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4760 
4761             /* Since the client did not get assigned an IP address
4762                make sure the requested lease time is reset to zero. */
4763             dhcp_client_ptr -> nx_dhcp_requested_lease_time = 0;
4764 
4765             /* Make sure the client record's 'assigned' IP address ir removed since it was not assigned. */
4766             dhcp_client_ptr -> nx_dhcp_assigned_ip_address = NX_DHCP_NO_ADDRESS;
4767 
4768             /* No, return the error status. */
4769             return(NX_DHCP_NO_AVAILABLE_IP_ADDRESSES);
4770         }
4771     }
4772 
4773     /* Was the assigned ip address available? */
4774     if (interface_address_ptr)
4775     {
4776 
4777         /* Set the client as the IP address owner in the server interface table. */
4778         _nx_dhcp_record_ip_address_owner(interface_address_ptr, dhcp_client_ptr, lease_time);
4779 
4780         /* Set the client's assigned IP address. */
4781         dhcp_client_ptr -> nx_dhcp_assigned_ip_address = interface_address_ptr -> nx_assignable_ip_address;
4782 
4783         /* Set the Your IP address field for the server response message. */
4784         dhcp_client_ptr -> nx_dhcp_your_ip_address = interface_address_ptr -> nx_assignable_ip_address;
4785 
4786         /* We are done! */
4787         return(NX_SUCCESS);
4788     }
4789 
4790     /* If we're here we were not able to assign an IP address. */
4791 
4792     /* The server is not obliged to respond, but it should let the client
4793        know if it cannot provide what it requests. */
4794     dhcp_client_ptr -> nx_dhcp_client_state = NX_DHCP_STATE_INIT;
4795 
4796 #ifdef EL_PRINTF_ENABLE
4797     EL_PRINTF("DHCPserv: NACK! Server cannot assign requested IP address\n");
4798 #endif
4799 
4800     dhcp_client_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPNACK;
4801 
4802     /* Make sure the client record's 'assigned' IP address ir removed since it was not assigned. */
4803     dhcp_client_ptr -> nx_dhcp_assigned_ip_address = NX_DHCP_NO_ADDRESS;
4804 
4805     /* Since the client did not get assigned an IP address
4806        make sure the requested lease time is reset to zero. */
4807     dhcp_client_ptr -> nx_dhcp_requested_lease_time = 0;
4808 
4809     return(NX_DHCP_NO_AVAILABLE_IP_ADDRESSES);
4810 }
4811 
4812 
4813 /**************************************************************************/
4814 /*                                                                        */
4815 /*  FUNCTION                                               RELEASE        */
4816 /*                                                                        */
4817 /*    _nx_dhcp_server_extract_information                 PORTABLE C      */
4818 /*                                                           6.3.0        */
4819 /*  AUTHOR                                                                */
4820 /*                                                                        */
4821 /*    Yuxin Zhou, Microsoft Corporation                                   */
4822 /*                                                                        */
4823 /*  DESCRIPTION                                                           */
4824 /*                                                                        */
4825 /*    This function extracts information from a DHCP Client packet and    */
4826 /*    updates the server's client database. If no client record exists for*/
4827 /*    the client this function will create one for it.  It does some      */
4828 /*    message validation but primary extracts DHCP header and option      */
4829 /*    fields to the client record.                                        */
4830 /*                                                                        */
4831 /*    If an internal error is encountered parsing the packet buffer, this */
4832 /*    function returns the error status.  If it finds the client DHCP     */
4833 /*    message invalid, it returns successful completion but sets the DHCP */
4834 /*    server to respond with either NACK or silence.                      */
4835 /*                                                                        */
4836 /*    When this function is finished, the caller releases the packet.     */
4837 /*                                                                        */
4838 /*  INPUT                                                                 */
4839 /*                                                                        */
4840 /*    dhcp_cptr                             Pointer to DHCP Server        */
4841 /*    dhcp_client_ptr                       Pointer to client record      */
4842 /*    packet_ptr                            Pointer to DHCP client packet */
4843 /*    iface_index                           Interface index packet was    */
4844 /*                                                  received on           */
4845 /*                                                                        */
4846 /*  OUTPUT                                                                */
4847 /*                                                                        */
4848 /*    NX_SUCCESS                            Successful completion         */
4849 /*    status                                Actual completion status      */
4850 /*                                                                        */
4851 /*  CALLS                                                                 */
4852 /*                                                                        */
4853 /*    _nx_dhcp_find_client_record_by_chaddr Find Client record using the  */
4854 /*                                            parsed mac address          */
4855 /*    _nx_dhcp_server_get_data              Parse DHCP data from buffer   */
4856 /*                                                                        */
4857 /*  CALLED BY                                                             */
4858 /*                                                                        */
4859 /*    _nx_dhcp_listen_for_messages          Process DHCP Client messages  */
4860 /*                                                                        */
4861 /*  RELEASE HISTORY                                                       */
4862 /*                                                                        */
4863 /*    DATE              NAME                      DESCRIPTION             */
4864 /*                                                                        */
4865 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4866 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4867 /*                                            fixed the issue of read     */
4868 /*                                            and write overflow,         */
4869 /*                                            fixed compiler warnings,    */
4870 /*                                            resulting in version 6.1    */
4871 /*  10-31-2023     Haiqing Zhao             Modified comment(s), and      */
4872 /*                                            improved internal logic,  */
4873 /*                                            resulting in version 6.3.0  */
4874 /*                                                                        */
4875 /**************************************************************************/
_nx_dhcp_server_extract_information(NX_DHCP_SERVER * dhcp_ptr,NX_DHCP_CLIENT ** dhcp_client_ptr,NX_PACKET * packet_ptr,UINT iface_index)4876 static UINT  _nx_dhcp_server_extract_information(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT **dhcp_client_ptr,
4877                                           NX_PACKET *packet_ptr, UINT iface_index)
4878 {
4879 
4880 UINT            status;
4881 ULONG           value;
4882 ULONG           size = 0;
4883 ULONG           xid;
4884 UCHAR           *work_ptr;
4885 ULONG           client_mac_msw;
4886 ULONG           client_mac_lsw;
4887 NX_IPV4_HEADER  *ip_header_ptr;
4888 NX_DHCP_CLIENT  *temp_client_rec_ptr;
4889 
4890 
4891     /* Initialize the DHCP Client pointer to null pending successful data extraction. */
4892     *dhcp_client_ptr = NX_NULL;
4893 
4894     /* Set up UCHAR pointer to HW address field to extract client hardware address
4895        which we will use as the client's unique identifier, since not all clients may use
4896        Option 61/Client Identifier.  */
4897     work_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_CLIENT_HW;
4898 
4899     /* Pickup the MSW of the MAC address.  */
4900     client_mac_msw = (((ULONG) work_ptr[0]) << 8)  | ((ULONG) work_ptr[1]);
4901     client_mac_lsw = (((ULONG) work_ptr[2]) << 24) |
4902                      (((ULONG) work_ptr[3]) << 16) |
4903                      (((ULONG) work_ptr[4]) << 8)  |
4904                      ((ULONG) work_ptr[5]);
4905 
4906     /* Check the client hardware (mac address) field is filled in. */
4907     if ((client_mac_msw == 0) && (client_mac_lsw == 0))
4908     {
4909 
4910         return(NX_DHCP_INVALID_HW_ADDRESS);
4911     }
4912 
4913     /* Look up the client record by IP address and interface index in Client Records table. */
4914     status = _nx_dhcp_find_client_record_by_chaddr(dhcp_ptr, iface_index, client_mac_msw,
4915                                                    client_mac_lsw, &temp_client_rec_ptr, NX_TRUE);
4916 
4917 
4918     /* Check for error during search. */
4919     if ((status != NX_SUCCESS) ||  !temp_client_rec_ptr)
4920     {
4921         return(status);
4922     }
4923 
4924 
4925     /* Note: No need to check for NULL pointer because we asked to add the
4926        record if no match is found. */
4927 
4928 
4929     /* Get the client's current binding IP address from the packet interface. */
4930     ip_header_ptr = (NX_IPV4_HEADER *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER) - sizeof(NX_IPV4_HEADER));
4931 
4932     temp_client_rec_ptr -> nx_dhcp_source_ip_address = ip_header_ptr -> nx_ip_header_source_ip;
4933     temp_client_rec_ptr -> nx_dhcp_destination_ip_address = ip_header_ptr -> nx_ip_header_destination_ip;
4934 
4935     /* Get the message type. */
4936     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_OP, 1, &value);
4937     if (status)
4938     {
4939         return(status);
4940     }
4941 
4942     /* Check this is a 'request' DHCP Client message (not to be confused with the REQUEST
4943        message type. */
4944     if (value != NX_DHCP_OP_REQUEST)
4945     {
4946 
4947 #ifdef EL_PRINTF_ENABLE
4948         EL_PRINTF("DHCPserv: SILENCE! Client DHCP packet not coded as a BOOT Request. Invalid request.\n");
4949 #endif
4950 
4951         /* Set the server to ignore the 'reply'. */
4952         temp_client_rec_ptr -> nx_dhcp_response_type_to_client = NX_DHCP_TYPE_DHCPSILENT;
4953 
4954         /* Return successful completion status. */
4955         return(NX_SUCCESS);
4956     }
4957 
4958     /* Get the hardware type. */
4959     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_HTYPE, 1, &value);
4960     if (status)
4961     {
4962         return(status);
4963     }
4964 
4965     /* This is the Client interface type which is used in the default client identifier tag. */
4966     temp_client_rec_ptr -> nx_dhcp_client_hwtype = value;
4967 
4968     /* Get the hardware length. */
4969     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_HLEN, 1, &value);
4970     if (status)
4971     {
4972         return(status);
4973     }
4974 
4975     /* This is the size of the hardware address. Used in the default client identifier tag. */
4976     temp_client_rec_ptr -> nx_dhcp_client_hwlen = value;
4977 
4978     /* Extract the message ID. */
4979     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_XID, 4, &xid);
4980     if (status)
4981     {
4982         return(status);
4983     }
4984 
4985     /* Save the client xid to use in the server's reply back. */
4986     temp_client_rec_ptr -> nx_dhcp_xid = xid;
4987 
4988     /* Check if response to client should unicast or (default) broadcast.  */
4989     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_FLAGS, 1, &value);
4990     if (status)
4991     {
4992         return(status);
4993     }
4994 
4995     /* Get the Client's preference for unicast vs broadcast. */
4996     temp_client_rec_ptr -> nx_dhcp_broadcast_flag_set = (value & NX_DHCP_FLAGS_BROADCAST) ? 0x80 : 0x0;
4997 
4998     /* Extract the Requested Client IP address, if there is one. */
4999     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_CLIENT_IP, 4, &value);
5000     if (status)
5001     {
5002         return(status);
5003     }
5004 
5005     /* This is the Client IP address reported by the Client. */
5006     temp_client_rec_ptr -> nx_dhcp_clientip_address = value;
5007 
5008     /* Update the IP address assigned to the Client "Your/client IP address".  */
5009     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_YOUR_IP, 4, &value);
5010     if (status)
5011     {
5012         return(status);
5013     }
5014 
5015     /* This is the "Your IP address" which only the server should fill in. Should be zero in
5016        client messages. */
5017     temp_client_rec_ptr -> nx_dhcp_your_ip_address =  value;
5018 
5019     /* Extract the "Next Server IP address".     */
5020     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_SERVER_IP, 4, &value);
5021     if (status)
5022     {
5023         return(status);
5024     }
5025     temp_client_rec_ptr -> nx_dhcp_clientrec_server_ip =  value;
5026 
5027     /* Store relay IP address for DHCP server (on another subnet) if there is one. */
5028     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_RELAY_IP, 4, &value);
5029     if (status)
5030     {
5031         return(status);
5032     }
5033     temp_client_rec_ptr -> nx_dhcp_relay_ip_address =  value;
5034 
5035     /* Look for the marker indicating option data (magic cookie).  */
5036     status = _nx_dhcp_server_get_data(packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_VENDOR, 4, &value);
5037     if (status)
5038     {
5039         return(status);
5040     }
5041 
5042     /* Note we don't store the magic cookie value. */
5043 
5044     /* Are there user options?  */
5045     if (value == NX_DHCP_MAGIC_COOKIE)
5046     {
5047         /* Yes there are user options in the Client message. */
5048 
5049         /* Move up the buffer pointer past the magic cookie thing. */
5050         work_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_DHCP_OFFSET_VENDOR + 4;
5051 
5052         /* Extract all the client option data. */
5053         while (*work_ptr != 0xFF)
5054         {
5055 
5056             /* Guard against a missing "END" marker by checking if we are at the end of the DHCP packet data. */
5057             if (work_ptr + 2 > packet_ptr -> nx_packet_append_ptr)
5058             {
5059 
5060                 /* Yes, Client must have sent a DHCP message with improperly terminated option
5061                    data (or Client is using a super large DHCP packet). */
5062                 return(NX_DHCP_IMPROPERLY_TERMINATED_OPTION);
5063             }
5064 
5065             /* Get the next option. */
5066             _nx_dhcp_server_get_data(work_ptr, 1, &value);
5067 
5068             /* Move up the buffer pointer to the option length. */
5069             work_ptr++;
5070 
5071             /* Get the option length. */
5072             _nx_dhcp_server_get_data(work_ptr, 1, &size);
5073 
5074             /* Move up the buffer pointer to the next option. */
5075             work_ptr++;
5076 
5077             /* Validate the size. */
5078             if (work_ptr + size > packet_ptr -> nx_packet_append_ptr)
5079             {
5080                 return(NX_DHCP_IMPROPERLY_TERMINATED_OPTION);
5081             }
5082 
5083             /* Is this the client ID option? */
5084             if (value != NX_DHCP_SERVER_OPTION_CLIENT_ID)
5085             {
5086 
5087                 /* Check if there is enough space to store client requested options. */
5088                 if (temp_client_rec_ptr -> nx_dhcp_client_option_count < NX_DHCP_CLIENT_OPTIONS_MAX)
5089                 {
5090 
5091                     /* Process as any other option. */
5092                     _nx_dhcp_process_option_data(temp_client_rec_ptr, (CHAR *)work_ptr, (UCHAR)value, NX_TRUE, (UINT)size);
5093                 }
5094             }
5095 
5096             /* Move up the buffer pointer past the current option data size to the next option. */
5097             work_ptr += size;
5098         }
5099     }
5100 
5101     /* Return the location of the client record. */
5102     *dhcp_client_ptr = temp_client_rec_ptr;
5103 
5104     return(NX_SUCCESS);
5105 }
5106 
5107 
5108 /**************************************************************************/
5109 /*                                                                        */
5110 /*  FUNCTION                                               RELEASE        */
5111 /*                                                                        */
5112 /*    _nx_dhcp_get_option_data                            PORTABLE C      */
5113 /*                                                           6.1          */
5114 /*  AUTHOR                                                                */
5115 /*                                                                        */
5116 /*    Yuxin Zhou, Microsoft Corporation                                   */
5117 /*                                                                        */
5118 /*  DESCRIPTION                                                           */
5119 /*                                                                        */
5120 /*    This routine extracts data from the specified location and adds the */
5121 /*    Client's requested option to the Client record.  The caller can ask */
5122 /*    for the option data as well to be extracted and stored to client    */
5123 /*    record.                                                             */
5124 /*                                                                        */
5125 /*  INPUT                                                                 */
5126 /*                                                                        */
5127 /*    dhcp_client_ptr                      Pointer to DHCP Client         */
5128 /*    buffer                               Pointer to data buffer         */
5129 /*    option                               Option from Client DHCP packet */
5130 /*    size                                 Size of data buffer            */
5131 /*    get_option_data                      Indicate if server wants option*/
5132 /*                                           data stored in client record */
5133 /*                                                                        */
5134 /*  OUTPUT                                                                */
5135 /*                                                                        */
5136 /*    status                               Error status extracting data   */
5137 /*    NX_SUCCESS                           Successful completion          */
5138 /*                                                                        */
5139 /*  CALLS                                                                 */
5140 /*                                                                        */
5141 /*    _nx_dhcp_server_get_data             Extract data from specified    */
5142 /*                                                  buffer location       */
5143 /*    memcpy                               Copy specified area of memory  */
5144 /*                                                                        */
5145 /*  CALLED BY                                                             */
5146 /*                                                                        */
5147 /*    _nx_dhcp_server_extract_information   Extract DHCP data from packet */
5148 /*                                                                        */
5149 /*  RELEASE HISTORY                                                       */
5150 /*                                                                        */
5151 /*    DATE              NAME                      DESCRIPTION             */
5152 /*                                                                        */
5153 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5154 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
5155 /*                                            verified memcpy use cases,  */
5156 /*                                            fixed the issue of infinite */
5157 /*                                            recursion,                  */
5158 /*                                            resulting in version 6.1    */
5159 /*                                                                        */
5160 /**************************************************************************/
_nx_dhcp_process_option_data(NX_DHCP_CLIENT * dhcp_client_ptr,CHAR * buffer,UCHAR option,UINT get_option_data,UINT size)5161 static UINT  _nx_dhcp_process_option_data(NX_DHCP_CLIENT *dhcp_client_ptr, CHAR *buffer, UCHAR option, UINT get_option_data, UINT size)
5162 {
5163 
5164 UINT  status;
5165 ULONG option_value = 0;
5166 
5167     /* Do we parse option data for this option? */
5168     if (get_option_data)
5169     {
5170 
5171         /* Yes, store to local variable to be applied to the Client record below. */
5172         status = _nx_dhcp_server_get_data((UCHAR *)buffer, size, &option_value);
5173         if (status)
5174         {
5175             return(status);
5176         }
5177     }
5178 
5179     switch (option)
5180     {
5181 
5182         case 1:
5183             /* Subnet mask */
5184             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5185             if (get_option_data)
5186             {
5187                 dhcp_client_ptr -> nx_dhcp_subnet_mask = option_value;
5188             }
5189             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5190             break;
5191 
5192         case 3:
5193             /* Router or gateway */
5194             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5195             if (get_option_data)
5196             {
5197                 dhcp_client_ptr -> nx_dhcp_router_ip_address = option_value;
5198             }
5199             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5200             break;
5201 
5202         case 6:
5203             /* Domain name server */
5204             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5205             if (get_option_data)
5206             {
5207                 dhcp_client_ptr -> nx_dhcp_dns_ip_address = option_value;
5208             }
5209             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5210             break;
5211 
5212 
5213         case 12:
5214             /* Client host name */
5215             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5216             if (get_option_data)
5217             {
5218 
5219                 /* Only store as much of the host name as will fit in the host name buffer. */
5220                 size  = (size <= NX_DHCP_CLIENT_HOSTNAME_MAX) ? size : NX_DHCP_CLIENT_HOSTNAME_MAX;
5221 
5222                 /* Clear the memory buffer before writing the host name to it. */
5223                 memset(&dhcp_client_ptr -> nx_dhcp_client_name[0], 0, NX_DHCP_CLIENT_HOSTNAME_MAX);
5224                 memcpy(&dhcp_client_ptr -> nx_dhcp_client_name[0], buffer, size); /* Use case of memcpy is verified. */
5225             }
5226             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5227             break;
5228 
5229         case 50:
5230 
5231             /* Client's requested IP address */
5232             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5233             if (get_option_data)
5234             {
5235 
5236                 dhcp_client_ptr -> nx_dhcp_requested_ip_address = option_value;
5237             }
5238             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5239             break;
5240 
5241         case 51:
5242 
5243             /* Client's requested IP address lease time */
5244             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5245             if (get_option_data)
5246             {
5247 
5248                 dhcp_client_ptr -> nx_dhcp_requested_lease_time = option_value;
5249             }
5250             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5251             break;
5252 
5253         case 53:
5254             /* Message type */
5255             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5256             dhcp_client_ptr -> nx_dhcp_message_type = (UCHAR)option_value;
5257             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5258             break;
5259 
5260         case 54:
5261             /* Server ID by which server identifies itself to client(usually server IP address).
5262                The Client includes this option in a REQUEST message to identify which server
5263                it wants to lease an IP address from. */
5264             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5265             if (get_option_data)
5266             {
5267 
5268                 dhcp_client_ptr -> nx_dhcp_server_id = option_value;
5269             }
5270             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5271             break;
5272 
5273         case 55:
5274 
5275             /* Check if there is enough space to store all the client requested options. */
5276             if (dhcp_client_ptr -> nx_dhcp_client_option_count + size > NX_DHCP_CLIENT_OPTIONS_MAX)
5277             {
5278                 size = NX_DHCP_CLIENT_OPTIONS_MAX - dhcp_client_ptr -> nx_dhcp_client_option_count;
5279             }
5280 
5281             /* Update the client record with that option. */
5282             memcpy(&(dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count]), buffer, size); /* Use case of memcpy is verified. */
5283             dhcp_client_ptr -> nx_dhcp_client_option_count += size;
5284             break;
5285 
5286         case 61:
5287 
5288             /* Note Client ID is handled separately. */
5289             dhcp_client_ptr -> nx_dhcp_user_options[dhcp_client_ptr -> nx_dhcp_client_option_count] = option;
5290             dhcp_client_ptr -> nx_dhcp_client_option_count++;
5291 
5292             break;
5293 
5294         case 116: /* Auto configuration option */
5295         case 60:  /* Vendor class Identifier. */
5296 
5297             /* Not supported at this time. */
5298             break;
5299 
5300         default:
5301             break;
5302     }
5303 
5304     return(NX_SUCCESS);
5305 }
5306 
5307 
5308 /**************************************************************************/
5309 /*                                                                        */
5310 /*  FUNCTION                                               RELEASE        */
5311 /*                                                                        */
5312 /*    _nx_dhcp_add_requested_option                       PORTABLE C      */
5313 /*                                                           6.1          */
5314 /*  AUTHOR                                                                */
5315 /*                                                                        */
5316 /*    Yuxin Zhou, Microsoft Corporation                                   */
5317 /*                                                                        */
5318 /*  DESCRIPTION                                                           */
5319 /*                                                                        */
5320 /*    This routine receives options and which interface the DHCP client is*/
5321 /*    on and adds the server information if there is any for that option  */
5322 /*    into the packet reply buffer.                                       */
5323 /*                                                                        */
5324 /*  INPUT                                                                 */
5325 /*                                                                        */
5326 /*    dhcp_message                         Pointer to message buffer      */
5327 /*    iface_index                          Index to server interface table*/
5328 /*    buffer                               Pointer to buffer to write to  */
5329 /*    option                               Option to add                  */
5330 /*                                                                        */
5331 /*  OUTPUT                                                                */
5332 /*                                                                        */
5333 /*    NX_SUCCESS                            Successful completion status  */
5334 /*    status                                Actual completion status      */
5335 /*                                                                        */
5336 /*  CALLS                                                                 */
5337 /*                                                                        */
5338 /*    _nx_dhcp_add_option                   Adds the actual option to the */
5339 /*                                             DHCP message buffer        */
5340 /*                                                                        */
5341 /*  CALLED BY                                                             */
5342 /*                                                                        */
5343 /*    _nx_dhcp_respond_to_dhcp_message     Prepare and send out DHCP      */
5344 /*                                                 response to client     */
5345 /*                                                                        */
5346 /*  RELEASE HISTORY                                                       */
5347 /*                                                                        */
5348 /*    DATE              NAME                      DESCRIPTION             */
5349 /*                                                                        */
5350 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5351 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5352 /*                                            resulting in version 6.1    */
5353 /*                                                                        */
5354 /**************************************************************************/
_nx_dhcp_add_requested_option(NX_DHCP_SERVER * dhcp_ptr,UINT iface_index,UCHAR * buffer,UINT option,UINT * index)5355 static UINT  _nx_dhcp_add_requested_option(NX_DHCP_SERVER *dhcp_ptr, UINT iface_index, UCHAR *buffer, UINT option, UINT *index)
5356 {
5357 
5358 UINT status = NX_SUCCESS;
5359 
5360     /* The NetX DHCP server provides a limited list of DHCP options for ACK responses. These do NOT
5361        include the server's 'required' options. */
5362     switch (option)
5363     {
5364 
5365         case 1: /* Subnet mask  */
5366             status = _nx_dhcp_add_option(buffer, option, NX_DHCP_SERVER_OPTION_SUBNET_MASK_SIZE,
5367                                          dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_subnet_mask, index);
5368             break;
5369 
5370         case 3:  /* Router IP address */
5371 
5372 
5373             status = _nx_dhcp_add_option(buffer, option, NX_DHCP_SERVER_OPTION_ROUTER_SIZE,
5374                                          dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_router_ip_address, index);
5375             break;
5376 
5377         case 6:  /* DNS IP address */
5378             status = _nx_dhcp_add_option(buffer, option, NX_DHCP_SERVER_OPTION_ADDRESS_SIZE,
5379                                          dhcp_ptr -> nx_dhcp_interface_table[iface_index].nx_dhcp_dns_ip_address, index);
5380             break;
5381 
5382         /* The NetX DHCP server does not reply to other options at this time. */
5383         default:
5384             break;
5385     }
5386 
5387     return(status);
5388 }
5389 
5390 
5391 /**************************************************************************/
5392 /*                                                                        */
5393 /*  FUNCTION                                               RELEASE        */
5394 /*                                                                        */
5395 /*    _nx_dhcp_add_option                                 PORTABLE C      */
5396 /*                                                           6.1          */
5397 /*  AUTHOR                                                                */
5398 /*                                                                        */
5399 /*    Yuxin Zhou, Microsoft Corporation                                   */
5400 /*                                                                        */
5401 /*  DESCRIPTION                                                           */
5402 /*                                                                        */
5403 /*    This routine adds a DHCP option data to the DHCP message in the     */
5404 /*    supplied buffer.  Adding the option includes adding the option code,*/
5405 /*    length of the data and option data value.                           */
5406 /*                                                                        */
5407 /*  INPUT                                                                 */
5408 /*                                                                        */
5409 /*    dhcp_message                          Pointer to message buffer     */
5410 /*    option                                Option to add                 */
5411 /*    value                                 Value of Option to add        */
5412 /*                                                                        */
5413 /*  OUTPUT                                                                */
5414 /*                                                                        */
5415 /*    status                                Completion status             */
5416 /*                                                                        */
5417 /*  CALLS                                                                 */
5418 /*                                                                        */
5419 /*    _nx_dhcp_server_store_data            Store data value              */
5420 /*                                                                        */
5421 /*  CALLED BY                                                             */
5422 /*                                                                        */
5423 /*    _nx_dhcp_process                      Process the DHCP state machine*/
5424 /*                                                                        */
5425 /*  RELEASE HISTORY                                                       */
5426 /*                                                                        */
5427 /*    DATE              NAME                      DESCRIPTION             */
5428 /*                                                                        */
5429 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5430 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5431 /*                                            resulting in version 6.1    */
5432 /*                                                                        */
5433 /**************************************************************************/
_nx_dhcp_add_option(UCHAR * dhcp_message,UINT option,UINT size,ULONG value,UINT * index)5434 static UINT  _nx_dhcp_add_option(UCHAR *dhcp_message, UINT option, UINT size, ULONG value, UINT *index)
5435 {
5436 
5437 
5438     /* Store the option.  */
5439     *(dhcp_message + (*index)) = (UCHAR)option;
5440     (*index) ++;
5441 
5442     /* Store the option size.  */
5443     *(dhcp_message + (*index)) = (UCHAR)size;
5444     (*index) ++;
5445 
5446     /* Store the option value.  */
5447     _nx_dhcp_server_store_data(dhcp_message + (*index), size, value);
5448     (*index) += size;
5449 
5450     /* Return a successful completion.  */
5451     return(NX_SUCCESS);
5452 }
5453 
5454 
5455 /**************************************************************************/
5456 /*                                                                        */
5457 /*  FUNCTION                                               RELEASE        */
5458 /*                                                                        */
5459 /*    _nx_dhcp_server_get_data                            PORTABLE C      */
5460 /*                                                           6.1          */
5461 /*  AUTHOR                                                                */
5462 /*                                                                        */
5463 /*    Yuxin Zhou, Microsoft Corporation                                   */
5464 /*                                                                        */
5465 /*  DESCRIPTION                                                           */
5466 /*                                                                        */
5467 /*    This routine gets a data value from a buffer, assuming the data is  */
5468 /*    stored in standard Network format (big endian). Up to 4 bytes of    */
5469 /*    data are used, if there are more than 4 bytes, only the lower 4     */
5470 /*    bytes are returned.                                                 */
5471 /*                                                                        */
5472 /*  INPUT                                                                 */
5473 /*                                                                        */
5474 /*    data                                  Pointer to buffer data        */
5475 /*    size                                  Size of data value            */
5476 /*    value                                 Data value retrieved          */
5477 /*                                                                        */
5478 /*  OUTPUT                                                                */
5479 /*                                                                        */
5480 /*    NX_SUCCESS                            Successful completion         */
5481 /*    NX_DHCP_PARAMETER_ERROR               Invalid parameter input       */
5482 /*                                                                        */
5483 /*  CALLS                                                                 */
5484 /*                                                                        */
5485 /*    None                                                                */
5486 /*                                                                        */
5487 /*  CALLED BY                                                             */
5488 /*                                                                        */
5489 /*    _nx_dhcp_get_response                 Get response from server      */
5490 /*    _nx_dhcp_server_extract_information   Extract server information    */
5491 /*    _nx_dhcp_update_address_list          Update address list           */
5492 /*                                                                        */
5493 /*  RELEASE HISTORY                                                       */
5494 /*                                                                        */
5495 /*    DATE              NAME                      DESCRIPTION             */
5496 /*                                                                        */
5497 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5498 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5499 /*                                            resulting in version 6.1    */
5500 /*                                                                        */
5501 /**************************************************************************/
_nx_dhcp_server_get_data(UCHAR * data,UINT size,ULONG * value)5502 static UINT  _nx_dhcp_server_get_data(UCHAR *data, UINT size, ULONG *value)
5503 {
5504 
5505 
5506     /* Check for invalid buffer parameters. */
5507     if ((size == 0) || (data == 0x0) || (value == 0))
5508     {
5509         return(NX_DHCP_PARAMETER_ERROR);
5510     }
5511 
5512     /* Initialize value to zero. */
5513     *value = 0;
5514 
5515     /* Store each byte of data from buffer into result.  */
5516     while (size > 0)
5517     {
5518 
5519         /* Build return value.  */
5520         *value = (*value << 8) | *data++;
5521         size--;
5522     }
5523 
5524     /* Return value.  */
5525     return(NX_SUCCESS);
5526 }
5527 
5528 
5529 /**************************************************************************/
5530 /*                                                                        */
5531 /*  FUNCTION                                               RELEASE        */
5532 /*                                                                        */
5533 /*    _nx_dhcp_server_store_data                          PORTABLE C      */
5534 /*                                                           6.1          */
5535 /*  AUTHOR                                                                */
5536 /*                                                                        */
5537 /*    Yuxin Zhou, Microsoft Corporation                                   */
5538 /*                                                                        */
5539 /*  DESCRIPTION                                                           */
5540 /*                                                                        */
5541 /*    This function stores a data value in a buffer in standard Network   */
5542 /*    format (big endian) where the destination may be unaligned. Up to   */
5543 /*    4 bytes of data are stored, if the size is larger than 4 bytes, the */
5544 /*    remaining bytes are set to zero.                                    */
5545 /*                                                                        */
5546 /*  INPUT                                                                 */
5547 /*                                                                        */
5548 /*    data                                  Pointer to buffer data        */
5549 /*    size                                  Size of data value            */
5550 /*    value                                 Value to store                */
5551 /*                                                                        */
5552 /*  OUTPUT                                                                */
5553 /*                                                                        */
5554 /*    None                                                                */
5555 /*                                                                        */
5556 /*  CALLS                                                                 */
5557 /*                                                                        */
5558 /*    None                                                                */
5559 /*                                                                        */
5560 /*  CALLED BY                                                             */
5561 /*                                                                        */
5562 /*    _nx_dhcp_send_request                 Send DHCP request             */
5563 /*    _nx_dhcp_add_option                   Add a DHCP option             */
5564 /*                                                                        */
5565 /*  RELEASE HISTORY                                                       */
5566 /*                                                                        */
5567 /*    DATE              NAME                      DESCRIPTION             */
5568 /*                                                                        */
5569 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5570 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5571 /*                                            resulting in version 6.1    */
5572 /*                                                                        */
5573 /**************************************************************************/
_nx_dhcp_server_store_data(UCHAR * data,UINT size,ULONG value)5574 static VOID  _nx_dhcp_server_store_data(UCHAR *data, UINT size, ULONG value)
5575 {
5576 
5577     /* Make sure that data is left justified.  */
5578     switch (size)
5579     {
5580 
5581         case 1:
5582 
5583             value <<= 24;
5584             break;
5585 
5586         case 2:
5587 
5588             value <<= 16;
5589             break;
5590 
5591         case 3:
5592 
5593             value <<= 8;
5594             break;
5595 
5596         default:
5597             break;
5598     }
5599 
5600     /* Store the value.  */
5601     while (size-- > 0)
5602     {
5603 
5604         *data = (UCHAR)((value >> 24) & 0xff);
5605         data++;
5606         value <<= 8;
5607     }
5608 }
5609 
5610 #endif /* NX_DISABLE_IPV4 */
5611