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