1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Component                                                        */
16 /**                                                                       */
17 /**   Dynamic Host Configuration Protocol (DHCP) Client                   */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_DHCP_SOURCE_CODE
23 
24 
25 /* Force error checking to be disabled in this module */
26 
27 #ifndef NX_DISABLE_ERROR_CHECKING
28 #define NX_DISABLE_ERROR_CHECKING
29 #endif
30 
31 /* Include necessary system files.  */
32 
33 #include "nx_api.h"
34 #ifndef NX_DISABLE_IPV4
35 #include "nx_system.h"
36 #include "nx_ip.h"
37 #include "nx_arp.h"
38 #include "nxd_dhcp_client.h"
39 #include "tx_timer.h"
40 
41 
42 /* Define the DHCP Internal Function.  */
43 static VOID        _nx_dhcp_thread_entry(ULONG ip_instance);
44 static UINT        _nx_dhcp_extract_information(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, UCHAR *dhcp_message, UINT length);
45 static UINT        _nx_dhcp_get_option_value(UCHAR *bootp_message, UINT option, ULONG *value, UINT length);
46 static UINT        _nx_dhcp_add_option_value(UCHAR *bootp_message, UINT option, UINT size, ULONG value, UINT *index);
47 static UINT        _nx_dhcp_add_option_string(UCHAR *bootp_message, UINT option, UINT size, UCHAR *value, UINT *index);
48 static UINT        _nx_dhcp_add_option_parameter_request(NX_DHCP *dhcp_ptr, UCHAR *bootp_message, UINT *index);
49 static ULONG       _nx_dhcp_update_timeout(ULONG timeout);
50 static ULONG       _nx_dhcp_update_renewal_timeout(ULONG timeout);
51 static UCHAR       *_nx_dhcp_search_buffer(UCHAR *option_message, UINT option, UINT length);
52 static ULONG       _nx_dhcp_get_data(UCHAR *data, UINT size);
53 static VOID        _nx_dhcp_store_data(UCHAR *data, UINT size, ULONG value);
54 static VOID        _nx_dhcp_move_string(UCHAR *dest, UCHAR *source, UINT size);
55 static UINT        _nx_dhcp_send_request_internal(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, UINT dhcp_message_type);
56 static UINT        _nx_dhcp_client_send_with_zero_source_address(NX_DHCP *dhcp_ptr, UINT iface_index, NX_PACKET *packet_ptr);
57 static ULONG       _nx_dhcp_add_randomize(ULONG timeout);
58 static VOID        _nx_dhcp_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
59 static VOID        _nx_dhcp_packet_process(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *dhcp_interface, NX_PACKET *packet_ptr);
60 static VOID        _nx_dhcp_timeout_entry(ULONG dhcp);
61 static VOID        _nx_dhcp_timeout_process(NX_DHCP *dhcp_ptr);
62 static UINT        _nx_dhcp_interface_record_find(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_INTERFACE_RECORD **interface_record);
63 
64 
65 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
66 static VOID        _nx_dhcp_ip_conflict(NX_IP *ip_ptr, UINT interface_index, ULONG ip_address, ULONG physical_msw, ULONG physical_lsw);
67 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE */
68 
69 
70 
71 /* Define the Request string that specifies which options are to be added
72    to the DHCP Client discover request to the server. Additional options
73    (found in nx_dhcp.h) may be added by calling nx_dhcp_user_option_request().  */
74 
75 UCHAR _nx_dhcp_request_parameters[] = { NX_DHCP_OPTION_SUBNET_MASK,
76                                         NX_DHCP_OPTION_GATEWAYS,
77                                         NX_DHCP_OPTION_DNS_SVR};
78 
79 #define NX_DHCP_REQUEST_PARAMETER_SIZE sizeof(_nx_dhcp_request_parameters)
80 
81 static struct NX_DHCP_STRUCT    *_nx_dhcp_created_ptr;
82 
83 /* Bring in externs for caller checking code.  */
84 
85 NX_CALLER_CHECKING_EXTERNS
86 
87 
88 
89 /**************************************************************************/
90 /*                                                                        */
91 /*  FUNCTION                                               RELEASE        */
92 /*                                                                        */
93 /*    _nxe_dhcp_create                                    PORTABLE C      */
94 /*                                                           6.1          */
95 /*  AUTHOR                                                                */
96 /*                                                                        */
97 /*    Yuxin Zhou, Microsoft Corporation                                   */
98 /*                                                                        */
99 /*  DESCRIPTION                                                           */
100 /*                                                                        */
101 /*    This function checks for errors in the DHCP create function call.   */
102 /*                                                                        */
103 /*  INPUT                                                                 */
104 /*                                                                        */
105 /*    dhcp_ptr                              Pointer to DHCP instance      */
106 /*    ip_ptr                                Pointer to IP instance        */
107 /*    name_ptr                              DHCP name pointer             */
108 /*                                                                        */
109 /*  OUTPUT                                                                */
110 /*                                                                        */
111 /*    status                                Completion status             */
112 /*                                                                        */
113 /*  CALLS                                                                 */
114 /*                                                                        */
115 /*    _nx_dhcp_create                       Actual DHCP create function   */
116 /*                                                                        */
117 /*  CALLED BY                                                             */
118 /*                                                                        */
119 /*    Application Code                                                    */
120 /*                                                                        */
121 /*  RELEASE HISTORY                                                       */
122 /*                                                                        */
123 /*    DATE              NAME                      DESCRIPTION             */
124 /*                                                                        */
125 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
126 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
127 /*                                            resulting in version 6.1    */
128 /*                                                                        */
129 /**************************************************************************/
_nxe_dhcp_create(NX_DHCP * dhcp_ptr,NX_IP * ip_ptr,CHAR * name_ptr)130 UINT  _nxe_dhcp_create(NX_DHCP *dhcp_ptr, NX_IP *ip_ptr, CHAR *name_ptr)
131 {
132 
133 UINT    status;
134 
135 
136     /* Check for invalid input pointers.  */
137     if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) || (dhcp_ptr == NX_NULL))
138     {
139 
140         return(NX_PTR_ERROR);
141     }
142 
143     /* Call actual DHCP create service.  */
144     status =  _nx_dhcp_create(dhcp_ptr, ip_ptr, name_ptr);
145 
146     /* Return status.  */
147     return(status);
148 }
149 
150 
151 /**************************************************************************/
152 /*                                                                        */
153 /*  FUNCTION                                               RELEASE        */
154 /*                                                                        */
155 /*    _nx_dhcp_create                                     PORTABLE C      */
156 /*                                                           6.1.12       */
157 /*  AUTHOR                                                                */
158 /*                                                                        */
159 /*    Yuxin Zhou, Microsoft Corporation                                   */
160 /*                                                                        */
161 /*  DESCRIPTION                                                           */
162 /*                                                                        */
163 /*    This function initializes the DHCP structure and associated IP      */
164 /*    instance for DHCP operation.  In doing so, it creates a packet      */
165 /*    pool for DHCP messages, a UDP socket for communication with the     */
166 /*    server, and a DHCP processing thread.                               */
167 /*                                                                        */
168 /*    The primary interface is automatically enabled for DHCP.  To run    */
169 /*    DHCP on a different interface, use the nx_dhcp_set_interface_index  */
170 /*    service.  To run DHCP on multiple interfaces, see                   */
171 /*    nx_dhcp_interface_enable and nx_dhcp_interface_start                */
172 /*                                                                        */
173 /*  INPUT                                                                 */
174 /*                                                                        */
175 /*    dhcp_ptr                              Pointer to DHCP instance      */
176 /*    ip_ptr                                Pointer to IP instance        */
177 /*    name_ptr                              DHCP name pointer             */
178 /*                                                                        */
179 /*  OUTPUT                                                                */
180 /*                                                                        */
181 /*    status                                Completion status             */
182 /*                                                                        */
183 /*  CALLS                                                                 */
184 /*                                                                        */
185 /*    nx_packet_pool_create                 Create the DHCP packet pool   */
186 /*    nx_packet_pool_delete                 Delete the DHCP packet pool   */
187 /*    nx_udp_socket_create                  Create the DHCP UDP socket    */
188 /*    nx_udp_socket_delete                  Delete the DHCP UDP socket    */
189 /*    tx_mutex_create                       Create DHCP mutex             */
190 /*    tx_mutex_delete                       Delete DHCP mutex             */
191 /*    tx_thread_create                      Create DHCP processing thread */
192 /*    tx_timer_create                       Create DHCP timer             */
193 /*    tx_timer_delete                       Delete DHCP timer             */
194 /*                                                                        */
195 /*  CALLED BY                                                             */
196 /*                                                                        */
197 /*    Application Code                                                    */
198 /*                                                                        */
199 /*  RELEASE HISTORY                                                       */
200 /*                                                                        */
201 /*    DATE              NAME                      DESCRIPTION             */
202 /*                                                                        */
203 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
204 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
205 /*                                            resulting in version 6.1    */
206 /*  08-02-2021     Yuxin Zhou               Modified comment(s), and      */
207 /*                                            improved the code,          */
208 /*                                            resulting in version 6.1.8  */
209 /*  01-31-2022     Yuxin Zhou               Modified comment(s), supported*/
210 /*                                            multiple client instances,  */
211 /*                                            resulting in version 6.1.10 */
212 /*  07-29-2022     Yuxin Zhou               Modified comment(s), cleaned  */
213 /*                                            up error check logic, and   */
214 /*                                            properly terminated thread, */
215 /*                                            resulting in version 6.1.12 */
216 /*                                                                        */
217 /**************************************************************************/
_nx_dhcp_create(NX_DHCP * dhcp_ptr,NX_IP * ip_ptr,CHAR * name_ptr)218 UINT  _nx_dhcp_create(NX_DHCP *dhcp_ptr, NX_IP *ip_ptr, CHAR *name_ptr)
219 {
220 
221 TX_INTERRUPT_SAVE_AREA
222 
223 UINT    status;
224 #ifdef NX_DHCP_CLIENT_ENABLE_HOST_NAME_CHECK
225 CHAR    *temp_ptr;
226 UINT    label_length = 0;
227 #endif /* NX_DHCP_CLIENT_ENABLE_HOST_NAME_CHECK  */
228 
229 
230 #ifdef NX_DHCP_CLIENT_ENABLE_HOST_NAME_CHECK
231 
232     /* Set the pointer.  */
233     temp_ptr = name_ptr;
234 
235     /* The total length of a domain name (host name) is restricted to 255 octets or less.  */
236     if (_nx_utility_string_length_check(temp_ptr, NX_NULL, 255))
237     {
238         return (NX_DHCP_INVALID_NAME);
239     }
240 
241     /* The labels must follow the rules for ARPANET host names.  They must
242        start with a letter, end with a letter or digit, and have as interior
243        characters only letters, digits, and hyphen.  There are also some
244        restrictions on the length. Labels must be 63 characters or less.
245        RFC 1035, Section 2.3.1, Page8.  */
246     while (*temp_ptr)
247     {
248 
249         /* Is a dot?  */
250         if (*temp_ptr == '.')
251         {
252 
253             /* Current label is end.  */
254 
255             /* Labels must be 63 characters or less, and check the continuous dot '..' for host name.  */
256             if ((label_length == 0) || (label_length > 63))
257                 return (NX_DHCP_INVALID_NAME);
258 
259             /* End with a letter or digit. Only need to check the Hyphen '-' since
260                *(temp_ptr - 1) must be Letter, Hyphen or Digits in 'else'.  */
261             if (*(temp_ptr - 1) == '-')
262                 return (NX_DHCP_INVALID_NAME);
263 
264             /* Continue the next lable.  */
265             label_length = 0;
266         }
267         else
268         {
269 
270             /* Update the lable length.  */
271             label_length++;
272 
273             /* Letter.  */
274             if((((*temp_ptr) | 0x20) >= 'a') && (((*temp_ptr) | 0x20) <= 'z'))
275             {
276 
277                 /* Continue next character.  */
278                 temp_ptr++;
279                 continue;
280             }
281 
282             /* Start with a letter.  */
283             if (label_length == 1)
284                 return (NX_DHCP_INVALID_NAME);
285 
286             /* Hyphen or Digits.  */
287             if ((*temp_ptr != '-') &&
288                 ((*temp_ptr < '0') || (*temp_ptr > '9')))
289                 return (NX_DHCP_INVALID_NAME);
290         }
291 
292         /* Continue next character.  */
293         temp_ptr++;
294     }
295 
296     /* Check again if the host name have not the 'dot' terminator.  */
297     if (*(temp_ptr - 1) != '.')
298     {
299 
300         /* Labels must be 63 characters or less.  */
301         if (label_length > 63)
302             return (NX_DHCP_INVALID_NAME);
303 
304         /* End with a letter or digit. Only need to check the Hyphen '-' since
305             *(temp_ptr - 1) must be Letter, Hyphen or Digits in 'else'.  */
306         if (*(temp_ptr - 1) == '-')
307             return (NX_DHCP_INVALID_NAME);
308     }
309 #endif /* NX_DHCP_CLIENT_ENABLE_HOST_NAME_CHECK  */
310 
311     /* Initialize the DHCP control block to zero.  */
312     memset((void *) dhcp_ptr, 0, sizeof(NX_DHCP));
313 
314     /* Save the IP pointer.  */
315     dhcp_ptr -> nx_dhcp_ip_ptr =  ip_ptr;
316 
317     /* Save the DHCP name.  */
318     dhcp_ptr -> nx_dhcp_name =  name_ptr;
319 
320     /* If the host does not intend to supply their own packet pool, create one here. */
321 #ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
322 
323     /* Check the packet payload size, DHCP Client must be prepared to receive a message of up to 576 octets.
324        RFC 2131, Section 2, Page10.  */
325     if (NX_DHCP_PACKET_PAYLOAD < (NX_PHYSICAL_HEADER + NX_DHCP_MINIMUM_IP_DATAGRAM))
326     {
327 
328         /* Invalid payload, return error status.  */
329         return(NX_DHCP_INVALID_PAYLOAD);
330     }
331 
332     /* Create the pool and check the status */
333     nx_packet_pool_create(&dhcp_ptr -> nx_dhcp_pool, "NetX DHCP Client", NX_DHCP_PACKET_PAYLOAD,
334                           dhcp_ptr -> nx_dhcp_pool_area, NX_DHCP_PACKET_POOL_SIZE);
335 
336     /* Set an internal packet pool pointer to the newly created packet pool. */
337     dhcp_ptr -> nx_dhcp_packet_pool_ptr = &dhcp_ptr -> nx_dhcp_pool;
338 
339 #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
340 
341     /* Set the maximum DHCP message size.  */
342     dhcp_ptr -> nx_dhcp_max_dhcp_message_size = NX_DHCP_PACKET_PAYLOAD - NX_PHYSICAL_HEADER;
343 #endif /* NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION  */
344 
345 #endif /* NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL  */
346 
347     /* Create the Socket and check the status */
348     nx_udp_socket_create(ip_ptr, &(dhcp_ptr -> nx_dhcp_socket), "NetX DHCP Client",
349                          NX_DHCP_TYPE_OF_SERVICE, NX_DHCP_FRAGMENT_OPTION, NX_DHCP_TIME_TO_LIVE, NX_DHCP_QUEUE_DEPTH);
350 
351     /* Set the UDP socket receive callback function.  */
352     nx_udp_socket_receive_notify(&(dhcp_ptr -> nx_dhcp_socket), _nx_dhcp_udp_receive_notify);
353 
354     dhcp_ptr -> nx_dhcp_socket.nx_udp_socket_reserved_ptr = (VOID*)dhcp_ptr;
355 
356     /* Create the ThreadX activity timeout timer.  This will be used to periodically check to see if
357        a client connection has gone silent and needs to be terminated.  */
358     status =  tx_timer_create(&(dhcp_ptr -> nx_dhcp_timer), "DHCP Client Timer", _nx_dhcp_timeout_entry,
359                               (ULONG)(ALIGN_TYPE)dhcp_ptr, (NX_DHCP_TIME_INTERVAL),
360                               (NX_DHCP_TIME_INTERVAL), TX_NO_ACTIVATE);
361 
362     NX_TIMER_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_timer), dhcp_ptr)
363 
364     /* Determine if the semaphore creation was successful.  */
365     if (status != TX_SUCCESS)
366     {
367 
368         /* Delete the UDP socket.  */
369         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
370 
371 #ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
372         /* Delete the packet pool.  */
373         nx_packet_pool_delete(dhcp_ptr -> nx_dhcp_packet_pool_ptr);
374 #endif
375 
376         /* No, return error status.  */
377         return(status);
378     }
379 
380     /* Create the DHCP mutex.  */
381     status =  tx_mutex_create(&(dhcp_ptr -> nx_dhcp_mutex), "NetX DHCP Client", TX_NO_INHERIT);
382 
383     /* Determine if the semaphore creation was successful.  */
384     if (status != TX_SUCCESS)
385     {
386 
387         /* Delete the UDP socket.  */
388         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
389 
390 #ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
391         /* Delete the packet pool.  */
392         nx_packet_pool_delete(dhcp_ptr -> nx_dhcp_packet_pool_ptr);
393 #endif
394 
395         /* Delete the timer.  */
396         tx_timer_delete(&(dhcp_ptr -> nx_dhcp_timer));
397 
398         /* No, return error status.  */
399         return(status);
400     }
401 
402     /* Create the DHCP processing thread.  */
403     status =  tx_thread_create(&(dhcp_ptr -> nx_dhcp_thread), "NetX DHCP Client", _nx_dhcp_thread_entry, (ULONG)(ALIGN_TYPE)dhcp_ptr,
404                                 dhcp_ptr -> nx_dhcp_thread_stack, NX_DHCP_THREAD_STACK_SIZE,
405                                 NX_DHCP_THREAD_PRIORITY, NX_DHCP_THREAD_PRIORITY, 1, TX_DONT_START);
406 
407     NX_THREAD_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_thread), dhcp_ptr)
408 
409     /* Determine if the thread creation was successful.  */
410     if (status != TX_SUCCESS)
411     {
412 
413         /* Delete the mutex.  */
414         tx_mutex_delete(&(dhcp_ptr -> nx_dhcp_mutex));
415 
416         /* Delete the UDP socket.  */
417         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
418 
419 #ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
420         /* Delete the packet pool.  */
421         nx_packet_pool_delete(dhcp_ptr -> nx_dhcp_packet_pool_ptr);
422 #endif
423 
424         /* Delete the timer.  */
425         tx_timer_delete(&(dhcp_ptr -> nx_dhcp_timer));
426 
427         /* No, return error status.  */
428         return(status);
429     }
430 
431     /* Create a DHCP event flag group. .  */
432     status = tx_event_flags_create(&(dhcp_ptr -> nx_dhcp_events), (CHAR *)"DHCP Client Events");
433 
434     /* Check for error. */
435     if (status != TX_SUCCESS)
436     {
437 
438         /* First put the thread into TERMINATE state. */
439         tx_thread_terminate(&(dhcp_ptr -> nx_dhcp_thread));
440 
441         /* Delete the thread.  */
442         tx_thread_delete(&(dhcp_ptr -> nx_dhcp_thread));
443 
444         /* Delete the mutex.  */
445         tx_mutex_delete(&(dhcp_ptr -> nx_dhcp_mutex));
446 
447         /* Delete the timer.  */
448         tx_timer_delete(&(dhcp_ptr -> nx_dhcp_timer));
449 
450         /* Delete the UDP socket.  */
451         nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
452 
453 #ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
454         /* Delete the packet pool.  */
455         nx_packet_pool_delete(dhcp_ptr -> nx_dhcp_packet_pool_ptr);
456 #endif
457 
458         /* No, return error status.  */
459         return(status);
460     }
461 
462     /* Otherwise, the DHCP initialization was successful.  Place the
463        DHCP control block on the list of created DHCP instances.  */
464     TX_DISABLE
465 
466     /* Update the dhcp structure ID.  */
467     dhcp_ptr -> nx_dhcp_id =  NX_DHCP_ID;
468 
469     /* Setup this DHCP's created links.  */
470     dhcp_ptr -> nx_dhcp_created_next = _nx_dhcp_created_ptr;
471 
472     /* Place the new DHCP control block on the head of created DHCPs.  */
473     _nx_dhcp_created_ptr = dhcp_ptr;
474 
475     /* Restore previous interrupt posture.  */
476     TX_RESTORE
477 
478     /* Default enable DHCP on the primary interface (0).  */
479     _nx_dhcp_interface_enable(dhcp_ptr, 0);
480 
481     /* Return a successful status.  */
482     return(NX_SUCCESS);
483 }
484 
485 
486 /**************************************************************************/
487 /*                                                                        */
488 /*  FUNCTION                                               RELEASE        */
489 /*                                                                        */
490 /*    _nxe_dhcp_clear_broadcast_flag                      PORTABLE C      */
491 /*                                                           6.1          */
492 /*  AUTHOR                                                                */
493 /*                                                                        */
494 /*    Yuxin Zhou, Microsoft Corporation                                   */
495 /*                                                                        */
496 /*  DESCRIPTION                                                           */
497 /*                                                                        */
498 /*    This function checks for errors in the DHCP set the clear broadcast */
499 /*    flag in DHCP Client messages service.                               */
500 /*                                                                        */
501 /*  INPUT                                                                 */
502 /*                                                                        */
503 /*    dhcp_ptr                              Pointer to DHCP instance      */
504 /*    clear_flag                            Broadcast flag status         */
505 /*                                                                        */
506 /*  OUTPUT                                                                */
507 /*                                                                        */
508 /*    status                                Completion status             */
509 /*                                                                        */
510 /*  CALLS                                                                 */
511 /*                                                                        */
512 /*    _nx_dhcp_clear_broadcast_flag         Actual DHCP Client clear      */
513 /*                                            broadcast flag service      */
514 /*                                                                        */
515 /*  CALLED BY                                                             */
516 /*                                                                        */
517 /*    Application Code                                                    */
518 /*                                                                        */
519 /*  RELEASE HISTORY                                                       */
520 /*                                                                        */
521 /*    DATE              NAME                      DESCRIPTION             */
522 /*                                                                        */
523 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
524 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
525 /*                                            resulting in version 6.1    */
526 /*                                                                        */
527 /**************************************************************************/
_nxe_dhcp_clear_broadcast_flag(NX_DHCP * dhcp_ptr,UINT clear_flag)528 UINT  _nxe_dhcp_clear_broadcast_flag(NX_DHCP *dhcp_ptr, UINT clear_flag)
529 {
530 
531 UINT    status;
532 
533     /* Check for invalid input pointer.  */
534     if (dhcp_ptr == NX_NULL)
535     {
536 
537         return(NX_PTR_ERROR);
538     }
539 
540     /* Call actual DHCP clear flag service.  */
541     status =  _nx_dhcp_clear_broadcast_flag(dhcp_ptr, clear_flag);
542 
543     /* Return status.  */
544     return(status);
545 }
546 
547 
548 /**************************************************************************/
549 /*                                                                        */
550 /*  FUNCTION                                               RELEASE        */
551 /*                                                                        */
552 /*    _nx_dhcp_clear_broadcast_flag                       PORTABLE C      */
553 /*                                                           6.1          */
554 /*  AUTHOR                                                                */
555 /*                                                                        */
556 /*    Yuxin Zhou, Microsoft Corporation                                   */
557 /*                                                                        */
558 /*  DESCRIPTION                                                           */
559 /*                                                                        */
560 /*    This service uses the clear_flag input to clear or set the broadcast*/
561 /*    in DHCP Client messages to the DHCP server. By default the broadcast*/
562 /*    flag is set.                                                        */
563 /*                                                                        */
564 /*    This function is intended for DHCP Clients whose DHCP messages are  */
565 /*    routed through a relay agent (router) that will not accept DHCP     */
566 /*    messages with broadcast replies requested.                          */
567 /*                                                                        */
568 /*         NX_TRUE        broadcast flag is cleared for all messages      */
569 /*         NX_FALSE       broadcast flag set only if it normally would be */
570 /*                                                                        */
571 /*    The server reply will actually be broadcast when relayed by the     */
572 /*    router using this strategy.                                         */
573 /*                                                                        */
574 /*    If DHCP is enabled on multiple interfaces, this service will set the*/
575 /*    broadcast flag on all interfaces. To set this flag on a specific    */
576 /*    interface, use the nx_dhcp_interface_clear_broadcast_flag.          */
577 /*                                                                        */
578 /*  INPUT                                                                 */
579 /*                                                                        */
580 /*    dhcp_ptr                              Pointer to DHCP instance      */
581 /*    clear_flag                            Broadcast flag status         */
582 /*                                                                        */
583 /*  OUTPUT                                                                */
584 /*                                                                        */
585 /*    status                                Completion status             */
586 /*                                                                        */
587 /*  CALLS                                                                 */
588 /*                                                                        */
589 /*    tx_mutex_get                          Obtain protection mutex       */
590 /*    tx_mutex_put                          Release protection mutex      */
591 /*                                                                        */
592 /*  CALLED BY                                                             */
593 /*                                                                        */
594 /*    Application Code                                                    */
595 /*                                                                        */
596 /*  RELEASE HISTORY                                                       */
597 /*                                                                        */
598 /*    DATE              NAME                      DESCRIPTION             */
599 /*                                                                        */
600 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
601 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
602 /*                                            resulting in version 6.1    */
603 /*                                                                        */
604 /**************************************************************************/
_nx_dhcp_clear_broadcast_flag(NX_DHCP * dhcp_ptr,UINT clear_flag)605 UINT  _nx_dhcp_clear_broadcast_flag(NX_DHCP *dhcp_ptr, UINT clear_flag)
606 {
607 
608 UINT    i;
609 
610     /* Obtain DHCP Client protection mutex. */
611     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
612 
613     /* Loop to set the broadcast flag for all interface record enabled.  */
614     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
615     {
616 
617         /* Check if this record is valid.  */
618         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid == NX_TRUE)
619         {
620 
621             dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_clear_broadcast = clear_flag;
622         }
623     }
624 
625     /* Release the mutex.  */
626     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
627 
628     /* Return a successful status.  */
629     return(NX_SUCCESS);
630 
631 }
632 
633 /**************************************************************************/
634 /*                                                                        */
635 /*  FUNCTION                                               RELEASE        */
636 /*                                                                        */
637 /*    _nxe_dhcp_interface_clear_broadcast_flag            PORTABLE C      */
638 /*                                                           6.1          */
639 /*  AUTHOR                                                                */
640 /*                                                                        */
641 /*    Yuxin Zhou, Microsoft Corporation                                   */
642 /*                                                                        */
643 /*  DESCRIPTION                                                           */
644 /*                                                                        */
645 /*    This function checks for errors in the interface specific clear     */
646 /*    broadcast flag service.                                             */
647 /*                                                                        */
648 /*  INPUT                                                                 */
649 /*                                                                        */
650 /*    dhcp_ptr                              Pointer to DHCP instance      */
651 /*    iface_index                           Network interface index       */
652 /*    clear_flag                            Broadcast flag status         */
653 /*                                                                        */
654 /*  OUTPUT                                                                */
655 /*                                                                        */
656 /*    status                                Completion status             */
657 /*    NX_PTR_ERROR                          Invalid pointer input         */
658 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
659 /*                                                                        */
660 /*  CALLS                                                                 */
661 /*                                                                        */
662 /*    _nx_dhcp_interface_clear_broadcast_flag Actual DHCP Client clear    */
663 /*                                            broadcast flag service      */
664 /*                                                                        */
665 /*  CALLED BY                                                             */
666 /*                                                                        */
667 /*    Application Code                                                    */
668 /*                                                                        */
669 /*  RELEASE HISTORY                                                       */
670 /*                                                                        */
671 /*    DATE              NAME                      DESCRIPTION             */
672 /*                                                                        */
673 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
674 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
675 /*                                            resulting in version 6.1    */
676 /*                                                                        */
677 /**************************************************************************/
_nxe_dhcp_interface_clear_broadcast_flag(NX_DHCP * dhcp_ptr,UINT iface_index,UINT clear_flag)678 UINT  _nxe_dhcp_interface_clear_broadcast_flag(NX_DHCP *dhcp_ptr, UINT iface_index, UINT clear_flag)
679 {
680 
681 UINT    status;
682 
683     /* Check for invalid input pointer.  */
684     if (dhcp_ptr == NX_NULL)
685     {
686 
687         return(NX_PTR_ERROR);
688     }
689 
690     /* Check interface index.  */
691     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
692     {
693         return(NX_INVALID_INTERFACE);
694     }
695 
696     /* Call actual DHCP clear flag service.  */
697     status =  _nx_dhcp_interface_clear_broadcast_flag(dhcp_ptr, iface_index, clear_flag);
698 
699     /* Return status.  */
700     return(status);
701 }
702 
703 
704 /**************************************************************************/
705 /*                                                                        */
706 /*  FUNCTION                                               RELEASE        */
707 /*                                                                        */
708 /*    _nx_dhcp_interace_clear_broadcast_flag              PORTABLE C      */
709 /*                                                           6.1          */
710 /*  AUTHOR                                                                */
711 /*                                                                        */
712 /*    Yuxin Zhou, Microsoft Corporation                                   */
713 /*                                                                        */
714 /*  DESCRIPTION                                                           */
715 /*                                                                        */
716 /*    This service uses the clear_flag input to determine if the DHCP     */
717 /*    Client on the specified network interface should clear the broadcast*/
718 /*    flag in its DHCP messages to the DHCP server (normally it sets the  */
719 /*    broadcast flag.                                                     */
720 /*                                                                        */
721 /*    This is intended for DHCP Clients whose DHCP messages are routed    */
722 /*    through arelay agent (router) that will not accept DHCP messages    */
723 /*    withbroadcast replies requested.                                    */
724 /*                                                                        */
725 /*         NX_TRUE        broadcast flag is cleared for all messages      */
726 /*         NX_FALSE       broadcast flag set only if it normally would be */
727 /*                                                                        */
728 /*    The server reply will actually be broadcast when relayed by the     */
729 /*    router using this strategy.                                         */
730 /*                                                                        */
731 /*  INPUT                                                                 */
732 /*                                                                        */
733 /*    dhcp_ptr                              Pointer to DHCP instance      */
734 /*    iface_index                           Network interface index       */
735 /*    clear_flag                            Broadcast flag status         */
736 /*                                                                        */
737 /*  OUTPUT                                                                */
738 /*                                                                        */
739 /*    NX_SUCCESS                            Completion status             */
740 /*                                                                        */
741 /*  CALLS                                                                 */
742 /*                                                                        */
743 /*    tx_mutex_get                          Obtain protection mutex       */
744 /*    tx_mutex_put                          Release protection mutex      */
745 /*    _nx_dhcp_interface_record_find        Find Client record for input  */
746 /*                                              DHCP interface            */
747 /*                                                                        */
748 /*  CALLED BY                                                             */
749 /*                                                                        */
750 /*    Application Code                                                    */
751 /*                                                                        */
752 /*  RELEASE HISTORY                                                       */
753 /*                                                                        */
754 /*    DATE              NAME                      DESCRIPTION             */
755 /*                                                                        */
756 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
757 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
758 /*                                            resulting in version 6.1    */
759 /*                                                                        */
760 /**************************************************************************/
_nx_dhcp_interface_clear_broadcast_flag(NX_DHCP * dhcp_ptr,UINT iface_index,UINT clear_flag)761 UINT  _nx_dhcp_interface_clear_broadcast_flag(NX_DHCP *dhcp_ptr, UINT iface_index, UINT clear_flag)
762 {
763 
764 UINT    status;
765 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
766 
767     /* Obtain DHCP Client protection mutex. */
768     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
769 
770     /* Find the interface record.  */
771     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
772 
773     /* Check status.  */
774     if (status)
775     {
776 
777         /* Release the mutex.  */
778         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
779         return(status);
780     }
781 
782     /* Set or clear the option to request unicast/clear broadcast flag. */
783     interface_record -> nx_dhcp_clear_broadcast = clear_flag;
784 
785     /* Release the mutex.  */
786     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
787 
788     /* Return a successful status.  */
789     return(NX_SUCCESS);
790 }
791 
792 /**************************************************************************/
793 /*                                                                        */
794 /*  FUNCTION                                               RELEASE        */
795 /*                                                                        */
796 /*    _nxe_dhcp_packet_pool_set                           PORTABLE C      */
797 /*                                                           6.1          */
798 /*  AUTHOR                                                                */
799 /*                                                                        */
800 /*    Yuxin Zhou, Microsoft Corporation                                   */
801 /*                                                                        */
802 /*  DESCRIPTION                                                           */
803 /*                                                                        */
804 /*    This function performs error checking for the set the DHCP Client   */
805 /*    packet pool service.                                                */
806 /*                                                                        */
807 /*  INPUT                                                                 */
808 /*                                                                        */
809 /*    dhcp_ptr                              Pointer to DHCP instance      */
810 /*    packet_pool_ptr                       Pointer to packet pool        */
811 /*                                                                        */
812 /*  OUTPUT                                                                */
813 /*                                                                        */
814 /*    NX_SUCCESS                            Packet pool successfully set  */
815 /*    NX_PTR_ERROR                          Invalid pointer input         */
816 /*    NX_NOT_ENABLED                        DHCP client not enabled for   */
817 /*                                             user create packet pool    */
818 /*                                                                        */
819 /*  CALLS                                                                 */
820 /*                                                                        */
821 /*    _nx_dhcp_packet_pool_set                                            */
822 /*                                          Actual set packet pool service*/
823 /*  CALLED BY                                                             */
824 /*                                                                        */
825 /*    Application Code                                                    */
826 /*                                                                        */
827 /*  RELEASE HISTORY                                                       */
828 /*                                                                        */
829 /*    DATE              NAME                      DESCRIPTION             */
830 /*                                                                        */
831 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
832 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
833 /*                                            resulting in version 6.1    */
834 /*                                                                        */
835 /**************************************************************************/
_nxe_dhcp_packet_pool_set(NX_DHCP * dhcp_ptr,NX_PACKET_POOL * packet_pool_ptr)836 UINT  _nxe_dhcp_packet_pool_set(NX_DHCP *dhcp_ptr, NX_PACKET_POOL *packet_pool_ptr)
837 {
838 
839 #ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
840     NX_PARAMETER_NOT_USED(dhcp_ptr);
841     NX_PARAMETER_NOT_USED(packet_pool_ptr);
842 
843     /* Client not configured for the user creating the packet pool. Return an error status. */
844     return NX_NOT_ENABLED;
845 #else
846 
847 UINT  status;
848 
849 
850     /* Check for invalid pointer input. */
851     if ((dhcp_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL))
852     {
853 
854         return NX_PTR_ERROR;
855     }
856 
857     /* Check the packet payload size, DHCP Client must be prepared to receive a message of up to 576 octets.
858        RFC2131, Section2, Page10.  */
859     if (packet_pool_ptr -> nx_packet_pool_payload_size < (NX_PHYSICAL_HEADER + NX_DHCP_MINIMUM_IP_DATAGRAM))
860     {
861 
862         /* Invalid payload, return error status.  */
863         return(NX_DHCP_INVALID_PAYLOAD);
864     }
865 
866     status = _nx_dhcp_packet_pool_set(dhcp_ptr, packet_pool_ptr);
867 
868     return status;
869 #endif
870 }
871 
872 
873 /**************************************************************************/
874 /*                                                                        */
875 /*  FUNCTION                                               RELEASE        */
876 /*                                                                        */
877 /*    _nx_dhcp_packet_pool_set                            PORTABLE C      */
878 /*                                                           6.1          */
879 /*  AUTHOR                                                                */
880 /*                                                                        */
881 /*    Yuxin Zhou, Microsoft Corporation                                   */
882 /*                                                                        */
883 /*  DESCRIPTION                                                           */
884 /*                                                                        */
885 /*    This function sets the DHCP Client packet pool by passing in a      */
886 /*    packet pool pointer to packet pool already create.  The             */
887 /*    NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL must be set.                 */
888 /*                                                                        */
889 /*  INPUT                                                                 */
890 /*                                                                        */
891 /*    dhcp_ptr                              Pointer to DHCP instance      */
892 /*    packet_pool_ptr                       Pointer to packet pool        */
893 /*                                                                        */
894 /*  OUTPUT                                                                */
895 /*                                                                        */
896 /*    NX_SUCCESS                            Successful completion status  */
897 /*    NX_NOT_ENABLED                        Setting DHCP Client packet    */
898 /*                                             pool not enabled           */
899 /*  CALLS                                                                 */
900 /*                                                                        */
901 /*    None                                                                */
902 /*                                                                        */
903 /*  CALLED BY                                                             */
904 /*                                                                        */
905 /*    Application Code                                                    */
906 /*                                                                        */
907 /*  RELEASE HISTORY                                                       */
908 /*                                                                        */
909 /*    DATE              NAME                      DESCRIPTION             */
910 /*                                                                        */
911 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
912 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
913 /*                                            resulting in version 6.1    */
914 /*                                                                        */
915 /**************************************************************************/
_nx_dhcp_packet_pool_set(NX_DHCP * dhcp_ptr,NX_PACKET_POOL * packet_pool_ptr)916 UINT  _nx_dhcp_packet_pool_set(NX_DHCP *dhcp_ptr, NX_PACKET_POOL *packet_pool_ptr)
917 {
918 
919 
920     /* Determine if the DHCP Client is configured for accepting a packet pool pointer. */
921 #ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
922     NX_PARAMETER_NOT_USED(dhcp_ptr);
923     NX_PARAMETER_NOT_USED(packet_pool_ptr);
924 
925     /* No, return the error status. */
926     return NX_NOT_ENABLED;
927 #else
928 
929     /* Set the Client packet pool to the supplied packet pool. */
930     dhcp_ptr -> nx_dhcp_packet_pool_ptr = packet_pool_ptr;
931 
932 #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
933 
934     /* Set the maximum DHCP message size.  */
935     dhcp_ptr -> nx_dhcp_max_dhcp_message_size = packet_pool_ptr -> nx_packet_pool_payload_size - NX_PHYSICAL_HEADER;
936 #endif /* NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION  */
937 
938     return NX_SUCCESS;
939 #endif
940 }
941 
942 
943 /**************************************************************************/
944 /*                                                                        */
945 /*  FUNCTION                                               RELEASE        */
946 /*                                                                        */
947 /*    _nxe_dhcp_reinitialize                              PORTABLE C      */
948 /*                                                           6.1          */
949 /*  AUTHOR                                                                */
950 /*                                                                        */
951 /*    Yuxin Zhou, Microsoft Corporation                                   */
952 /*                                                                        */
953 /*  DESCRIPTION                                                           */
954 /*                                                                        */
955 /*    This function performs error checking for the reinitialize service. */
956 /*                                                                        */
957 /*  INPUT                                                                 */
958 /*                                                                        */
959 /*    dhcp_ptr                              Pointer to DHCP instance      */
960 /*                                                                        */
961 /*  OUTPUT                                                                */
962 /*                                                                        */
963 /*    status                                Completion status             */
964 /*    NX_PTR_ERROR                          Invalid pointer input         */
965 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
966 /*                                                                        */
967 /*  CALLS                                                                 */
968 /*                                                                        */
969 /*    None                                                                */
970 /*                                                                        */
971 /*  CALLED BY                                                             */
972 /*                                                                        */
973 /*    Application Code                                                    */
974 /*                                                                        */
975 /*  RELEASE HISTORY                                                       */
976 /*                                                                        */
977 /*    DATE              NAME                      DESCRIPTION             */
978 /*                                                                        */
979 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
980 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
981 /*                                            resulting in version 6.1    */
982 /*                                                                        */
983 /**************************************************************************/
_nxe_dhcp_reinitialize(NX_DHCP * dhcp_ptr)984 UINT _nxe_dhcp_reinitialize(NX_DHCP *dhcp_ptr)
985 {
986 
987 UINT status;
988 
989     if (dhcp_ptr == NX_NULL)
990     {
991         return NX_PTR_ERROR;
992     }
993 
994     /* Call the actual reinitialize service.  */
995     status = _nx_dhcp_reinitialize(dhcp_ptr);
996 
997     return status;
998 }
999 
1000 
1001 /**************************************************************************/
1002 /*                                                                        */
1003 /*  FUNCTION                                               RELEASE        */
1004 /*                                                                        */
1005 /*    _nx_dhcp_reinitialize                               PORTABLE C      */
1006 /*                                                           6.1          */
1007 /*  AUTHOR                                                                */
1008 /*                                                                        */
1009 /*    Yuxin Zhou, Microsoft Corporation                                   */
1010 /*                                                                        */
1011 /*  DESCRIPTION                                                           */
1012 /*                                                                        */
1013 /*    This function reinitializes all enabled DHCP interfaces for         */
1014 /*    restarting the DHCP client protocol.  Network parameters in the DHCP*/
1015 /*    Client and IP interface(s) are both cleared, and sets the DHCP state*/
1016 /*    back to the not started state.                                      */
1017 /*                                                                        */
1018 /*    To reinitialize the DHCP Client on a specific interface when        */
1019 /*    multiple interfaces are enabled for DHCP, use the                   */
1020 /*    nx_dhcp_interface_reinitialize service.                             */
1021 /*                                                                        */
1022 /*  INPUT                                                                 */
1023 /*                                                                        */
1024 /*    dhcp_ptr                              Pointer to DHCP instance      */
1025 /*                                                                        */
1026 /*  OUTPUT                                                                */
1027 /*                                                                        */
1028 /*    status                                Actual completion status      */
1029 /*                                                                        */
1030 /*  CALLS                                                                 */
1031 /*                                                                        */
1032 /*    _nx_dhcp_interface_reinitialize       Reinitialize DHCP interface   */
1033 /*    tx_mutex_get                          Obtain protection mutex       */
1034 /*    tx_mutex_put                          Release protection mutex      */
1035 /*                                                                        */
1036 /*  CALLED BY                                                             */
1037 /*                                                                        */
1038 /*    Application Code                                                    */
1039 /*                                                                        */
1040 /*  RELEASE HISTORY                                                       */
1041 /*                                                                        */
1042 /*    DATE              NAME                      DESCRIPTION             */
1043 /*                                                                        */
1044 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1045 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1046 /*                                            resulting in version 6.1    */
1047 /*                                                                        */
1048 /**************************************************************************/
_nx_dhcp_reinitialize(NX_DHCP * dhcp_ptr)1049 UINT _nx_dhcp_reinitialize(NX_DHCP *dhcp_ptr)
1050 {
1051 
1052 UINT    i;
1053 
1054     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
1055 
1056     /* Loop to reinitalize the record.  */
1057     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
1058     {
1059 
1060         /* Check if this record is valid.  */
1061         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid == NX_TRUE)
1062         {
1063 
1064             /* Reinitialize the record.  */
1065            _nx_dhcp_interface_reinitialize(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index);
1066         }
1067     }
1068 
1069     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1070     return(NX_SUCCESS);
1071 }
1072 
1073 
1074 /**************************************************************************/
1075 /*                                                                        */
1076 /*  FUNCTION                                               RELEASE        */
1077 /*                                                                        */
1078 /*    _nxe_dhcp_interface_reinitialize                    PORTABLE C      */
1079 /*                                                           6.1          */
1080 /*  AUTHOR                                                                */
1081 /*                                                                        */
1082 /*    Yuxin Zhou, Microsoft Corporation                                   */
1083 /*                                                                        */
1084 /*  DESCRIPTION                                                           */
1085 /*                                                                        */
1086 /*    This function performs error checking on the reinitialize service.  */
1087 /*                                                                        */
1088 /*  INPUT                                                                 */
1089 /*                                                                        */
1090 /*    dhcp_ptr                              Pointer to DHCP instance      */
1091 /*    iface_index                           Specify interface to init     */
1092 /*                                                                        */
1093 /*  OUTPUT                                                                */
1094 /*                                                                        */
1095 /*    status                                Actual completion status      */
1096 /*    NX_INVALID_INTERFACE                  Index exceeds max interface   */
1097 /*    NX_PTR_ERROR                          Invalid pointer input         */
1098 /*                                                                        */
1099 /*  CALLS                                                                 */
1100 /*                                                                        */
1101 /*    _nx_dhcp_interface_reinitialize       Actual reinitialize service   */
1102 /*                                                                        */
1103 /*  CALLED BY                                                             */
1104 /*                                                                        */
1105 /*    Application Code                                                    */
1106 /*                                                                        */
1107 /*  RELEASE HISTORY                                                       */
1108 /*                                                                        */
1109 /*    DATE              NAME                      DESCRIPTION             */
1110 /*                                                                        */
1111 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1112 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1113 /*                                            resulting in version 6.1    */
1114 /*                                                                        */
1115 /**************************************************************************/
_nxe_dhcp_interface_reinitialize(NX_DHCP * dhcp_ptr,UINT iface_index)1116 UINT _nxe_dhcp_interface_reinitialize(NX_DHCP *dhcp_ptr, UINT iface_index)
1117 {
1118 
1119 UINT status;
1120 
1121     if (dhcp_ptr == NX_NULL)
1122     {
1123         return NX_PTR_ERROR;
1124     }
1125 
1126     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
1127     {
1128         return NX_INVALID_INTERFACE;
1129     }
1130 
1131     /* Check for appropriate caller.  */
1132     NX_THREADS_ONLY_CALLER_CHECKING
1133 
1134     /* Call the actual reinitialize service.  */
1135     status = _nx_dhcp_interface_reinitialize(dhcp_ptr, iface_index);
1136 
1137     return status;
1138 }
1139 
1140 
1141 /**************************************************************************/
1142 /*                                                                        */
1143 /*  FUNCTION                                               RELEASE        */
1144 /*                                                                        */
1145 /*    _nx_dhcp_interface_reinitialize                     PORTABLE C      */
1146 /*                                                           6.1.12       */
1147 /*  AUTHOR                                                                */
1148 /*                                                                        */
1149 /*    Yuxin Zhou, Microsoft Corporation                                   */
1150 /*                                                                        */
1151 /*  DESCRIPTION                                                           */
1152 /*                                                                        */
1153 /*    This function reinitializes the DHCP instance for restarting the    */
1154 /*    DHCP client state machine and re-running the DHCP protocol on the   */
1155 /*    specified interface.  The IP address and other network parameters in*/
1156 /*    the DHCP Client and in the IP interface are cleared.                */
1157 /*                                                                        */
1158 /*    This function also sets the DHCP server IP address to the broadcast */
1159 /*    address and sets the DHCP client state back to the INIT state.      */
1160 /*                                                                        */
1161 /*                                                                        */
1162 /*  INPUT                                                                 */
1163 /*                                                                        */
1164 /*    dhcp_ptr                              Pointer to DHCP instance      */
1165 /*    iface_index                           Specify interface to init     */
1166 /*                                                                        */
1167 /*  OUTPUT                                                                */
1168 /*                                                                        */
1169 /*    NX_SUCCESS                            Successful completion status  */
1170 /*                                                                        */
1171 /*  CALLS                                                                 */
1172 /*                                                                        */
1173 /*    _nx_dhcp_interface_record_find        Find Client record  for input */
1174 /*                                             DHCP interface             */
1175 /*    nx_ip_interface_address_set           Clear IP inteface address of  */
1176 /*                                             the input DHCP interface   */
1177 /*    tx_mutex_get                          Obtain protection mutex       */
1178 /*    tx_mutex_put                          Release protection mutex      */
1179 /*    nx_ip_gateway_address_clear           Clear the gateway address     */
1180 /*                                                                        */
1181 /*  CALLED BY                                                             */
1182 /*                                                                        */
1183 /*    Application Code                                                    */
1184 /*                                                                        */
1185 /*  RELEASE HISTORY                                                       */
1186 /*                                                                        */
1187 /*    DATE              NAME                      DESCRIPTION             */
1188 /*                                                                        */
1189 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1190 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1191 /*                                            resulting in version 6.1    */
1192 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
1193 /*                                            improved internal logic,    */
1194 /*                                            resulting in version 6.1.12 */
1195 /*                                                                        */
1196 /**************************************************************************/
_nx_dhcp_interface_reinitialize(NX_DHCP * dhcp_ptr,UINT iface_index)1197 UINT _nx_dhcp_interface_reinitialize(NX_DHCP *dhcp_ptr, UINT iface_index)
1198 {
1199 
1200 UINT                      status;
1201 ULONG                     ip_address;
1202 ULONG                     network_mask;
1203 ULONG                     gateway_address;
1204 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
1205 
1206 
1207     /* Obtain DHCP Client protection mutex. */
1208     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
1209 
1210     /* Find the interface record.  */
1211     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
1212 
1213     /* Check status.  */
1214     if (status)
1215     {
1216 
1217         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1218         return(status);
1219     }
1220 
1221     /* Check if have IP address.  */
1222     if (interface_record -> nx_dhcp_ip_address)
1223     {
1224 
1225         /* Get the IP address.  */
1226         nx_ip_interface_address_get(dhcp_ptr -> nx_dhcp_ip_ptr, iface_index, &ip_address, &network_mask);
1227 
1228         /* Check if the IP address is set by DHCP.  */
1229         if (ip_address == interface_record -> nx_dhcp_ip_address)
1230         {
1231 
1232             /* Clear the IP address.  */
1233             nx_ip_interface_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, iface_index, 0, 0);
1234         }
1235     }
1236 
1237     /* Check if have gateway address.  */
1238     if (interface_record -> nx_dhcp_gateway_address)
1239     {
1240 
1241         /* Get the gateway address.  */
1242         status = nx_ip_gateway_address_get(dhcp_ptr -> nx_dhcp_ip_ptr, &gateway_address);
1243 
1244         /* Check status.  */
1245         if ((status == NX_SUCCESS) && (gateway_address == interface_record -> nx_dhcp_gateway_address))
1246         {
1247 
1248             /* Clear the Gateway/Router IP address.  */
1249             nx_ip_gateway_address_clear(dhcp_ptr -> nx_dhcp_ip_ptr);
1250         }
1251     }
1252 
1253     /* Initialize the client DHCP IP address with the NULL IP address.  */
1254     interface_record -> nx_dhcp_ip_address =  NX_BOOTP_NO_ADDRESS;
1255 
1256     /* Initialize the client DHCP server IP address.  */
1257     interface_record -> nx_dhcp_server_ip =  NX_BOOTP_NO_ADDRESS;
1258 
1259     /* Clear these DHCP Client network values too.*/
1260     interface_record -> nx_dhcp_gateway_address = NX_BOOTP_NO_ADDRESS;
1261     interface_record -> nx_dhcp_network_mask = NX_BOOTP_NO_ADDRESS;
1262 
1263     /* Clear the flag to skip the discovery step. The host application must
1264        call the nx_dhcp_request_ip_address to reset the flag and the requested IP address. */
1265     interface_record -> nx_dhcp_skip_discovery = NX_FALSE;
1266 
1267     /* Initialize renew and rebind timeout values to zero.  */
1268     interface_record -> nx_dhcp_rebind_time = 0;
1269     interface_record -> nx_dhcp_renewal_time =  0;
1270 
1271     /* Setup for infinite lease time request.  */
1272     interface_record -> nx_dhcp_lease_time =  NX_DHCP_INFINITE_LEASE;
1273 
1274     /* Reset the seconds field for starting the DHCP request process. */
1275     interface_record -> nx_dhcp_seconds = 0;
1276 
1277     /* Reset the timeout and retransmission interval.  */
1278     interface_record -> nx_dhcp_timeout = 0;
1279     interface_record -> nx_dhcp_rtr_interval = 0;
1280 
1281     /* Set the DHCP state to the initial state.  */
1282     interface_record -> nx_dhcp_state =  NX_DHCP_STATE_NOT_STARTED;
1283 
1284     /* Release the mutex.  */
1285     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1286     return NX_SUCCESS;
1287 }
1288 
1289 
1290 /**************************************************************************/
1291 /*                                                                        */
1292 /*  FUNCTION                                               RELEASE        */
1293 /*                                                                        */
1294 /*    _nxe_dhcp_request_client_ip                         PORTABLE C      */
1295 /*                                                           6.1          */
1296 /*  AUTHOR                                                                */
1297 /*                                                                        */
1298 /*    Yuxin Zhou, Microsoft Corporation                                   */
1299 /*                                                                        */
1300 /*  DESCRIPTION                                                           */
1301 /*                                                                        */
1302 /*    This function performs error checking for the client ip request     */
1303 /*    service.                                                            */
1304 /*                                                                        */
1305 /*  INPUT                                                                 */
1306 /*                                                                        */
1307 /*    dhcp_ptr                              Pointer to DHCP instance      */
1308 /*    client_request_address                Client's requested IP address */
1309 /*    skip_discover_message                 Initialize Client state to    */
1310 /*                                            BOOT (skip discover message)*/
1311 /*                                                                        */
1312 /*  OUTPUT                                                                */
1313 /*                                                                        */
1314 /*    NX_PTR_ERROR                          Invalid pointer input         */
1315 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
1316 /*    status                                Completion status             */
1317 /*                                                                        */
1318 /*  CALLS                                                                 */
1319 /*                                                                        */
1320 /*    None                                                                */
1321 /*                                                                        */
1322 /*  CALLED BY                                                             */
1323 /*                                                                        */
1324 /*    Application Code                                                    */
1325 /*                                                                        */
1326 /*  RELEASE HISTORY                                                       */
1327 /*                                                                        */
1328 /*    DATE              NAME                      DESCRIPTION             */
1329 /*                                                                        */
1330 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1331 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1332 /*                                            resulting in version 6.1    */
1333 /*                                                                        */
1334 /**************************************************************************/
_nxe_dhcp_request_client_ip(NX_DHCP * dhcp_ptr,ULONG client_request_address,UINT skip_discover_message)1335 UINT  _nxe_dhcp_request_client_ip(NX_DHCP *dhcp_ptr, ULONG client_request_address, UINT skip_discover_message)
1336 {
1337 
1338 UINT status;
1339 
1340 
1341     /* Check for an invalid DHCP pointer .  */
1342     if (dhcp_ptr == NX_NULL)
1343     {
1344 
1345         /* Return an error.  */
1346         return(NX_PTR_ERROR);
1347     }
1348 
1349     /* Determine that a nonzero IP address is entered. */
1350     if (client_request_address == NX_BOOTP_NO_ADDRESS)
1351     {
1352 
1353         return NX_DHCP_INVALID_IP_REQUEST;
1354     }
1355 
1356     /* Call actual request client IP service.  */
1357     status = _nx_dhcp_request_client_ip(dhcp_ptr, client_request_address, skip_discover_message);
1358 
1359     return(status);
1360 }
1361 
1362 
1363 /**************************************************************************/
1364 /*                                                                        */
1365 /*  FUNCTION                                               RELEASE        */
1366 /*                                                                        */
1367 /*    _nx_dhcp_request_client_ip                          PORTABLE C      */
1368 /*                                                           6.1          */
1369 /*  AUTHOR                                                                */
1370 /*                                                                        */
1371 /*    Yuxin Zhou, Microsoft Corporation                                   */
1372 /*                                                                        */
1373 /*  DESCRIPTION                                                           */
1374 /*                                                                        */
1375 /*    This function sets the requested client IP address in DHCP Client   */
1376 /*    messages, and enables or disables the skip discovery option         */
1377 /*    based on the skip_discover_message input.                           */
1378 /*                                                                        */
1379 /*    If multiple interfaces are enabled for DHCP, this function sets the */
1380 /*    requested Client IP on the first valid interface it finds.          */
1381 /*                                                                        */
1382 /*    To set the requested Client IP for a specific interface, use the    */
1383 /*    nx_dhcp_interface_request_ip() service.                             */
1384 /*                                                                        */
1385 /*  INPUT                                                                 */
1386 /*                                                                        */
1387 /*    dhcp_ptr                              Pointer to DHCP instance      */
1388 /*    client_request_address                Client's requested IP address */
1389 /*    skip_discover_message                 To set DHCP Client flag       */
1390 /*                                                                        */
1391 /*  OUTPUT                                                                */
1392 /*                                                                        */
1393 /*    status                                Completion status             */
1394 /*                                                                        */
1395 /*  CALLS                                                                 */
1396 /*                                                                        */
1397 /*    _nx_dhcp_interface_request_client_ip  Interface specific request    */
1398 /*                                            IP service                  */
1399 /*    tx_mutex_get                          Obtain protection mutex       */
1400 /*    tx_mutex_put                          Release protection mutex      */
1401 
1402 /*                                                                        */
1403 /*  CALLED BY                                                             */
1404 /*                                                                        */
1405 /*    Application Code                                                    */
1406 /*                                                                        */
1407 /*  RELEASE HISTORY                                                       */
1408 /*                                                                        */
1409 /*    DATE              NAME                      DESCRIPTION             */
1410 /*                                                                        */
1411 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1412 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1413 /*                                            resulting in version 6.1    */
1414 /*                                                                        */
1415 /**************************************************************************/
_nx_dhcp_request_client_ip(NX_DHCP * dhcp_ptr,ULONG client_request_address,UINT skip_discover_message)1416 UINT  _nx_dhcp_request_client_ip(NX_DHCP *dhcp_ptr, ULONG client_request_address, UINT skip_discover_message)
1417 {
1418 
1419 UINT    i;
1420 UINT    status;
1421 
1422     /* Obtain the DHCP mutex.  */
1423     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
1424 
1425     /* Find the DHCP interface record.  */
1426     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
1427     {
1428 
1429         /* Check which interface record is valid.  */
1430         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
1431         {
1432 
1433             /* Set the request IP.  */
1434             status = _nx_dhcp_interface_request_client_ip(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index,
1435                                                           client_request_address, skip_discover_message);
1436 
1437             /* Release the DHCP mutex.  */
1438             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1439             return(status);
1440         }
1441     }
1442 
1443     /* Release the DHCP mutex.  */
1444     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1445     return(NX_DHCP_NO_INTERFACES_ENABLED);
1446 }
1447 
1448 
1449 /**************************************************************************/
1450 /*                                                                        */
1451 /*  FUNCTION                                               RELEASE        */
1452 /*                                                                        */
1453 /*    _nxe_dhcp_interface_request_client_ip               PORTABLE C      */
1454 /*                                                           6.1          */
1455 /*  AUTHOR                                                                */
1456 /*                                                                        */
1457 /*    Yuxin Zhou, Microsoft Corporation                                   */
1458 /*                                                                        */
1459 /*  DESCRIPTION                                                           */
1460 /*                                                                        */
1461 /*    This function performs error checking on the request IP service.    */
1462 /*                                                                        */
1463 /*  INPUT                                                                 */
1464 /*                                                                        */
1465 /*    dhcp_ptr                              Pointer to DHCP instance      */
1466 /*    iface_index                           Index to apply parameter to   */
1467 /*    client_request_address                Client's requested IP address */
1468 /*    skip_discover_message                 To set DHCP Client flag       */
1469 /*                                                                        */
1470 /*  OUTPUT                                                                */
1471 /*                                                                        */
1472 /*    status                                Completion status             */
1473 /*    NX_PTR_ERROR                          Invalid pointer input         */
1474 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
1475 /*                                                                        */
1476 /*  CALLS                                                                 */
1477 /*                                                                        */
1478 /*    None                                                                */
1479 /*                                                                        */
1480 /*  CALLED BY                                                             */
1481 /*                                                                        */
1482 /*    Application Code                                                    */
1483 /*                                                                        */
1484 /*  RELEASE HISTORY                                                       */
1485 /*                                                                        */
1486 /*    DATE              NAME                      DESCRIPTION             */
1487 /*                                                                        */
1488 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1489 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1490 /*                                            resulting in version 6.1    */
1491 /*                                                                        */
1492 /**************************************************************************/
_nxe_dhcp_interface_request_client_ip(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG client_request_address,UINT skip_discover_message)1493 UINT  _nxe_dhcp_interface_request_client_ip(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG client_request_address, UINT skip_discover_message)
1494 {
1495 
1496 UINT status;
1497 
1498     if (dhcp_ptr == NX_NULL)
1499     {
1500         return NX_PTR_ERROR;
1501     }
1502 
1503     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
1504     {
1505         return NX_INVALID_INTERFACE;
1506     }
1507 
1508     status = _nx_dhcp_interface_request_client_ip(dhcp_ptr, iface_index, client_request_address, skip_discover_message);
1509 
1510     return(status);
1511 }
1512 
1513 
1514 /**************************************************************************/
1515 /*                                                                        */
1516 /*  FUNCTION                                               RELEASE        */
1517 /*                                                                        */
1518 /*    _nx_dhcp_interface_request_client_ip                PORTABLE C      */
1519 /*                                                           6.1          */
1520 /*  AUTHOR                                                                */
1521 /*                                                                        */
1522 /*    Yuxin Zhou, Microsoft Corporation                                   */
1523 /*                                                                        */
1524 /*  DESCRIPTION                                                           */
1525 /*                                                                        */
1526 /*    This function sets the requested client IP address in the client    */
1527 /*    REQUEST message on the input interface. If the skip_discover_message*/
1528 /*    flag is set, the DISCOVER message is skipped when the DHCP Client   */
1529 /*    (re))starts.                                                        */
1530 /*                                                                        */
1531 /*  INPUT                                                                 */
1532 /*                                                                        */
1533 /*    dhcp_ptr                              Pointer to DHCP instance      */
1534 /*    iface_index                           Index to apply parameter to   */
1535 /*    client_request_address                Client's requested IP address */
1536 /*    skip_discover_message                 To set DHCP Client flag       */
1537 /*                                                                        */
1538 /*  OUTPUT                                                                */
1539 /*                                                                        */
1540 /*    status                                Completion status             */
1541 /*                                                                        */
1542 /*  CALLS                                                                 */
1543 /*                                                                        */
1544 /*    _nx_dhcp_interface_record_find        Find Client record for the    */
1545 /*                                            input interface             */
1546 /*    tx_mutex_get                          Obtain protection mutex       */
1547 /*    tx_mutex_put                          Release protection mutex      */
1548 /*                                                                        */
1549 /*  CALLED BY                                                             */
1550 /*                                                                        */
1551 /*    Application Code                                                    */
1552 /*                                                                        */
1553 /*  RELEASE HISTORY                                                       */
1554 /*                                                                        */
1555 /*    DATE              NAME                      DESCRIPTION             */
1556 /*                                                                        */
1557 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1558 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1559 /*                                            resulting in version 6.1    */
1560 /*                                                                        */
1561 /**************************************************************************/
_nx_dhcp_interface_request_client_ip(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG client_request_address,UINT skip_discover_message)1562 UINT  _nx_dhcp_interface_request_client_ip(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG client_request_address, UINT skip_discover_message)
1563 {
1564 
1565 UINT    status;
1566 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
1567 
1568 
1569     /* Obtain the DHCP mutex.  */
1570     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
1571 
1572     /* Find the interface record.  */
1573     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
1574 
1575     /* Check status.  */
1576     if (status)
1577     {
1578 
1579         /* Release the mutex.  */
1580         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1581         return(status);
1582     }
1583 
1584     /* Use input IP address.  */
1585     interface_record -> nx_dhcp_ip_address =  client_request_address;
1586 
1587     /* Set the flag for skipping the discovery state. */
1588     interface_record -> nx_dhcp_skip_discovery =  skip_discover_message;
1589 
1590     /* Release the mutex.  */
1591     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1592 
1593     /* Return success!  */
1594     return(NX_SUCCESS);
1595 }
1596 
1597 
1598 /**************************************************************************/
1599 /*                                                                        */
1600 /*  FUNCTION                                               RELEASE        */
1601 /*                                                                        */
1602 /*    _nxe_dhcp_delete                                    PORTABLE C      */
1603 /*                                                           6.1          */
1604 /*  AUTHOR                                                                */
1605 /*                                                                        */
1606 /*    Yuxin Zhou, Microsoft Corporation                                   */
1607 /*                                                                        */
1608 /*  DESCRIPTION                                                           */
1609 /*                                                                        */
1610 /*    This function checks for errors in the DHCP delete function call.   */
1611 /*                                                                        */
1612 /*  INPUT                                                                 */
1613 /*                                                                        */
1614 /*    dhcp_ptr                              Pointer to DHCP instance      */
1615 /*                                                                        */
1616 /*  OUTPUT                                                                */
1617 /*                                                                        */
1618 /*    status                                Completion status             */
1619 /*                                                                        */
1620 /*  CALLS                                                                 */
1621 /*                                                                        */
1622 /*    _nx_dhcp_delete                       Actual DHCP delete function   */
1623 /*                                                                        */
1624 /*  CALLED BY                                                             */
1625 /*                                                                        */
1626 /*    Application Code                                                    */
1627 /*                                                                        */
1628 /*  RELEASE HISTORY                                                       */
1629 /*                                                                        */
1630 /*    DATE              NAME                      DESCRIPTION             */
1631 /*                                                                        */
1632 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1633 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1634 /*                                            resulting in version 6.1    */
1635 /*                                                                        */
1636 /**************************************************************************/
_nxe_dhcp_delete(NX_DHCP * dhcp_ptr)1637 UINT  _nxe_dhcp_delete(NX_DHCP *dhcp_ptr)
1638 {
1639 
1640 UINT    status;
1641 
1642 
1643     /* Check for invalid input pointers.  */
1644     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
1645         return(NX_PTR_ERROR);
1646 
1647     /* Check for appropriate caller.  */
1648     NX_THREADS_ONLY_CALLER_CHECKING
1649 
1650     /* Call actual DHCP delete service.  */
1651     status =  _nx_dhcp_delete(dhcp_ptr);
1652 
1653     /* Return status.  */
1654     return(status);
1655 }
1656 
1657 
1658 /**************************************************************************/
1659 /*                                                                        */
1660 /*  FUNCTION                                               RELEASE        */
1661 /*                                                                        */
1662 /*    _nx_dhcp_delete                                     PORTABLE C      */
1663 /*                                                           6.1.10       */
1664 /*  AUTHOR                                                                */
1665 /*                                                                        */
1666 /*    Yuxin Zhou, Microsoft Corporation                                   */
1667 /*                                                                        */
1668 /*  DESCRIPTION                                                           */
1669 /*                                                                        */
1670 /*    This function disables DHCP on all enabled interfaces, deletes the  */
1671 /*    DHCP instance and releases all of its resources. All DHCP and IP    */
1672 /*    interface IP addresses and the IP gateway are cleared on all        */
1673 /*    valid DHCP interfaces.                                              */
1674 /*                                                                        */
1675 /*  INPUT                                                                 */
1676 /*                                                                        */
1677 /*    dhcp_ptr                              Pointer to DHCP instance      */
1678 /*                                                                        */
1679 /*  OUTPUT                                                                */
1680 /*                                                                        */
1681 /*    status                                Completion status             */
1682 /*                                                                        */
1683 /*  CALLS                                                                 */
1684 /*                                                                        */
1685 /*    nx_dhcp_interface_disable             Disable DHCP on interface     */
1686 /*    nx_packet_pool_delete                 Delete the DHCP packet pool   */
1687 /*    nx_udp_socket_delete                  Delete the DHCP UDP socket    */
1688 /*    tx_thread_suspend                     Suspend DHCP Thread           */
1689 /*    tx_thread_terminate                   Terminate DHCP thread         */
1690 /*    tx_mutex_delete                       Delete DHCP mutex             */
1691 /*    tx_event_flags_delete                 Delete DHCP flag group        */
1692 /*    tx_timer_deactivate                   Stop the DHCP timer           */
1693 /*    tx_timer_delete                       Delete the DHCP timer         */
1694 /*    tx_thread_delete                      Delete DHCP thread            */
1695 /*                                                                        */
1696 /*  CALLED BY                                                             */
1697 /*                                                                        */
1698 /*    Application Code                                                    */
1699 /*                                                                        */
1700 /*  RELEASE HISTORY                                                       */
1701 /*                                                                        */
1702 /*    DATE              NAME                      DESCRIPTION             */
1703 /*                                                                        */
1704 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1705 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1706 /*                                            resulting in version 6.1    */
1707 /*  01-31-2022     Yuxin Zhou               Modified comment(s), supported*/
1708 /*                                            multiple client instances,  */
1709 /*                                            resulting in version 6.1.10 */
1710 /*                                                                        */
1711 /**************************************************************************/
_nx_dhcp_delete(NX_DHCP * dhcp_ptr)1712 UINT  _nx_dhcp_delete(NX_DHCP *dhcp_ptr)
1713 {
1714 
1715 TX_INTERRUPT_SAVE_AREA
1716 
1717 UINT    i;
1718 NX_DHCP *dhcp_previous;
1719 
1720     /* Get the DHCP mutex.  */
1721     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
1722 
1723     /* Disable all the interfaces enabled for DHCP. */
1724     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
1725     {
1726 
1727        /* Check if this interface (i) is enabled for DHCP. */
1728        if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
1729        {
1730 
1731            /* Disable the interface record.  */
1732            _nx_dhcp_interface_disable(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index);
1733        }
1734     }
1735 
1736     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread));
1737 
1738     /* Terminate the DHCP processing thread.  */
1739     tx_thread_terminate(&(dhcp_ptr -> nx_dhcp_thread));
1740 
1741     /* Delete the DHCP processing thread.  */
1742     tx_thread_delete(&(dhcp_ptr -> nx_dhcp_thread));
1743 
1744     /* Delete the DHCP event flags.  */
1745     tx_event_flags_delete(&(dhcp_ptr -> nx_dhcp_events));
1746 
1747     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer));
1748 
1749     tx_timer_delete(&(dhcp_ptr -> nx_dhcp_timer));
1750 
1751     /* Unbind the port.  */
1752     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
1753 
1754     /* Delete the UDP socket.  */
1755     nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket));
1756 
1757 #ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
1758     /* Delete the packet pool.  */
1759     nx_packet_pool_delete(dhcp_ptr -> nx_dhcp_packet_pool_ptr);
1760 #endif
1761 
1762     /* Get the DHCP mutex.  */
1763     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1764 
1765     /* Delete the DHCP mutex.  */
1766     tx_mutex_delete(&(dhcp_ptr -> nx_dhcp_mutex));
1767 
1768     /* Disable interrupts.  */
1769     TX_DISABLE
1770 
1771     /* Clear the dhcp structure ID. */
1772     dhcp_ptr -> nx_dhcp_id =  0;
1773 
1774     /* Remove the DHCP instance from the created list.  */
1775     if (_nx_dhcp_created_ptr == dhcp_ptr)
1776     {
1777         _nx_dhcp_created_ptr = _nx_dhcp_created_ptr -> nx_dhcp_created_next;
1778     }
1779     else
1780     {
1781         for (dhcp_previous = _nx_dhcp_created_ptr;
1782              dhcp_previous -> nx_dhcp_created_next;
1783              dhcp_previous = dhcp_previous -> nx_dhcp_created_next)
1784         {
1785             if (dhcp_previous -> nx_dhcp_created_next == dhcp_ptr)
1786             {
1787                 dhcp_previous -> nx_dhcp_created_next  = dhcp_ptr -> nx_dhcp_created_next;
1788                 break;
1789             }
1790         }
1791     }
1792 
1793     /* Restore interrupts.  */
1794     TX_RESTORE
1795 
1796     /* Return a successful status.  */
1797     return(NX_SUCCESS);
1798 }
1799 
1800 
1801 /**************************************************************************/
1802 /*                                                                        */
1803 /*  FUNCTION                                                RELEASE       */
1804 /*                                                                        */
1805 /*    _nxe_dhcp_force_renew                                PORTABLE C     */
1806 /*                                                           6.1          */
1807 /*  AUTHOR                                                                */
1808 /*                                                                        */
1809 /*    Yuxin Zhou, Microsoft Corporation                                   */
1810 /*                                                                        */
1811 /*  DESCRIPTION                                                           */
1812 /*                                                                        */
1813 /*    This function checks for errors in the DHCP force renew function    */
1814 /*    call.                                                               */
1815 /*                                                                        */
1816 /*  INPUT                                                                 */
1817 /*                                                                        */
1818 /*    dhcp_ptr                               Pointer to DHCP instance     */
1819 /*                                                                        */
1820 /*  OUTPUT                                                                */
1821 /*                                                                        */
1822 /*    status                                 Completion status            */
1823 /*                                                                        */
1824 /*  CALLS                                                                 */
1825 /*                                                                        */
1826 /*    _nx_dhcp_force_renew                   Actual DHCP force renew      */
1827 /*                                             function                   */
1828 /*                                                                        */
1829 /*  CALLED BY                                                             */
1830 /*                                                                        */
1831 /*    Application Code                                                    */
1832 /*                                                                        */
1833 /*  RELEASE HISTORY                                                       */
1834 /*                                                                        */
1835 /*    DATE              NAME                      DESCRIPTION             */
1836 /*                                                                        */
1837 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1838 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1839 /*                                            resulting in version 6.1    */
1840 /*                                                                        */
1841 /**************************************************************************/
_nxe_dhcp_force_renew(NX_DHCP * dhcp_ptr)1842 UINT  _nxe_dhcp_force_renew(NX_DHCP *dhcp_ptr)
1843 {
1844 
1845 UINT    status;
1846 
1847 
1848     /* Check for invalid input pointer.  */
1849     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
1850         return(NX_PTR_ERROR);
1851 
1852     /* Check for appropriate caller.  */
1853     NX_THREADS_ONLY_CALLER_CHECKING
1854 
1855     /* Call actual DHCP force renew service.  */
1856     status =  _nx_dhcp_force_renew(dhcp_ptr);
1857 
1858     /* Return status.  */
1859     return(status);
1860 }
1861 
1862 
1863 /**************************************************************************/
1864 /*                                                                        */
1865 /*  FUNCTION                                               RELEASE        */
1866 /*                                                                        */
1867 /*    _nx_dhcp_force_renew                                PORTABLE C      */
1868 /*                                                           6.1          */
1869 /*  AUTHOR                                                                */
1870 /*                                                                        */
1871 /*    Yuxin Zhou, Microsoft Corporation                                   */
1872 /*                                                                        */
1873 /*  DESCRIPTION                                                           */
1874 /*                                                                        */
1875 /*    This function forces the DHCP processing thread to renew the lease  */
1876 /*    on all valid (DHCP enabled) interfaces. To force renew on a specific*/
1877 /*    interface if multiple interfaces are enabled for DHCP, use the      */
1878 /*    nx_dhcp_interface_force_renew service.                              */
1879 /*                                                                        */
1880 /*  INPUT                                                                 */
1881 /*                                                                        */
1882 /*    dhcp_ptr                              Pointer to DHCP instance      */
1883 /*                                                                        */
1884 /*  OUTPUT                                                                */
1885 /*                                                                        */
1886 /*    status                                Completion status             */
1887 /*                                                                        */
1888 /*  CALLS                                                                 */
1889 /*                                                                        */
1890 /*    tx_mutex_get                          Get the DHCP mutex            */
1891 /*    tx_mutex_put                          Release the DHCP mutex        */
1892 /*    nx_dhcp_interface_force_renew         Force renew on DHCP interface */
1893 /*                                                                        */
1894 /*  CALLED BY                                                             */
1895 /*                                                                        */
1896 /*    Application Code                                                    */
1897 /*                                                                        */
1898 /*  RELEASE HISTORY                                                       */
1899 /*                                                                        */
1900 /*    DATE              NAME                      DESCRIPTION             */
1901 /*                                                                        */
1902 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1903 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1904 /*                                            resulting in version 6.1    */
1905 /*                                                                        */
1906 /**************************************************************************/
_nx_dhcp_force_renew(NX_DHCP * dhcp_ptr)1907 UINT  _nx_dhcp_force_renew(NX_DHCP *dhcp_ptr)
1908 {
1909 
1910 UINT    i;
1911 
1912 
1913     /* Obtain the DHCP mutex.  */
1914     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
1915 
1916     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
1917     {
1918 
1919         /* Check if this record is valid.  */
1920         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
1921             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
1922         {
1923 
1924             /* Force renew on this interface.  */
1925             _nx_dhcp_interface_force_renew(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index);
1926         }
1927     }
1928 
1929     /* Release the DHCP mutex.  */
1930     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
1931 
1932     return (NX_SUCCESS);
1933 }
1934 
1935 
1936 /**************************************************************************/
1937 /*                                                                        */
1938 /*  FUNCTION                                               RELEASE        */
1939 /*                                                                        */
1940 /*    _nxe_dhcp_interface_force_renew                     PORTABLE C      */
1941 /*                                                           6.1          */
1942 /*  AUTHOR                                                                */
1943 /*                                                                        */
1944 /*    Yuxin Zhou, Microsoft Corporation                                   */
1945 /*                                                                        */
1946 /*  DESCRIPTION                                                           */
1947 /*                                                                        */
1948 /*    This function forces the DHCP processing thread to renew the lease  */
1949 /*    on the specified interface.                                         */
1950 /*                                                                        */
1951 /*  INPUT                                                                 */
1952 /*                                                                        */
1953 /*    dhcp_ptr                              Pointer to DHCP instance      */
1954 /*    iface_index                           Interface to force renew on   */
1955 /*                                                                        */
1956 /*  OUTPUT                                                                */
1957 /*                                                                        */
1958 /*    status                                Completion status             */
1959 /*    NX_PTR_ERROR                          Invalid pointer input         */
1960 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
1961 /*                                                                        */
1962 /*  CALLS                                                                 */
1963 /*                                                                        */
1964 /*    nx_dhcp_interface_force_renew         Actual force renew service    */
1965 /*                                                                        */
1966 /*  CALLED BY                                                             */
1967 /*                                                                        */
1968 /*    Application Code                                                    */
1969 /*                                                                        */
1970 /*  RELEASE HISTORY                                                       */
1971 /*                                                                        */
1972 /*    DATE              NAME                      DESCRIPTION             */
1973 /*                                                                        */
1974 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1975 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1976 /*                                            resulting in version 6.1    */
1977 /*                                                                        */
1978 /**************************************************************************/
_nxe_dhcp_interface_force_renew(NX_DHCP * dhcp_ptr,UINT iface_index)1979 UINT  _nxe_dhcp_interface_force_renew(NX_DHCP *dhcp_ptr, UINT iface_index)
1980 {
1981 
1982 UINT status;
1983 
1984     if (dhcp_ptr == NX_NULL)
1985     {
1986         return(NX_PTR_ERROR);
1987     }
1988 
1989     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
1990     {
1991         return(NX_INVALID_INTERFACE);
1992     }
1993 
1994     /* Call the actual reinitialize service.  */
1995     status = _nx_dhcp_interface_force_renew(dhcp_ptr, iface_index);
1996 
1997     /* Return status.  */
1998     return(status);
1999 }
2000 
2001 
2002 /**************************************************************************/
2003 /*                                                                        */
2004 /*  FUNCTION                                               RELEASE        */
2005 /*                                                                        */
2006 /*    _nx_dhcp_interface_force_renew                      PORTABLE C      */
2007 /*                                                           6.1          */
2008 /*  AUTHOR                                                                */
2009 /*                                                                        */
2010 /*    Yuxin Zhou, Microsoft Corporation                                   */
2011 /*                                                                        */
2012 /*  DESCRIPTION                                                           */
2013 /*                                                                        */
2014 /*    This function allows the DHCP Client to force a renew on a          */
2015 /*    previously obtained lease on the input interface.                   */
2016 /*                                                                        */
2017 /*  INPUT                                                                 */
2018 /*                                                                        */
2019 /*    dhcp_ptr                              Pointer to DHCP instance      */
2020 /*    iface_index                           Interface to force renew on   */
2021 /*                                                                        */
2022 /*  OUTPUT                                                                */
2023 /*                                                                        */
2024 /*    status                                Completion status             */
2025 /*                                                                        */
2026 /*  CALLS                                                                 */
2027 /*                                                                        */
2028 /*    _nx_dhcp_interface_record_find       Find record for the interface  */
2029 /*    _nx_dhcp_send_request_internal       Send request to DHCP server    */
2030 /*    _nx_dhcp_update_renewal_timeout      Update time left on renew lease*/
2031 /*    tx_mutex_get                         Obtain protection mutex        */
2032 /*    tx_mutex_put                         Release protection mutex       */
2033 /*                                                                        */
2034 /*  CALLED BY                                                             */
2035 /*                                                                        */
2036 /*    Application Code                                                    */
2037 /*                                                                        */
2038 /*  RELEASE HISTORY                                                       */
2039 /*                                                                        */
2040 /*    DATE              NAME                      DESCRIPTION             */
2041 /*                                                                        */
2042 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2043 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2044 /*                                            resulting in version 6.1    */
2045 /*                                                                        */
2046 /**************************************************************************/
_nx_dhcp_interface_force_renew(NX_DHCP * dhcp_ptr,UINT iface_index)2047 UINT  _nx_dhcp_interface_force_renew(NX_DHCP *dhcp_ptr, UINT iface_index)
2048 {
2049 UINT    status;
2050 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
2051 
2052 
2053     /* Get the DHCP mutex.  */
2054     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
2055 
2056     /* Find the interface record for this interface.  */
2057     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
2058 
2059     /* Check status.  */
2060     if (status)
2061     {
2062 
2063         /* Release the DHCP mutex.  */
2064         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2065 
2066         /* Return status.  */
2067         return(status);
2068     }
2069 
2070     /* Determine if DHCP is in the Bound state.  */
2071     if (interface_record -> nx_dhcp_state >= NX_DHCP_STATE_BOUND)
2072     {
2073 
2074         /* Since the Client is initiating RENEW ('force' renew'), set the state to RENEW. */
2075         interface_record -> nx_dhcp_state = NX_DHCP_STATE_RENEWING;
2076 
2077         /* Send the renew request. */
2078         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
2079 
2080         /* Reset the renew time remaining (before transition to the REBIND state) and
2081            the dhcp timeout for retransmission of RENEW request. */
2082         interface_record -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_rebind_time - interface_record -> nx_dhcp_renewal_time;
2083         interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
2084 
2085         /* Record the retransmission interval.  */
2086         interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
2087 
2088         /* Determine if the application has specified a routine for DHCP state change notification.  */
2089         if (dhcp_ptr -> nx_dhcp_state_change_callback)
2090         {
2091 
2092             /* Yes, call the application's state change notify function with the new state.  */
2093             (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
2094         }
2095 
2096         /* Determine if the application has specified a routine for DHCP interface state change notification.  */
2097         if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
2098         {
2099 
2100             /* Yes, call the application's state change notify function with the new state.  */
2101             (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
2102         }
2103     }
2104     else
2105     {
2106 
2107         /* Return a not bound error code.  */
2108         status =  NX_DHCP_NOT_BOUND;
2109     }
2110 
2111     /* Release the DHCP mutex.  */
2112     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2113 
2114     /* Return completion status.  */
2115     return(status);
2116 }
2117 
2118 
2119 /**************************************************************************/
2120 /*                                                                        */
2121 /*  FUNCTION                                               RELEASE        */
2122 /*                                                                        */
2123 /*    _nxe_dhcp_decline                                   PORTABLE C      */
2124 /*                                                           6.1          */
2125 /*  AUTHOR                                                                */
2126 /*                                                                        */
2127 /*    Yuxin Zhou, Microsoft Corporation                                   */
2128 /*                                                                        */
2129 /*  DESCRIPTION                                                           */
2130 /*                                                                        */
2131 /*    This function checks for errors in the DHCP decline function call.  */
2132 /*                                                                        */
2133 /*  INPUT                                                                 */
2134 /*                                                                        */
2135 /*    dhcp_ptr                              Pointer to DHCP instance      */
2136 /*                                                                        */
2137 /*  OUTPUT                                                                */
2138 /*                                                                        */
2139 /*    status                                Completion status             */
2140 /*                                                                        */
2141 /*  CALLS                                                                 */
2142 /*                                                                        */
2143 /*    _nx_dhcp_decline                      Actual DHCP decline function  */
2144 /*                                                                        */
2145 /*  CALLED BY                                                             */
2146 /*                                                                        */
2147 /*    Application Code                                                    */
2148 /*                                                                        */
2149 /*  RELEASE HISTORY                                                       */
2150 /*                                                                        */
2151 /*    DATE              NAME                      DESCRIPTION             */
2152 /*                                                                        */
2153 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2154 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2155 /*                                            resulting in version 6.1    */
2156 /*                                                                        */
2157 /**************************************************************************/
_nxe_dhcp_decline(NX_DHCP * dhcp_ptr)2158 UINT  _nxe_dhcp_decline(NX_DHCP *dhcp_ptr)
2159 {
2160 
2161 UINT    status;
2162 
2163 
2164     /* Check for an invalid input pointer.  */
2165     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
2166         return(NX_PTR_ERROR);
2167 
2168     /* Check for appropriate caller.  */
2169     NX_THREADS_ONLY_CALLER_CHECKING
2170 
2171     /* Call actual DHCP release service.  */
2172     status =  _nx_dhcp_decline(dhcp_ptr);
2173 
2174     /* Return status.  */
2175     return(status);
2176 }
2177 
2178 
2179 /**************************************************************************/
2180 /*                                                                        */
2181 /*  FUNCTION                                               RELEASE        */
2182 /*                                                                        */
2183 /*    _nx_dhcp_decline                                    PORTABLE C      */
2184 /*                                                           6.1          */
2185 /*  AUTHOR                                                                */
2186 /*                                                                        */
2187 /*    Yuxin Zhou, Microsoft Corporation                                   */
2188 /*                                                                        */
2189 /*  DESCRIPTION                                                           */
2190 /*                                                                        */
2191 /*    This function declines the IP address(es) assigned to the DHCP      */
2192 /*    Client on all valid interfaces.  The DHCP Client state is set back  */
2193 /*    to the INIT state and DHCP is automatically restarted.              */
2194 /*                                                                        */
2195 /*    To decline an IP address on a specific interface where multiple     */
2196 /*    interfaces are enabled for DHCP, use the                            */
2197 /*    nx_dhcp_interface_decline service.                                  */
2198 /*                                                                        */
2199 /*  INPUT                                                                 */
2200 /*                                                                        */
2201 /*    dhcp_ptr                              Pointer to DHCP instance      */
2202 /*                                                                        */
2203 /*  OUTPUT                                                                */
2204 /*                                                                        */
2205 /*    status                                Completion status             */
2206 /*                                                                        */
2207 /*  CALLS                                                                 */
2208 /*                                                                        */
2209 /*    _nx_dhcp_interface_decline            Interface specific decline    */
2210 /*    tx_mutex_get                          Get the DHCP mutex            */
2211 /*    tx_mutex_put                          Release the DHCP mutex        */
2212 /*                                                                        */
2213 /*  CALLED BY                                                             */
2214 /*                                                                        */
2215 /*    Application Code                                                    */
2216 /*                                                                        */
2217 /*  RELEASE HISTORY                                                       */
2218 /*                                                                        */
2219 /*    DATE              NAME                      DESCRIPTION             */
2220 /*                                                                        */
2221 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2222 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2223 /*                                            resulting in version 6.1    */
2224 /*                                                                        */
2225 /**************************************************************************/
_nx_dhcp_decline(NX_DHCP * dhcp_ptr)2226 UINT  _nx_dhcp_decline(NX_DHCP *dhcp_ptr)
2227 {
2228 
2229 UINT    i;
2230 
2231     /* Obtain the DHCP mutex.  */
2232     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);\
2233 
2234     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
2235     {
2236 
2237         /* Check if this record is valid.  */
2238         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
2239             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
2240         {
2241 
2242             /* Decline the address.  */
2243             _nx_dhcp_interface_decline(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index);
2244         }
2245     }
2246 
2247     /* Release the DHCP mutex.  */
2248     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2249 
2250     /* Return.  */
2251     return(NX_SUCCESS);
2252 }
2253 
2254 
2255 /**************************************************************************/
2256 /*                                                                        */
2257 /*  FUNCTION                                               RELEASE        */
2258 /*                                                                        */
2259 /*    _nxe_dhcp_interface_decline                         PORTABLE C      */
2260 /*                                                           6.1          */
2261 /*  AUTHOR                                                                */
2262 /*                                                                        */
2263 /*    Yuxin Zhou, Microsoft Corporation                                   */
2264 /*                                                                        */
2265 /*  DESCRIPTION                                                           */
2266 /*                                                                        */
2267 /*    This function performs error checking on the decline service.       */
2268 /*                                                                        */
2269 /*  INPUT                                                                 */
2270 /*                                                                        */
2271 /*    dhcp_ptr                              Pointer to DHCP instance      */
2272 /*    iface_index                           Interface to decline IP on    */
2273 /*                                                                        */
2274 /*  OUTPUT                                                                */
2275 /*                                                                        */
2276 /*    status                                Completion status             */
2277 /*    NX_PTR_ERROR                          Invalid pointer input         */
2278 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
2279 /*                                                                        */
2280 /*  CALLS                                                                 */
2281 /*                                                                        */
2282 /*    _nx_dhcp_interface_decline            Actual decline service        */
2283 /*                                                                        */
2284 /*  CALLED BY                                                             */
2285 /*                                                                        */
2286 /*    Application Code                                                    */
2287 /*                                                                        */
2288 /*  RELEASE HISTORY                                                       */
2289 /*                                                                        */
2290 /*    DATE              NAME                      DESCRIPTION             */
2291 /*                                                                        */
2292 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2293 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2294 /*                                            resulting in version 6.1    */
2295 /*                                                                        */
2296 /**************************************************************************/
2297 
_nxe_dhcp_interface_decline(NX_DHCP * dhcp_ptr,UINT iface_index)2298 UINT _nxe_dhcp_interface_decline(NX_DHCP *dhcp_ptr, UINT iface_index)
2299 {
2300 UINT status;
2301 
2302     if (dhcp_ptr == NX_NULL)
2303     {
2304         return(NX_PTR_ERROR);
2305     }
2306 
2307     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
2308     {
2309         return(NX_INVALID_INTERFACE);
2310     }
2311 
2312     /* Check for appropriate caller.  */
2313     NX_THREADS_ONLY_CALLER_CHECKING
2314 
2315     /* Call the actual decline service.  */
2316     status = _nx_dhcp_interface_decline(dhcp_ptr, iface_index);
2317 
2318     /* Return status.  */
2319     return(status);
2320 }
2321 
2322 
2323 /**************************************************************************/
2324 /*                                                                        */
2325 /*  FUNCTION                                               RELEASE        */
2326 /*                                                                        */
2327 /*    _nx_dhcp_interface_decline                          PORTABLE C      */
2328 /*                                                           6.1.12       */
2329 /*  AUTHOR                                                                */
2330 /*                                                                        */
2331 /*    Yuxin Zhou, Microsoft Corporation                                   */
2332 /*                                                                        */
2333 /*  DESCRIPTION                                                           */
2334 /*                                                                        */
2335 /*    This function declines the IP assigned to the input DHCP Client     */
2336 /*    interface. The DHCP Client state is set back to the INIT state and  */
2337 /*    DHCP is automatically restarted.                                    */
2338 /*                                                                        */
2339 /*  INPUT                                                                 */
2340 /*                                                                        */
2341 /*    dhcp_ptr                              Pointer to DHCP instance      */
2342 /*    iface_index                           Interface to decline IP on    */
2343 /*                                                                        */
2344 /*  OUTPUT                                                                */
2345 /*                                                                        */
2346 /*    status                                Completion status             */
2347 /*                                                                        */
2348 /*  CALLS                                                                 */
2349 /*                                                                        */
2350 /*    _nx_dhcp_interface_record_find        Find record for the interface */
2351 /*    _nx_dhcp_send_request_internal        Send DHCP request             */
2352 /*    _nx_dhcp_interface_reinitialize       Reset IP and DHCP Client      */
2353 /*                                            network parameters          */
2354 /*    tx_mutex_get                          Get the DHCP mutex            */
2355 /*    tx_mutex_put                          Release the DHCP mutex        */
2356 /*                                                                        */
2357 /*  CALLED BY                                                             */
2358 /*                                                                        */
2359 /*    Application Code                                                    */
2360 /*                                                                        */
2361 /*  RELEASE HISTORY                                                       */
2362 /*                                                                        */
2363 /*    DATE              NAME                      DESCRIPTION             */
2364 /*                                                                        */
2365 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2366 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2367 /*                                            resulting in version 6.1    */
2368 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
2369 /*                                            improved internal logic,    */
2370 /*                                            resulting in version 6.1.12 */
2371 /*                                                                        */
2372 /**************************************************************************/
_nx_dhcp_interface_decline(NX_DHCP * dhcp_ptr,UINT iface_index)2373 UINT _nx_dhcp_interface_decline(NX_DHCP *dhcp_ptr, UINT iface_index)
2374 {
2375 
2376 UINT                      status;
2377 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
2378 
2379 
2380     /* Get the DHCP mutex.  */
2381     tx_mutex_get(&(dhcp_ptr ->nx_dhcp_mutex), TX_WAIT_FOREVER);
2382 
2383     /* Find the interface record.  */
2384     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
2385 
2386     /* Check status.  */
2387     if (status)
2388     {
2389 
2390         /* Release the DHCP mutex.  */
2391         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2392         return(status);
2393     }
2394 
2395     /* Check the record state.  */
2396     if (interface_record -> nx_dhcp_state < NX_DHCP_STATE_BOUND)
2397     {
2398 
2399         /* Release the DHCP mutex.  */
2400         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2401         return(NX_DHCP_NOT_BOUND);
2402     }
2403 
2404     /* Send the decline DHCP request.  */
2405     _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPDECLINE);
2406 
2407     /* Reinitialize DHCP.  */
2408     _nx_dhcp_interface_reinitialize(dhcp_ptr, iface_index);
2409 
2410     /* Start the DHCP protocol again by setting the state back to INIT. */
2411     interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
2412 
2413     /* Wait for some time before restarting the configuration process to avoid excessive network traffic in case of looping. RFC2131, Section3.1, Page17.  */
2414     interface_record -> nx_dhcp_timeout = NX_DHCP_RESTART_WAIT;
2415 
2416     /* Set the retransmission interval.  */
2417     interface_record -> nx_dhcp_rtr_interval = 0;
2418 
2419     /* Determine if the application has specified a routine for DHCP state change notification.  */
2420     if (dhcp_ptr -> nx_dhcp_state_change_callback)
2421     {
2422 
2423         /* Yes, call the application's state change notify function with the new state.  */
2424         (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
2425     }
2426 
2427     /* Determine if the application has specified a routine for DHCP interface state change notification.  */
2428     if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
2429     {
2430 
2431         /* Yes, call the application's state change notify function with the new state.  */
2432         (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
2433     }
2434 
2435     /* Release the DHCP mutex.  */
2436     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2437 
2438     /* Return completion status.  */
2439     return(NX_SUCCESS);
2440 }
2441 
2442 
2443 /**************************************************************************/
2444 /*                                                                        */
2445 /*  FUNCTION                                               RELEASE        */
2446 /*                                                                        */
2447 /*    _nxe_dhcp_release                                   PORTABLE C      */
2448 /*                                                           6.1          */
2449 /*  AUTHOR                                                                */
2450 /*                                                                        */
2451 /*    Yuxin Zhou, Microsoft Corporation                                   */
2452 /*                                                                        */
2453 /*  DESCRIPTION                                                           */
2454 /*                                                                        */
2455 /*    This function checks for errors in the DHCP release function call.  */
2456 /*                                                                        */
2457 /*  INPUT                                                                 */
2458 /*                                                                        */
2459 /*    dhcp_ptr                              Pointer to DHCP instance      */
2460 /*                                                                        */
2461 /*  OUTPUT                                                                */
2462 /*                                                                        */
2463 /*    status                                Completion status             */
2464 /*    NX_PTR_ERROR                          Invalid pointer input         */
2465 /*                                                                        */
2466 /*  CALLS                                                                 */
2467 /*                                                                        */
2468 /*    _nx_dhcp_release                      Actual DHCP release function  */
2469 /*                                                                        */
2470 /*  CALLED BY                                                             */
2471 /*                                                                        */
2472 /*    Application Code                                                    */
2473 /*                                                                        */
2474 /*  RELEASE HISTORY                                                       */
2475 /*                                                                        */
2476 /*    DATE              NAME                      DESCRIPTION             */
2477 /*                                                                        */
2478 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2479 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2480 /*                                            resulting in version 6.1    */
2481 /*                                                                        */
2482 /**************************************************************************/
_nxe_dhcp_release(NX_DHCP * dhcp_ptr)2483 UINT  _nxe_dhcp_release(NX_DHCP *dhcp_ptr)
2484 {
2485 
2486 UINT    status;
2487 
2488 
2489     /* Check for an invalid input pointer.  */
2490     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
2491         return(NX_PTR_ERROR);
2492 
2493     /* Check for appropriate caller.  */
2494     NX_THREADS_ONLY_CALLER_CHECKING
2495 
2496     /* Call actual DHCP release service.  */
2497     status =  _nx_dhcp_release(dhcp_ptr);
2498 
2499     /* Return status.  */
2500     return(status);
2501 }
2502 
2503 
2504 /**************************************************************************/
2505 /*                                                                        */
2506 /*  FUNCTION                                               RELEASE        */
2507 /*                                                                        */
2508 /*    _nx_dhcp_release                                    PORTABLE C      */
2509 /*                                                           6.1          */
2510 /*  AUTHOR                                                                */
2511 /*                                                                        */
2512 /*    Yuxin Zhou, Microsoft Corporation                                   */
2513 /*                                                                        */
2514 /*  DESCRIPTION                                                           */
2515 /*                                                                        */
2516 /*    This function releases the IP previously assigned to this DHCP      */
2517 /*    instance on all interfaces enabled for DHCP. A subsequent  call to  */
2518 /*    nx_dhcp_start initiates a new request to obtain an IP address.      */
2519 /*                                                                        */
2520 /*  INPUT                                                                 */
2521 /*                                                                        */
2522 /*    dhcp_ptr                              Pointer to DHCP instance      */
2523 /*                                                                        */
2524 /*  OUTPUT                                                                */
2525 /*                                                                        */
2526 /*    status                                Completion status             */
2527 /*                                                                        */
2528 /*  CALLS                                                                 */
2529 /*                                                                        */
2530 /*    _nx_dhcp_interface_release            Interface specific send       */
2531 /*                                            release request service     */
2532 /*    tx_mutex_get                          Obtain protection mutex       */
2533 /*    tx_mutex_put                          Release protection mutex      */
2534 /*                                                                        */
2535 /*  CALLED BY                                                             */
2536 /*                                                                        */
2537 /*    Application Code                                                    */
2538 /*                                                                        */
2539 /*  RELEASE HISTORY                                                       */
2540 /*                                                                        */
2541 /*    DATE              NAME                      DESCRIPTION             */
2542 /*                                                                        */
2543 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2544 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2545 /*                                            resulting in version 6.1    */
2546 /*                                                                        */
2547 /**************************************************************************/
_nx_dhcp_release(NX_DHCP * dhcp_ptr)2548 UINT _nx_dhcp_release(NX_DHCP *dhcp_ptr)
2549 {
2550 
2551 UINT    i;
2552 
2553     /* Obtain the DHCP mutex.  */
2554     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
2555 
2556     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
2557     {
2558 
2559         /* Check if this record is valid.  */
2560         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
2561             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
2562         {
2563 
2564             /* Release the address.  */
2565             _nx_dhcp_interface_release(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index);
2566         }
2567     }
2568 
2569     /* Release the DHCP mutex.  */
2570     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2571 
2572     /* Return.  */
2573     return (NX_SUCCESS);
2574 }
2575 
2576 
2577 /**************************************************************************/
2578 /*                                                                        */
2579 /*  FUNCTION                                               RELEASE        */
2580 /*                                                                        */
2581 /*    _nxe_dhcp_interface_release                         PORTABLE C      */
2582 /*                                                           6.1          */
2583 /*  AUTHOR                                                                */
2584 /*                                                                        */
2585 /*    Yuxin Zhou, Microsoft Corporation                                   */
2586 /*                                                                        */
2587 /*  DESCRIPTION                                                           */
2588 /*                                                                        */
2589 /*    This function performs error checking on the release service.       */
2590 /*                                                                        */
2591 /*  INPUT                                                                 */
2592 /*                                                                        */
2593 /*    dhcp_ptr                              Pointer to DHCP instance      */
2594 /*    iface_index                           Interface to release IP on    */
2595 /*                                                                        */
2596 /*  OUTPUT                                                                */
2597 /*                                                                        */
2598 /*    status                                Completion status             */
2599 /*    NX_PTR_ERROR                          Invalid pointer input         */
2600 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
2601 /*                                                                        */
2602 /*  CALLS                                                                 */
2603 /*                                                                        */
2604 /*    _nx_dhcp_interface_release            Actual release service        */
2605 /*                                                                        */
2606 /*  CALLED BY                                                             */
2607 /*                                                                        */
2608 /*    Application Code                                                    */
2609 /*                                                                        */
2610 /*  RELEASE HISTORY                                                       */
2611 /*                                                                        */
2612 /*    DATE              NAME                      DESCRIPTION             */
2613 /*                                                                        */
2614 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2615 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2616 /*                                            resulting in version 6.1    */
2617 /*                                                                        */
2618 /**************************************************************************/
_nxe_dhcp_interface_release(NX_DHCP * dhcp_ptr,UINT iface_index)2619 UINT _nxe_dhcp_interface_release(NX_DHCP *dhcp_ptr, UINT iface_index)
2620 {
2621 
2622 UINT status;
2623 
2624     if (dhcp_ptr == NX_NULL)
2625     {
2626         return(NX_PTR_ERROR);
2627     }
2628 
2629     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
2630     {
2631         return(NX_INVALID_INTERFACE);
2632     }
2633 
2634     /* Check for appropriate caller.  */
2635     NX_THREADS_ONLY_CALLER_CHECKING
2636 
2637     /* Call the actual interface release service.  */
2638     status = _nx_dhcp_interface_release(dhcp_ptr, iface_index);
2639 
2640     /* Return status.  */
2641     return(status);
2642 }
2643 
2644 
2645 /**************************************************************************/
2646 /*                                                                        */
2647 /*  FUNCTION                                               RELEASE        */
2648 /*                                                                        */
2649 /*    _nx_dhcp_interface_release                          PORTABLE C      */
2650 /*                                                           6.1.12       */
2651 /*  AUTHOR                                                                */
2652 /*                                                                        */
2653 /*    Yuxin Zhou, Microsoft Corporation                                   */
2654 /*                                                                        */
2655 /*  DESCRIPTION                                                           */
2656 /*                                                                        */
2657 /*    This function releases the IP previously assigned to this DHCP      */
2658 /*    interface. The DHCP state is returned back to the NOT STARTED state.*/
2659 /*    A subsequent call to _nx_dhcp_interface_start will initiate a new   */
2660 /*    request to obtain an IP address.                                    */
2661 /*                                                                        */
2662 /*  INPUT                                                                 */
2663 /*                                                                        */
2664 /*    dhcp_ptr                              Pointer to DHCP instance      */
2665 /*    iface_index                           Interface to release IP on    */
2666 /*                                                                        */
2667 /*  OUTPUT                                                                */
2668 /*                                                                        */
2669 /*    status                                Completion status             */
2670 /*                                                                        */
2671 /*  CALLS                                                                 */
2672 /*                                                                        */
2673 /*    _nx_dhcp_interface_record_find       Find record for the interface  */
2674 /*    _nx_dhcp_send_request_internal       Send request to DHCP server    */
2675 /*    _nx_dhcp_interface_reinitialize      Clear IP and DHCP network      */
2676 /*                                           parameters to restart DHCP   */
2677 /*    tx_mutex_get                         Obtain protection mutex        */
2678 /*    tx_mutex_put                         Release protection mutex       */
2679 /*                                                                        */
2680 /*  CALLED BY                                                             */
2681 /*                                                                        */
2682 /*    Application Code                                                    */
2683 /*                                                                        */
2684 /*  RELEASE HISTORY                                                       */
2685 /*                                                                        */
2686 /*    DATE              NAME                      DESCRIPTION             */
2687 /*                                                                        */
2688 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2689 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2690 /*                                            resulting in version 6.1    */
2691 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
2692 /*                                            improved internal logic,    */
2693 /*                                            resulting in version 6.1.12 */
2694 /*                                                                        */
2695 /**************************************************************************/
_nx_dhcp_interface_release(NX_DHCP * dhcp_ptr,UINT iface_index)2696 UINT  _nx_dhcp_interface_release(NX_DHCP *dhcp_ptr, UINT iface_index)
2697 {
2698 
2699 UINT                     i;
2700 UINT                     status;
2701 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
2702 
2703 
2704     /* Get the DHCP mutex.  */
2705     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
2706 
2707     /* Find the interface record.  */
2708     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
2709 
2710     /* Check status.  */
2711     if (status)
2712     {
2713 
2714         /* Release the DHCP mutex.  */
2715         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2716 
2717         return(status);
2718     }
2719 
2720     /* Determine if DHCP is in the Boot state.  */
2721     if (interface_record -> nx_dhcp_state < NX_DHCP_STATE_BOUND)
2722     {
2723 
2724         /* Release the DHCP mutex.  */
2725         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2726 
2727         /* Return an error code.  */
2728         return(NX_DHCP_NOT_BOUND);
2729     }
2730 
2731     /* Send the release DHCP request.  */
2732     _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPRELEASE);
2733 
2734     /* Reinitialize DHCP. Note: the state is changed to NX_DHCP_STATE_NOT_STARTED in this function. */
2735     _nx_dhcp_interface_reinitialize(dhcp_ptr, iface_index);
2736 
2737     /* Determine if the application has specified a routine for DHCP state change notification.  */
2738     if (dhcp_ptr -> nx_dhcp_state_change_callback)
2739     {
2740 
2741         /* Yes, call the application's state change notify function with the new state.  */
2742         (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
2743     }
2744 
2745     /* Determine if the application has specified a routine for DHCP interface state change notification.  */
2746     if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
2747     {
2748 
2749         /* Yes, call the application's state change notify function with the new state.  */
2750         (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
2751     }
2752 
2753     /* Check if other interfaces are running DHCP.  */
2754     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
2755     {
2756 
2757         /* Check which interface record is valid.  */
2758         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
2759             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state != NX_DHCP_STATE_NOT_STARTED))
2760         {
2761 
2762             /* Yes, other interfaces have started DHCP. We can assume Netx and ThreadX
2763                resources need to stay activated. */
2764 
2765             /* Release the DHCP mutex.  */
2766             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2767             return(NX_SUCCESS);
2768         }
2769     }
2770 
2771     /* Yes, stop DHCP Thread. */
2772     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread));
2773 
2774     /* Deactivate DHCP Timer.  */
2775     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer));
2776 
2777     /* Unbind UDP socket.  */
2778     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
2779 
2780     /* Release the DHCP mutex.  */
2781     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2782 
2783     /* Return completion status.  */
2784     return(NX_SUCCESS);
2785 }
2786 
2787 
2788 /**************************************************************************/
2789 /*                                                                        */
2790 /*  FUNCTION                                               RELEASE        */
2791 /*                                                                        */
2792 /*    _nxe_dhcp_start                                     PORTABLE C      */
2793 /*                                                           6.1          */
2794 /*  AUTHOR                                                                */
2795 /*                                                                        */
2796 /*    Yuxin Zhou, Microsoft Corporation                                   */
2797 /*                                                                        */
2798 /*  DESCRIPTION                                                           */
2799 /*                                                                        */
2800 /*    This function checks for errors in the DHCP start function call.    */
2801 /*                                                                        */
2802 /*  INPUT                                                                 */
2803 /*                                                                        */
2804 /*    dhcp_ptr                              Pointer to DHCP instance      */
2805 /*                                                                        */
2806 /*  OUTPUT                                                                */
2807 /*                                                                        */
2808 /*    status                                Completion status             */
2809 /*    NX_PTR_ERROR                          Invalid pointer input         */
2810 /*                                                                        */
2811 /*  CALLS                                                                 */
2812 /*                                                                        */
2813 /*    _nx_dhcp_start                        Actual DHCP start function    */
2814 /*                                                                        */
2815 /*  CALLED BY                                                             */
2816 /*                                                                        */
2817 /*    Application Code                                                    */
2818 /*                                                                        */
2819 /*  RELEASE HISTORY                                                       */
2820 /*                                                                        */
2821 /*    DATE              NAME                      DESCRIPTION             */
2822 /*                                                                        */
2823 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2824 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2825 /*                                            resulting in version 6.1    */
2826 /*                                                                        */
2827 /**************************************************************************/
_nxe_dhcp_start(NX_DHCP * dhcp_ptr)2828 UINT  _nxe_dhcp_start(NX_DHCP *dhcp_ptr)
2829 {
2830 
2831 UINT    status;
2832 
2833 
2834     /* Check for invalid input pointer.  */
2835     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
2836         return(NX_PTR_ERROR);
2837 
2838     /* Check for appropriate caller.  */
2839     NX_THREADS_ONLY_CALLER_CHECKING
2840 
2841     /* Call actual DHCP start service.  */
2842     status =  _nx_dhcp_start(dhcp_ptr);
2843 
2844     /* Return status.  */
2845     return(status);
2846 }
2847 
2848 
2849 /**************************************************************************/
2850 /*                                                                        */
2851 /*  FUNCTION                                               RELEASE        */
2852 /*                                                                        */
2853 /*    _nx_dhcp_start                                      PORTABLE C      */
2854 /*                                                           6.1          */
2855 /*  AUTHOR                                                                */
2856 /*                                                                        */
2857 /*    Yuxin Zhou, Microsoft Corporation                                   */
2858 /*                                                                        */
2859 /*  DESCRIPTION                                                           */
2860 /*                                                                        */
2861 /*    This function starts DHCP on all interfaces that are enabled for    */
2862 /*    DHCP. If no interfaces have previously been started on DHCP, this   */
2863 /*    function re/starts the DHCP CLient thread, binds the socket and     */
2864 /*    re/starts the timer.                                                */
2865 /*                                                                        */
2866 /*    To start DHCP on a specific interface if multiple interfaces are    */
2867 /*    enabled for DHCP, use the nx_dhcp_interface_start service.          */
2868 /*                                                                        */
2869 /*  INPUT                                                                 */
2870 /*                                                                        */
2871 /*    dhcp_ptr                              Pointer to DHCP instance      */
2872 /*                                                                        */
2873 /*  OUTPUT                                                                */
2874 /*                                                                        */
2875 /*    status                                Completion status             */
2876 /*    NX_DHCP_NO_INTERFACES_STARTED         Unable to start any interfaces*/
2877 /*                                                                        */
2878 /*  CALLS                                                                 */
2879 /*                                                                        */
2880 /*    _nx_dhcp_interface_start              Interface specific start DHCP */
2881 /*                                             Client service             */
2882 /*    tx_mutex_get                          Obtain protection mutex       */
2883 /*    tx_mutex_put                          Release protection mutex      */
2884 /*                                                                        */
2885 /*  CALLED BY                                                             */
2886 /*                                                                        */
2887 /*    Application Code                                                    */
2888 /*                                                                        */
2889 /*  RELEASE HISTORY                                                       */
2890 /*                                                                        */
2891 /*    DATE              NAME                      DESCRIPTION             */
2892 /*                                                                        */
2893 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2894 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2895 /*                                            resulting in version 6.1    */
2896 /*                                                                        */
2897 /**************************************************************************/
_nx_dhcp_start(NX_DHCP * dhcp_ptr)2898 UINT  _nx_dhcp_start(NX_DHCP *dhcp_ptr)
2899 {
2900 
2901 UINT    status;
2902 UINT    interfaces_started = 0;
2903 UINT    i;
2904 
2905 
2906     /* Get the DHCP mutex.  */
2907     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
2908 
2909     /* Check all interfaces to find out which need to start the DHCP protocol.  */
2910     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
2911     {
2912 
2913         /* Check if this record is valid.  */
2914         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid == NX_TRUE)
2915         {
2916 
2917             /* Start DHCP on this interface.   */
2918              status = _nx_dhcp_interface_start(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index);
2919 
2920              /* Note, not all interfaces are enabled to run, so
2921                 status may not be successful. Skip to the next
2922                 interface. */
2923 
2924              /* Check status.  */
2925              if ((status == NX_SUCCESS) || (status == NX_DHCP_ALREADY_STARTED))
2926              {
2927                  interfaces_started++;
2928              }
2929         }
2930     }
2931 
2932     /* Check if any interfaces started DHCP. */
2933     if (interfaces_started == 0)
2934     {
2935 
2936         /* Release the DHCP mutex.  */
2937         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2938 
2939         /* Unable to start any interfaces. */
2940         return NX_DHCP_NO_INTERFACES_STARTED;
2941     }
2942 
2943     /* Release the DHCP mutex.  */
2944     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
2945 
2946     /* Return completion status.  */
2947     return(NX_SUCCESS);
2948 }
2949 
2950 
2951 /**************************************************************************/
2952 /*                                                                        */
2953 /*  FUNCTION                                               RELEASE        */
2954 /*                                                                        */
2955 /*    _nxe_dhcp_interface_start                          PORTABLE C      */
2956 /*                                                           6.1          */
2957 /*  AUTHOR                                                                */
2958 /*                                                                        */
2959 /*    Yuxin Zhou, Microsoft Corporation                                   */
2960 /*                                                                        */
2961 /*  DESCRIPTION                                                           */
2962 /*                                                                        */
2963 /*    This function performs error checking for the interface specific    */
2964 /*    DHCP start service.                                                 */
2965 /*                                                                        */
2966 /*  INPUT                                                                 */
2967 /*                                                                        */
2968 /*    dhcp_ptr                              Pointer to DHCP instance      */
2969 /*    iface_index                           Interface to start DHCP       */
2970 /*                                                                        */
2971 /*  OUTPUT                                                                */
2972 /*                                                                        */
2973 /*    status                                Completion status             */
2974 /*    NX_PTR_ERROR                          Invalid pointer input         */
2975 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
2976 /*                                                                        */
2977 /*  CALLS                                                                 */
2978 /*                                                                        */
2979 /*    _nx_dhcp_interface_start              Actual interface start service*/
2980 /*                                                                        */
2981 /*  CALLED BY                                                             */
2982 /*                                                                        */
2983 /*    Application Code                                                    */
2984 /*                                                                        */
2985 /*  RELEASE HISTORY                                                       */
2986 /*                                                                        */
2987 /*    DATE              NAME                      DESCRIPTION             */
2988 /*                                                                        */
2989 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2990 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2991 /*                                            resulting in version 6.1    */
2992 /*                                                                        */
2993 /**************************************************************************/
_nxe_dhcp_interface_start(NX_DHCP * dhcp_ptr,UINT iface_index)2994 UINT  _nxe_dhcp_interface_start(NX_DHCP *dhcp_ptr, UINT iface_index)
2995 {
2996 
2997 UINT status;
2998 
2999     if (dhcp_ptr == NX_NULL)
3000     {
3001         return(NX_PTR_ERROR);
3002     }
3003 
3004     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
3005     {
3006         return(NX_INVALID_INTERFACE);
3007     }
3008 
3009     /* Check for appropriate caller.  */
3010     NX_THREADS_ONLY_CALLER_CHECKING
3011 
3012     /* Call actual DHCP interface start service.  */
3013     status =  _nx_dhcp_interface_start(dhcp_ptr, iface_index);
3014 
3015     /* Return status.  */
3016     return(status);
3017 }
3018 
3019 
3020 /**************************************************************************/
3021 /*                                                                        */
3022 /*  FUNCTION                                               RELEASE        */
3023 /*                                                                        */
3024 /*    _nx_dhcp_interface_start                            PORTABLE C      */
3025 /*                                                           6.1          */
3026 /*  AUTHOR                                                                */
3027 /*                                                                        */
3028 /*    Yuxin Zhou, Microsoft Corporation                                   */
3029 /*                                                                        */
3030 /*  DESCRIPTION                                                           */
3031 /*                                                                        */
3032 /*  This function 'starts' the specified interface.  It finds the matching*/
3033 /*  DHCP Client record for that interface and checks that the interface   */
3034 /*  has been enabled for DHCP (see nx_dhcp_interface_enable). It then     */
3035 /*  checks if any interfaces are running DHCP. If not it binds the DHCP   */
3036 /*  socket port, activates the DHCP timer, and resumes the DHCP Client    */
3037 /*  thread.                                                               */
3038 /*                                                                        */
3039 /*  INPUT                                                                 */
3040 /*                                                                        */
3041 /*    dhcp_ptr                              Pointer to DHCP instance      */
3042 /*    iface_index                           Interface to start DHCP       */
3043 /*                                                                        */
3044 /*  OUTPUT                                                                */
3045 /*                                                                        */
3046 /*    status                                Completion status             */
3047 /*                                                                        */
3048 /*  CALLS                                                                 */
3049 /*                                                                        */
3050 /*    _nx_dhcp_interface_record_find        Find the Client record for the*/
3051 /*                                              specified  interface      */
3052 /*    nx_udp_socket_bind                    Bind DHCP socket              */
3053 /*    nx_udp_socket_unbind                  Unbind DHCP socket            */
3054 /*    tx_thread_resume                      Initiate DHCP processing      */
3055 /*    tx_timer_activate                     Activate DHCP timer           */
3056 /*    tx_mutex_get                          Get the DHCP mutex            */
3057 /*    tx_mutex_put                          Release the DHCP mutex        */
3058 /*                                                                        */
3059 /*  CALLED BY                                                             */
3060 /*                                                                        */
3061 /*    Application Code                                                    */
3062 /*                                                                        */
3063 /*  RELEASE HISTORY                                                       */
3064 /*                                                                        */
3065 /*    DATE              NAME                      DESCRIPTION             */
3066 /*                                                                        */
3067 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3068 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3069 /*                                            resulting in version 6.1    */
3070 /*                                                                        */
3071 /**************************************************************************/
_nx_dhcp_interface_start(NX_DHCP * dhcp_ptr,UINT iface_index)3072 UINT  _nx_dhcp_interface_start(NX_DHCP *dhcp_ptr, UINT iface_index)
3073 {
3074 
3075 UINT    i;
3076 UINT    status;
3077 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
3078 
3079 
3080     /* Get the DHCP mutex.  */
3081     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
3082 
3083     /* Find the interface record.  */
3084     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
3085 
3086     /* Check status.  */
3087     if (status)
3088     {
3089 
3090         /* Release the DHCP mutex.  */
3091         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3092 
3093         return(status);
3094     }
3095 
3096     /* Check if DHCP is already started.  */
3097     if (interface_record -> nx_dhcp_state != NX_DHCP_STATE_NOT_STARTED)
3098     {
3099 
3100         /* Release the DHCP mutex.  */
3101         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3102         return(NX_DHCP_ALREADY_STARTED);
3103     }
3104 
3105     /* Check if other interface are working.  */
3106     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
3107     {
3108 
3109         /* Check which interface record is valid.  */
3110         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
3111             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state != NX_DHCP_STATE_NOT_STARTED))
3112         {
3113 
3114             /* Yes, other interface have started DHCP.  */
3115             break;
3116         }
3117     }
3118 
3119     /* Check if any interfaces have started DHCP.  */
3120     if (i == NX_DHCP_CLIENT_MAX_RECORDS)
3121     {
3122 
3123         /* Bind the UDP socket to the DHCP Client port.  */
3124         status =  nx_udp_socket_bind(&(dhcp_ptr -> nx_dhcp_socket), NX_DHCP_CLIENT_UDP_PORT, NX_WAIT_FOREVER);
3125 
3126         /* Check for error */
3127         if (status != NX_SUCCESS)
3128         {
3129 
3130             /* Release the DHCP mutex.  */
3131             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3132             return(status);
3133         }
3134 
3135         /* Resume the DHCP processing thread.  */
3136         status = tx_thread_resume(&(dhcp_ptr -> nx_dhcp_thread));
3137 
3138         /* Determine if the resume was successful.  */
3139         if ((status != TX_SUCCESS) && (status != TX_SUSPEND_LIFTED))
3140         {
3141 
3142             /* Error, unbind the DHCP socket.  */
3143             nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
3144 
3145             /* Release the DHCP mutex.  */
3146             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3147             return(status);
3148         }
3149 
3150         /* Activate DHCP Timer.  */
3151         status = tx_timer_activate(&(dhcp_ptr -> nx_dhcp_timer));
3152 
3153         /* Determine if the resume was successful.  */
3154         if (status != NX_SUCCESS)
3155         {
3156 
3157             /* Error, unbind the DHCP socket.  */
3158             nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
3159 
3160             /* Release the DHCP mutex.  */
3161             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3162             return(status);
3163         }
3164     }
3165 
3166     /* Start DHCP service for this interface record.  */
3167     /* Start the DHCP protocol again by setting the state back to INIT. */
3168     interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
3169 
3170     /* The client begins in INIT state and forms a DHCPDISCOVER message.
3171        The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
3172        RFC2131, Section4.4.1, Page36.  */
3173 
3174     /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
3175     interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
3176     interface_record -> nx_dhcp_rtr_interval = 0;
3177 
3178     /* Determine if the application has specified a routine for DHCP state change notification.  */
3179     if (dhcp_ptr -> nx_dhcp_state_change_callback)
3180     {
3181 
3182         /* Yes, call the application's state change notify function with the new state.  */
3183         (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
3184     }
3185 
3186     /* Determine if the application has specified a routine for DHCP interface state change notification.  */
3187     if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
3188     {
3189 
3190         /* Yes, call the application's state change notify function with the new state.  */
3191         (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
3192     }
3193 
3194     /* Release the DHCP mutex.  */
3195     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3196 
3197     return NX_SUCCESS;
3198 }
3199 
3200 
3201 /**************************************************************************/
3202 /*                                                                        */
3203 /*  FUNCTION                                               RELEASE        */
3204 /*                                                                        */
3205 /*    _nxe_dhcp_interface_enable                          PORTABLE C      */
3206 /*                                                           6.1          */
3207 /*  AUTHOR                                                                */
3208 /*                                                                        */
3209 /*    Yuxin Zhou, Microsoft Corporation                                   */
3210 /*                                                                        */
3211 /*  DESCRIPTION                                                           */
3212 /*                                                                        */
3213 /*    This function performs error checking for the interface specific    */
3214 /*    DHCP enable interface service.                                      */
3215 /*                                                                        */
3216 /*  INPUT                                                                 */
3217 /*                                                                        */
3218 /*    dhcp_ptr                              Pointer to DHCP instance      */
3219 /*    iface_index                           Interface to enable DHCP      */
3220 /*                                                                        */
3221 /*  OUTPUT                                                                */
3222 /*                                                                        */
3223 /*    status                                Completion status             */
3224 /*    NX_PTR_ERROR                          Invalid pointer input         */
3225 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
3226 /*                                                                        */
3227 /*  CALLS                                                                 */
3228 /*                                                                        */
3229 /*    _nx_dhcp_interface_add               Actual interface enable service*/
3230 /*                                                                        */
3231 /*  CALLED BY                                                             */
3232 /*                                                                        */
3233 /*    Application Code                                                    */
3234 /*                                                                        */
3235 /*  RELEASE HISTORY                                                       */
3236 /*                                                                        */
3237 /*    DATE              NAME                      DESCRIPTION             */
3238 /*                                                                        */
3239 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3240 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3241 /*                                            resulting in version 6.1    */
3242 /*                                                                        */
3243 /**************************************************************************/
_nxe_dhcp_interface_enable(NX_DHCP * dhcp_ptr,UINT iface_index)3244 UINT  _nxe_dhcp_interface_enable(NX_DHCP *dhcp_ptr, UINT iface_index)
3245 {
3246 
3247 UINT status;
3248 
3249     if (dhcp_ptr == NX_NULL)
3250     {
3251         return(NX_PTR_ERROR);
3252     }
3253 
3254     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
3255     {
3256         return(NX_INVALID_INTERFACE);
3257     }
3258 
3259     /* Call actual DHCP interface enable service.  */
3260     status = _nx_dhcp_interface_enable(dhcp_ptr, iface_index);
3261 
3262     /* Return status.  */
3263     return(status);
3264 }
3265 
3266 
3267 /**************************************************************************/
3268 /*                                                                        */
3269 /*  FUNCTION                                               RELEASE        */
3270 /*                                                                        */
3271 /*    _nx_dhcp_interface_enable                           PORTABLE C      */
3272 /*                                                           6.1          */
3273 /*  AUTHOR                                                                */
3274 /*                                                                        */
3275 /*    Yuxin Zhou, Microsoft Corporation                                   */
3276 /*                                                                        */
3277 /*  DESCRIPTION                                                           */
3278 /*                                                                        */
3279 /*  This function sets the specified interface as enabled to run DHCP.    */
3280 /*  It ensures all DHCP parameters are initialized to zero, and uses the  */
3281 /*  physical interface MAC address to set the unique Client ID used for   */
3282 /*  transactions with the DHCP server.                                    */
3283 /*                                                                        */
3284 /*  By default the primary interface is enabled in nx_dhcp_create.  An    */
3285 /*  interface must be enabled before DHCP can be started on it.           */
3286 /*  Thereafter, it is only necessary to call this function on an interface*/
3287 /*  that has been disabled.                                               */
3288 /*                                                                        */
3289 /*  INPUT                                                                 */
3290 /*                                                                        */
3291 /*    dhcp_ptr                              Pointer to DHCP instance      */
3292 /*    iface_index                           Interface to enable DHCP      */
3293 /*                                                                        */
3294 /*  OUTPUT                                                                */
3295 /*                                                                        */
3296 /*    NX_SUCCESS                            Successful completion status  */
3297 /*    NX_DHCP_NO_RECORDS_AVAILABLE          No more records available to  */
3298 /*                                            enable DHCP on an interface */
3299 /*                                                                        */
3300 /*  CALLS                                                                 */
3301 /*                                                                        */
3302 /*    tx_mutex_get                          Get the DHCP mutex            */
3303 /*    tx_mutex_put                          Release the DHCP mutex        */
3304 /*                                                                        */
3305 /*  CALLED BY                                                             */
3306 /*                                                                        */
3307 /*    Application Code                                                    */
3308 /*                                                                        */
3309 /*  RELEASE HISTORY                                                       */
3310 /*                                                                        */
3311 /*    DATE              NAME                      DESCRIPTION             */
3312 /*                                                                        */
3313 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3314 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3315 /*                                            resulting in version 6.1    */
3316 /*                                                                        */
3317 /**************************************************************************/
_nx_dhcp_interface_enable(NX_DHCP * dhcp_ptr,UINT iface_index)3318 UINT  _nx_dhcp_interface_enable(NX_DHCP *dhcp_ptr, UINT iface_index)
3319 {
3320 UINT                      i;
3321 ULONG                     client_physical_lsw, client_physical_msw;
3322 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
3323 
3324 
3325     /* Get the DHCP mutex.  */
3326     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
3327 
3328     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
3329     {
3330 
3331         /* Check if this record is valid.  */
3332         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid == NX_TRUE)
3333         {
3334 
3335             /* Check if the interface is already enabled. */
3336             if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index == iface_index)
3337             {
3338 
3339                 /* Release the DHCP mutex.  */
3340                  tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3341                  return(NX_DHCP_INTERFACE_ALREADY_ENABLED);
3342             }
3343         }
3344         else
3345         {
3346 
3347             /* Yes, we found an available record.  */
3348             if (interface_record == NX_NULL)
3349                 interface_record = &dhcp_ptr -> nx_dhcp_interface_record[i];
3350         }
3351     }
3352 
3353     /* Check if we found an valid DHCP interface record.  */
3354     if (interface_record == NX_NULL)
3355     {
3356 
3357         /* No, release the mutex.  */
3358         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3359         return(NX_DHCP_NO_RECORDS_AVAILABLE);
3360     }
3361 
3362     /* Set this record as valid.  */
3363     interface_record -> nx_dhcp_record_valid = NX_TRUE;
3364 
3365     /* Set interface index. */
3366     interface_record -> nx_dhcp_interface_index = iface_index;
3367 
3368     /* Initialize the client DHCP IP address with the NULL IP address.  */
3369     interface_record -> nx_dhcp_ip_address =  NX_BOOTP_NO_ADDRESS;
3370 
3371     /* Initialize the client DHCP server IP address.  */
3372     interface_record -> nx_dhcp_server_ip =  NX_BOOTP_NO_ADDRESS;
3373 
3374     /* Initialize renew and rebind timeout values to zero.  */
3375     interface_record -> nx_dhcp_rebind_time = 0;
3376     interface_record -> nx_dhcp_renewal_time =  0;
3377 
3378     /* Setup for infinite lease time request.  */
3379     interface_record -> nx_dhcp_lease_time =  NX_DHCP_INFINITE_LEASE;
3380 
3381     /* Get the client MAC address from the device interface. */
3382     client_physical_msw = dhcp_ptr ->  nx_dhcp_ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_msw;
3383     client_physical_lsw = dhcp_ptr ->  nx_dhcp_ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_lsw;
3384 
3385     /* Generate a 'unique' client transaction ID from the MAC address for each message to the server. */
3386     interface_record -> nx_dhcp_xid =  (ULONG)(client_physical_msw ^ client_physical_lsw ^ (ULONG)NX_RAND());
3387 
3388     /* Clear the timeout.  */
3389     interface_record -> nx_dhcp_timeout = 0;
3390 
3391     /* Release the DHCP mutex.  */
3392     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3393     return(NX_SUCCESS);
3394 }
3395 
3396 
3397 /**************************************************************************/
3398 /*                                                                        */
3399 /*  FUNCTION                                               RELEASE        */
3400 /*                                                                        */
3401 /*    _nxe_dhcp_interface_disable                         PORTABLE C      */
3402 /*                                                           6.1          */
3403 /*  AUTHOR                                                                */
3404 /*                                                                        */
3405 /*    Yuxin Zhou, Microsoft Corporation                                   */
3406 /*                                                                        */
3407 /*  DESCRIPTION                                                           */
3408 /*                                                                        */
3409 /*    This function performs error checking on the disable service.       */
3410 /*                                                                        */
3411 /*  INPUT                                                                 */
3412 /*                                                                        */
3413 /*    dhcp_ptr                              Pointer to DHCP instance      */
3414 /*    iface_index                           Interface to disable DHCP     */
3415 /*                                                                        */
3416 /*  OUTPUT                                                                */
3417 /*                                                                        */
3418 /*    status                                Completion status             */
3419 /*    NX_PTR_ERROR                          Invalid pointer input         */
3420 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
3421 /*                                                                        */
3422 /*  CALLS                                                                 */
3423 /*                                                                        */
3424 /*    _nx_dhcp_interface_disable            Actual disable service        */
3425 /*                                                                        */
3426 /*  CALLED BY                                                             */
3427 /*                                                                        */
3428 /*    Application Code                                                    */
3429 /*                                                                        */
3430 /*  RELEASE HISTORY                                                       */
3431 /*                                                                        */
3432 /*    DATE              NAME                      DESCRIPTION             */
3433 /*                                                                        */
3434 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3435 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3436 /*                                            resulting in version 6.1    */
3437 /*                                                                        */
3438 /**************************************************************************/
_nxe_dhcp_interface_disable(NX_DHCP * dhcp_ptr,UINT iface_index)3439 UINT _nxe_dhcp_interface_disable(NX_DHCP *dhcp_ptr, UINT iface_index)
3440 {
3441 UINT status;
3442 
3443     if (dhcp_ptr == NX_NULL)
3444     {
3445         return(NX_PTR_ERROR);
3446     }
3447 
3448     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
3449     {
3450         return(NX_INVALID_INTERFACE);
3451     }
3452 
3453     /* Check for appropriate caller.  */
3454     NX_THREADS_ONLY_CALLER_CHECKING
3455 
3456     /* Call the actual delete service.  */
3457     status = _nx_dhcp_interface_disable(dhcp_ptr, iface_index);
3458 
3459     /* Return status.  */
3460     return(status);
3461 }
3462 
3463 
3464 /**************************************************************************/
3465 /*                                                                        */
3466 /*  FUNCTION                                               RELEASE        */
3467 /*                                                                        */
3468 /*    _nx_dhcp_interface_disable                          PORTABLE C      */
3469 /*                                                           6.1          */
3470 /*  AUTHOR                                                                */
3471 /*                                                                        */
3472 /*    Yuxin Zhou, Microsoft Corporation                                   */
3473 /*                                                                        */
3474 /*  DESCRIPTION                                                           */
3475 /*                                                                        */
3476 /*    This function disables the input interface to run DHCP. The DHCP    */
3477 /*    Client need not be in any state or DHCP to be started on this       */
3478 /*    interface to disable it.                                            */
3479 /*                                                                        */
3480 /*    This function clears the DHCP and IP interface network parameters.  */
3481 /*    Before DHCP can be restarted on this interface, it must be enabled  */
3482 /*    by calling nx_dhcp_interface_enable.                                */
3483 /*                                                                        */
3484 /*  INPUT                                                                 */
3485 /*                                                                        */
3486 /*    dhcp_ptr                              Pointer to DHCP instance      */
3487 /*    iface_index                           Interface to disable DHCP on  */
3488 /*                                                                        */
3489 /*  OUTPUT                                                                */
3490 /*                                                                        */
3491 /*    status                                Completion status             */
3492 /*                                                                        */
3493 /*  CALLS                                                                 */
3494 /*                                                                        */
3495 /*    _nx_dhcp_interface_record_find        Find Client record for input  */
3496 /*                                            interface                   */
3497 /*    _nx_dhcp_interface_reinitialize       Clear DHCP and IP network     */
3498 /*                                            parameters                  */
3499 /*    tx_mutex_get                          Get the DHCP mutex            */
3500 /*    tx_mutex_put                          Release the DHCP mutex        */
3501 /*                                                                        */
3502 /*  CALLED BY                                                             */
3503 /*                                                                        */
3504 /*    Application Code                                                    */
3505 /*                                                                        */
3506 /*  RELEASE HISTORY                                                       */
3507 /*                                                                        */
3508 /*    DATE              NAME                      DESCRIPTION             */
3509 /*                                                                        */
3510 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3511 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3512 /*                                            resulting in version 6.1    */
3513 /*                                                                        */
3514 /**************************************************************************/
_nx_dhcp_interface_disable(NX_DHCP * dhcp_ptr,UINT iface_index)3515 UINT _nx_dhcp_interface_disable(NX_DHCP *dhcp_ptr, UINT iface_index)
3516 {
3517 
3518 UINT status;
3519 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
3520 
3521 
3522     /* Obtain the DHCP mutex.  */
3523     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
3524 
3525     /* Find the interface record.  */
3526     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
3527 
3528     /* Check status.  */
3529     if (status)
3530     {
3531 
3532         /* Release the DHCP mutex.  */
3533         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3534         return(status);
3535     }
3536 
3537     /* Reinitalize the DHCP. This clears network values in DHCP and IP interfaces  */
3538     _nx_dhcp_interface_reinitialize(dhcp_ptr, iface_index);
3539 
3540     /* Set the record as invalid.  */
3541     interface_record -> nx_dhcp_record_valid = NX_FALSE;
3542 
3543     /* Release the DHCP mutex.  */
3544     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3545     return(NX_SUCCESS);
3546 }
3547 
3548 
3549 /**************************************************************************/
3550 /*                                                                        */
3551 /*  FUNCTION                                               RELEASE        */
3552 /*                                                                        */
3553 /*    _nxe_dhcp_state_change_notify                       PORTABLE C      */
3554 /*                                                           6.3.0        */
3555 /*  AUTHOR                                                                */
3556 /*                                                                        */
3557 /*    Yuxin Zhou, Microsoft Corporation                                   */
3558 /*                                                                        */
3559 /*  DESCRIPTION                                                           */
3560 /*                                                                        */
3561 /*    This function checks for errors in the DHCP notify function call.   */
3562 /*                                                                        */
3563 /*  INPUT                                                                 */
3564 /*                                                                        */
3565 /*    dhcp_ptr                              Pointer to DHCP instance      */
3566 /*    dchp_state_change_notify              Application function to call  */
3567 /*                                            upon DHCP state change      */
3568 /*                                                                        */
3569 /*  OUTPUT                                                                */
3570 /*                                                                        */
3571 /*    status                                Completion status             */
3572 /*                                                                        */
3573 /*  CALLS                                                                 */
3574 /*                                                                        */
3575 /*    _nx_dhcp_state_change_notify          Actual DHCP notify function   */
3576 /*                                                                        */
3577 /*  CALLED BY                                                             */
3578 /*                                                                        */
3579 /*    Application Code                                                    */
3580 /*                                                                        */
3581 /*  RELEASE HISTORY                                                       */
3582 /*                                                                        */
3583 /*    DATE              NAME                      DESCRIPTION             */
3584 /*                                                                        */
3585 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3586 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3587 /*                                            resulting in version 6.1    */
3588 /*  10-31-2023     Haiqing Zhao             Modified comment(s), and      */
3589 /*                                            corrected caller checking,  */
3590 /*                                            resulting in version 6.3.0  */
3591 /*                                                                        */
3592 /**************************************************************************/
_nxe_dhcp_state_change_notify(NX_DHCP * dhcp_ptr,VOID (* dhcp_state_change_notify)(NX_DHCP * dhcp_ptr,UCHAR new_state))3593 UINT  _nxe_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state))
3594 {
3595 
3596 UINT    status;
3597 
3598 
3599     /* Check for invalid input pointer.  */
3600     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
3601         return(NX_PTR_ERROR);
3602 
3603     /* Check for appropriate caller.  */
3604     NX_INIT_AND_THREADS_CALLER_CHECKING
3605 
3606     /* Call actual DHCP notify service.  */
3607     status =  _nx_dhcp_state_change_notify(dhcp_ptr, dhcp_state_change_notify);
3608 
3609     /* Return status.  */
3610     return(status);
3611 }
3612 
3613 
3614 /**************************************************************************/
3615 /*                                                                        */
3616 /*  FUNCTION                                               RELEASE        */
3617 /*                                                                        */
3618 /*    _nx_dhcp_state_change_notify                        PORTABLE C      */
3619 /*                                                           6.1          */
3620 /*  AUTHOR                                                                */
3621 /*                                                                        */
3622 /*    Yuxin Zhou, Microsoft Corporation                                   */
3623 /*                                                                        */
3624 /*  DESCRIPTION                                                           */
3625 /*                                                                        */
3626 /*    This function sets up an application notification function that is  */
3627 /*    called whenever a DHCP interface enters a new state.  If a NULL     */
3628 /*    pointer is supplied, the notification is effectively cancelled.     */
3629 /*                                                                        */
3630 /*  INPUT                                                                 */
3631 /*                                                                        */
3632 /*    dhcp_ptr                              Pointer to DHCP instance      */
3633 /*    dchp_state_change_notify              Application function to call  */
3634 /*                                            upon DHCP state change      */
3635 /*                                                                        */
3636 /*  OUTPUT                                                                */
3637 /*                                                                        */
3638 /*    status                                Completion status             */
3639 /*                                                                        */
3640 /*  CALLS                                                                 */
3641 /*                                                                        */
3642 /*    tx_mutex_get                          Get the DHCP mutex            */
3643 /*    tx_mutex_put                          Release the DHCP mutex        */
3644 /*                                                                        */
3645 /*  CALLED BY                                                             */
3646 /*                                                                        */
3647 /*    Application Code                                                    */
3648 /*                                                                        */
3649 /*  RELEASE HISTORY                                                       */
3650 /*                                                                        */
3651 /*    DATE              NAME                      DESCRIPTION             */
3652 /*                                                                        */
3653 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3654 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3655 /*                                            resulting in version 6.1    */
3656 /*                                                                        */
3657 /**************************************************************************/
_nx_dhcp_state_change_notify(NX_DHCP * dhcp_ptr,VOID (* dhcp_state_change_notify)(NX_DHCP * dhcp_ptr,UCHAR new_state))3658 UINT  _nx_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state))
3659 {
3660 
3661 
3662     /* Get the DHCP mutex.  */
3663     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
3664 
3665     /* Setup the DHCP notify function.  */
3666     dhcp_ptr -> nx_dhcp_state_change_callback =  dhcp_state_change_notify;
3667 
3668     /* Release the DHCP mutex.  */
3669     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3670 
3671     /* Return completion status.  */
3672     return(NX_SUCCESS);
3673 }
3674 
3675 
3676 /**************************************************************************/
3677 /*                                                                        */
3678 /*  FUNCTION                                               RELEASE        */
3679 /*                                                                        */
3680 /*    _nxe_dhcp_interface_state_change_notify             PORTABLE C      */
3681 /*                                                           6.1          */
3682 /*  AUTHOR                                                                */
3683 /*                                                                        */
3684 /*    Yuxin Zhou, Microsoft Corporation                                   */
3685 /*                                                                        */
3686 /*  DESCRIPTION                                                           */
3687 /*                                                                        */
3688 /*    This function checks for errors in the state change notify call.    */
3689 /*                                                                        */
3690 /*  INPUT                                                                 */
3691 /*                                                                        */
3692 /*    dhcp_ptr                              Pointer to DHCP instance      */
3693 /*    dhcp_state_interface_change_notify    Application function to call  */
3694 /*                                            upon DHCP state change      */
3695 /*                                                                        */
3696 /*  OUTPUT                                                                */
3697 /*                                                                        */
3698 /*    NX_SUCCESS                            Successful completion status  */
3699 /*    NX_PTR_ERROR                          Invalid pointer input         */
3700 /*                                                                        */
3701 /*  CALLS                                                                 */
3702 /*                                                                        */
3703 /*    _nx_dhcp_interface_state_change_notify Actual DHCP notify function  */
3704 /*                                                                        */
3705 /*  CALLED BY                                                             */
3706 /*                                                                        */
3707 /*    Application Code                                                    */
3708 /*                                                                        */
3709 /*  RELEASE HISTORY                                                       */
3710 /*                                                                        */
3711 /*    DATE              NAME                      DESCRIPTION             */
3712 /*                                                                        */
3713 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3714 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3715 /*                                            resulting in version 6.1    */
3716 /*                                                                        */
3717 /**************************************************************************/
_nxe_dhcp_interface_state_change_notify(NX_DHCP * dhcp_ptr,VOID (* dhcp_state_interface_change_notify)(NX_DHCP * dhcp_ptr,UINT iface_index,UCHAR new_state))3718 UINT  _nxe_dhcp_interface_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_interface_change_notify)(NX_DHCP *dhcp_ptr, UINT iface_index, UCHAR new_state))
3719 {
3720 
3721 UINT    status;
3722 
3723     /* Check for invalid input pointer.  */
3724     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
3725     {
3726         return(NX_PTR_ERROR);
3727     }
3728 
3729     /* Call actual DHCP notify service.  */
3730     status =  _nx_dhcp_interface_state_change_notify(dhcp_ptr, dhcp_state_interface_change_notify);
3731 
3732     /* Return status.  */
3733     return(status);
3734 }
3735 
3736 
3737 /**************************************************************************/
3738 /*                                                                        */
3739 /*  FUNCTION                                               RELEASE        */
3740 /*                                                                        */
3741 /*    _nx_dhcp_interface_state_change_notify              PORTABLE C      */
3742 /*                                                           6.1          */
3743 /*  AUTHOR                                                                */
3744 /*                                                                        */
3745 /*    Yuxin Zhou, Microsoft Corporation                                   */
3746 /*                                                                        */
3747 /*  DESCRIPTION                                                           */
3748 /*                                                                        */
3749 /*    This function sets up an application notification function that is  */
3750 /*    called whenever DHCP on the input interface enters a new state. If  */
3751 /*    NULL function pointer is supplied, the notification is  cancelled.  */
3752 /*    The interface on which the DHCP state changed is indicated by the   */
3753 /*    iface_index input.                                                  */
3754 /*                                                                        */
3755 /*  INPUT                                                                 */
3756 /*                                                                        */
3757 /*    dhcp_ptr                              Pointer to DHCP instance      */
3758 /*    dchp_state_change_notify              interface-specific callback   */
3759 /*                                            for DHCP state change       */
3760 /*                                                                        */
3761 /*  OUTPUT                                                                */
3762 /*                                                                        */
3763 /*    NX_SUCCESS                            Successful status             */
3764 /*                                                                        */
3765 /*  CALLS                                                                 */
3766 /*                                                                        */
3767 /*    tx_mutex_get                          Get the DHCP mutex            */
3768 /*    tx_mutex_put                          Release the DHCP mutex        */
3769 /*                                                                        */
3770 /*  CALLED BY                                                             */
3771 /*                                                                        */
3772 /*    Application Code                                                    */
3773 /*                                                                        */
3774 /*  RELEASE HISTORY                                                       */
3775 /*                                                                        */
3776 /*    DATE              NAME                      DESCRIPTION             */
3777 /*                                                                        */
3778 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3779 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3780 /*                                            resulting in version 6.1    */
3781 /*                                                                        */
3782 /**************************************************************************/
_nx_dhcp_interface_state_change_notify(NX_DHCP * dhcp_ptr,VOID (* dhcp_interface_state_change_notify)(NX_DHCP * dhcp_ptr,UINT iface_index,UCHAR new_state))3783 UINT  _nx_dhcp_interface_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_interface_state_change_notify)(NX_DHCP *dhcp_ptr, UINT iface_index, UCHAR new_state))
3784 {
3785 
3786 
3787     /* Obtain the DHCP mutex.  */
3788     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
3789 
3790     /* Setup the DHCP notify function.  */
3791     dhcp_ptr -> nx_dhcp_interface_state_change_callback =  dhcp_interface_state_change_notify;
3792 
3793     /* Release the DHCP mutex.  */
3794     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3795 
3796     /* Return completion status.  */
3797     return(NX_SUCCESS);
3798 }
3799 
3800 
3801 /**************************************************************************/
3802 /*                                                                        */
3803 /*  FUNCTION                                               RELEASE        */
3804 /*                                                                        */
3805 /*    _nxe_dhcp_stop                                      PORTABLE C      */
3806 /*                                                           6.1          */
3807 /*  AUTHOR                                                                */
3808 /*                                                                        */
3809 /*    Yuxin Zhou, Microsoft Corporation                                   */
3810 /*                                                                        */
3811 /*  DESCRIPTION                                                           */
3812 /*                                                                        */
3813 /*    This function checks for errors in the DHCP stop function call.     */
3814 /*                                                                        */
3815 /*  INPUT                                                                 */
3816 /*                                                                        */
3817 /*    dhcp_ptr                              Pointer to DHCP instance      */
3818 /*                                                                        */
3819 /*  OUTPUT                                                                */
3820 /*                                                                        */
3821 /*    status                                Completion status             */
3822 /*    NX_PTR_ERROR                          Invalid pointer input         */
3823 /*                                                                        */
3824 /*  CALLS                                                                 */
3825 /*                                                                        */
3826 /*    _nx_dhcp_stop                         Actual DHCP stop function     */
3827 /*                                                                        */
3828 /*  CALLED BY                                                             */
3829 /*                                                                        */
3830 /*    Application Code                                                    */
3831 /*                                                                        */
3832 /*  RELEASE HISTORY                                                       */
3833 /*                                                                        */
3834 /*    DATE              NAME                      DESCRIPTION             */
3835 /*                                                                        */
3836 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3837 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3838 /*                                            resulting in version 6.1    */
3839 /*                                                                        */
3840 /**************************************************************************/
_nxe_dhcp_stop(NX_DHCP * dhcp_ptr)3841 UINT  _nxe_dhcp_stop(NX_DHCP *dhcp_ptr)
3842 {
3843 
3844 UINT    status;
3845 
3846 
3847     /* Check for invalid input pointer.  */
3848     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
3849         return(NX_PTR_ERROR);
3850 
3851     /* Check for appropriate caller.  */
3852     NX_THREADS_ONLY_CALLER_CHECKING
3853 
3854     /* Call actual DHCP stop service.  */
3855     status =  _nx_dhcp_stop(dhcp_ptr);
3856 
3857     /* Return status.  */
3858     return(status);
3859 }
3860 
3861 
3862 /**************************************************************************/
3863 /*                                                                        */
3864 /*  FUNCTION                                               RELEASE        */
3865 /*                                                                        */
3866 /*    _nx_dhcp_stop                                       PORTABLE C      */
3867 /*                                                           6.1          */
3868 /*  AUTHOR                                                                */
3869 /*                                                                        */
3870 /*    Yuxin Zhou, Microsoft Corporation                                   */
3871 /*                                                                        */
3872 /*  DESCRIPTION                                                           */
3873 /*                                                                        */
3874 /*    This function halts DHCP processing on all interfaces enabled for   */
3875 /*    DHCP.  The Client state is reset to NOT STARTED, and if no          */
3876 /*    interfaces are currently running DHCP, this function suspends the   */
3877 /*    DHCP Client thread, and unbinds the DHCP socket port.               */
3878 /*                                                                        */
3879 /*    To stop DHCP on a specific interface when multiple interfaces are   */
3880 /*    enabled for DHCP, use the nx_dhcp_interface_stop service.           */
3881 /*                                                                        */
3882 /*    To restart DHCP Client on a stopped interface, the interface must   */
3883 /*    be reinitialized using either nx_dhcp_reinitialize() to reinitialize*/
3884 /*    all enabled DHCP interfaces, or nx_dhcp_interface_reinitialize() for*/
3885 /*    a specific interface.                                               */
3886 /*                                                                        */
3887 /*  INPUT                                                                 */
3888 /*                                                                        */
3889 /*    dhcp_ptr                              Pointer to DHCP instance      */
3890 /*                                                                        */
3891 /*  OUTPUT                                                                */
3892 /*                                                                        */
3893 /*    NX_SUCCESS                            Completion status             */
3894 /*                                                                        */
3895 /*  CALLS                                                                 */
3896 /*                                                                        */
3897 /*    _nx_dhcp_interface_stop               Interface specific DHCP stop  */
3898 /*    tx_mutex_get                          Obtain protection mutex       */
3899 /*    tx_mutex_put                          Release protection mutex      */
3900 /*                                                                        */
3901 /*  CALLED BY                                                             */
3902 /*                                                                        */
3903 /*    Application Code                                                    */
3904 /*                                                                        */
3905 /*  RELEASE HISTORY                                                       */
3906 /*                                                                        */
3907 /*    DATE              NAME                      DESCRIPTION             */
3908 /*                                                                        */
3909 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3910 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3911 /*                                            resulting in version 6.1    */
3912 /*                                                                        */
3913 /**************************************************************************/
_nx_dhcp_stop(NX_DHCP * dhcp_ptr)3914 UINT  _nx_dhcp_stop(NX_DHCP *dhcp_ptr)
3915 {
3916 
3917 UINT i;
3918 
3919 
3920     /* Get the DHCP mutex.  */
3921     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
3922 
3923     /* Check all interfaces to find out which need to stop the DHCP protocol.  */
3924     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
3925     {
3926 
3927         /* Check if this record is valid.  */
3928         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
3929             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state != NX_DHCP_STATE_NOT_STARTED))
3930         {
3931 
3932             /* Stop DHCP.  */
3933             _nx_dhcp_interface_stop(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index);
3934        }
3935     }
3936 
3937     /* Stop DHCP Thread. */
3938     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread));
3939 
3940     /* Deactivate DHCP Timer.  */
3941     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer));
3942 
3943     /* Ubind UDP socket.  */
3944     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
3945 
3946     /* Release the DHCP mutex.  */
3947     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3948     return(NX_SUCCESS);
3949 }
3950 
3951 
3952 /**************************************************************************/
3953 /*                                                                        */
3954 /*  FUNCTION                                               RELEASE        */
3955 /*                                                                        */
3956 /*    _nxe_dhcp_interface_stop                           PORTABLE C       */
3957 /*                                                           6.1          */
3958 /*  AUTHOR                                                                */
3959 /*                                                                        */
3960 /*    Yuxin Zhou, Microsoft Corporation                                   */
3961 /*                                                                        */
3962 /*  DESCRIPTION                                                           */
3963 /*                                                                        */
3964 /*    This function performs error checking for the interface specific    */
3965 /*    DHCP stop service.                                                  */
3966 /*                                                                        */
3967 /*  INPUT                                                                 */
3968 /*                                                                        */
3969 /*    dhcp_ptr                              Pointer to DHCP instance      */
3970 /*    iface_index                           Interface to stop DHCP        */
3971 /*                                                                        */
3972 /*  OUTPUT                                                                */
3973 /*                                                                        */
3974 /*    status                                Completion status             */
3975 /*    NX_PTR_ERROR                          Invalid pointer input         */
3976 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
3977 /*                                                                        */
3978 /*  CALLS                                                                 */
3979 /*                                                                        */
3980 /*    _nx_dhcp_interface_stop               Actual interface stop service */
3981 /*                                                                        */
3982 /*  CALLED BY                                                             */
3983 /*                                                                        */
3984 /*    Application Code                                                    */
3985 /*                                                                        */
3986 /*  RELEASE HISTORY                                                       */
3987 /*                                                                        */
3988 /*    DATE              NAME                      DESCRIPTION             */
3989 /*                                                                        */
3990 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3991 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3992 /*                                            resulting in version 6.1    */
3993 /*                                                                        */
3994 /**************************************************************************/
_nxe_dhcp_interface_stop(NX_DHCP * dhcp_ptr,UINT iface_index)3995 UINT  _nxe_dhcp_interface_stop(NX_DHCP *dhcp_ptr, UINT iface_index)
3996 {
3997 
3998 UINT status;
3999 
4000     if (dhcp_ptr == NX_NULL)
4001     {
4002         return NX_PTR_ERROR;
4003     }
4004 
4005     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
4006     {
4007         return NX_INVALID_INTERFACE;
4008     }
4009 
4010     /* Check for appropriate caller.  */
4011     NX_THREADS_ONLY_CALLER_CHECKING
4012 
4013     status =  _nx_dhcp_interface_stop(dhcp_ptr, iface_index);
4014 
4015     return status;
4016 }
4017 
4018 
4019 /**************************************************************************/
4020 /*                                                                        */
4021 /*  FUNCTION                                               RELEASE        */
4022 /*                                                                        */
4023 /*    _nx_dhcp_interface_stop                             PORTABLE C      */
4024 /*                                                           6.1.12       */
4025 /*  AUTHOR                                                                */
4026 /*                                                                        */
4027 /*    Yuxin Zhou, Microsoft Corporation                                   */
4028 /*                                                                        */
4029 /*  DESCRIPTION                                                           */
4030 /*                                                                        */
4031 /*    This function stops DHCP processing on the specified interface. It  */
4032 /*    sets the DHCP state to the unstarted status. If any state changes   */
4033 /*    occurred it calls the record state change callback.                 */
4034 /*                                                                        */
4035 /*    If DHCP is not started on any of the DHCP Client interfaces, this   */
4036 /*    function will suspend the thread, unbind the socket and stop the    */
4037 /*    timer.                                                              */
4038 /*                                                                        */
4039 /*    Note: before DHCP Client can be restarted on the interface, the     */
4040 /*    DHCP Client must be reinitialized by calling                        */
4041 /*    nx_dhcp_interface_reinitialize().                                   */
4042 /*                                                                        */
4043 /*  INPUT                                                                 */
4044 /*                                                                        */
4045 /*    dhcp_ptr                              Pointer to DHCP instance      */
4046 /*    iface_index                           Interface to stop DHCP on     */
4047 /*                                                                        */
4048 /*  OUTPUT                                                                */
4049 /*                                                                        */
4050 /*    status                                Completion status             */
4051 /*                                                                        */
4052 /*  CALLS                                                                 */
4053 /*                                                                        */
4054 /*    _nx_dhcp_interface_record_find        Find record assigned to  the  */
4055 /*                                            input interface             */
4056 /*    tx_mutex_get                          Get the DHCP mutex            */
4057 /*    tx_mutex_put                          Release the DHCP mutex        */
4058 /*                                                                        */
4059 /*  CALLED BY                                                             */
4060 /*                                                                        */
4061 /*    Application Code                                                    */
4062 /*                                                                        */
4063 /*  RELEASE HISTORY                                                       */
4064 /*                                                                        */
4065 /*    DATE              NAME                      DESCRIPTION             */
4066 /*                                                                        */
4067 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4068 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4069 /*                                            resulting in version 6.1    */
4070 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
4071 /*                                            improved internal logic,    */
4072 /*                                            resulting in version 6.1.12 */
4073 /*                                                                        */
4074 /**************************************************************************/
_nx_dhcp_interface_stop(NX_DHCP * dhcp_ptr,UINT iface_index)4075 UINT _nx_dhcp_interface_stop(NX_DHCP *dhcp_ptr, UINT iface_index)
4076 {
4077 
4078 UINT                     i;
4079 UINT                     status;
4080 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
4081 
4082 
4083     /* Obtain the DHCP mutex.  */
4084     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
4085 
4086     /* Find the interface record.  */
4087     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
4088 
4089     /* Check status.  */
4090     if (status)
4091     {
4092 
4093         /* Not found. Release the DHCP mutex.  */
4094         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4095         return(status);
4096     }
4097 
4098     /* Determine if DHCP is started.  */
4099     if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_NOT_STARTED)
4100     {
4101 
4102         /* Release the DHCP mutex.  */
4103         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4104 
4105         /* DHCP is not started so it can't be stopped.  */
4106         return(NX_DHCP_NOT_STARTED);
4107     }
4108 
4109     /* Set the state to NX_DHCP_STATE_NOT_STARTED.  */
4110     interface_record -> nx_dhcp_state = NX_DHCP_STATE_NOT_STARTED;
4111 
4112     /* Determine if the application has specified a routine for DHCP state change notification.  */
4113     if (dhcp_ptr -> nx_dhcp_state_change_callback)
4114     {
4115 
4116         /* Yes, call the application's state change notify function with the new state.  */
4117         (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
4118     }
4119 
4120     /* Determine if the application has specified a routine for DHCP interface state change notification.  */
4121     if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
4122     {
4123 
4124         /* Yes, call the application's state change notify function with the new state.  */
4125         (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record->nx_dhcp_state);
4126     }
4127 
4128     /* Check if other interfaces are running DHCP.  */
4129     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
4130     {
4131 
4132         /* Check which interface record is valid.  */
4133         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
4134             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state != NX_DHCP_STATE_NOT_STARTED))
4135         {
4136 
4137             /* Yes, other interfaces have started DHCP. We can assume Netx and ThreadX
4138                resources need to stay activated. */
4139 
4140             /* Release the DHCP mutex.  */
4141             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4142             return(NX_SUCCESS);
4143         }
4144     }
4145 
4146     /* Yes, stop DHCP Thread. */
4147     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread));
4148 
4149     /* Deactivate DHCP Timer.  */
4150     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer));
4151 
4152     /* Unbind UDP socket.  */
4153     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
4154 
4155     /* Release the DHCP mutex.  */
4156     tx_mutex_put(&(dhcp_ptr->nx_dhcp_mutex));
4157     return(NX_SUCCESS);
4158 
4159 }
4160 
4161 
4162 /**************************************************************************/
4163 /*                                                                        */
4164 /*  FUNCTION                                               RELEASE        */
4165 /*                                                                        */
4166 /*    _nxe_dhcp_user_option_retrieve                      PORTABLE C      */
4167 /*                                                           6.1          */
4168 /*  AUTHOR                                                                */
4169 /*                                                                        */
4170 /*    Yuxin Zhou, Microsoft Corporation                                   */
4171 /*                                                                        */
4172 /*  DESCRIPTION                                                           */
4173 /*                                                                        */
4174 /*    This function checks for errors in the DHCP user option function    */
4175 /*    call.                                                               */
4176 /*                                                                        */
4177 /*  INPUT                                                                 */
4178 /*                                                                        */
4179 /*    dhcp_ptr                              Pointer to DHCP instance      */
4180 /*    option_request                        Option request                */
4181 /*    destination_ptr                       Pointer to return buffer      */
4182 /*    destination_size                      Size of return buffer (and    */
4183 /*                                            modified to reflect how     */
4184 /*                                            much information is in the  */
4185 /*                                            response)                   */
4186 /*                                                                        */
4187 /*  OUTPUT                                                                */
4188 /*                                                                        */
4189 /*    status                                Completion status             */
4190 /*    NX_PTR_ERROR                          Invalid pointer input         */
4191 /*                                                                        */
4192 /*  CALLS                                                                 */
4193 /*                                                                        */
4194 /*    _nx_dhcp_user_option_request          Actual DHCP user option       */
4195 /*                                            function call               */
4196 /*                                                                        */
4197 /*  CALLED BY                                                             */
4198 /*                                                                        */
4199 /*    Application Code                                                    */
4200 /*                                                                        */
4201 /*  RELEASE HISTORY                                                       */
4202 /*                                                                        */
4203 /*    DATE              NAME                      DESCRIPTION             */
4204 /*                                                                        */
4205 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4206 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4207 /*                                            resulting in version 6.1    */
4208 /*                                                                        */
4209 /**************************************************************************/
_nxe_dhcp_user_option_retrieve(NX_DHCP * dhcp_ptr,UINT option_request,UCHAR * destination_ptr,UINT * destination_size)4210 UINT  _nxe_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT option_request, UCHAR *destination_ptr, UINT *destination_size)
4211 {
4212 
4213 UINT    status;
4214 
4215 
4216     /* Check for invalid input pointer.  */
4217     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID) ||
4218         (destination_ptr == NX_NULL) || (destination_size == NX_NULL))
4219         return(NX_PTR_ERROR);
4220 
4221     /* Check for appropriate caller.  */
4222     NX_THREADS_ONLY_CALLER_CHECKING
4223 
4224     /* Call actual DHCP user option request service.  */
4225     status =  _nx_dhcp_user_option_retrieve(dhcp_ptr, option_request, destination_ptr, destination_size);
4226 
4227     /* Return status.  */
4228     return(status);
4229 }
4230 
4231 
4232 /**************************************************************************/
4233 /*                                                                        */
4234 /*  FUNCTION                                               RELEASE        */
4235 /*                                                                        */
4236 /*    _nx_dhcp_user_option_retrieve                       PORTABLE C      */
4237 /*                                                           6.1          */
4238 /*  AUTHOR                                                                */
4239 /*                                                                        */
4240 /*    Yuxin Zhou, Microsoft Corporation                                   */
4241 /*                                                                        */
4242 /*  DESCRIPTION                                                           */
4243 /*                                                                        */
4244 /*    This function searches the DHCP options buffer to obtain the        */
4245 /*    specified option. If successful, the option is placed in the        */
4246 /*    supplied destination string.                                        */
4247 /*                                                                        */
4248 /*  INPUT                                                                 */
4249 /*                                                                        */
4250 /*    dhcp_ptr                              Pointer to DHCP instance      */
4251 /*    option_request                        Option request                */
4252 /*    destination_ptr                       Pointer to return buffer      */
4253 /*    destination_size                      Size of return buffer (and    */
4254 /*                                            modified to reflect how     */
4255 /*                                            much information is in the  */
4256 /*                                            response)                   */
4257 /*                                                                        */
4258 /*  OUTPUT                                                                */
4259 /*                                                                        */
4260 /*    status                                Completion status             */
4261 /*    NX_DHCP_NO_INTERFACES_ENABLED         No DHCP interfaces enabled    */
4262 /*                                                                        */
4263 /*  CALLS                                                                 */
4264 /*                                                                        */
4265 /*    _nx_dhcp_interface_user_option_retrieve                             */
4266 /*                                          Search DHCP interface options */
4267 /*    tx_mutex_get                          Get the DHCP mutex            */
4268 /*    tx_mutex_put                          Release the DHCP mutex        */
4269 /*                                                                        */
4270 /*  CALLED BY                                                             */
4271 /*                                                                        */
4272 /*    Application Code                                                    */
4273 /*                                                                        */
4274 /*  RELEASE HISTORY                                                       */
4275 /*                                                                        */
4276 /*    DATE              NAME                      DESCRIPTION             */
4277 /*                                                                        */
4278 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4279 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4280 /*                                            resulting in version 6.1    */
4281 /*                                                                        */
4282 /**************************************************************************/
_nx_dhcp_user_option_retrieve(NX_DHCP * dhcp_ptr,UINT option_request,UCHAR * destination_ptr,UINT * destination_size)4283 UINT  _nx_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT option_request, UCHAR *destination_ptr, UINT *destination_size)
4284 {
4285 
4286 UINT    i;
4287 UINT    status;
4288 
4289     /* Obtain the DHCP mutex.  */
4290     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
4291 
4292     /* Find the DHCP interface record.  */
4293     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
4294     {
4295 
4296         /* Check which interface record is valid.  */
4297         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
4298             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
4299         {
4300 
4301             /* Retrieve the user option.  */
4302             status = _nx_dhcp_interface_user_option_retrieve(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index,
4303                                                              option_request, destination_ptr, destination_size);
4304 
4305             /* Release the DHCP mutex.  */
4306             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4307             return(status);
4308         }
4309     }
4310 
4311     /* Release the DHCP mutex.  */
4312     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4313     return(NX_DHCP_NO_INTERFACES_ENABLED);
4314 }
4315 
4316 
4317 /**************************************************************************/
4318 /*                                                                        */
4319 /*  FUNCTION                                               RELEASE        */
4320 /*                                                                        */
4321 /*    _nxe_dhcp_user_option_request                       PORTABLE C      */
4322 /*                                                           6.1.8        */
4323 /*  AUTHOR                                                                */
4324 /*                                                                        */
4325 /*    Yuxin Zhou, Microsoft Corporation                                   */
4326 /*                                                                        */
4327 /*  DESCRIPTION                                                           */
4328 /*                                                                        */
4329 /*    This function checks for errors in the DHCP user option function    */
4330 /*    call.                                                               */
4331 /*                                                                        */
4332 /*  INPUT                                                                 */
4333 /*                                                                        */
4334 /*    dhcp_ptr                              Pointer to DHCP instance      */
4335 /*    option_code                           Option code                   */
4336 /*                                                                        */
4337 /*  OUTPUT                                                                */
4338 /*                                                                        */
4339 /*    status                                Completion status             */
4340 /*    NX_PTR_ERROR                          Invalid pointer input         */
4341 /*                                                                        */
4342 /*  CALLS                                                                 */
4343 /*                                                                        */
4344 /*    _nx_dhcp_user_option_request          Actual DHCP user option       */
4345 /*                                            request function call       */
4346 /*                                                                        */
4347 /*  CALLED BY                                                             */
4348 /*                                                                        */
4349 /*    Application Code                                                    */
4350 /*                                                                        */
4351 /*  RELEASE HISTORY                                                       */
4352 /*                                                                        */
4353 /*    DATE              NAME                      DESCRIPTION             */
4354 /*                                                                        */
4355 /*  08-02-2021     Yuxin Zhou               Initial Version 6.1.8         */
4356 /*                                                                        */
4357 /**************************************************************************/
_nxe_dhcp_user_option_request(NX_DHCP * dhcp_ptr,UINT option_code)4358 UINT  _nxe_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code)
4359 {
4360 
4361 UINT    status;
4362 
4363 
4364     /* Check for invalid input pointer.  */
4365     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
4366         return(NX_PTR_ERROR);
4367 
4368     /* Check for appropriate caller.  */
4369     NX_THREADS_ONLY_CALLER_CHECKING
4370 
4371     /* Call actual DHCP interface user option request service.  */
4372     status =  _nx_dhcp_user_option_request(dhcp_ptr, option_code);
4373 
4374     /* Return status.  */
4375     return(status);
4376 }
4377 
4378 
4379 /**************************************************************************/
4380 /*                                                                        */
4381 /*  FUNCTION                                               RELEASE        */
4382 /*                                                                        */
4383 /*    _nx_dhcp_user_option_request                        PORTABLE C      */
4384 /*                                                           6.1.8        */
4385 /*  AUTHOR                                                                */
4386 /*                                                                        */
4387 /*    Yuxin Zhou, Microsoft Corporation                                   */
4388 /*                                                                        */
4389 /*  DESCRIPTION                                                           */
4390 /*                                                                        */
4391 /*    This function requests the additional user option.                  */
4392 /*                                                                        */
4393 /*  INPUT                                                                 */
4394 /*                                                                        */
4395 /*    dhcp_ptr                              Pointer to DHCP instance      */
4396 /*    option_code                           Option code                   */
4397 /*                                                                        */
4398 /*  OUTPUT                                                                */
4399 /*                                                                        */
4400 /*    status                                Completion status             */
4401 /*                                                                        */
4402 /*  CALLS                                                                 */
4403 /*                                                                        */
4404 /*    tx_mutex_get                          Get the DHCP mutex            */
4405 /*    tx_mutex_put                          Release the DHCP mutex        */
4406 /*                                                                        */
4407 /*  CALLED BY                                                             */
4408 /*                                                                        */
4409 /*    Application Code                                                    */
4410 /*                                                                        */
4411 /*  RELEASE HISTORY                                                       */
4412 /*                                                                        */
4413 /*    DATE              NAME                      DESCRIPTION             */
4414 /*                                                                        */
4415 /*  08-02-2021     Yuxin Zhou               Initial Version 6.1.8         */
4416 /*                                                                        */
4417 /**************************************************************************/
_nx_dhcp_user_option_request(NX_DHCP * dhcp_ptr,UINT option_code)4418 UINT  _nx_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code)
4419 {
4420 UINT i;
4421 
4422 
4423     /* Obtain DHCP Client protection mutex. */
4424     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
4425 
4426     /* Check if the default option array already has it.  */
4427     for (i = 0; i < NX_DHCP_REQUEST_PARAMETER_SIZE; i++)
4428     {
4429         if (_nx_dhcp_request_parameters[i] == option_code)
4430         {
4431             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4432             return(NX_DUPLICATED_ENTRY);
4433         }
4434     }
4435 
4436     /* Check if the user option array already has it.  */
4437     for (i = 0; i < dhcp_ptr -> nx_dhcp_user_request_parameter_size; i++)
4438     {
4439         if (dhcp_ptr -> nx_dhcp_user_request_parameter[i] == option_code)
4440         {
4441             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4442             return(NX_DUPLICATED_ENTRY);
4443         }
4444     }
4445 
4446     /* Check if there is space to add option.  */
4447     if (dhcp_ptr -> nx_dhcp_user_request_parameter_size >= NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER)
4448     {
4449         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4450         return(NX_NO_MORE_ENTRIES);
4451     }
4452 
4453     /* Add the option.  */
4454     dhcp_ptr -> nx_dhcp_user_request_parameter[dhcp_ptr -> nx_dhcp_user_request_parameter_size++] = (UCHAR)option_code;
4455 
4456     /* Release the DHCP mutex.  */
4457     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4458 
4459     /* Return success.  */
4460     return(NX_SUCCESS);
4461 }
4462 
4463 
4464 /**************************************************************************/
4465 /*                                                                        */
4466 /*  FUNCTION                                               RELEASE        */
4467 /*                                                                        */
4468 /*    _nxe_dhcp_interface_user_option_retrieve            PORTABLE C      */
4469 /*                                                           6.1          */
4470 /*  AUTHOR                                                                */
4471 /*                                                                        */
4472 /*    Yuxin Zhou, Microsoft Corporation                                   */
4473 /*                                                                        */
4474 /*  DESCRIPTION                                                           */
4475 /*                                                                        */
4476 /*    This function checks for errors in the DHCP user option function    */
4477 /*    call.                                                               */
4478 /*                                                                        */
4479 /*  INPUT                                                                 */
4480 /*                                                                        */
4481 /*    dhcp_ptr                              Pointer to DHCP instance      */
4482 /*    iface_index                           Interface index               */
4483 /*    option_request                        Option request                */
4484 /*    destination_ptr                       Pointer to return buffer      */
4485 /*    destination_size                      Size of return buffer (and    */
4486 /*                                            modified to reflect how     */
4487 /*                                            much information is in the  */
4488 /*                                            response)                   */
4489 /*                                                                        */
4490 /*  OUTPUT                                                                */
4491 /*                                                                        */
4492 /*    status                                Completion status             */
4493 /*    NX_PTR_ERROR                          Invalid pointer input         */
4494 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
4495 /*                                                                        */
4496 /*  CALLS                                                                 */
4497 /*                                                                        */
4498 /*    _nx_dhcp_user_option_request          Actual DHCP user option       */
4499 /*                                            function call               */
4500 /*                                                                        */
4501 /*  CALLED BY                                                             */
4502 /*                                                                        */
4503 /*    Application Code                                                    */
4504 /*                                                                        */
4505 /*  RELEASE HISTORY                                                       */
4506 /*                                                                        */
4507 /*    DATE              NAME                      DESCRIPTION             */
4508 /*                                                                        */
4509 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4510 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4511 /*                                            resulting in version 6.1    */
4512 /*                                                                        */
4513 /**************************************************************************/
_nxe_dhcp_interface_user_option_retrieve(NX_DHCP * dhcp_ptr,UINT iface_index,UINT option_request,UCHAR * destination_ptr,UINT * destination_size)4514 UINT  _nxe_dhcp_interface_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT iface_index, UINT option_request, UCHAR *destination_ptr, UINT *destination_size)
4515 {
4516 
4517 UINT    status;
4518 
4519 
4520     /* Check for invalid input pointer.  */
4521     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID) ||
4522         (destination_ptr == NX_NULL) || (destination_size == NX_NULL))
4523         return(NX_PTR_ERROR);
4524 
4525     /* Check interface index.  */
4526     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
4527     {
4528         return(NX_INVALID_INTERFACE);
4529     }
4530 
4531     /* Check for appropriate caller.  */
4532     NX_THREADS_ONLY_CALLER_CHECKING
4533 
4534     /* Call actual DHCP interface user option request service.  */
4535     status =  _nx_dhcp_interface_user_option_retrieve(dhcp_ptr, iface_index, option_request, destination_ptr, destination_size);
4536 
4537     /* Return status.  */
4538     return(status);
4539 }
4540 
4541 
4542 /**************************************************************************/
4543 /*                                                                        */
4544 /*  FUNCTION                                               RELEASE        */
4545 /*                                                                        */
4546 /*    _nx_dhcp_interface_user_option_retrieve             PORTABLE C      */
4547 /*                                                           6.1          */
4548 /*  AUTHOR                                                                */
4549 /*                                                                        */
4550 /*    Yuxin Zhou, Microsoft Corporation                                   */
4551 /*                                                                        */
4552 /*  DESCRIPTION                                                           */
4553 /*                                                                        */
4554 /*    This function searches the DHCP options buffer to obtain the        */
4555 /*    specified option. If successful, the option is placed in the        */
4556 /*    supplied destination string.                                        */
4557 /*                                                                        */
4558 /*  INPUT                                                                 */
4559 /*                                                                        */
4560 /*    dhcp_ptr                              Pointer to DHCP instance      */
4561 /*    iface_index                           Interface index               */
4562 /*    option_request                        Option request                */
4563 /*    destination_ptr                       Pointer to return buffer      */
4564 /*    destination_size                      Size of return buffer (and    */
4565 /*                                            modified to reflect how     */
4566 /*                                            much information is in the  */
4567 /*                                            response)                   */
4568 /*    memcpy                                Copy specified area of memory */
4569 /*                                                                        */
4570 /*  OUTPUT                                                                */
4571 /*                                                                        */
4572 /*    destination_size                      Size of returned option       */
4573 /*    status                                Completion status             */
4574 /*                                                                        */
4575 /*  CALLS                                                                 */
4576 /*                                                                        */
4577 /*    _nx_dhcp_search_buffer                Search the buffer             */
4578 /*    _nx_dhcp_interface_record_find        Find record of input interface*/
4579 /*    tx_mutex_get                          Get the DHCP mutex            */
4580 /*    tx_mutex_put                          Release the DHCP mutex        */
4581 /*                                                                        */
4582 /*  CALLED BY                                                             */
4583 /*                                                                        */
4584 /*    Application Code                                                    */
4585 /*                                                                        */
4586 /*  RELEASE HISTORY                                                       */
4587 /*                                                                        */
4588 /*    DATE              NAME                      DESCRIPTION             */
4589 /*                                                                        */
4590 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4591 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
4592 /*                                            buffer length verification, */
4593 /*                                            verified memcpy use cases,  */
4594 /*                                            resulting in version 6.1    */
4595 /*                                                                        */
4596 /**************************************************************************/
_nx_dhcp_interface_user_option_retrieve(NX_DHCP * dhcp_ptr,UINT iface_index,UINT option_request,UCHAR * destination_ptr,UINT * destination_size)4597 UINT  _nx_dhcp_interface_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT iface_index, UINT option_request, UCHAR *destination_ptr, UINT *destination_size)
4598 {
4599 
4600 UCHAR                    *buffer_ptr;
4601 UINT                      size;
4602 UINT                      status;
4603 UINT                      i;
4604 ULONG                    *long_ptr;
4605 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
4606 
4607 
4608     /* Obtain DHCP Client protection mutex. */
4609     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
4610 
4611     /* Find the interface record.  */
4612     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
4613 
4614     /* Check status.  */
4615     if (status)
4616     {
4617 
4618         /* Release the mutex.  */
4619         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4620         return(status);
4621     }
4622 
4623     /* Check state.  */
4624     if (interface_record -> nx_dhcp_state < NX_DHCP_STATE_BOUND)
4625     {
4626 
4627         /* Release the DHCP mutex.  */
4628         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4629 
4630         /* Return an error.  */
4631         return(NX_DHCP_NOT_BOUND);
4632     }
4633 
4634     /* Setup a pointer to the previous buffer.  */
4635     buffer_ptr =  _nx_dhcp_search_buffer(interface_record -> nx_dhcp_options_buffer,
4636                                          option_request, interface_record -> nx_dhcp_options_size);
4637 
4638     /* Determine if the option was found.  */
4639     if (!buffer_ptr)
4640     {
4641 
4642         /* Release the DHCP mutex.  */
4643         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4644 
4645         /* Return an error.  */
4646         return(NX_DHCP_PARSE_ERROR);
4647     }
4648 
4649     /* Calculate the size of the option.  */
4650     size =  (UINT) *buffer_ptr;
4651 
4652     /* Determine if the destination is large enough.  */
4653     if (size > *destination_size)
4654     {
4655 
4656         /* Release the DHCP mutex.  */
4657         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4658 
4659         /* Server did not respond.  */
4660         return(NX_DHCP_DEST_TO_SMALL);
4661     }
4662 
4663     /* Skip the option size field.  */
4664     buffer_ptr++;
4665 
4666     /* Check to see which option data is requested: */
4667     switch (option_request)
4668     {
4669         case NX_DHCP_OPTION_SUBNET_MASK:
4670         case NX_DHCP_OPTION_TIME_OFFSET:
4671         case NX_DHCP_OPTION_GATEWAYS:
4672         case NX_DHCP_OPTION_TIMESVR:
4673         case NX_DHCP_OPTION_DNS_SVR:
4674         case NX_DHCP_OPTION_NTP_SVR:
4675         case NX_DHCP_OPTION_DHCP_LEASE:
4676         case NX_DHCP_OPTION_DHCP_SERVER:
4677         case NX_DHCP_OPTION_RENEWAL:
4678         case NX_DHCP_OPTION_REBIND:
4679         {
4680 
4681             /* The length of these options must always be a multiple of 4 octets.  */
4682             /* Store the value as host byte order.  */
4683             long_ptr = (ULONG *) destination_ptr;
4684 
4685             /* Loop to set the long value.  */
4686             for (i = 0; i + 4 <= size;)
4687             {
4688 
4689                 /* Set the long value.  */
4690                 *long_ptr = _nx_dhcp_get_data(buffer_ptr + i, 4);
4691 
4692                 /* Update the pointer.  */
4693                 long_ptr ++;
4694                 i += 4;
4695             }
4696             break;
4697         }
4698         default:
4699         {
4700 
4701             /* Directly copy the data into destination buffer.  */
4702             memcpy(destination_ptr, buffer_ptr, size); /* Use case of memcpy is verified. */
4703             break;
4704         }
4705     }
4706 
4707     /* Return the actual option size.  */
4708     *destination_size =  size;
4709 
4710     /* Release the DHCP mutex.  */
4711     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4712 
4713     /* Return success.  */
4714     return(NX_SUCCESS);
4715 }
4716 
4717 
4718 /**************************************************************************/
4719 /*                                                                        */
4720 /*  FUNCTION                                               RELEASE        */
4721 /*                                                                        */
4722 /*    _nxe_dhcp_user_option_convert                        PORTABLE C     */
4723 /*                                                           6.1          */
4724 /*  AUTHOR                                                                */
4725 /*                                                                        */
4726 /*    Yuxin Zhou, Microsoft Corporation                                   */
4727 /*                                                                        */
4728 /*  DESCRIPTION                                                           */
4729 /*                                                                        */
4730 /*    This function performs error checking on the option convert service.*/
4731 /*                                                                        */
4732 /*  INPUT                                                                 */
4733 /*                                                                        */
4734 /*    source_ptr                            Source of string area         */
4735 /*                                                                        */
4736 /*  OUTPUT                                                                */
4737 /*                                                                        */
4738 /*    value                                 Pointer to conversion value   */
4739 /*    NULL                                  Invalid pointer input         */
4740 /*                                                                        */
4741 /*  CALLS                                                                 */
4742 /*                                                                        */
4743 /*    _nx_dhcp_user_option_convert         Actual option convert service  */
4744 /*                                                                        */
4745 /*  CALLED BY                                                             */
4746 /*                                                                        */
4747 /*    Application Code                                                    */
4748 /*                                                                        */
4749 /*  RELEASE HISTORY                                                       */
4750 /*                                                                        */
4751 /*    DATE              NAME                      DESCRIPTION             */
4752 /*                                                                        */
4753 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4754 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4755 /*                                            resulting in version 6.1    */
4756 /*                                                                        */
4757 /**************************************************************************/
_nxe_dhcp_user_option_convert(UCHAR * source_ptr)4758 ULONG  _nxe_dhcp_user_option_convert(UCHAR *source_ptr)
4759 {
4760 
4761 ULONG   temp;
4762 
4763     /* Check for invalid input. */
4764     if (source_ptr == NX_NULL)
4765     {
4766         return NX_NULL;
4767     }
4768 
4769     /* Pickup the ULONG.  */
4770     temp =  _nx_dhcp_user_option_convert(source_ptr);
4771 
4772     /* Return the ULONG.  */
4773     return(temp);
4774 }
4775 
4776 
4777 /**************************************************************************/
4778 /*                                                                        */
4779 /*  FUNCTION                                               RELEASE        */
4780 /*                                                                        */
4781 /*    _nx_dhcp_user_option_convert                        PORTABLE C      */
4782 /*                                                           6.1          */
4783 /*  AUTHOR                                                                */
4784 /*                                                                        */
4785 /*    Yuxin Zhou, Microsoft Corporation                                   */
4786 /*                                                                        */
4787 /*  DESCRIPTION                                                           */
4788 /*                                                                        */
4789 /*    This function converts the four bytes pointed to by the input       */
4790 /*    string pointer to an ULONG and returns the value.                   */
4791 /*                                                                        */
4792 /*  INPUT                                                                 */
4793 /*                                                                        */
4794 /*    source_ptr                            Source of string area         */
4795 /*                                                                        */
4796 /*  OUTPUT                                                                */
4797 /*                                                                        */
4798 /*    value                                 Pointer to conversion value   */
4799 /*                                                                        */
4800 /*  CALLS                                                                 */
4801 /*                                                                        */
4802 /*    None                                                                */
4803 /*                                                                        */
4804 /*  CALLED BY                                                             */
4805 /*                                                                        */
4806 /*    Application Code                                                    */
4807 /*                                                                        */
4808 /*  RELEASE HISTORY                                                       */
4809 /*                                                                        */
4810 /*    DATE              NAME                      DESCRIPTION             */
4811 /*                                                                        */
4812 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4813 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4814 /*                                            resulting in version 6.1    */
4815 /*                                                                        */
4816 /**************************************************************************/
_nx_dhcp_user_option_convert(UCHAR * source_ptr)4817 ULONG  _nx_dhcp_user_option_convert(UCHAR *source_ptr)
4818 {
4819 
4820 ULONG   temp;
4821 
4822 
4823     /* Pickup the ULONG.  */
4824     temp =  (((ULONG) *(source_ptr))   << 24) |
4825             (((ULONG) *(source_ptr+1)) << 16) |
4826             (((ULONG) *(source_ptr+2)) << 8)  |
4827              ((ULONG) *(source_ptr+3));
4828 
4829     /* Return the ULONG.  */
4830     return(temp);
4831 }
4832 
4833 
4834 /**************************************************************************/
4835 /*                                                                        */
4836 /*  FUNCTION                                               RELEASE        */
4837 /*                                                                        */
4838 /*    _nxe_dhcp_user_option_add_callback_set               PORTABLE C     */
4839 /*                                                           6.1          */
4840 /*  AUTHOR                                                                */
4841 /*                                                                        */
4842 /*    Yuxin Zhou, Microsoft Corporation                                   */
4843 /*                                                                        */
4844 /*  DESCRIPTION                                                           */
4845 /*                                                                        */
4846 /*    This function performs error checking on the user option add        */
4847 /*    callback set service.                                               */
4848 /*                                                                        */
4849 /*  INPUT                                                                 */
4850 /*                                                                        */
4851 /*    dhcp_ptr                              Pointer to DHCP instance      */
4852 /*    dhcp_user_option_add                  Pointer to application's      */
4853 /*                                            option add function         */
4854 /*                                                                        */
4855 /*  OUTPUT                                                                */
4856 /*                                                                        */
4857 /*    status                                Completion status             */
4858 /*                                                                        */
4859 /*  CALLS                                                                 */
4860 /*                                                                        */
4861 /*    _nx_dhcp_user_option_add_callback_set Actual user option callback   */
4862 /*                                            set service                 */
4863 /*                                                                        */
4864 /*  CALLED BY                                                             */
4865 /*                                                                        */
4866 /*    Application Code                                                    */
4867 /*                                                                        */
4868 /*  RELEASE HISTORY                                                       */
4869 /*                                                                        */
4870 /*    DATE              NAME                      DESCRIPTION             */
4871 /*                                                                        */
4872 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4873 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4874 /*                                            resulting in version 6.1    */
4875 /*                                                                        */
4876 /**************************************************************************/
_nxe_dhcp_user_option_add_callback_set(NX_DHCP * dhcp_ptr,UINT (* dhcp_user_option_add)(NX_DHCP * dhcp_ptr,UINT iface_index,UINT message_type,UCHAR * user_option_ptr,UINT * user_option_length))4877 UINT  _nxe_dhcp_user_option_add_callback_set(NX_DHCP *dhcp_ptr, UINT (*dhcp_user_option_add)(NX_DHCP *dhcp_ptr, UINT iface_index, UINT message_type,
4878                                                                                              UCHAR *user_option_ptr, UINT *user_option_length))
4879 {
4880 
4881 UINT    status;
4882 
4883     /* Check for invalid input. */
4884     if ((dhcp_ptr == NX_NULL) || (dhcp_user_option_add == NX_NULL))
4885     {
4886         return(NX_PTR_ERROR);
4887     }
4888 
4889     /* Call actual DHCP user option callback set service.  */
4890     status =  _nx_dhcp_user_option_add_callback_set(dhcp_ptr, dhcp_user_option_add);
4891 
4892     /* Return status.  */
4893     return(status);
4894 }
4895 
4896 
4897 /**************************************************************************/
4898 /*                                                                        */
4899 /*  FUNCTION                                               RELEASE        */
4900 /*                                                                        */
4901 /*    _nx_dhcp_user_option_add_callback_set               PORTABLE C      */
4902 /*                                                           6.1          */
4903 /*  AUTHOR                                                                */
4904 /*                                                                        */
4905 /*    Yuxin Zhou, Microsoft Corporation                                   */
4906 /*                                                                        */
4907 /*  DESCRIPTION                                                           */
4908 /*                                                                        */
4909 /*    This function sets the user option add callback.                    */
4910 /*                                                                        */
4911 /*  INPUT                                                                 */
4912 /*                                                                        */
4913 /*    dhcp_ptr                              Pointer to DHCP instance      */
4914 /*    dhcp_user_option_add                  Pointer to application's      */
4915 /*                                            option add function         */
4916 /*                                                                        */
4917 /*  OUTPUT                                                                */
4918 /*                                                                        */
4919 /*    status                                Completion status             */
4920 /*                                                                        */
4921 /*  CALLS                                                                 */
4922 /*                                                                        */
4923 /*    None                                                                */
4924 /*                                                                        */
4925 /*  CALLED BY                                                             */
4926 /*                                                                        */
4927 /*    Application Code                                                    */
4928 /*                                                                        */
4929 /*  RELEASE HISTORY                                                       */
4930 /*                                                                        */
4931 /*    DATE              NAME                      DESCRIPTION             */
4932 /*                                                                        */
4933 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4934 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4935 /*                                            resulting in version 6.1    */
4936 /*                                                                        */
4937 /**************************************************************************/
_nx_dhcp_user_option_add_callback_set(NX_DHCP * dhcp_ptr,UINT (* dhcp_user_option_add)(NX_DHCP * dhcp_ptr,UINT iface_index,UINT message_type,UCHAR * user_option_ptr,UINT * user_option_length))4938 UINT  _nx_dhcp_user_option_add_callback_set(NX_DHCP *dhcp_ptr, UINT (*dhcp_user_option_add)(NX_DHCP *dhcp_ptr, UINT iface_index, UINT message_type,
4939                                                                                              UCHAR *user_option_ptr, UINT *user_option_length))
4940 {
4941 
4942     /* Obtain DHCP Client protection mutex. */
4943     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
4944 
4945     /* Set the callback.  */
4946     dhcp_ptr -> nx_dhcp_user_option_add = dhcp_user_option_add;
4947 
4948     /* Release the mutex.  */
4949     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4950 
4951     /* Return a successful status.  */
4952     return(NX_SUCCESS);
4953 }
4954 
4955 
4956 /**************************************************************************/
4957 /*                                                                        */
4958 /*  FUNCTION                                               RELEASE        */
4959 /*                                                                        */
4960 /*    _nx_dhcp_udp_receive_notify                         PORTABLE C      */
4961 /*                                                           6.1.10       */
4962 /*  AUTHOR                                                                */
4963 /*                                                                        */
4964 /*    Yuxin Zhou, Microsoft Corporation                                   */
4965 /*                                                                        */
4966 /*  DESCRIPTION                                                           */
4967 /*                                                                        */
4968 /*    This function is called when the IP thread task detects a UDP packet*/
4969 /*    has been received on this socket. It allows the DHCP Client to make */
4970 /*    a non blocking nx_udp_socket_receive call.                          */
4971 /*                                                                        */
4972 /*  INPUT                                                                 */
4973 /*                                                                        */
4974 /*    socket_ptr                            Pointer to DHCP socket        */
4975 /*                                                                        */
4976 /*  OUTPUT                                                                */
4977 /*                                                                        */
4978 /*    None                                                                */
4979 /*                                                                        */
4980 /*  CALLS                                                                 */
4981 /*                                                                        */
4982 /*   tx_event_flags_set                    Set event packet is received   */
4983 /*                                                                        */
4984 /*  CALLED BY                                                             */
4985 /*                                                                        */
4986 /*    IP thread task                                                      */
4987 /*                                                                        */
4988 /*  RELEASE HISTORY                                                       */
4989 /*                                                                        */
4990 /*    DATE              NAME                      DESCRIPTION             */
4991 /*                                                                        */
4992 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4993 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4994 /*                                            resulting in version 6.1    */
4995 /*  01-31-2022     Yuxin Zhou               Modified comment(s), supported*/
4996 /*                                            multiple client instances,  */
4997 /*                                            resulting in version 6.1.10 */
4998 /*                                                                        */
4999 /**************************************************************************/
_nx_dhcp_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)5000 VOID _nx_dhcp_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
5001 {
5002 
5003 NX_DHCP *dhcp_ptr;
5004 
5005     dhcp_ptr = (NX_DHCP *)(socket_ptr -> nx_udp_socket_reserved_ptr);
5006 
5007     /* Set the data received event flag.  */
5008     tx_event_flags_set(&(dhcp_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_RECEIVE_EVENT, TX_OR);
5009 }
5010 
5011 
5012 /**************************************************************************/
5013 /*                                                                        */
5014 /*  FUNCTION                                               RELEASE        */
5015 /*                                                                        */
5016 /*    _nx_dhcp_timeout_entry                              PORTABLE C      */
5017 /*                                                           6.1          */
5018 /*  AUTHOR                                                                */
5019 /*                                                                        */
5020 /*    Yuxin Zhou, Microsoft Corporation                                   */
5021 /*                                                                        */
5022 /*  DESCRIPTION                                                           */
5023 /*                                                                        */
5024 /*    This function is called when the DHCP Client timer expires. It      */
5025 /*    loops through all valid interfaces that have started DHCP, and      */
5026 /*    updates their DHCP timeout.  If an interface timeout has expired, it*/
5027 /*    processes that interface depending on which DHCP state it is in.    */
5028 /*                                                                        */
5029 /*  INPUT                                                                 */
5030 /*                                                                        */
5031 /*    dhcp_ptr                              Pointer to DHCP instance      */
5032 /*                                                                        */
5033 /*  OUTPUT                                                                */
5034 /*                                                                        */
5035 /*    None                                                                */
5036 /*                                                                        */
5037 /*  CALLS                                                                 */
5038 /*                                                                        */
5039 /*   tx_event_flags_set                    Set an event that timer expired*/
5040 /*                                                                        */
5041 /*  CALLED BY                                                             */
5042 /*                                                                        */
5043 /*    ThreadX timer                                                       */
5044 /*                                                                        */
5045 /*  RELEASE HISTORY                                                       */
5046 /*                                                                        */
5047 /*    DATE              NAME                      DESCRIPTION             */
5048 /*                                                                        */
5049 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5050 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5051 /*                                            resulting in version 6.1    */
5052 /*                                                                        */
5053 /**************************************************************************/
_nx_dhcp_timeout_entry(ULONG dhcp)5054 VOID _nx_dhcp_timeout_entry(ULONG dhcp)
5055 {
5056 
5057 NX_DHCP     *dhcp_ptr;
5058 
5059 
5060     /* Setup DHCP pointer.  */
5061     NX_TIMER_EXTENSION_PTR_GET(dhcp_ptr, NX_DHCP, dhcp)
5062 
5063     /* Set the data event flag.  */
5064     tx_event_flags_set(&(dhcp_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_TIMER_EVENT, TX_OR);
5065 }
5066 
5067 
5068 
5069 /**************************************************************************/
5070 /*                                                                        */
5071 /*  FUNCTION                                               RELEASE        */
5072 /*                                                                        */
5073 /*    _nx_dhcp_thread_entry                               PORTABLE C      */
5074 /*                                                           6.1          */
5075 /*  AUTHOR                                                                */
5076 /*                                                                        */
5077 /*    Yuxin Zhou, Microsoft Corporation                                   */
5078 /*                                                                        */
5079 /*  DESCRIPTION                                                           */
5080 /*                                                                        */
5081 /*    This function is the processing thread for the DHCP Client.         */
5082 /*    Its processing consists of executing a while-forever loop that      */
5083 /*    checks for events (e.g. packet receive, timer expiration). For      */
5084 /*    received packets, some initial packet validation is done before     */
5085 /*    calling _nx_dhcp_packet_process.                                    */
5086 /*                                                                        */
5087 /*  INPUT                                                                 */
5088 /*                                                                        */
5089 /*    dhcp_instance                         Pointer to DHCP instance      */
5090 /*                                                                        */
5091 /*  OUTPUT                                                                */
5092 /*                                                                        */
5093 /*    status                                Completion status             */
5094 /*                                                                        */
5095 /*  CALLS                                                                 */
5096 /*                                                                        */
5097 /*    tx_event_flags_get                    Check for events              */
5098 /*    _nx_udp_socket_receive                Retrieve packet from socket   */
5099 /*    _nx_dhcp_interface_record_find        Find record of this interface */
5100 /*    tx_mutex_get                          Get the DHCP mutex            */
5101 /*    tx_mutex_put                          Release the DHCP mutex        */
5102 /*    _nx_dhcp_packet_process               Process received packet       */
5103 /*    _nx_dhcp_timout_entry                 Process timer expiration      */
5104 /*                                                                        */
5105 /*  CALLED BY                                                             */
5106 /*                                                                        */
5107 /*    ThreadX                                                             */
5108 /*                                                                        */
5109 /*  RELEASE HISTORY                                                       */
5110 /*                                                                        */
5111 /*    DATE              NAME                      DESCRIPTION             */
5112 /*                                                                        */
5113 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5114 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5115 /*                                            resulting in version 6.1    */
5116 /*                                                                        */
5117 /**************************************************************************/
_nx_dhcp_thread_entry(ULONG dhcp_instance)5118 static VOID  _nx_dhcp_thread_entry(ULONG dhcp_instance)
5119 {
5120 
5121 NX_DHCP                  *dhcp_ptr;
5122 NX_PACKET                *packet_ptr;
5123 ULONG                     events;
5124 UINT                      status;
5125 UINT                      iface_index;
5126 UINT                      source_port;
5127 ULONG                     source_ip_address;
5128 UINT                      protocol;
5129 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
5130 
5131     /* Setup the DHCP pointer.  */
5132     NX_THREAD_EXTENSION_PTR_GET(dhcp_ptr, NX_DHCP, dhcp_instance)
5133 
5134     /* Obtain the DHCP mutex before processing an.  */
5135     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
5136 
5137     /* Enter the DHCP Client task loop.  */
5138     do
5139     {
5140 
5141         /* Release the DHCP mutex.  */
5142         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
5143 
5144         /* Wait for a DHCP client activity.  */
5145         tx_event_flags_get(&(dhcp_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_ALL_EVENTS,
5146                            TX_OR_CLEAR, &events, TX_WAIT_FOREVER);
5147 
5148         /* Obtain the DHCP mutex before processing an.  */
5149         tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
5150 
5151         /* Check for DHCP data received event.  */
5152         if  (events & NX_DHCP_CLIENT_RECEIVE_EVENT)
5153         {
5154 
5155             /* Loop to receive DHCP message.  */
5156             while(1)
5157             {
5158 
5159                 /* Check for an incoming DHCP packet with non blocking option. */
5160                 status = _nx_udp_socket_receive(&dhcp_ptr -> nx_dhcp_socket, &packet_ptr, NX_NO_WAIT);
5161 
5162                 /* Check for packet receive errors. */
5163                 if (status != NX_SUCCESS)
5164                 {
5165                     break;
5166                 }
5167 
5168                 /* Find the source IP address, port, interface this packet is on. */
5169                 status = nx_udp_packet_info_extract(packet_ptr, &source_ip_address, &protocol, &source_port, &iface_index);
5170 
5171                 /* Check status.  */
5172                 if (status != NX_SUCCESS)
5173                 {
5174 
5175                     nx_packet_release(packet_ptr);
5176                     continue;
5177                 }
5178 
5179                 /* Find the interface record.  */
5180                 status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
5181 
5182                 /* Check status.  */
5183                 if (status != NX_SUCCESS)
5184                 {
5185 
5186                     /* Release the original packet . */
5187                     nx_packet_release(packet_ptr);
5188                     continue;
5189                 }
5190 
5191                 /* Process DHCP packet.  */
5192                 _nx_dhcp_packet_process(dhcp_ptr, interface_record, packet_ptr);
5193             }
5194         }
5195 
5196         /* Timer event.  */
5197         if (events & NX_DHCP_CLIENT_TIMER_EVENT)
5198         {
5199             _nx_dhcp_timeout_process(dhcp_ptr);
5200         }
5201 
5202 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5203 
5204         /* IP address conflict event.  */
5205         if (events & NX_DHCP_CLIENT_CONFLICT_EVENT)
5206         {
5207 
5208             /* Loop to check the interface.  */
5209             for (iface_index = 0; iface_index < NX_MAX_PHYSICAL_INTERFACES; iface_index++)
5210             {
5211 
5212                 /* Check the flag.  */
5213                 if (dhcp_ptr -> nx_dhcp_interface_conflict_flag == 0)
5214                 {
5215                     break;
5216                 }
5217 
5218                 /* Check if IP address conflict for this interface.  */
5219                 if (dhcp_ptr -> nx_dhcp_interface_conflict_flag & ((UINT)(1 << iface_index)))
5220                 {
5221 
5222                     /* Handle notice of address conflict event. Let the server know we
5223                        did not get assigned a unique IP address. */
5224                     _nx_dhcp_interface_decline(dhcp_ptr, iface_index);
5225 
5226                     /* Clear the flag.  */
5227                     dhcp_ptr -> nx_dhcp_interface_conflict_flag &= (UINT)(~(1 << iface_index));
5228                 }
5229             }
5230         }
5231 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE  */
5232 
5233     } while (1);
5234 }
5235 
5236 
5237 /**************************************************************************/
5238 /*                                                                        */
5239 /*  FUNCTION                                               RELEASE        */
5240 /*                                                                        */
5241 /*    _nx_dhcp_packet_process                             PORTABLE C      */
5242 /*                                                           6.1.12       */
5243 /*  AUTHOR                                                                */
5244 /*                                                                        */
5245 /*    Yuxin Zhou, Microsoft Corporation                                   */
5246 /*                                                                        */
5247 /*  DESCRIPTION                                                           */
5248 /*                                                                        */
5249 /*    This function is called when the DHCP Client thread is notified of a*/
5250 /*    receive event. If verifies the packet is intended for this host,    */
5251 /*    and checks the transaction ID from the Server to match its ID,      */
5252 /*    processing the packet based on DHCP state.                          */
5253 /*                                                                        */
5254 /*  INPUT                                                                 */
5255 /*                                                                        */
5256 /*    dhcp_ptr                              Pointer to DHCP instance      */
5257 /*    interface_record                      Pointer to DHCP interface     */
5258 /*    packet_ptr                            Pointer to received packet    */
5259 /*                                                                        */
5260 /*  OUTPUT                                                                */
5261 /*                                                                        */
5262 /*    None                                                                */
5263 /*                                                                        */
5264 /*  CALLS                                                                 */
5265 /*                                                                        */
5266 /*   _nx_dhcp_find_matching_record          Find Client record matching   */
5267 /*                                            the packet interface        */
5268 /*   nx_packet_allocate                     Allocate new packet from DHCP */
5269 /*                                            Client packet pool          */
5270 /*   nx_packet_release                      Release packet back to DHCP   */
5271 /*                                            Client packet pool          */
5272 /*   nx_packet_data_extract_offset          Copy data to new packet buffer*/
5273 /*   _nx_dhcp_get_option_value              Get data for input option     */
5274 /*   _nx_dhcp_extract_information           Extract basic info from packet*/
5275 /*   _nx_dhcp_send_request_internal         Send DHCP message             */
5276 /*   nx_ip_interface_address_set            Set IP interface address      */
5277 /*   nx_ip_gateway_address_set              Set IP gateway address        */
5278 /*   _nx_dhcp_interface_reinitialize        Clear DHCP interface data     */
5279 /*                                            for restarting DHCP         */
5280 /*                                                                        */
5281 /*  CALLED BY                                                             */
5282 /*                                                                        */
5283 /*    nx_dhcp_thread_entry                  DHCP Client thread entry fcn  */
5284 /*                                                                        */
5285 /*  RELEASE HISTORY                                                       */
5286 /*                                                                        */
5287 /*    DATE              NAME                      DESCRIPTION             */
5288 /*                                                                        */
5289 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5290 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5291 /*                                            resulting in version 6.1    */
5292 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
5293 /*                                            improved internal logic,    */
5294 /*                                            resulting in version 6.1.12 */
5295 /*                                                                        */
5296 /**************************************************************************/
_nx_dhcp_packet_process(NX_DHCP * dhcp_ptr,NX_DHCP_INTERFACE_RECORD * interface_record,NX_PACKET * packet_ptr)5297 VOID  _nx_dhcp_packet_process(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, NX_PACKET *packet_ptr)
5298 {
5299 
5300 UINT        status;
5301 NX_PACKET   *new_packet_ptr;
5302 ULONG       dhcp_type;
5303 UCHAR       *work_ptr;
5304 ULONG       bytes_copied;
5305 UINT        offset;
5306 NX_IP       *ip_ptr;
5307 UINT        iface_index;
5308 ULONG       packet_client_mac_msw, packet_client_mac_lsw;
5309 ULONG       dhcp_client_mac_msw, dhcp_client_mac_lsw;
5310 UINT        original_state;
5311 UCHAR       *buffer;
5312 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5313 ULONG       probing_delay;
5314 #endif
5315 
5316     /* Set the IP pointer and interface index.  */
5317     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
5318     iface_index = interface_record -> nx_dhcp_interface_index;
5319 
5320     /* Check for valid packet length.  */
5321     if (packet_ptr -> nx_packet_length <= NX_BOOTP_OFFSET_OPTIONS)
5322     {
5323 
5324         /* Release the packet. */
5325         nx_packet_release(packet_ptr);
5326 
5327         /* Return.  */
5328         return;
5329     }
5330 
5331     /* Copy the received packet (datagram) over to a packet from the DHCP Client pool and release
5332        the packet back to receive packet pool as soon as possible. */
5333     status =  nx_packet_allocate(dhcp_ptr -> nx_dhcp_packet_pool_ptr, &new_packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
5334 
5335     /* Check status.  */
5336     if (status != NX_SUCCESS)
5337     {
5338 
5339         /* Release the original packet. */
5340         nx_packet_release(packet_ptr);
5341 
5342         /* Error allocating packet, return error status.  */
5343         return;
5344     }
5345 
5346     /* Verify the incoming packet does not exceed our DHCP Client packet payload. */
5347     if ((ULONG)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr) < ((packet_ptr) -> nx_packet_length))
5348     {
5349 
5350         /* Release the newly allocated packet . */
5351         nx_packet_release(new_packet_ptr);
5352 
5353         /* Release the original packet. */
5354         nx_packet_release(packet_ptr);
5355 
5356         return;
5357     }
5358 
5359     /* Initialize the offset to the beginning of the packet buffer. */
5360     offset = 0;
5361     status = nx_packet_data_extract_offset(packet_ptr, offset, (VOID *)new_packet_ptr -> nx_packet_prepend_ptr, (packet_ptr) -> nx_packet_length, &bytes_copied);
5362     NX_ASSERT((status == NX_SUCCESS) && (bytes_copied > 0));
5363 
5364     /* Update the new packet with the bytes copied.  For chained packets, this will reflect the total
5365        'datagram' length. */
5366     new_packet_ptr -> nx_packet_length = bytes_copied;
5367 
5368 
5369     /* Now we can release the original packet. */
5370     nx_packet_release(packet_ptr);
5371 
5372     /* Set the interface index and MAC address.  */
5373     dhcp_client_mac_msw = ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_msw;
5374     dhcp_client_mac_lsw = ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_lsw;
5375 
5376     /* Set work_ptr.  */
5377     work_ptr = new_packet_ptr -> nx_packet_prepend_ptr + NX_BOOTP_OFFSET_CLIENT_HW;
5378 
5379     /* Pickup the target MAC address in the DHCP message.  */
5380     packet_client_mac_msw = (((ULONG)work_ptr[0]) << 8) | ((ULONG)work_ptr[1]);
5381     packet_client_mac_lsw = (((ULONG)work_ptr[2]) << 24) |
5382                             (((ULONG)work_ptr[3]) << 16) |
5383                             (((ULONG)work_ptr[4]) << 8) |
5384                             ((ULONG)work_ptr[5]);
5385 
5386     /* Determine if the  MAC address matches ours.  */
5387     if ((packet_client_mac_msw != dhcp_client_mac_msw) || (packet_client_mac_lsw != dhcp_client_mac_lsw))
5388     {
5389 
5390         /* Release the allocated packet. */
5391         nx_packet_release(new_packet_ptr);
5392         return;
5393     }
5394 
5395     /* Check if XIDs match.  */
5396     if (_nx_dhcp_get_data(new_packet_ptr -> nx_packet_prepend_ptr + NX_BOOTP_OFFSET_XID, 4) != interface_record -> nx_dhcp_xid)
5397     {
5398 
5399         /* Release the original packet . */
5400         nx_packet_release(new_packet_ptr);
5401 
5402         /* Error with XID data, return error status.  */
5403         return;
5404     }
5405 
5406     /* Save the original state for the state change callback; after this point we will likely change it. */
5407     original_state  = interface_record -> nx_dhcp_state;
5408 
5409     /* The action depends on the current state of the dhcp client. */
5410     switch (interface_record -> nx_dhcp_state)
5411     {
5412 
5413         case NX_DHCP_STATE_SELECTING:
5414         {
5415 
5416             /* Set up a buffer pointer.  */
5417             buffer =  new_packet_ptr -> nx_packet_prepend_ptr;
5418 
5419             /* Get what type of DHCP message it is. */
5420             status = _nx_dhcp_get_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, &dhcp_type, new_packet_ptr -> nx_packet_length);
5421 
5422             /* Determine if it is an Offer.  */
5423             if ((status == NX_SUCCESS) && (dhcp_type == NX_DHCP_TYPE_DHCPOFFER))
5424             {
5425 
5426                 /* Yes, a valid Offer is received!  */
5427 
5428                 /* Increment the number of offers received.  */
5429                 interface_record -> nx_dhcp_offers_received++;
5430 
5431                 /* Update the DHCP Client interface parameters (IP address, server IP, lease, renewal and rebind times */
5432                 if (_nx_dhcp_extract_information(dhcp_ptr, interface_record, buffer, new_packet_ptr -> nx_packet_length))
5433                     break;
5434 
5435                 /* Send the DHCP Request to accept the offer.  */
5436                 _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
5437 
5438                 /* Reset the initial timeout to NX_DHCP_MIN_RETRANS_TIMEOUT seconds  */
5439                 interface_record -> nx_dhcp_rtr_interval = NX_DHCP_MIN_RETRANS_TIMEOUT;
5440                 interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_rtr_interval;
5441 
5442                 /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */
5443                 interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout);
5444 
5445                 /* Update the state to Requesting state.  */
5446                 interface_record -> nx_dhcp_state = NX_DHCP_STATE_REQUESTING;
5447            }
5448 
5449            /* Let the timeout processing handle retransmissions. We're done here */
5450            break;
5451         }
5452 
5453         case NX_DHCP_STATE_REQUESTING:
5454         {
5455 
5456 #ifdef NX_DHCP_ENABLE_BOOTP
5457 
5458             /* Initialize the value of dhcp type since we do not care for BOOTP. */
5459             dhcp_type = NX_DHCP_TYPE_DHCPACK;
5460 
5461             /* Also initialize status to success since we won't make the get option call. */
5462             status = NX_SUCCESS;
5463 #endif
5464 
5465             /* Setup buffer pointer.  */
5466             buffer = new_packet_ptr -> nx_packet_prepend_ptr;
5467 
5468 #ifndef NX_DHCP_ENABLE_BOOTP
5469             /* There is a valid DHCP response, see if it is an ACK.  */
5470             status = _nx_dhcp_get_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, &dhcp_type, new_packet_ptr ->nx_packet_length);
5471 #endif
5472             /* Proceed to processing the server response?   */
5473             if (status == NX_SUCCESS)
5474             {
5475 
5476                 /* Yes, check and see if it is an ACK back to our previous request.  */
5477                 if (dhcp_type == NX_DHCP_TYPE_DHCPACK)
5478                 {
5479 
5480                     /* Increment the number of ACKs received.  */
5481                     interface_record -> nx_dhcp_acks_received++;
5482 
5483                     /* Either we got an ACK or we are using BOOTP.  */
5484 
5485                     /* Update the parameters (IP address, server IP, lease, renewal and rebind times */
5486                     if (_nx_dhcp_extract_information(dhcp_ptr, interface_record, buffer, new_packet_ptr -> nx_packet_length))
5487                         break;
5488 
5489                     /* If the host is configured to send an ARP probe to verify Client address is
5490                        not in use, do so now. */
5491 
5492 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5493 
5494                     /* Change to the Address Probing state.  */
5495                     interface_record -> nx_dhcp_state =  NX_DHCP_STATE_ADDRESS_PROBING;
5496 
5497                     /* Initalize the time for probing.  */
5498                     probing_delay = (ULONG)NX_RAND() % (NX_DHCP_ARP_PROBE_WAIT);
5499 
5500                     /* Check the probing_delay for timer interval.  */
5501                     if (probing_delay)
5502                         interface_record -> nx_dhcp_timeout = probing_delay;
5503                     else
5504                         interface_record -> nx_dhcp_timeout = 1;
5505 
5506                     /* Set the probing count.  */
5507                     interface_record -> nx_dhcp_probe_count = NX_DHCP_ARP_PROBE_NUM;
5508 
5509                     /* Setup the handler to indicate the we want collision notification.  */
5510                     ip_ptr -> nx_ip_interface[iface_index].nx_interface_ip_conflict_notify_handler = _nx_dhcp_ip_conflict;
5511 
5512 #else    /* NX_DHCP_CLIENT_SEND_ARP_PROBE not defined: */
5513 
5514                     nx_ip_interface_address_set(ip_ptr, iface_index,
5515                                                 interface_record -> nx_dhcp_ip_address,
5516                                                 interface_record -> nx_dhcp_network_mask);
5517 
5518                     /* Check if the gateway address is valid.  */
5519                     if (interface_record -> nx_dhcp_gateway_address)
5520                     {
5521 
5522                         /* Set the gateway address.  */
5523                         nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
5524                     }
5525 
5526                     /* No ARP probe performed. OK to change to the Bound state.  */
5527                     interface_record -> nx_dhcp_state =  NX_DHCP_STATE_BOUND;
5528 
5529 #ifdef NX_DHCP_ENABLE_BOOTP
5530                     /* BOOTP does not use timeouts.  For the life of this DHCP Client application, keep the same IP address. */
5531                     interface_record -> nx_dhcp_timeout = NX_WAIT_FOREVER;
5532 #else
5533                     /* Set the renewal time received from the server.  */
5534                     interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_renewal_time;
5535 #endif /* NX_DHCP_ENABLE_BOOTP  */
5536 
5537 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE*/
5538 
5539                     break;
5540                 }
5541                 else if (dhcp_type == NX_DHCP_TYPE_DHCPNACK)
5542                 {
5543 
5544                     /* Increment the number of NACKs received.  */
5545                     interface_record -> nx_dhcp_nacks_received++;
5546 
5547                     /* Reinitialize DHCP.  */
5548                     _nx_dhcp_interface_reinitialize(dhcp_ptr, interface_record -> nx_dhcp_interface_index);
5549 
5550                     /* Restart DHCP service for this interface record.  */
5551 
5552                     /* Start the DHCP protocol again by setting the state back to INIT. */
5553                     interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
5554 
5555                     /* The client begins in INIT state and forms a DHCPDISCOVER message.
5556                        The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
5557                        RFC2131, Section4.4.1, Page36.  */
5558 
5559                     /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
5560                     interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
5561                     interface_record -> nx_dhcp_rtr_interval = 0;
5562                 }
5563             }
5564             break;
5565         }
5566 
5567         case NX_DHCP_STATE_BOUND:
5568         {
5569 
5570             /* Silently discard all received packets in the BOUND state, RFC2131, Section 4.4 Figure 5  */
5571 
5572             break;
5573         }
5574 
5575         case NX_DHCP_STATE_RENEWING:
5576         {
5577 
5578             /* Setup the buffer pointer.  */
5579             buffer =  new_packet_ptr -> nx_packet_prepend_ptr;
5580 
5581             /* Check the server response if it accepts are renewal.  */
5582             status = _nx_dhcp_get_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, &dhcp_type, new_packet_ptr ->nx_packet_length);
5583 
5584             /* Was the option retrieved?  */
5585             if (status == NX_SUCCESS)
5586             {
5587 
5588                 /* Yes, Check for an ACK.  */
5589                 if (dhcp_type == NX_DHCP_TYPE_DHCPACK)
5590                 {
5591 
5592                     /* Increment the number of ACKs received.  */
5593                     interface_record -> nx_dhcp_acks_received++;
5594 
5595                     /* Update the parameters (IP address, server IP, lease, renewal and rebind times */
5596                     if (_nx_dhcp_extract_information(dhcp_ptr, interface_record, buffer, new_packet_ptr -> nx_packet_length))
5597                         break;
5598 
5599                     /* Set the IP address and gateway address from the value extracted from the Server's DHCP response. */
5600                     nx_ip_interface_address_set(ip_ptr, iface_index,
5601                                                 interface_record -> nx_dhcp_ip_address,
5602                                                 interface_record -> nx_dhcp_network_mask);
5603 
5604                     /* Check if the gateway address is valid.  */
5605                     if (interface_record -> nx_dhcp_gateway_address)
5606                     {
5607 
5608                         /* Set the gateway address.  */
5609                         nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
5610                     }
5611 
5612                     /* Lease has been renewed, set the countdown timer back to the renewal time and go back
5613                        to the Bound state*/
5614                     interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_renewal_time;
5615 
5616                     /* Change the state back to bound.  */
5617                     interface_record -> nx_dhcp_state =  NX_DHCP_STATE_BOUND;
5618 
5619                 }
5620                 else if (dhcp_type == NX_DHCP_TYPE_DHCPNACK)
5621                 {
5622 
5623                     /* Increment the number of NACKs received.  */
5624                     interface_record -> nx_dhcp_nacks_received++;
5625 
5626                     /* Reinitialize DHCP.  */
5627                     _nx_dhcp_interface_reinitialize(dhcp_ptr, interface_record -> nx_dhcp_interface_index);
5628 
5629                     /* Restart DHCP service for this interface record.  */
5630 
5631                     /* Start the DHCP protocol again by setting the state back to INIT. */
5632                     interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
5633 
5634                     /* The client begins in INIT state and forms a DHCPDISCOVER message.
5635                        The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
5636                        RFC2131, Section4.4.1, Page36.  */
5637 
5638                     /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
5639                     interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
5640                     interface_record -> nx_dhcp_rtr_interval = 0;
5641                 }
5642             }
5643             break;
5644         }
5645 
5646         case NX_DHCP_STATE_REBINDING:
5647         {
5648 
5649             /* Setup buffer pointer.  */
5650             buffer =  new_packet_ptr -> nx_packet_prepend_ptr;
5651 
5652             /* There is a valid DHCP response, pickup the type of response.  */
5653             status = _nx_dhcp_get_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, &dhcp_type, new_packet_ptr ->nx_packet_length);
5654 
5655             /* Valid response?  */
5656             if (status == NX_SUCCESS)
5657             {
5658 
5659                 /* Is it an ACK response?  */
5660                 if (dhcp_type == NX_DHCP_TYPE_DHCPACK)
5661                 {
5662 
5663                     /* Increment the number of ACKs received.  */
5664                     interface_record -> nx_dhcp_acks_received++;
5665 
5666                     /* Update the parameters (IP address, server IP, lease, renewal and rebind times */
5667                     if (_nx_dhcp_extract_information(dhcp_ptr, interface_record, buffer, new_packet_ptr -> nx_packet_length))
5668                         break;
5669 
5670                     /* Set the IP address and gateway address from the value extracted from the Server's DHCP response. */
5671                     nx_ip_interface_address_set(ip_ptr, iface_index,
5672                                                 interface_record -> nx_dhcp_ip_address,
5673                                                 interface_record -> nx_dhcp_network_mask);
5674 
5675                     /* Check if the gateway address is valid.  */
5676                     if (interface_record -> nx_dhcp_gateway_address)
5677                     {
5678 
5679                         /* Set the gateway address.  */
5680                         nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
5681                     }
5682 
5683                     /* Lease has been renewed, set the countdown timer back to the renewal time and go back
5684                        to the Bound state.  */
5685                     interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_renewal_time;
5686 
5687                     /* Change to bound state.  */
5688                     interface_record -> nx_dhcp_state = NX_DHCP_STATE_BOUND;
5689                 }
5690                 else if (dhcp_type == NX_DHCP_TYPE_DHCPNACK)
5691                 {
5692 
5693                     /* Increment the number of NACKs received.  */
5694                     interface_record -> nx_dhcp_nacks_received++;
5695 
5696                     /* Reinitialize DHCP.  */
5697                     _nx_dhcp_interface_reinitialize(dhcp_ptr, interface_record -> nx_dhcp_interface_index);
5698 
5699                     /* Restart DHCP service for this interface record.  */
5700 
5701                     /* Start the DHCP protocol again by setting the state back to INIT. */
5702                     interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
5703 
5704                     /* The client begins in INIT state and forms a DHCPDISCOVER message.
5705                        The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
5706                        RFC2131, Section4.4.1, Page36.  */
5707 
5708                     /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
5709                     interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
5710                     interface_record -> nx_dhcp_rtr_interval = 0;
5711                 }
5712             }
5713             break;
5714         }
5715 
5716         default:
5717             break;
5718 
5719     } /* End of switch case */
5720 
5721     /* Release the packet.  */
5722     nx_packet_release(new_packet_ptr);
5723 
5724     /* Check if the state is changed.  */
5725     if (original_state != interface_record -> nx_dhcp_state)
5726     {
5727 
5728         /* Determine if the application has specified a routine for DHCP state change notification.  */
5729         if (dhcp_ptr -> nx_dhcp_state_change_callback)
5730         {
5731 
5732             /* Yes, call the application's state change notify function with the new state.  */
5733             (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
5734         }
5735 
5736         /* Determine if the application has specified a routine for DHCP interface state change notification.  */
5737         if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
5738         {
5739 
5740             /* Yes, call the application's state change notify function with the new state.  */
5741             (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
5742         }
5743     }
5744 
5745     return;
5746 }
5747 
5748 
5749 /**************************************************************************/
5750 /*                                                                        */
5751 /*  FUNCTION                                               RELEASE        */
5752 /*                                                                        */
5753 /*    _nx_dhcp_timeout_process                            PORTABLE C      */
5754 /*                                                           6.1.12       */
5755 /*  AUTHOR                                                                */
5756 /*                                                                        */
5757 /*    Yuxin Zhou, Microsoft Corporation                                   */
5758 /*                                                                        */
5759 /*  DESCRIPTION                                                           */
5760 /*                                                                        */
5761 /*    This function is by the DHCP Client when it checks for a timer      */
5762 /*    expiration event. It checks all the DHCP interface records who have */
5763 /*    started DHCP and updates the time remaining on their timeout.       */
5764 /*    If a timeout has expired, this function then processes it according */
5765 /*    to the DHCP state it is in.                                         */
5766 /*                                                                        */
5767 /*  INPUT                                                                 */
5768 /*                                                                        */
5769 /*    dhcp_ptr                              Pointer to DHCP instance      */
5770 /*                                                                        */
5771 /*  OUTPUT                                                                */
5772 /*                                                                        */
5773 /*    None                                                                */
5774 /*                                                                        */
5775 /*  CALLS                                                                 */
5776 /*                                                                        */
5777 /*   _nx_dhcp_send_request_internal         Send a request to DHCP server */
5778 /*   _nx_dhcp_update_timeout                Reset the DHCP timeout        */
5779 /*   _nx_dhcp_add_randomize                 Modify timeout by random value*/
5780 /*   _nx_dhcp_update_renewal_timeout        Set the retransmission timeout*/
5781 /*   _nx_arp_probe_send                     Send ARP probe for IP address */
5782 /*                                            uniqueness if ARP probe     */
5783 /*                                            enabled                     */
5784 /*   nx_ip_interface_address_set            Set the IP interface address  */
5785 /*   nx_ip_gateway_address_set              Set the IP gateway address    */
5786 /*                                                                        */
5787 /*  CALLED BY                                                             */
5788 /*                                                                        */
5789 /*    _nx_dhcp_thread_entry                                               */
5790 /*                                                                        */
5791 /*  RELEASE HISTORY                                                       */
5792 /*                                                                        */
5793 /*    DATE              NAME                      DESCRIPTION             */
5794 /*                                                                        */
5795 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5796 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5797 /*                                            resulting in version 6.1    */
5798 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
5799 /*                                            improved internal logic,    */
5800 /*                                            resulting in version 6.1.12 */
5801 /*                                                                        */
5802 /**************************************************************************/
_nx_dhcp_timeout_process(NX_DHCP * dhcp_ptr)5803 VOID _nx_dhcp_timeout_process(NX_DHCP *dhcp_ptr)
5804 {
5805 
5806 UINT            i;
5807 UINT            original_state;
5808 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
5809 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5810 ULONG            probing_delay;
5811 NX_IP           *ip_ptr;
5812 
5813 
5814     /* Pickup the associated IP pointer.  */
5815     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
5816 
5817 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE  */
5818 
5819     /* Update the timeout on both interfaces. Check what needs to be done
5820        if a timeout expires, based on Client state. */
5821     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
5822     {
5823 
5824          /* Check if the DHCP Client is active on this interface. */
5825          if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid == NX_FALSE)
5826              continue;
5827 
5828          /* Set the interface reocrd pointer.  */
5829          interface_record = &dhcp_ptr -> nx_dhcp_interface_record[i];
5830 
5831          /* Update the count.  */
5832          interface_record -> nx_dhcp_seconds ++;
5833 
5834         /* Check the timer.  */
5835         if (interface_record -> nx_dhcp_timeout != 0)
5836         {
5837 
5838             /* Apply the timer interval to the current DHCP Client timeout.  */
5839             if (interface_record -> nx_dhcp_timeout > NX_DHCP_TIME_INTERVAL)
5840             {
5841 
5842                 /* Update the timeout.  */
5843                 interface_record -> nx_dhcp_timeout -= (ULONG)NX_DHCP_TIME_INTERVAL;
5844             }
5845             else
5846             {
5847 
5848                 /* The DHCP Client timeout has expired. */
5849                 interface_record -> nx_dhcp_timeout = 0;
5850 
5851                 /* Save the current state for state change callback. */
5852                 original_state = interface_record -> nx_dhcp_state;
5853 
5854                 /* Process according to what state the Client is in. */
5855                 switch (interface_record -> nx_dhcp_state)
5856                 {
5857 
5858                     case NX_DHCP_STATE_INIT:
5859                     {
5860 
5861                         /* Reset the seconds field for starting the DHCP address acquistiion. */
5862                         interface_record -> nx_dhcp_seconds = 0;
5863 
5864                         /* Initial state when there is no address.  Send a DHCPDISCOVER message
5865                            to find a DHCP server and switch to the SELECTING state.
5866                            Initial timeout is NX_DHCP_MIN_RETRANS_TIMEOUT seconds. */
5867 #ifndef NX_DHCP_ENABLE_BOOTP
5868                         /* Only if the DHCP Client is requesting an IP address and is configured to skip the Discovery message. */
5869                         if ((interface_record -> nx_dhcp_ip_address != NX_BOOTP_NO_ADDRESS) &&
5870                             (interface_record -> nx_dhcp_skip_discovery))
5871                         {
5872 
5873                             /* Send out the DHCP request.  */
5874                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
5875 
5876                             /* And change to the Requesting state. */
5877                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_REQUESTING;
5878                         }
5879                         else
5880                         {
5881 
5882                             /* Send out the DHCP request.  */
5883                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPDISCOVER);
5884 
5885                             /* And change to the Selecting state. */
5886                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_SELECTING;
5887                         }
5888 #else
5889                         /* Send the BOOTP Request message.  */
5890                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_BOOT_REQUEST);
5891 
5892                         /* And change to the Requesting state. */
5893                         interface_record -> nx_dhcp_state = NX_DHCP_STATE_REQUESTING;
5894 #endif
5895 
5896                         /* Check if the retransmission interval is zero.  */
5897                         if (interface_record -> nx_dhcp_rtr_interval == 0)
5898                         {
5899 
5900                             /* Set the interval to min retransmission timeout.  */
5901                             interface_record -> nx_dhcp_rtr_interval = NX_DHCP_MIN_RETRANS_TIMEOUT;
5902                         }
5903                         else
5904                         {
5905 
5906                             /* Record the retransmission interval for next retransmission.  */
5907                             interface_record -> nx_dhcp_rtr_interval = _nx_dhcp_update_timeout(interface_record -> nx_dhcp_rtr_interval);
5908                         }
5909 
5910                         /* Update the timeout for next retransmission.  */
5911                         interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_rtr_interval;
5912 
5913                         /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */
5914                         interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout);
5915 
5916                         break;
5917                     }
5918 
5919                     case NX_DHCP_STATE_SELECTING:
5920                     {
5921 
5922 #ifndef NX_DHCP_ENABLE_BOOTP
5923                         /* Retransmit the Discover message.  */
5924                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPDISCOVER);
5925 #else
5926                         /* Retransmit the BOOTP Request message.  */
5927                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_BOOT_REQUEST);
5928 #endif
5929 
5930                         /* Update the retransmision interval.   */
5931                         interface_record -> nx_dhcp_rtr_interval = _nx_dhcp_update_timeout(interface_record -> nx_dhcp_rtr_interval);
5932 
5933                         /* Update the timeout for next retransmission.  */
5934                         interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_rtr_interval;
5935 
5936                         /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */
5937                         interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout);
5938 
5939                         break;
5940                     }
5941 
5942                     case NX_DHCP_STATE_REQUESTING:
5943                     {
5944 
5945 #ifndef NX_DHCP_ENABLE_BOOTP
5946                         /* Send a DHCP request. */
5947                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
5948 #else
5949                         /* Send a BOOTP request. */
5950                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_BOOT_REQUEST);
5951 #endif
5952 
5953                         /* Update the retransmision interval.   */
5954                         interface_record->nx_dhcp_rtr_interval = _nx_dhcp_update_timeout(interface_record -> nx_dhcp_rtr_interval);
5955 
5956                         /* Reset the timeout for next retransmision. */
5957                         interface_record -> nx_dhcp_timeout = interface_record->nx_dhcp_rtr_interval;
5958 
5959                         /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */
5960                         interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout);
5961 
5962                         break;
5963                     }
5964 
5965                     case NX_DHCP_STATE_ADDRESS_PROBING:
5966                     {
5967 
5968 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5969 
5970                         /* Send the ARP probe.  */
5971                         _nx_arp_probe_send(ip_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_ip_address);
5972 
5973                         /* Decrease the probe count.  */
5974                         interface_record -> nx_dhcp_probe_count--;
5975 
5976                         /* Check the probe count.  */
5977                         if (interface_record -> nx_dhcp_probe_count)
5978                         {
5979 
5980                             /* Calculate the delay time.  */
5981                             probing_delay = (ULONG)NX_RAND() % (NX_DHCP_ARP_PROBE_MAX);
5982 
5983                             /* Determine if this is less than the minimum.  */
5984                             if (probing_delay < NX_DHCP_ARP_PROBE_MIN)
5985                             {
5986 
5987                                 /* Set the delay to the minimum.  */
5988                                 probing_delay = NX_DHCP_ARP_PROBE_MIN;
5989                             }
5990 
5991                             /* Check the probing_delay for timer interval.  */
5992                             if (probing_delay)
5993                                 interface_record -> nx_dhcp_timeout = probing_delay;
5994                             else
5995                                 interface_record -> nx_dhcp_timeout = 1;
5996                         }
5997                         else
5998                         {
5999 
6000                             /* No address conflict.  */
6001                             ip_ptr -> nx_ip_interface[interface_record -> nx_dhcp_interface_index].nx_interface_ip_conflict_notify_handler = NX_NULL;
6002 
6003                             /* Set the IP address.  */
6004                             nx_ip_interface_address_set(ip_ptr, interface_record -> nx_dhcp_interface_index,
6005                                                         interface_record -> nx_dhcp_ip_address, interface_record -> nx_dhcp_network_mask);
6006 
6007                             /* Check if the gateway address is valid.  */
6008                             if (interface_record -> nx_dhcp_gateway_address)
6009                             {
6010 
6011                                 /* Set the gateway address.  */
6012                                 nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
6013                             }
6014 
6015                             /* Change to the Bound state.  */
6016                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_BOUND;
6017 
6018  #ifdef NX_DHCP_ENABLE_BOOTP
6019                             /* BOOTP does not use timeouts.  For the life of this DHCP Client application, keep the same IP address. */
6020                             interface_record -> nx_dhcp_timeout = NX_WAIT_FOREVER;
6021 #else
6022                             /* Set the renewal time received from the server.  */
6023                             interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_renewal_time;
6024 #endif /* NX_DHCP_ENABLE_BOOTP  */
6025                         }
6026 
6027 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE */
6028 
6029                         break;
6030                     }
6031 
6032                     case NX_DHCP_STATE_BOUND:
6033                     {
6034 
6035                         /* Reset the seconds field for starting the DHCP request process. */
6036                         interface_record -> nx_dhcp_seconds = 0;
6037 
6038                         /* The lease has timed out. Time to renew.  */
6039 
6040                         /* And change to the Renewing state. */
6041                         interface_record -> nx_dhcp_state = NX_DHCP_STATE_RENEWING;
6042 
6043                         /* Send the renewal request.  */
6044                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
6045 
6046                         /* Set the time remaining based on RFC 2131 when T1 expires. */
6047                         interface_record -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_rebind_time - interface_record -> nx_dhcp_renewal_time;
6048                         interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
6049 
6050                         /* Record the retransmission interval.  */
6051                         interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
6052 
6053                         break;
6054                     }
6055 
6056                     case NX_DHCP_STATE_RENEWING:
6057                     {
6058 
6059                         /* Check if we have reached the end of the renewal time.  */
6060                         if (interface_record -> nx_dhcp_renewal_remain_time >= interface_record -> nx_dhcp_rtr_interval)
6061                         {
6062                             interface_record -> nx_dhcp_renewal_remain_time -= interface_record -> nx_dhcp_rtr_interval;
6063                         }
6064                         else
6065                         {
6066                             interface_record -> nx_dhcp_renewal_remain_time = 0;
6067                         }
6068 
6069                         /* Update the timeout for renew retranmission.  */
6070                         interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
6071 
6072                         /* Check if we are at the limit on retransmission.  */
6073                         if (interface_record -> nx_dhcp_timeout == 0)
6074                         {
6075 
6076                             /* And change to the Rebinding state. */
6077                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_REBINDING;
6078 
6079                             /* Send the rebind request.  */
6080                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
6081 
6082                             /* Calculate the rebind time based on the RFC 2131. */
6083                             interface_record -> nx_dhcp_rebind_remain_time = interface_record -> nx_dhcp_lease_time - interface_record -> nx_dhcp_rebind_time;
6084 
6085                             /* Calculate the timeout for the response.  */
6086                             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_rebind_remain_time);
6087 
6088                             /* Record the retransmission interval.  */
6089                             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
6090                         }
6091                         else
6092                         {
6093 
6094                             /* Retransmit the Renewing message and wait again */
6095                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
6096 
6097                             /* Record the retransmission interval.  */
6098                             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
6099                         }
6100 
6101                         break;
6102                     }
6103 
6104                     case NX_DHCP_STATE_REBINDING:
6105                     {
6106 
6107                         /* No response yet, the response must have timed out,
6108                             update the timeout and check if we have reached the
6109                             end of the rebinding time.  */
6110                         if (interface_record -> nx_dhcp_rebind_remain_time >= interface_record -> nx_dhcp_rtr_interval)
6111                         {
6112                             interface_record -> nx_dhcp_rebind_remain_time -= interface_record -> nx_dhcp_rtr_interval;
6113                         }
6114                         else
6115                         {
6116                             interface_record -> nx_dhcp_rebind_remain_time = 0;
6117                         }
6118 
6119                         /* Update the timeout for renew retranmission.  */
6120                         interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_rebind_remain_time);
6121 
6122                         /* Check if we are at the limit on retransmission.  */
6123                         if (interface_record -> nx_dhcp_timeout == 0)
6124                         {
6125 
6126                             /* Timeout. Restart DHCP service for this interface record.  */
6127 
6128                             /* Reinitialize DHCP.  */
6129                             _nx_dhcp_interface_reinitialize(dhcp_ptr, interface_record -> nx_dhcp_interface_index);
6130 
6131                             /* Start the DHCP protocol again by setting the state back to INIT. */
6132                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
6133 
6134                             /* The client begins in INIT state and forms a DHCPDISCOVER message.
6135                                The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
6136                                RFC2131, Section4.4.1, Page36.  */
6137 
6138                             /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
6139                             interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
6140                             interface_record -> nx_dhcp_rtr_interval = 0;
6141                         }
6142                         else
6143                         {
6144 
6145                             /* Retransmit the Renewing message and wait again */
6146                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
6147 
6148                             /* Record the retransmission interval.  */
6149                             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
6150                         }
6151                         break;
6152                     }
6153 
6154                     default:
6155                     {
6156 
6157                         break;
6158                     }
6159                 }
6160 
6161                 /* Check if the state is changed.  */
6162                 if (original_state != interface_record -> nx_dhcp_state)
6163                 {
6164 
6165                     /* Determine if the application has specified a routine for DHCP state change notification.  */
6166                     if (dhcp_ptr -> nx_dhcp_state_change_callback)
6167                     {
6168 
6169                         /* Yes, call the application's state change notify function with the new state.  */
6170                         (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
6171                     }
6172 
6173                     /* Determine if the application has specified a routine for DHCP interface state change notification.  */
6174                     if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
6175                     {
6176 
6177                         /* Yes, call the application's state change notify function with the new state.  */
6178                         (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
6179                     }
6180                 }
6181 
6182             } /* End of switch statement. */
6183         }
6184 
6185     } /* Try the next interface record.  */
6186 }
6187 
6188 
6189 /**************************************************************************/
6190 /*                                                                        */
6191 /*  FUNCTION                                               RELEASE        */
6192 /*                                                                        */
6193 /*    _nxe_dhcp_send_request                              PORTABLE C      */
6194 /*                                                           6.1          */
6195 /*  AUTHOR                                                                */
6196 /*                                                                        */
6197 /*    Yuxin Zhou, Microsoft Corporation                                   */
6198 /*                                                                        */
6199 /*  DESCRIPTION                                                           */
6200 /*                                                                        */
6201 /*    This function performs error checking for the DHCP client send      */
6202 /*    request service.                                                    */
6203 /*                                                                        */
6204 /*  INPUT                                                                 */
6205 /*                                                                        */
6206 /*    dhcp_ptr                              Pointer to DHCP instance      */
6207 /*    dhcp_message_type                     Type of DHCP message to send , */
6208 /*                                                                        */
6209 /*  OUTPUT                                                                */
6210 /*    NX_PTR_ERROR                          Invalid pointer input         */
6211 /*    status                                Completion status             */
6212 /*                                                                        */
6213 /*  CALLS                                                                 */
6214 /*                                                                        */
6215 /*    _nxe_dhcp_send_request                Actual send request service   */
6216 /*                                                                        */
6217 /*  CALLED BY                                                             */
6218 /*                                                                        */
6219 /*    Application thread                                                  */
6220 /*                                                                        */
6221 /*  RELEASE HISTORY                                                       */
6222 /*                                                                        */
6223 /*    DATE              NAME                      DESCRIPTION             */
6224 /*                                                                        */
6225 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6226 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6227 /*                                            resulting in version 6.1    */
6228 /*                                                                        */
6229 /**************************************************************************/
_nxe_dhcp_send_request(NX_DHCP * dhcp_ptr,UINT dhcp_message_type)6230 UINT  _nxe_dhcp_send_request(NX_DHCP *dhcp_ptr, UINT dhcp_message_type)
6231 {
6232 
6233 UINT status;
6234 
6235 
6236     /* Check for invalid input. */
6237     if (!dhcp_ptr || (dhcp_message_type == 0) || (dhcp_message_type > NX_DHCP_TYPE_DHCPFORCERENEW))
6238     {
6239         return (NX_PTR_ERROR);
6240     }
6241 
6242     /* Call the actual service and return completion status. */
6243     status = _nx_dhcp_send_request(dhcp_ptr, dhcp_message_type);
6244 
6245     return(status);
6246 
6247 }
6248 
6249 
6250 /**************************************************************************/
6251 /*                                                                        */
6252 /*  FUNCTION                                               RELEASE        */
6253 /*                                                                        */
6254 /*    _nx_dhcp_send_request                               PORTABLE C      */
6255 /*                                                           6.1          */
6256 /*  AUTHOR                                                                */
6257 /*                                                                        */
6258 /*    Yuxin Zhou, Microsoft Corporation                                   */
6259 /*                                                                        */
6260 /*  DESCRIPTION                                                           */
6261 /*                                                                        */
6262 /*    This function sends the specified request to the first DHCP enabled */
6263 /*    interface found. To send a RELEASE or DECLINE message, use the      */
6264 /*    nx_dhcp_release/nx_dhcp_interface_release or nx_dhcp_decline/       */
6265 /*    nx_dhcp_interface_decline respectively.                             */
6266 /*                                                                        */
6267 /*    To send a request on a specific DHCP interface if multiple          */
6268 /*    interfaces are DHCP enabled, use the                                */
6269 /*    nx_dhcp_interface_send_request service.                             */
6270 /*                                                                        */
6271 /*    Note: Except for an INFORM REQUEST message, the application should  */
6272 /*    not need to send DHCP messages out independently of the DHCP Client */
6273 /*    processing thread. It is not recommended to use this function once  */
6274 /*    the DHCP Client has started until it is BOUND.                      */
6275 /*                                                                        */
6276 /*  INPUT                                                                 */
6277 /*                                                                        */
6278 /*    dhcp_ptr                              Pointer to DHCP instance      */
6279 /*    dhcp_message_type                     Type of DHCP message to send  */
6280 /*                                                                        */
6281 /*  OUTPUT                                                                */
6282 /*                                                                        */
6283 /*    status                                Actual completion status      */
6284 /*    NX_DHCP_NO_INTERFACES_ENABLED         No DHCP interface enabled     */
6285 /*                                                                        */
6286 /*  CALLS                                                                 */
6287 /*                                                                        */
6288 /*    _nx_dhcp_interface_send_request       Send DHCP request to server   */
6289 /*    tx_mutex_get                          Obtain protection mutex       */
6290 /*    tx_mutex_put                          Release protection mutex      */
6291 /*                                                                        */
6292 /*  CALLED BY                                                             */
6293 /*                                                                        */
6294 /*    Application code                                                    */
6295 /*                                                                        */
6296 /*  RELEASE HISTORY                                                       */
6297 /*                                                                        */
6298 /*    DATE              NAME                      DESCRIPTION             */
6299 /*                                                                        */
6300 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6301 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6302 /*                                            resulting in version 6.1    */
6303 /*                                                                        */
6304 /**************************************************************************/
_nx_dhcp_send_request(NX_DHCP * dhcp_ptr,UINT dhcp_message_type)6305 UINT  _nx_dhcp_send_request(NX_DHCP *dhcp_ptr, UINT dhcp_message_type)
6306 {
6307 
6308 UINT  status;
6309 UINT  i;
6310 
6311     /* Obtain the DHCP mutex.  */
6312     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
6313 
6314     /* Find the DHCP interface record.  */
6315     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
6316     {
6317 
6318         /* Check which interface record is valid.  */
6319         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
6320         {
6321 
6322             /* Set the request on only the first (only) valid interface.  */
6323             status = _nx_dhcp_interface_send_request(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index,  dhcp_message_type);
6324 
6325             /* Release the DHCP mutex.  */
6326             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6327             return(status);
6328         }
6329     }
6330 
6331     /* Release the DHCP mutex.  */
6332     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6333     return(NX_DHCP_NO_INTERFACES_ENABLED);
6334 
6335 }
6336 
6337 
6338 /**************************************************************************/
6339 /*                                                                        */
6340 /*  FUNCTION                                               RELEASE        */
6341 /*                                                                        */
6342 /*    _nxe_dhcp_interface_send_request                    PORTABLE C      */
6343 /*                                                           6.1          */
6344 /*  AUTHOR                                                                */
6345 /*                                                                        */
6346 /*    Yuxin Zhou, Microsoft Corporation                                   */
6347 /*                                                                        */
6348 /*  DESCRIPTION                                                           */
6349 /*                                                                        */
6350 /*    This function performs error checking on the send request service.  */
6351 /*                                                                        */
6352 /*  INPUT                                                                 */
6353 /*                                                                        */
6354 /*    dhcp_ptr                              Pointer to DHCP instance      */
6355 /*    iface_index                           Interface to send message on  */
6356 /*    dhcp_message_type                     DHCP messages to send:        */
6357 /*                                              NX_DHCP_TYPE_DHCPDECLINE  */
6358 /*                                              NX_DHCP_TYPE_DHCPRELEASE  */
6359 /*                                                                        */
6360 /*  OUTPUT                                                                */
6361 /*                                                                        */
6362 /*    status                                Completion status             */
6363 /*    NX_PTR_ERROR                          Invalid pointer input         */
6364 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
6365 /*                                                                        */
6366 /*  CALLS                                                                 */
6367 /*                                                                        */
6368 /*    _nx_dhcp_interface_send_request       Actual send the DHCP request  */
6369 /*                                                                        */
6370 /*  CALLED BY                                                             */
6371 /*                                                                        */
6372 /*    Application code                                                    */
6373 /*                                                                        */
6374 /*  RELEASE HISTORY                                                       */
6375 /*                                                                        */
6376 /*    DATE              NAME                      DESCRIPTION             */
6377 /*                                                                        */
6378 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6379 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6380 /*                                            resulting in version 6.1    */
6381 /*                                                                        */
6382 /**************************************************************************/
_nxe_dhcp_interface_send_request(NX_DHCP * dhcp_ptr,UINT iface_index,UINT dhcp_message_type)6383 UINT  _nxe_dhcp_interface_send_request(NX_DHCP *dhcp_ptr, UINT iface_index, UINT dhcp_message_type)
6384 {
6385 
6386 UINT status;
6387 
6388 
6389     if (dhcp_ptr == NX_NULL)
6390     {
6391         return(NX_PTR_ERROR);
6392     }
6393 
6394     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
6395     {
6396         return(NX_INVALID_INTERFACE);
6397     }
6398 
6399     /* Check for appropriate caller.  */
6400     NX_THREADS_ONLY_CALLER_CHECKING
6401 
6402     status = _nx_dhcp_interface_send_request(dhcp_ptr, iface_index, dhcp_message_type);
6403 
6404     return status;
6405 }
6406 
6407 
6408 /**************************************************************************/
6409 /*                                                                        */
6410 /*  FUNCTION                                               RELEASE        */
6411 /*                                                                        */
6412 /*    _nx_dhcp_interface_send_request                     PORTABLE C      */
6413 /*                                                           6.1          */
6414 /*  AUTHOR                                                                */
6415 /*                                                                        */
6416 /*    Yuxin Zhou, Microsoft Corporation                                   */
6417 /*                                                                        */
6418 /*  DESCRIPTION                                                           */
6419 /*                                                                        */
6420 /*    This function allows the host application to send a specific request*/
6421 /*    on the specified interface. The interface must be enabled for DHCP. */
6422 /*                                                                        */
6423 /*    To send a RELEASE or DECLINE message on a specific interface, use   */
6424 /*    the nx_dhcp_interface_release or nx_dhcp_interface_decline          */
6425 /*    respectively.                                                       */
6426 /*                                                                        */
6427 /*    Note: Except for an INFORM REQUEST message, the application should  */
6428 /*    not need to send DHCP messages out independently of the DHCP Client */
6429 /*    processing thread. It is not recommended to use this function once  */
6430 /*    the DHCP Client has started until it is BOUND.                      */
6431 /*                                                                        */
6432 /*  INPUT                                                                 */
6433 /*                                                                        */
6434 /*    dhcp_ptr                              Pointer to DHCP instance      */
6435 /*    iface_index                           Interface to send message on  */
6436 /*    dhcp_message_type                     Type of DHCP message to send, */
6437 /*                                              NX_DHCP_TYPE_DHCPDECLINE  */
6438 /*                                              NX_DHCP_TYPE_DHCPRELEASE  */
6439 /*                                                                        */
6440 /*  OUTPUT                                                                */
6441 /*                                                                        */
6442 /*    NX_DHCP_INVALID_MESSAGE               Message type not allowed      */
6443 /*    status                                Actual completion status      */
6444 /*                                                                        */
6445 /*  CALLS                                                                 */
6446 /*                                                                        */
6447 /*    _nx_dhcp_interface_record_find        Find Client record for the    */
6448 /*                                            specified interface         */
6449 /*    _nx_dhcp_send_request_internal        Send the DHCP request         */
6450 /*    tx_mutex_get                          Obtain protection mutex       */
6451 /*    tx_mutex_put                          Release protection mutex      */
6452 /*                                                                        */
6453 /*  CALLED BY                                                             */
6454 /*                                                                        */
6455 /*    Application code                                                    */
6456 /*                                                                        */
6457 /*  RELEASE HISTORY                                                       */
6458 /*                                                                        */
6459 /*    DATE              NAME                      DESCRIPTION             */
6460 /*                                                                        */
6461 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6462 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6463 /*                                            resulting in version 6.1    */
6464 /*                                                                        */
6465 /**************************************************************************/
_nx_dhcp_interface_send_request(NX_DHCP * dhcp_ptr,UINT iface_index,UINT dhcp_message_type)6466 UINT  _nx_dhcp_interface_send_request(NX_DHCP *dhcp_ptr, UINT iface_index, UINT dhcp_message_type)
6467 {
6468 
6469 UINT                      status;
6470 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
6471 
6472 
6473     /* Get the DHCP mutex.  */
6474     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
6475 
6476     /* Find the interface record.  */
6477     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
6478 
6479     /* Check status.  */
6480     if (status)
6481     {
6482 
6483         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6484 
6485         return(status);
6486     }
6487 
6488     /* If the message is a RELEASE or DECLINE request, the host should call nx_dhcp_release
6489        or nx_dhcp_decline respectively. */
6490     if ((dhcp_message_type == NX_DHCP_TYPE_DHCPRELEASE) || (dhcp_message_type == NX_DHCP_TYPE_DHCPDECLINE))
6491     {
6492 
6493         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6494 
6495         return NX_DHCP_INVALID_MESSAGE;
6496     }
6497 
6498     /* The DHCP INFORM message is independent of the Client thread task activity. */
6499     if (dhcp_message_type != NX_DHCP_TYPE_DHCPINFORM)
6500     {
6501 
6502         /* Determine if DHCP is started.  */
6503         if (dhcp_ptr -> nx_dhcp_interface_record[iface_index].nx_dhcp_state == NX_DHCP_STATE_NOT_STARTED)
6504         {
6505 
6506             /* Release the DHCP mutex.  */
6507             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6508 
6509             /* DHCP is not started so it should not 'send' a request to the server.  */
6510             return(NX_DHCP_NOT_STARTED);
6511         }
6512     }
6513 
6514 
6515     status = _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, dhcp_message_type);
6516 
6517     /* Release the DHCP mutex.  */
6518     tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
6519 
6520     return status;
6521 
6522 }
6523 
6524 /**************************************************************************/
6525 /*                                                                        */
6526 /*  FUNCTION                                               RELEASE        */
6527 /*                                                                        */
6528 /*    _nx_dhcp_send_request_internal                      PORTABLE C      */
6529 /*                                                           6.1.12       */
6530 /*  AUTHOR                                                                */
6531 /*                                                                        */
6532 /*    Yuxin Zhou, Microsoft Corporation                                   */
6533 /*                                                                        */
6534 /*  DESCRIPTION                                                           */
6535 /*                                                                        */
6536 /*    This function sends a DHCP request to the server.  Any additional   */
6537 /*    options are appended to the request structure for certain types of  */
6538 /*    DHCP requests.                                                      */
6539 /*                                                                        */
6540 /*  INPUT                                                                 */
6541 /*                                                                        */
6542 /*    dhcp_ptr                              Pointer to DHCP instance      */
6543 /*    iface_index                           Interface to send message on  */
6544 /*    dhcp_message_type                     Type of DHCP message to send  */
6545 /*                                                                        */
6546 /*  OUTPUT                                                                */
6547 /*                                                                        */
6548 /*    status                                Completion status             */
6549 /*                                                                        */
6550 /*  CALLS                                                                 */
6551 /*                                                                        */
6552 /*    nx_packet_allocate                    Allocate a DHCP packet        */
6553 /*    nx_packet_release                     Release DHCP packet           */
6554 /*    nx_udp_socket_send                    Send DHCP packet              */
6555 /*    _nx_dhcp_store_data                   Write data into message       */
6556 /*    _nx_dhcp_add_option_value             Add an option to the request  */
6557 /*    _nx_dhcp_add_option_string            Add an option string to the   */
6558 /*                                            request                     */
6559 /*    _nx_dhcp_add_option_parameter_request Add a parameter request option*/
6560 /*    nx_udp_socket_interface_send          Send packet out on interface  */
6561 /*    _nx_dhcp_client_send_with_zero_source_address                       */
6562 /*                                          Send broadcast packet with    */
6563 /*                                            zero source IP address      */
6564 /*                                                                        */
6565 /*  CALLED BY                                                             */
6566 /*                                                                        */
6567 /*    _nx_dhcp_interface_send_request       Send request on specified     */
6568 /*                                             interface                  */
6569 /*    _nx_dhcp_interface_force_renew        Send Force Renew message      */
6570 /*    _nx_dhcp_interface_decline            Send DECLINE message          */
6571 /*    _nx_dhcp_interface_release            Send RELEASE message          */
6572 /*    _nx_dhcp_packet_process               Process received packets      */
6573 /*    _nx_dhcp_timeout_process              Process timer expirations     */
6574 #ifdef NX_DHCP_CLIENT_RESTORE_STATE
6575 /*    _nx_dhcp_resume                       Resume the DHCP Client thread */
6576 #endif
6577 /*                                                                        */
6578 /*  RELEASE HISTORY                                                       */
6579 /*                                                                        */
6580 /*    DATE              NAME                      DESCRIPTION             */
6581 /*                                                                        */
6582 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6583 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6584 /*                                            resulting in version 6.1    */
6585 /*  08-02-2021     Yuxin Zhou               Modified comment(s), supported*/
6586 /*                                            adding additional request   */
6587 /*                                            option in parameter request,*/
6588 /*                                            resulting in version 6.1.8  */
6589 /*  07-29-2022     Yuxin Zhou               Modified comment(s), corrected*/
6590 /*                                            the logic of adding server  */
6591 /*                                            identifier option,          */
6592 /*                                            resulting in version 6.1.12 */
6593 /*                                                                        */
6594 /**************************************************************************/
_nx_dhcp_send_request_internal(NX_DHCP * dhcp_ptr,NX_DHCP_INTERFACE_RECORD * interface_record,UINT dhcp_message_type)6595 static UINT  _nx_dhcp_send_request_internal(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, UINT dhcp_message_type)
6596 {
6597 
6598 NX_PACKET       *packet_ptr;
6599 UCHAR           *buffer;
6600 ULONG           targetIP;
6601 UINT            status;
6602 ULONG           dhcp_client_mac_msw;
6603 ULONG           dhcp_client_mac_lsw;
6604 UINT            iface_index;
6605 UINT            index = 0;
6606 UCHAR          *user_option_ptr;
6607 UINT            user_option_length;
6608 UINT            name_length;
6609 
6610 
6611     /* Set the interface idnex.  */
6612     iface_index = interface_record -> nx_dhcp_interface_index;
6613 
6614     /* Allocate a DHCP packet.  */
6615     status =  nx_packet_allocate(dhcp_ptr -> nx_dhcp_packet_pool_ptr, &packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
6616 
6617     /* Was the packet allocation successful?  */
6618     if (status != NX_SUCCESS)
6619     {
6620 
6621         /* Increment the DHCP internal error counter.  */
6622         interface_record -> nx_dhcp_internal_errors++;
6623 
6624         /* Return status.  */
6625         return(status);
6626     }
6627 
6628     /* Set the interface index and MAC address.  */
6629     dhcp_client_mac_msw = dhcp_ptr -> nx_dhcp_ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_msw;
6630     dhcp_client_mac_lsw = dhcp_ptr -> nx_dhcp_ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_lsw;
6631 
6632     /* Setup the buffer pointer.  */
6633     buffer =  packet_ptr -> nx_packet_prepend_ptr;
6634 
6635     /* Clear the buffer out... just in case.  */
6636     memset((void *) buffer, 0, NX_BOOTP_OFFSET_END);
6637 
6638     /* Setup the standard BootP fields.  */
6639     buffer[NX_BOOTP_OFFSET_OP] =        NX_BOOTP_OP_REQUEST;
6640     buffer[NX_BOOTP_OFFSET_HTYPE] =     NX_BOOTP_TYPE_ETHERNET;
6641     buffer[NX_BOOTP_OFFSET_HLEN] =      NX_BOOTP_HLEN_ETHERNET;
6642     buffer[NX_BOOTP_OFFSET_HOPS] =      0;
6643     buffer[NX_BOOTP_OFFSET_SERVER_NM] = 0;
6644     buffer[NX_BOOTP_OFFSET_BOOT_FILE] = 0;
6645 
6646     /* Setup the 'Xid' field.  */
6647     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_XID, 4, interface_record -> nx_dhcp_xid);
6648 
6649     /* Set the 'secs' field according to RFC2131, Secion4.4.1, Page37, Table5. */
6650     if ((dhcp_message_type == NX_DHCP_TYPE_DHCPDECLINE) || (dhcp_message_type == NX_DHCP_TYPE_DHCPRELEASE))
6651     {
6652         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_SECS, 2, 0);
6653     }
6654     else
6655     {
6656         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_SECS, 2, interface_record -> nx_dhcp_seconds);
6657     }
6658 
6659     /* Set the broadcast flag according to RFC2131, Secion4.4.1, Page38, Table5.  */
6660 
6661     /* Set the broadcast flag to 0 for DHCP Decline and DHCP Release.  */
6662     if ((dhcp_message_type == NX_DHCP_TYPE_DHCPDECLINE) || (dhcp_message_type == NX_DHCP_TYPE_DHCPRELEASE))
6663     {
6664 
6665         /* Request the response be sent unicast.  */
6666         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_FLAGS, 1, NX_BOOTP_FLAGS_UNICAST);
6667     }
6668 
6669     /* Set the 'broadcast' flag according to user requirement for DHCP Discover, DHCP Request and DHCP Inform.  */
6670     else if (interface_record -> nx_dhcp_clear_broadcast == NX_TRUE)
6671     {
6672 
6673         /* Request the response be sent unicast.  */
6674         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_FLAGS, 1, NX_BOOTP_FLAGS_UNICAST);
6675     }
6676     else
6677     {
6678 
6679         /* Request the response be sent broadcast.  */
6680         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_FLAGS, 1, NX_BOOTP_FLAGS_BROADCAST);
6681     }
6682 
6683     /* RFC 2131 4.4.1: Do not set the Client IP ("ciaddr" field) address...*/
6684     if (dhcp_message_type != NX_DHCP_TYPE_DHCPINFORM)
6685     {
6686         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, NX_BOOTP_NO_ADDRESS);
6687     }
6688     /* ...unless this is an INFORM REQUEST message. */
6689     else
6690     {
6691         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
6692     }
6693 
6694     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_YOUR_IP, 4, NX_BOOTP_NO_ADDRESS);
6695     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_SERVER_IP, 4, NX_BOOTP_NO_ADDRESS);
6696     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_GATEWAY_IP, 4, NX_BOOTP_NO_ADDRESS);
6697     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_HW, 2, dhcp_client_mac_msw);
6698     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_HW + 2, 4, dhcp_client_mac_lsw);
6699 
6700 #ifndef NX_DHCP_ENABLE_BOOTP
6701     /* Update the index.  */
6702     index = NX_BOOTP_OFFSET_OPTIONS;
6703 
6704     /*  A BOOTP Client should not request DHCP option data. */
6705     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_VENDOR, 4, NX_BOOTP_MAGIC_COOKIE);
6706 
6707     /* Add the actual DHCP request.  */
6708     _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, NX_DHCP_OPTION_DHCP_TYPE_SIZE, dhcp_message_type, &index);
6709 #endif
6710 
6711     /* Determine if any additional options need to be added relative to the DHCP message type.
6712        RFC 2131, Table 5: Fields and options used by DHCP Clients.  */
6713     switch (dhcp_message_type)
6714     {
6715 
6716 #ifdef NX_DHCP_ENABLE_BOOTP
6717 
6718         case NX_DHCP_TYPE_BOOT_REQUEST:
6719 
6720             _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
6721             _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_SERVER_IP, 4, interface_record -> nx_dhcp_server_ip);
6722 
6723             break;
6724 #endif
6725 
6726         case NX_DHCP_TYPE_DHCPDISCOVER:
6727 
6728 
6729             /* Determine if we have a valid IP address.  */
6730             if ((interface_record -> nx_dhcp_ip_address != NX_BOOTP_NO_ADDRESS) &&
6731                 (interface_record -> nx_dhcp_ip_address != NX_BOOTP_BC_ADDRESS))
6732             {
6733 
6734                 /* Add a IP request option if we have a valid IP address */
6735                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_IP_REQ, NX_DHCP_OPTION_DHCP_IP_REQ_SIZE,
6736                                           interface_record -> nx_dhcp_ip_address, &index);
6737             }
6738 
6739             /* Add an option request for an infinite lease.  */
6740             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_LEASE, NX_DHCP_OPTION_DHCP_LEASE_SIZE, NX_DHCP_INFINITE_LEASE, &index);
6741 
6742             /* Add the system name */
6743             if (dhcp_ptr -> nx_dhcp_name)
6744             {
6745 
6746                 /* Check name length.  */
6747                 if (_nx_utility_string_length_check(dhcp_ptr -> nx_dhcp_name, &name_length, 255))
6748                 {
6749                     nx_packet_release(packet_ptr);
6750                     return(NX_DHCP_INVALID_NAME);
6751                 }
6752 
6753                 _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_HOST_NAME, name_length,
6754                                            (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index);
6755             }
6756 
6757             /* Add parameter request option.  */
6758             _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
6759 
6760 #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
6761 
6762             /* Add an option to specify the maximum length DHCP message that DHCP Client is willing to accept.
6763                RFC2132, Section9.10, Page28.  */
6764             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_MAX_DHCP_MESSAGE, 2, dhcp_ptr -> nx_dhcp_max_dhcp_message_size, &index);
6765 #endif
6766 
6767             /* Increment the number of Discovery messages sent.  */
6768             interface_record -> nx_dhcp_discoveries_sent++;
6769             break;
6770 
6771         case NX_DHCP_TYPE_DHCPREQUEST:
6772 
6773             /* Add the system name */
6774             if (dhcp_ptr -> nx_dhcp_name)
6775             {
6776 
6777                 /* Check name length.  */
6778                 if (_nx_utility_string_length_check(dhcp_ptr -> nx_dhcp_name, &name_length, 255))
6779                 {
6780                     nx_packet_release(packet_ptr);
6781                     return(NX_DHCP_INVALID_NAME);
6782                 }
6783 
6784                 _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_HOST_NAME, name_length, (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index);
6785             }
6786 
6787             /* Determine if we have a valid IP address. Must not include if Renewing or Rebinding RCV 2131 4.3.2.  */
6788             if ((interface_record -> nx_dhcp_ip_address != NX_BOOTP_NO_ADDRESS) &&
6789                 (interface_record -> nx_dhcp_ip_address != NX_BOOTP_BC_ADDRESS) &&
6790                 (interface_record -> nx_dhcp_state != NX_DHCP_STATE_RENEWING) &&
6791                 (interface_record -> nx_dhcp_state != NX_DHCP_STATE_REBINDING))
6792             {
6793 
6794                 /* Add an IP request option if we have a valid IP address.  */
6795                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_IP_REQ, NX_DHCP_OPTION_DHCP_IP_REQ_SIZE,
6796                                           interface_record -> nx_dhcp_ip_address, &index);
6797             }
6798 
6799             /* Add a request for an infinite lease if we haven't already set the timers.  */
6800             if ((interface_record -> nx_dhcp_rebind_time == 0) ||
6801                 (interface_record -> nx_dhcp_renewal_time == 0))
6802             {
6803 
6804                 /* Add the infinite lease option.  */
6805                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_LEASE, NX_DHCP_OPTION_DHCP_LEASE_SIZE, NX_DHCP_INFINITE_LEASE, &index);
6806             }
6807 
6808             /* Should add server ID if not renewing.  */
6809             if ((interface_record -> nx_dhcp_state != NX_DHCP_STATE_RENEWING) &&
6810                 (interface_record -> nx_dhcp_state != NX_DHCP_STATE_REBINDING) &&
6811                 (interface_record -> nx_dhcp_server_ip != NX_BOOTP_BC_ADDRESS) &&
6812                 (interface_record -> nx_dhcp_server_ip != NX_BOOTP_NO_ADDRESS)
6813                )
6814             {
6815 
6816                 /* Add Server identifier option.  */
6817                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_SERVER, NX_DHCP_OPTION_DHCP_SERVER_SIZE,
6818                                           interface_record -> nx_dhcp_server_ip, &index);
6819             }
6820             else if ((interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING) ||
6821                      (interface_record -> nx_dhcp_state == NX_DHCP_STATE_REBINDING))
6822 
6823             {
6824 
6825                 /* Ensure the renewal message fields are correct.  */
6826                 _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
6827             }
6828 
6829             /* Add parameter request option.  */
6830             _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
6831 
6832 #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
6833 
6834             /* Add an option to specify the maximum length DHCP message that DHCP Client is willing to accept.
6835                RFC2132, Section9.10, Page28.  */
6836             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_MAX_DHCP_MESSAGE, 2, dhcp_ptr -> nx_dhcp_max_dhcp_message_size, &index);
6837 #endif
6838 
6839             /* Increment the number of Request messages sent.  */
6840             interface_record -> nx_dhcp_requests_sent++;
6841             break;
6842 
6843         case NX_DHCP_TYPE_DHCPDECLINE:
6844 
6845             /* Does the Client have a nonzero requested address it is declining? */
6846             if ((interface_record -> nx_dhcp_ip_address != NX_BOOTP_NO_ADDRESS) &&
6847                 (interface_record -> nx_dhcp_ip_address != NX_BOOTP_BC_ADDRESS))
6848             {
6849 
6850                 /* Yes; add Request IP address option.  */
6851                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_IP_REQ, NX_DHCP_OPTION_DHCP_IP_REQ_SIZE,
6852                                           interface_record -> nx_dhcp_ip_address, &index);
6853             }
6854 
6855             /* Add Server identifier option.  */
6856             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_SERVER, NX_DHCP_OPTION_DHCP_SERVER_SIZE,
6857                                       interface_record -> nx_dhcp_server_ip, &index);
6858 
6859             break;
6860 
6861         case NX_DHCP_TYPE_DHCPRELEASE:
6862 
6863             /* Added the 'ciaddr', Indicate the IP address being released.  */
6864             _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
6865 
6866             /* Add Server identifier option.  */
6867             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_SERVER, NX_DHCP_OPTION_DHCP_SERVER_SIZE,
6868                                       interface_record -> nx_dhcp_server_ip, &index);
6869 
6870             /* Increment the number of Release messages sent.  */
6871             interface_record -> nx_dhcp_releases_sent++;
6872             break;
6873 
6874         case NX_DHCP_TYPE_DHCPINFORM:
6875 
6876             /* Add the system name */
6877             if (dhcp_ptr -> nx_dhcp_name)
6878             {
6879 
6880                 /* Check name length.  */
6881                 if (_nx_utility_string_length_check(dhcp_ptr -> nx_dhcp_name, &name_length, 255))
6882                 {
6883                     nx_packet_release(packet_ptr);
6884                     return(NX_DHCP_INVALID_NAME);
6885                 }
6886 
6887                 _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_HOST_NAME, name_length, (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index);
6888             }
6889 
6890             /* Add parameter request option.  */
6891             _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
6892 
6893             /* Increment the number of Inform messages sent.  */
6894             interface_record -> nx_dhcp_informs_sent++;
6895 
6896             break;
6897 
6898         default:
6899             break;
6900     }
6901 
6902     /* Add any user supplied options to the buffer.  */
6903     if (dhcp_ptr -> nx_dhcp_user_option_add)
6904     {
6905 
6906         /* Set the pointer for adding user option.  */
6907         user_option_ptr = buffer + index;
6908 
6909         /* Calculate the available length for user options. Minus 1 to add the END option.  */
6910         user_option_length = (UINT)(packet_ptr -> nx_packet_data_end - user_option_ptr - 1);
6911 
6912         /* Add the specific DHCP option user wanted.  */
6913         if (dhcp_ptr -> nx_dhcp_user_option_add(dhcp_ptr, iface_index, dhcp_message_type, user_option_ptr, &user_option_length) == NX_TRUE)
6914         {
6915 
6916             /* Update the index to include the user options.  */
6917             index += user_option_length;
6918         }
6919         else
6920         {
6921 
6922             /* Invalid user options. Release the packet.  */
6923             nx_packet_release(packet_ptr);
6924             return(NX_DHCP_UNKNOWN_OPTION);
6925         }
6926     }
6927 
6928     /* Setup the packet pointers.  */
6929     packet_ptr -> nx_packet_length =      NX_BOOTP_OFFSET_END;
6930     packet_ptr -> nx_packet_append_ptr =  packet_ptr -> nx_packet_prepend_ptr + NX_BOOTP_OFFSET_END;
6931 
6932 #ifndef NX_DHCP_ENABLE_BOOTP
6933 
6934     /* Added the END option.  */
6935     *(buffer + index) = NX_DHCP_OPTION_END;
6936     index ++;
6937 
6938     /* Check the option length.  */
6939     if (index > NX_BOOTP_OFFSET_END)
6940     {
6941         packet_ptr -> nx_packet_length = index;
6942         packet_ptr -> nx_packet_append_ptr =  packet_ptr -> nx_packet_prepend_ptr + index;
6943     }
6944 #endif
6945 
6946     /* Set the target address according to RFC2131, Section4.3.6, Page33, Table4 and Section4.4.4, Page40.
6947        DHCP Request for renewing and DHCP Release message must be unicast.  */
6948     if (((dhcp_message_type == NX_DHCP_TYPE_DHCPREQUEST) && (interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING)) ||
6949         (dhcp_message_type == NX_DHCP_TYPE_DHCPRELEASE))
6950     {
6951 
6952         /* Use the current server's IP address.  */
6953         targetIP = interface_record -> nx_dhcp_server_ip;
6954     }
6955     else
6956     {
6957 
6958         /* Set the server target IP address to broadcast.  */
6959         targetIP = NX_BOOTP_BC_ADDRESS;
6960     }
6961 
6962     /* DHCP messages broadcast by a client prior to that client obtaining
6963        its IP address must have the source address field in the IP header
6964        set to 0. RFC2131, Section4.1, Page23.  */
6965     if ((dhcp_message_type == NX_DHCP_TYPE_DHCPDISCOVER) ||
6966         ((dhcp_message_type == NX_DHCP_TYPE_DHCPREQUEST) && (interface_record -> nx_dhcp_state < NX_DHCP_STATE_BOUND)))
6967     {
6968 
6969         /* Call function to send the special packet with zero source address.*/
6970         status = _nx_dhcp_client_send_with_zero_source_address(dhcp_ptr, iface_index, packet_ptr);
6971     }
6972     else
6973     {
6974 
6975         /* Send the packet.  */
6976         status = nx_udp_socket_interface_send(&(dhcp_ptr -> nx_dhcp_socket), packet_ptr, targetIP, NX_DHCP_SERVER_UDP_PORT, iface_index);
6977     }
6978 
6979     /* If an error is detected, release the packet. */
6980     if (status != NX_SUCCESS)
6981     {
6982 
6983         /* Release the packet.  */
6984         nx_packet_release(packet_ptr);
6985     }
6986 
6987     /* Return completion status.  */
6988     return(status);
6989 }
6990 
6991 
6992 /**************************************************************************/
6993 /*                                                                        */
6994 /*  FUNCTION                                               RELEASE        */
6995 /*                                                                        */
6996 /*    _nx_dhcp_client_send_with_zero_source_address       PORTABLE C      */
6997 /*                                                           6.3.0        */
6998 /*  AUTHOR                                                                */
6999 /*                                                                        */
7000 /*    Yuxin Zhou, Microsoft Corporation                                   */
7001 /*                                                                        */
7002 /*  DESCRIPTION                                                           */
7003 /*                                                                        */
7004 /*    This function builds the UDP and IP header with zero source address,*/
7005 /*    then sends the packet to the appropriate link driver.               */
7006 /*                                                                        */
7007 /*  INPUT                                                                 */
7008 /*                                                                        */
7009 /*    dhcp_ptr                              Pointer to DHCP instance      */
7010 /*    iface_index                           Interface to send message on  */
7011 /*    packet_ptr                            Pointer to packet to send     */
7012 /*                                                                        */
7013 /*  OUTPUT                                                                */
7014 /*                                                                        */
7015 /*    status                                Completion status             */
7016 /*                                                                        */
7017 /*  CALLS                                                                 */
7018 /*                                                                        */
7019 /*    (ip_link_driver)                      User supplied link driver     */
7020 /*                                                                        */
7021 /*  CALLED BY                                                             */
7022 /*                                                                        */
7023 /*    _nx_dhcp_send_request_internal        Send DHCP Request             */
7024 /*                                                                        */
7025 /*  RELEASE HISTORY                                                       */
7026 /*                                                                        */
7027 /*    DATE              NAME                      DESCRIPTION             */
7028 /*                                                                        */
7029 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7030 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7031 /*                                            resulting in version 6.1    */
7032 /*  08-02-2021     Yuxin Zhou               Modified comment(s), and      */
7033 /*                                            supported new ip filter,    */
7034 /*                                            resulting in version 6.1.8  */
7035 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
7036 /*                                            set the IP header pointer,  */
7037 /*                                            resulting in version 6.1.11 */
7038 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
7039 /*                                            improved internal logic,    */
7040 /*                                            and solve inconformity with */
7041 /*                                            udp socket send and ip      */
7042 /*                                            header add,                 */
7043 /*                                            resulting in version 6.1.12 */
7044 /*  10-31-2023     Tiejun Zhou              Modified comment(s),          */
7045 /*                                            supported random IP id,     */
7046 /*                                            resulting in version 6.3.0  */
7047 /*                                                                        */
7048 /**************************************************************************/
_nx_dhcp_client_send_with_zero_source_address(NX_DHCP * dhcp_ptr,UINT iface_index,NX_PACKET * packet_ptr)7049 static UINT  _nx_dhcp_client_send_with_zero_source_address(NX_DHCP *dhcp_ptr, UINT iface_index, NX_PACKET *packet_ptr)
7050 {
7051 
7052 NX_IP          *ip_ptr;
7053 NX_UDP_SOCKET  *socket_ptr;
7054 NX_UDP_HEADER  *udp_header_ptr;
7055 NX_IPV4_HEADER *ip_header_ptr;
7056 NX_INTERFACE   *interface_ptr;
7057 ULONG           ip_src_addr, ip_dest_addr;
7058 #if defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY)
7059 UINT            compute_checksum = 1;
7060 #endif /* defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */
7061 ULONG           checksum;
7062 ULONG           val;
7063 NX_IP_DRIVER    driver_request;
7064 
7065     /* Set up the pointer to the associated IP instance.  */
7066     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
7067 
7068     /* Set up the pointer to the associated socket.  */
7069     socket_ptr = &dhcp_ptr -> nx_dhcp_socket;
7070 
7071     /* Set up the pointer to the interface.  */
7072     interface_ptr = &(ip_ptr -> nx_ip_interface[iface_index]);
7073     packet_ptr -> nx_packet_ip_interface = interface_ptr;
7074 
7075     /* Set up the address.  */
7076     ip_src_addr = NX_BOOTP_NO_ADDRESS;
7077     ip_dest_addr = NX_BOOTP_BC_ADDRESS;
7078 
7079     /* Check the interface.  */
7080     if ((!interface_ptr -> nx_interface_valid) || (!interface_ptr -> nx_interface_link_up))
7081     {
7082 
7083         /* None found; return the error status. */
7084         return(NX_INVALID_INTERFACE);
7085     }
7086 
7087     /* Build UDP header.  */
7088 
7089     /* Prepend the UDP header to the packet.  First, make room for the UDP header.  */
7090     packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER);
7091 
7092     /* Set the correct IP version. */
7093     packet_ptr -> nx_packet_ip_version = NX_IP_VERSION_V4;
7094 
7095 #ifndef NX_DISABLE_UDP_INFO
7096     /* Increment the total UDP packets sent count.  */
7097     ip_ptr -> nx_ip_udp_packets_sent++;
7098 
7099     /* Increment the total UDP bytes sent.  */
7100     ip_ptr -> nx_ip_udp_bytes_sent +=  packet_ptr -> nx_packet_length;
7101 
7102     /* Increment the total UDP packets sent count for this socket.  */
7103     socket_ptr -> nx_udp_socket_packets_sent++;
7104 
7105     /* Increment the total UDP bytes sent for this socket.  */
7106     socket_ptr -> nx_udp_socket_bytes_sent +=  packet_ptr -> nx_packet_length;
7107 #endif
7108 
7109     /* Increase the packet length.  */
7110     packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_UDP_HEADER);
7111 
7112     /* Setup the UDP header pointer.  */
7113     udp_header_ptr =  (NX_UDP_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
7114 
7115     /* Build the first 32-bit word of the UDP header.  */
7116     udp_header_ptr -> nx_udp_header_word_0 = (((ULONG)socket_ptr -> nx_udp_socket_port ) << NX_SHIFT_BY_16) | (ULONG) NX_DHCP_SERVER_UDP_PORT;
7117 
7118     /* Build the second 32-bit word of the UDP header.  */
7119     udp_header_ptr -> nx_udp_header_word_1 =  (packet_ptr -> nx_packet_length << NX_SHIFT_BY_16);
7120 
7121     /* Endian swapping logic.  If NX_LITTLE_ENDIAN is specified, these macros will
7122        swap the endian of the UDP header.  */
7123     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0);
7124     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
7125 
7126 #ifdef NX_DISABLE_UDP_TX_CHECKSUM
7127     compute_checksum = 0;
7128 #endif /* NX_DISABLE_UDP_TX_CHECKSUM */
7129 
7130 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
7131     if (interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM)
7132         compute_checksum = 0;
7133 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
7134 
7135 #if defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY)
7136     if (compute_checksum)
7137 #endif /* defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */
7138     {
7139         /* Yes, we need to compute the UDP checksum.  */
7140         checksum = _nx_ip_checksum_compute(packet_ptr,
7141                                            NX_PROTOCOL_UDP,
7142                                            (UINT)packet_ptr -> nx_packet_length,
7143                                            &ip_src_addr,
7144                                            &ip_dest_addr);
7145 
7146         checksum = ~checksum & NX_LOWER_16_MASK;
7147 
7148         /* If the computed checksum is zero, it will be transmitted as all ones. */
7149         /* RFC 768, page 2. */
7150         if (checksum == 0)
7151             checksum = 0xFFFF;
7152 
7153         NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
7154 
7155         udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 | checksum;
7156 
7157         NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
7158     }
7159 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
7160     else
7161         /* Set CHECKSUM flag so the driver would invoke the HW checksum. */
7162         packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM;
7163 #endif /* NX_ENABLE_INTERFACE_CAPABILITY  */
7164 
7165     /* Get mutex protection.  */
7166     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
7167 
7168     /* Build the IP header.  */
7169 
7170     /* Prepend the IP header to the packet.  First, make room for the IP header.  */
7171     packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - 20;
7172 
7173     /* Increase the packet length.  */
7174     packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + 20;
7175 
7176     /* Setup the IP header pointer.  */
7177     ip_header_ptr =  (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
7178     packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr;
7179     packet_ptr -> nx_packet_ip_header_length = sizeof(NX_IPV4_HEADER);
7180 
7181     /* Build the first 32-bit word of the IP header.  */
7182     ip_header_ptr -> nx_ip_header_word_0 =  (NX_IP_VERSION | socket_ptr -> nx_udp_socket_type_of_service | (0xFFFF & packet_ptr -> nx_packet_length));
7183 
7184     /* Build the second 32-bit word of the IP header.  */
7185 #ifdef NX_ENABLE_IP_ID_RANDOMIZATION
7186     ip_header_ptr -> nx_ip_header_word_1 =  (((ULONG)NX_RAND()) << NX_SHIFT_BY_16) | socket_ptr -> nx_udp_socket_fragment_enable;
7187 #else
7188     ip_header_ptr -> nx_ip_header_word_1 =  (ip_ptr -> nx_ip_packet_id++ << NX_SHIFT_BY_16) | socket_ptr -> nx_udp_socket_fragment_enable;
7189 #endif /* NX_ENABLE_IP_ID_RANDOMIZATION */
7190 
7191     /* Build the third 32-bit word of the IP header.  */
7192     ip_header_ptr -> nx_ip_header_word_2 =  ((socket_ptr -> nx_udp_socket_time_to_live << NX_IP_TIME_TO_LIVE_SHIFT) | NX_IP_UDP);
7193 
7194     /* Place the source IP address in the IP header.  */
7195     ip_header_ptr -> nx_ip_header_source_ip =  ip_src_addr;
7196 
7197     /* Place the destination IP address in the IP header.  */
7198     ip_header_ptr -> nx_ip_header_destination_ip =  ip_dest_addr;
7199 
7200     /* Endian swapping logic.  If NX_LITTLE_ENDIAN is specified, these macros will
7201        swap the endian of the IP header.  */
7202     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_0);
7203     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_1);
7204     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_2);
7205     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip);
7206     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip);
7207 
7208 #ifdef NX_DISABLE_IP_TX_CHECKSUM
7209     compute_checksum = 0;
7210 #elif defined(NX_ENABLE_INTERFACE_CAPABILITY)
7211     /* Re-initialize the value back to the default initial value (i.e. 1) */
7212     compute_checksum = 1;
7213 #endif /* defined(NX_DISABLE_IP_TX_CHECKSUM) */
7214 
7215 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
7216     if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM)
7217         compute_checksum = 0;
7218 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
7219 
7220 #if defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY)
7221     if (compute_checksum)
7222 #endif /* defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */
7223     {
7224         checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_VERSION_V4, 20, NULL, NULL);
7225 
7226         val = (ULONG)(~checksum);
7227         val = val & NX_LOWER_16_MASK;
7228 
7229         /* Convert to network byte order. */
7230         NX_CHANGE_ULONG_ENDIAN(val);
7231 
7232         /* Now store the checksum in the IP header.  */
7233         ip_header_ptr -> nx_ip_header_word_2 =  ip_header_ptr -> nx_ip_header_word_2 | val;
7234     }
7235 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
7236     else
7237     {
7238         packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM;
7239     }
7240 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
7241 
7242 #ifdef NX_ENABLE_IP_PACKET_FILTER
7243     /* Check if the IP packet filter is set.  */
7244     if (ip_ptr -> nx_ip_packet_filter)
7245     {
7246 
7247         /* Yes, call the IP packet filter routine.  */
7248         if ((ip_ptr -> nx_ip_packet_filter((VOID *)(ip_header_ptr), NX_IP_PACKET_OUT)) != NX_SUCCESS)
7249         {
7250 
7251             /* Release mutex protection.  */
7252             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7253 
7254             /* Return a not successful status.  */
7255             return(NX_NOT_SUCCESSFUL);
7256         }
7257     }
7258 
7259     /* Check if the IP packet filter extended is set. */
7260     if (ip_ptr -> nx_ip_packet_filter_extended)
7261     {
7262 
7263         /* Yes, call the IP packet filter extended routine. */
7264         if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS)
7265         {
7266 
7267             /* Release mutex protection.  */
7268             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7269 
7270             /* Return a not successful status.  */
7271             return(NX_NOT_SUCCESSFUL);
7272         }
7273     }
7274 #endif /* NX_ENABLE_IP_PACKET_FILTER */
7275 
7276     /* Build the driver request.  */
7277     driver_request.nx_ip_driver_ptr =                   ip_ptr;
7278     driver_request.nx_ip_driver_packet =                packet_ptr;
7279     driver_request.nx_ip_driver_interface =             packet_ptr -> nx_packet_ip_interface;
7280     driver_request.nx_ip_driver_command =               NX_LINK_PACKET_BROADCAST;
7281     driver_request.nx_ip_driver_physical_address_msw =  0xFFFFUL;
7282     driver_request.nx_ip_driver_physical_address_lsw =  0xFFFFFFFFUL;
7283 
7284     /* Determine if fragmentation is needed.  */
7285     if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_mtu_size)
7286     {
7287 
7288 #ifndef NX_DISABLE_FRAGMENTATION
7289         /* Check the DF bit flag.  */
7290         if ((ip_ptr -> nx_ip_fragment_processing) && (socket_ptr -> nx_udp_socket_fragment_enable != NX_DONT_FRAGMENT))
7291         {
7292 
7293             /* Fragmentation is needed, call the IP fragment processing routine.  */
7294             (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
7295 
7296             /* Release mutex protection.  */
7297             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7298 
7299             /* Return a successful status.  */
7300             return(NX_SUCCESS);
7301         }
7302         else
7303 #endif /* NX_DISABLE_FRAGMENTATION */
7304         {
7305 
7306 #ifndef NX_DISABLE_IP_INFO
7307 
7308             /* Increment the IP send packets dropped count.  */
7309             ip_ptr -> nx_ip_send_packets_dropped++;
7310 #endif
7311 
7312             /* Release mutex protection.  */
7313             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7314 
7315             /* Return a not successful status.  */
7316             return(NX_NOT_SUCCESSFUL);
7317         }
7318     }
7319 
7320 #ifndef NX_DISABLE_IP_INFO
7321 
7322     /* Increment the IP packet sent count.  */
7323     ip_ptr -> nx_ip_total_packets_sent++;
7324 
7325     /* Increment the IP bytes sent count.  */
7326     ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - 20;
7327 #endif
7328 
7329     /* Broadcast packet.  */
7330     (packet_ptr -> nx_packet_ip_interface -> nx_interface_link_driver_entry) (&driver_request);
7331 
7332     /* Release mutex protection.  */
7333     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7334 
7335     /* Return a successful status.  */
7336     return(NX_SUCCESS);
7337 }
7338 
7339 
7340 
7341 
7342 /**************************************************************************/
7343 /*                                                                        */
7344 /*  FUNCTION                                               RELEASE        */
7345 /*                                                                        */
7346 /*    _nx_dhcp_extract_information                        PORTABLE C      */
7347 /*                                                           6.1          */
7348 /*  AUTHOR                                                                */
7349 /*                                                                        */
7350 /*    Yuxin Zhou, Microsoft Corporation                                   */
7351 /*                                                                        */
7352 /*  DESCRIPTION                                                           */
7353 /*                                                                        */
7354 /*    This function extracts important information from the server's      */
7355 /*    response DHCP message.                                              */
7356 /*                                                                        */
7357 /*  INPUT                                                                 */
7358 /*                                                                        */
7359 /*    dhcp_ptr                              Pointer to DHCP instance      */
7360 /*    interface_record                      Pointer to DHCP interface     */
7361 /*    dhcp_message                          Pointer to DHCP message       */
7362 /*    length                                Size of DHCP message buffer   */
7363 /*                                                                        */
7364 /*  OUTPUT                                                                */
7365 /*                                                                        */
7366 /*    status                                Completion status             */
7367 /*                                                                        */
7368 /*  CALLS                                                                 */
7369 /*                                                                        */
7370 /*    _nx_dhcp_ip_address_set               Set the DHCP IP address       */
7371 /*    nx_ip_gateway_address_set             Set the Gateway address       */
7372 /*    _nx_dhcp_get_option_value             Get DHCP option from buffer   */
7373 /*    _nx_dhcp_get_data                     Get data from buffer          */
7374 /*    memcpy                                Copy specified area of memory */
7375 /*                                                                        */
7376 /*  CALLED BY                                                             */
7377 /*                                                                        */
7378 /*    _nx_dhcp_packet_process               Data received handler         */
7379 /*                                                                        */
7380 /*  RELEASE HISTORY                                                       */
7381 /*                                                                        */
7382 /*    DATE              NAME                      DESCRIPTION             */
7383 /*                                                                        */
7384 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7385 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
7386 /*                                            verified memcpy use cases,  */
7387 /*                                            resulting in version 6.1    */
7388 /*                                                                        */
7389 /**************************************************************************/
_nx_dhcp_extract_information(NX_DHCP * dhcp_ptr,NX_DHCP_INTERFACE_RECORD * interface_record,UCHAR * dhcp_message,UINT length)7390 static UINT  _nx_dhcp_extract_information(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, UCHAR *dhcp_message, UINT length)
7391 {
7392 
7393 ULONG       value;
7394 
7395 
7396     /* Extract the IP address.  */
7397     value =  _nx_dhcp_get_data(dhcp_message + NX_BOOTP_OFFSET_YOUR_IP, 4);
7398 
7399     /* Determine if it is valid.  */
7400     if ((value != NX_BOOTP_NO_ADDRESS) &&
7401         (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7402          ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7403          ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7404     {
7405 
7406         /* Store the IP address.  */
7407         interface_record -> nx_dhcp_ip_address =  value;
7408     }
7409     else
7410     {
7411         return(NX_DHCP_BAD_IP_ADDRESS);
7412     }
7413 
7414     /* Determine if there is a subnet mask. Note a DHCP Server receiving a BOOTP request
7415        may send DHCP option data for subnet masks as per RFC 1534 Section 2.  */
7416     if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_SUBNET_MASK, &value, length) == NX_SUCCESS)
7417     {
7418 
7419         /* Make sure there is a valid IP address too.  */
7420         if (value != NX_BOOTP_NO_ADDRESS)
7421         {
7422 
7423             interface_record -> nx_dhcp_network_mask =  value;
7424         }
7425         else
7426         {
7427             ULONG ip_address;
7428 
7429             /* No valid network mask info supplied; use the current network mask if any. Don't
7430                care about current IP address for now. */
7431             nx_ip_interface_address_get(dhcp_ptr -> nx_dhcp_ip_ptr,
7432                                         interface_record -> nx_dhcp_interface_index,
7433                                         &ip_address,
7434                                         &(interface_record -> nx_dhcp_network_mask));
7435         }
7436     }
7437 
7438 #ifdef NX_DHCP_ENABLE_BOOTP
7439 
7440     /* Update the IP address.  */
7441     value =  _nx_dhcp_get_data(dhcp_message + NX_BOOTP_OFFSET_SERVER_IP, 4);
7442 
7443     /* Determine if it is valid.  */
7444     if (value != NX_BOOTP_NO_ADDRESS)
7445     {
7446 
7447         /* Store the IP address.  */
7448         interface_record -> nx_dhcp_server_ip =  value;
7449     }
7450 
7451     /* Update the  IP address.  */
7452     value =  _nx_dhcp_get_data(dhcp_message + NX_BOOTP_OFFSET_GATEWAY_IP, 4);
7453 
7454     /* Determine if it is valid.  */
7455     if ((value != NX_BOOTP_NO_ADDRESS) &&
7456         (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7457          ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7458          ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7459     {
7460 
7461         /* Store the gateway/Router IP address to the Client record.  */
7462         interface_record -> nx_dhcp_gateway_address = value;
7463     }
7464     else
7465     {
7466 
7467         /* The gateway may be sent as an option: See note above about BOOTP Clients
7468            parsing DHCP option data. */
7469 
7470         /* Determine if the IP gateway/router IP address is present.  */
7471         if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_GATEWAYS, &value, length) == NX_SUCCESS)
7472         {
7473 
7474             /* Determine if it is valid.  */
7475             if ((value != NX_BOOTP_NO_ADDRESS) &&
7476                 (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7477                  ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7478                  ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7479             {
7480 
7481                 /* Store the gateway/Router IP address to the Client record.  */
7482                 interface_record -> nx_dhcp_gateway_address = value;
7483             }
7484             else
7485             {
7486                 return(NX_DHCP_BAD_IP_ADDRESS);
7487             }
7488         }
7489     }
7490 
7491 #else
7492 
7493     /* NX_DHCP_ENABLE_BOOTP  not defined */
7494 
7495     /* Overwrite the server ID if there is a DHCP option for Server ID */
7496     if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_DHCP_SERVER, &value, length) == NX_SUCCESS)
7497     {
7498 
7499         /* Determine if it is valid.  */
7500         if ((value != NX_BOOTP_NO_ADDRESS) &&
7501             (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7502              ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7503              ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7504         {
7505 
7506             /* Store the server IP address.  */
7507             interface_record -> nx_dhcp_server_ip = value;
7508         }
7509         else
7510         {
7511             return(NX_DHCP_BAD_IP_ADDRESS);
7512         }
7513     }
7514 
7515     /* Get the lease time.  */
7516     if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_DHCP_LEASE, &value, length) == NX_SUCCESS)
7517     {
7518 
7519         /* Check for an infinite lease. */
7520         if (value == 0xFFFFFFFF)
7521         {
7522             /* Store the 'infinite' lease time . */
7523             interface_record -> nx_dhcp_lease_time = value;
7524             interface_record -> nx_dhcp_renewal_time = value;
7525             interface_record -> nx_dhcp_rebind_time = value;
7526         }
7527         else
7528         {
7529 
7530             /* Store the lease time in timer ticks.  */
7531             interface_record -> nx_dhcp_lease_time =  value * (ULONG)NX_IP_PERIODIC_RATE;
7532 
7533             /* Set the renew and rebind times.  */
7534             interface_record -> nx_dhcp_renewal_time = interface_record -> nx_dhcp_lease_time / 2;
7535             interface_record -> nx_dhcp_rebind_time =  interface_record -> nx_dhcp_lease_time - (interface_record -> nx_dhcp_lease_time / 8);
7536         }
7537     }
7538 
7539     /* Overwrite the renew and rebind times with the specified values if the options are present.  */
7540     if ((_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_RENEWAL, &value, length) == NX_SUCCESS) &&
7541         (value <= interface_record -> nx_dhcp_lease_time))
7542     {
7543 
7544         /* Check for an infinite lease. */
7545         if (value == 0xFFFFFFFF)
7546         {
7547             /* Set the 'infinite least time.  */
7548             interface_record -> nx_dhcp_renewal_time = value;
7549         }
7550         else
7551         {
7552 
7553             /* Store the renewal time in timer ticks  */
7554             interface_record -> nx_dhcp_renewal_time =  value * (ULONG)NX_IP_PERIODIC_RATE;
7555         }
7556     }
7557 
7558     /* Determine if there is a rebind time.  */
7559     if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_REBIND, &value, length) == NX_SUCCESS)
7560     {
7561 
7562         /* Check for an infinite lease. */
7563         if (value == 0xFFFFFFFF)
7564         {
7565 
7566             /* Set the 'infinite least time.  */
7567             interface_record -> nx_dhcp_rebind_time = value;
7568         }
7569         else
7570         {
7571 
7572             /* Convert to timer ticks. */
7573             value = value * (ULONG)NX_IP_PERIODIC_RATE;
7574 
7575             /* Sanity check*/
7576             if ((value <= interface_record -> nx_dhcp_lease_time) &&
7577                 (value >= interface_record -> nx_dhcp_renewal_time))
7578             {
7579 
7580                 /* Store the rebind time.  */
7581                 interface_record -> nx_dhcp_rebind_time =  value;
7582             }
7583         }
7584     }
7585 
7586     /* Determine if this is an ACK from a server response, which can only happen from a handful of states.  */
7587     if ((interface_record -> nx_dhcp_state == NX_DHCP_STATE_REQUESTING) ||
7588         (interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING) ||
7589         (interface_record -> nx_dhcp_state == NX_DHCP_STATE_REBINDING))
7590     {
7591 
7592         /* Determine if the IP gateway/router IP address is present.  */
7593         if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_GATEWAYS, &value, length) == NX_SUCCESS)
7594         {
7595 
7596             /* Determine if it is valid.  */
7597             if ((value != NX_BOOTP_NO_ADDRESS) &&
7598                 (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7599                  ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7600                  ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7601             {
7602 
7603                 /* Store the gateway/Router IP address to the Client record.  */
7604                 interface_record -> nx_dhcp_gateway_address = value;
7605             }
7606             else
7607             {
7608                 return(NX_DHCP_BAD_IP_ADDRESS);
7609             }
7610         }
7611     }
7612 
7613      /* Check the DHCP options size.  */
7614      if ((length - NX_BOOTP_OFFSET_OPTIONS) > NX_DHCP_OPTIONS_BUFFER_SIZE)
7615          interface_record -> nx_dhcp_options_size = NX_DHCP_OPTIONS_BUFFER_SIZE;
7616      else
7617          interface_record -> nx_dhcp_options_size = length - NX_BOOTP_OFFSET_OPTIONS;
7618 
7619      /* Copy the DHCP options into DHCP Client options buffer.  */
7620      memcpy(interface_record -> nx_dhcp_options_buffer, /* Use case of memcpy is verified. */
7621             &dhcp_message[NX_BOOTP_OFFSET_OPTIONS], interface_record -> nx_dhcp_options_size);
7622 
7623 #endif  /* NX_DHCP_ENABLE_BOOTP */
7624 
7625     return (NX_SUCCESS);
7626 }
7627 
7628 
7629 /**************************************************************************/
7630 /*                                                                        */
7631 /*  FUNCTION                                               RELEASE        */
7632 /*                                                                        */
7633 /*    _nx_dhcp_get_option_value                           PORTABLE C      */
7634 /*                                                           6.1.12       */
7635 /*  AUTHOR                                                                */
7636 /*                                                                        */
7637 /*    Yuxin Zhou, Microsoft Corporation                                   */
7638 /*                                                                        */
7639 /*  DESCRIPTION                                                           */
7640 /*                                                                        */
7641 /*    This function searches through a buffer containing a BootP message  */
7642 /*    for a DHCP option parameter and gets the value of that option if    */
7643 /*    it exists. The function is restricted to options that are less      */
7644 /*    than 4 octets (bytes) in size.                                      */
7645 /*                                                                        */
7646 /*  INPUT                                                                 */
7647 /*                                                                        */
7648 /*    bootp_message                         Pointer to option buffer      */
7649 /*    option                                Option requested              */
7650 /*    value                                 Pointer to return value var   */
7651 /*    length                                Size of option buffer         */
7652 /*                                                                        */
7653 /*  OUTPUT                                                                */
7654 /*                                                                        */
7655 /*    status                                Completion status             */
7656 /*                                                                        */
7657 /*  CALLS                                                                 */
7658 /*                                                                        */
7659 /*    _nx_dhcp_search_buffer                Search the buffer             */
7660 /*    _nx_dhcp_get_data                     Get data from buffer          */
7661 /*                                                                        */
7662 /*  CALLED BY                                                             */
7663 /*                                                                        */
7664 /*    _nx_dhcp_packet_process               Data received handler         */
7665 /*    _nx_dhcp_extract_information          Extract info from server      */
7666 /*                                                                        */
7667 /*  RELEASE HISTORY                                                       */
7668 /*                                                                        */
7669 /*    DATE              NAME                      DESCRIPTION             */
7670 /*                                                                        */
7671 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7672 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7673 /*                                            resulting in version 6.1    */
7674 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
7675 /*                                            improved internal logic,    */
7676 /*                                            resulting in version 6.1.12 */
7677 /*                                                                        */
7678 /**************************************************************************/
_nx_dhcp_get_option_value(UCHAR * bootp_message,UINT option,ULONG * value,UINT length)7679 static UINT  _nx_dhcp_get_option_value(UCHAR *bootp_message, UINT option, ULONG *value, UINT length)
7680 {
7681 
7682 UCHAR *data;
7683 UCHAR *option_message;
7684 UINT   option_length;
7685 
7686 
7687     /* Setup buffer pointer.  */
7688     option_message = &bootp_message[NX_BOOTP_OFFSET_OPTIONS];
7689     option_length = length - NX_BOOTP_OFFSET_OPTIONS;
7690 
7691     /* There is no need to check whether the option is PAD or END here since no caller will pass these 2 options
7692        and for denfensive purpose, the function below could check them and guarantee appropriate behaviour */
7693 
7694     /* Search the buffer for the option.  */
7695     data =  _nx_dhcp_search_buffer(option_message, option, option_length);
7696 
7697     /* Check to see if the option was found.  */
7698     if (data != NX_NULL)
7699     {
7700 
7701         /* Check for the proper size.  */
7702         if (*data > 4)
7703         {
7704 
7705             /* Check for the gateway option.  */
7706             if (option == NX_DHCP_OPTION_GATEWAYS)
7707             {
7708 
7709                 /* Pickup the first gateway address.  */
7710                 *value =  _nx_dhcp_get_data(data + 1, 4);
7711 
7712                 /* For now, just disregard any additional gateway addresses.  */
7713                 return(NX_SUCCESS);
7714             }
7715             else
7716             {
7717 
7718                 /* Invalid size, return error.  */
7719                 return(NX_SIZE_ERROR);
7720             }
7721         }
7722         else
7723         {
7724 
7725             /* Get the actual value.  */
7726             *value = _nx_dhcp_get_data(data + 1, *data);
7727             return(NX_SUCCESS);
7728         }
7729     }
7730 
7731     /* Return an error if not found.  */
7732     return(NX_OPTION_ERROR);
7733 }
7734 
7735 
7736 /**************************************************************************/
7737 /*                                                                        */
7738 /*  FUNCTION                                               RELEASE        */
7739 /*                                                                        */
7740 /*    _nx_dhcp_add_option_value                           PORTABLE C      */
7741 /*                                                           6.1          */
7742 /*  AUTHOR                                                                */
7743 /*                                                                        */
7744 /*    Yuxin Zhou, Microsoft Corporation                                   */
7745 /*                                                                        */
7746 /*  DESCRIPTION                                                           */
7747 /*                                                                        */
7748 /*    This routine adds a DHCP vendor option value to the BootP message   */
7749 /*    in the supplied buffer.  Adding the option includes adding the      */
7750 /*    option code, length and option data value.                          */
7751 /*                                                                        */
7752 /*  INPUT                                                                 */
7753 /*                                                                        */
7754 /*    bootp_message                         Pointer to message buffer     */
7755 /*    option                                Option to add                 */
7756 /*    value                                 Value of Option to add        */
7757 /*                                                                        */
7758 /*  OUTPUT                                                                */
7759 /*                                                                        */
7760 /*    status                                Completion status             */
7761 /*                                                                        */
7762 /*  CALLS                                                                 */
7763 /*                                                                        */
7764 /*    _nx_dhcp_store_data                   Store data value              */
7765 /*                                                                        */
7766 /*  CALLED BY                                                             */
7767 /*                                                                        */
7768 /*    _nx_dhcp_send_request_internal        Send DHCP request             */
7769 /*                                                                        */
7770 /*  RELEASE HISTORY                                                       */
7771 /*                                                                        */
7772 /*    DATE              NAME                      DESCRIPTION             */
7773 /*                                                                        */
7774 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7775 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7776 /*                                            resulting in version 6.1    */
7777 /*                                                                        */
7778 /**************************************************************************/
_nx_dhcp_add_option_value(UCHAR * bootp_message,UINT option,UINT size,ULONG value,UINT * index)7779 UINT  _nx_dhcp_add_option_value(UCHAR *bootp_message, UINT option, UINT size, ULONG value, UINT *index)
7780 {
7781 
7782 
7783     /* Store the option.  */
7784     *(bootp_message + (*index)) = (UCHAR)option;
7785     (*index) ++;
7786 
7787     /* Store the option size.  */
7788     *(bootp_message + (*index)) = (UCHAR)size;
7789     (*index) ++;
7790 
7791     /* Store the option value.  */
7792     _nx_dhcp_store_data(bootp_message + (*index), size, value);
7793     (*index) += size;
7794 
7795     /* Return a successful completion.  */
7796     return(NX_SUCCESS);
7797 }
7798 
7799 
7800 /**************************************************************************/
7801 /*                                                                        */
7802 /*  FUNCTION                                               RELEASE        */
7803 /*                                                                        */
7804 /*    _nx_dhcp_add_option_string                          PORTABLE C      */
7805 /*                                                           6.1          */
7806 /*  AUTHOR                                                                */
7807 /*                                                                        */
7808 /*    Yuxin Zhou, Microsoft Corporation                                   */
7809 /*                                                                        */
7810 /*  DESCRIPTION                                                           */
7811 /*                                                                        */
7812 /*    This routine adds a DHCP option string to the BootP message in      */
7813 /*    supplied buffer.  Adding the option includes adding the option      */
7814 /*    code, length and option string.                                     */
7815 /*                                                                        */
7816 /*  INPUT                                                                 */
7817 /*                                                                        */
7818 /*    bootp_message                         Pointer to message buffer     */
7819 /*    option                                Option to add                 */
7820 /*    size                                  Size of option string         */
7821 /*    value                                 Option string pointer         */
7822 /*                                                                        */
7823 /*  OUTPUT                                                                */
7824 /*                                                                        */
7825 /*    status                                Completion status             */
7826 /*                                                                        */
7827 /*  CALLS                                                                 */
7828 /*                                                                        */
7829 /*    _nx_dhcp_move_string                  Store option string           */
7830 /*                                                                        */
7831 /*  CALLED BY                                                             */
7832 /*                                                                        */
7833 /*    _nx_dhcp_send_request_internal       Internal DHCP message send     */
7834 /*                                                                        */
7835 /*  RELEASE HISTORY                                                       */
7836 /*                                                                        */
7837 /*    DATE              NAME                      DESCRIPTION             */
7838 /*                                                                        */
7839 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7840 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7841 /*                                            resulting in version 6.1    */
7842 /*                                                                        */
7843 /**************************************************************************/
_nx_dhcp_add_option_string(UCHAR * bootp_message,UINT option,UINT size,UCHAR * value,UINT * index)7844 static UINT  _nx_dhcp_add_option_string(UCHAR *bootp_message, UINT option, UINT size, UCHAR *value, UINT *index)
7845 {
7846 
7847     /* Store the option.  */
7848     *(bootp_message + (*index)) = (UCHAR)option;
7849     (*index) ++;
7850 
7851     /* Store the option size.  */
7852     *(bootp_message + (*index)) = (UCHAR)size;
7853     (*index) ++;
7854 
7855     /* Store the option value.  */
7856     _nx_dhcp_move_string(bootp_message + (*index), value, size);
7857     (*index) += size;
7858 
7859     /* Return a successful completion.  */
7860     return(NX_SUCCESS);
7861 }
7862 
7863 
7864 /**************************************************************************/
7865 /*                                                                        */
7866 /*  FUNCTION                                               RELEASE        */
7867 /*                                                                        */
7868 /*    _nx_dhcp_add_option_parameter_request               PORTABLE C      */
7869 /*                                                           6.1.8        */
7870 /*  AUTHOR                                                                */
7871 /*                                                                        */
7872 /*    Yuxin Zhou, Microsoft Corporation                                   */
7873 /*                                                                        */
7874 /*  DESCRIPTION                                                           */
7875 /*                                                                        */
7876 /*    This routine adds a DHCP parameter request option to the BootP      */
7877 /*    message in supplied buffer. Adding the option includes adding the   */
7878 /*    option code, length and option value.                               */
7879 /*                                                                        */
7880 /*  INPUT                                                                 */
7881 /*                                                                        */
7882 /*    dhcp_ptr                              Pointer to DHCP instance      */
7883 /*    bootp_message                         Pointer to message buffer     */
7884 /*    index                                 Index to write data           */
7885 /*                                                                        */
7886 /*  OUTPUT                                                                */
7887 /*                                                                        */
7888 /*    status                                Completion status             */
7889 /*                                                                        */
7890 /*  CALLS                                                                 */
7891 /*                                                                        */
7892 /*    _nx_dhcp_move_string                  Store option string           */
7893 /*                                                                        */
7894 /*  CALLED BY                                                             */
7895 /*                                                                        */
7896 /*    _nx_dhcp_send_request_internal       Internal DHCP message send     */
7897 /*                                                                        */
7898 /*  RELEASE HISTORY                                                       */
7899 /*                                                                        */
7900 /*    DATE              NAME                      DESCRIPTION             */
7901 /*                                                                        */
7902 /*  08-02-2021     Yuxin Zhou               Initial Version 6.1.8         */
7903 /*                                                                        */
7904 /**************************************************************************/
_nx_dhcp_add_option_parameter_request(NX_DHCP * dhcp_ptr,UCHAR * bootp_message,UINT * index)7905 static UINT  _nx_dhcp_add_option_parameter_request(NX_DHCP *dhcp_ptr, UCHAR *bootp_message, UINT *index)
7906 {
7907 
7908     /* Store the option.  */
7909     *(bootp_message + (*index)) = NX_DHCP_OPTION_DHCP_PARAMETERS;
7910     (*index) ++;
7911 
7912     /* Store the option size.  */
7913     *(bootp_message + (*index)) = (UCHAR)(NX_DHCP_REQUEST_PARAMETER_SIZE + dhcp_ptr -> nx_dhcp_user_request_parameter_size);
7914     (*index) ++;
7915 
7916     /* Store the option value.  */
7917     _nx_dhcp_move_string(bootp_message + (*index), _nx_dhcp_request_parameters, NX_DHCP_REQUEST_PARAMETER_SIZE);
7918     (*index) += (UINT)NX_DHCP_REQUEST_PARAMETER_SIZE;
7919 
7920     /* Check if there are additional user options.  */
7921     if (dhcp_ptr -> nx_dhcp_user_request_parameter_size)
7922     {
7923         _nx_dhcp_move_string(bootp_message + (*index), dhcp_ptr -> nx_dhcp_user_request_parameter, dhcp_ptr -> nx_dhcp_user_request_parameter_size);
7924         (*index) += (UCHAR)dhcp_ptr -> nx_dhcp_user_request_parameter_size;
7925     }
7926 
7927     /* Return a successful completion.  */
7928     return(NX_SUCCESS);
7929 }
7930 
7931 
7932 /**************************************************************************/
7933 /*                                                                        */
7934 /*  FUNCTION                                               RELEASE        */
7935 /*                                                                        */
7936 /*    _nx_dhcp_add_randomize                              PORTABLE C      */
7937 /*                                                           6.1.12       */
7938 /*  AUTHOR                                                                */
7939 /*                                                                        */
7940 /*    Yuxin Zhou, Microsoft Corporation                                   */
7941 /*                                                                        */
7942 /*  DESCRIPTION                                                           */
7943 /*                                                                        */
7944 /*    This routine adds randomized variance to the input timeout up to    */
7945 /*    +/- one second.                                                     */
7946 /*                                                                        */
7947 /*  INPUT                                                                 */
7948 /*                                                                        */
7949 /*    timeout                               Timeout to randomize          */
7950 /*                                                                        */
7951 /*  OUTPUT                                                                */
7952 /*                                                                        */
7953 /*    ULONG                                 Modified timeout value        */
7954 /*                                                                        */
7955 /*  CALLS                                                                 */
7956 /*                                                                        */
7957 /*    None                                                                */
7958 /*                                                                        */
7959 /*  CALLED BY                                                             */
7960 /*                                                                        */
7961 /*    nx_dhcp_process                       Process the current state of  */
7962 /*                                           the DHCP Client state machine*/
7963 /*                                                                        */
7964 /*  RELEASE HISTORY                                                       */
7965 /*                                                                        */
7966 /*    DATE              NAME                      DESCRIPTION             */
7967 /*                                                                        */
7968 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7969 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7970 /*                                            resulting in version 6.1    */
7971 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
7972 /*                                            improved internal logic,    */
7973 /*                                            resulting in version 6.1.12 */
7974 /*                                                                        */
7975 /**************************************************************************/
_nx_dhcp_add_randomize(ULONG timeout)7976 static ULONG _nx_dhcp_add_randomize(ULONG timeout)
7977 {
7978 
7979 ULONG adjustment;
7980 
7981     /* Uniform random number chosen from the range -1 to +1 second as recommended by RFC2131, Section4.1, Page24. */
7982 
7983     /* Calculate random time adjustment in timer ticks from the range 0 to NX_IP_PERIODIC_RATE * 2.  */
7984     adjustment = (ULONG)NX_RAND() % ((NX_IP_PERIODIC_RATE << 1) + 1);
7985 
7986     /* Check for adjustment.  */
7987     if (adjustment < NX_IP_PERIODIC_RATE)
7988     {
7989 
7990         /* Updated timeout, minus NX_IP_PERIODIC_RATE - adjustment.  */
7991 
7992         /* Check for timeout.  */
7993         if (timeout > (NX_IP_PERIODIC_RATE - adjustment))
7994             timeout -= (ULONG)(NX_IP_PERIODIC_RATE - adjustment);
7995         else
7996             timeout = 1; /* Set 1 here since the minmum tick for timeout shall be larger than 0 */
7997     }
7998     else
7999     {
8000 
8001         /* Updated timeout, add adjustment- NX_IP_PERIODIC_RATE.  */
8002         timeout += (ULONG)(adjustment - NX_IP_PERIODIC_RATE);
8003     }
8004 
8005     return timeout;
8006 }
8007 
8008 
8009 /**************************************************************************/
8010 /*                                                                        */
8011 /*  FUNCTION                                               RELEASE        */
8012 /*                                                                        */
8013 /*    _nx_dhcp_update_timeout                             PORTABLE C      */
8014 /*                                                           6.1          */
8015 /*  AUTHOR                                                                */
8016 /*                                                                        */
8017 /*    Yuxin Zhou, Microsoft Corporation                                   */
8018 /*                                                                        */
8019 /*  DESCRIPTION                                                           */
8020 /*                                                                        */
8021 /*    This function updates the DHCP timeout for retransmission. When the */
8022 /*    current timeout expires, this function doubles the timeout, but     */
8023 /*    limits the timeout value to NX_DHCP_MAX_RETRANS_TIMEOUT (seconds).  */
8024 /*                                                                        */
8025 /*  INPUT                                                                 */
8026 /*                                                                        */
8027 /*    timeout                               The current Timeout value     */
8028 /*                                                                        */
8029 /*  OUTPUT                                                                */
8030 /*                                                                        */
8031 /*    timeout                               The updated timeout           */
8032 /*                                                                        */
8033 /*  CALLS                                                                 */
8034 /*                                                                        */
8035 /*    _nx_dhcp_convert_delay_to_ticks       Convert the delay to ticks    */
8036 /*                                                                        */
8037 /*  CALLED BY                                                             */
8038 /*                                                                        */
8039 /*    _nx_dhcp_timeout_process               Timer expiration handler     */
8040 /*                                                                        */
8041 /*  RELEASE HISTORY                                                       */
8042 /*                                                                        */
8043 /*    DATE              NAME                      DESCRIPTION             */
8044 /*                                                                        */
8045 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8046 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8047 /*                                            resulting in version 6.1    */
8048 /*                                                                        */
8049 /**************************************************************************/
_nx_dhcp_update_timeout(ULONG timeout)8050 static ULONG _nx_dhcp_update_timeout(ULONG timeout)
8051 {
8052 
8053     /* Timed out, double the timeout, limited to NX_DHCP_MAX_RETRANS_TIMEOUT */
8054     if ((2 * timeout) >= NX_DHCP_MAX_RETRANS_TIMEOUT)
8055     {
8056 
8057         /* Set the timeout as NX_DHCP_MAX_RETRANS_TIMEOUT.  */
8058         timeout = NX_DHCP_MAX_RETRANS_TIMEOUT;
8059     }
8060     else
8061     {
8062 
8063         /* Double timeout value.  */
8064         timeout = timeout * 2;
8065     }
8066 
8067     /* Return the sequence timeout.  */
8068     return(timeout);
8069 }
8070 
8071 /**************************************************************************/
8072 /*                                                                        */
8073 /*  FUNCTION                                               RELEASE        */
8074 /*                                                                        */
8075 /*    _nx_dhcp_update_renewal_timeout                     PORTABLE C      */
8076 /*                                                           6.1          */
8077 /*  AUTHOR                                                                */
8078 /*                                                                        */
8079 /*    Yuxin Zhou, Microsoft Corporation                                   */
8080 /*                                                                        */
8081 /*  DESCRIPTION                                                           */
8082 /*                                                                        */
8083 /*    This function updates the DHCP timeout when trying to renew a       */
8084 /*    lease according to the RFC. When the current period has timed out,  */
8085 /*    this function halves the timeout, limiting the minimum timeout      */
8086 /*    value to NX_DHCP_MIN_RENEW_TIMEOUT seconds.                         */
8087 /*                                                                        */
8088 /*  INPUT                                                                 */
8089 /*                                                                        */
8090 /*    timeout                               The current Timeout value     */
8091 /*                                                                        */
8092 /*  OUTPUT                                                                */
8093 /*                                                                        */
8094 /*    timeout                               Renewal time remaining        */
8095 /*                                                                        */
8096 /*  CALLS                                                                 */
8097 /*                                                                        */
8098 /*                                                                        */
8099 /*  CALLED BY                                                             */
8100 /*                                                                        */
8101 /*    _nx_dhcp_client_interface_update_time_remaining                     */
8102 /*                                          Apply input time elapsed to   */
8103 /*                                            the DHCP Client record      */
8104 /*    _nx_dhcp_timeout_process              Timer expiration handler      */
8105 /*                                                                        */
8106 /*  RELEASE HISTORY                                                       */
8107 /*                                                                        */
8108 /*    DATE              NAME                      DESCRIPTION             */
8109 /*                                                                        */
8110 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8111 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8112 /*                                            resulting in version 6.1    */
8113 /*                                                                        */
8114 /**************************************************************************/
_nx_dhcp_update_renewal_timeout(ULONG timeout)8115 static ULONG _nx_dhcp_update_renewal_timeout(ULONG timeout)
8116 {
8117 
8118     /* check if the timeout is non zero */
8119     if (timeout != 0)
8120     {
8121 
8122         /* Timed out, halve the timeout, limited to NX_DHCP_MIN_RENEW_TIMEOUT or
8123           the remaining timeout if it is less than NX_DHCP_MIN_RENEW_TIMEOUT */
8124         if (timeout > NX_DHCP_MIN_RENEW_TIMEOUT)
8125         {
8126 
8127             /* Timeout can still decrease, either
8128                force it to the minimum or halve it */
8129             if (timeout > (2 * NX_DHCP_MIN_RENEW_TIMEOUT ))
8130             {
8131 
8132                 /* Halve timeout.  */
8133                 timeout = timeout / 2;
8134             }
8135             else
8136             {
8137 
8138                 /* set timeout to minimum.  */
8139                 timeout =  NX_DHCP_MIN_RENEW_TIMEOUT ;
8140             }
8141         }
8142     }
8143 
8144     /* Return the sequence timeout.  */
8145     return(timeout);
8146 }
8147 
8148 
8149 /**************************************************************************/
8150 /*                                                                        */
8151 /*  FUNCTION                                               RELEASE        */
8152 /*                                                                        */
8153 /*    _nx_dhcp_search_buffer                              PORTABLE C      */
8154 /*                                                           6.1.12       */
8155 /*  AUTHOR                                                                */
8156 /*                                                                        */
8157 /*    Yuxin Zhou, Microsoft Corporation                                   */
8158 /*                                                                        */
8159 /*  DESCRIPTION                                                           */
8160 /*                                                                        */
8161 /*    This routine searches through a buffer containing a BootP message   */
8162 /*    for a DHCP option parameter and returns a pointer to the byte       */
8163 /*    containing the size of the data section of that option if it        */
8164 /*    exists. If the option cannot be found then function returns NULL.   */
8165 /*    If the option has no data (PAD and END) then the pointer is not     */
8166 /*    usable.                                                             */
8167 /*                                                                        */
8168 /*  INPUT                                                                 */
8169 /*                                                                        */
8170 /*    option_message                        Pointer to option buffer area */
8171 /*    option                                Option to search for          */
8172 /*    length                                Length of search buffer       */
8173 /*                                                                        */
8174 /*  OUTPUT                                                                */
8175 /*                                                                        */
8176 /*    pointer                               Pointer to found option       */
8177 /*                                                                        */
8178 /*  CALLS                                                                 */
8179 /*                                                                        */
8180 /*    None                                                                */
8181 /*                                                                        */
8182 /*  CALLED BY                                                             */
8183 /*                                                                        */
8184 /*    _nx_dhcp_get_option_value             Get the value of an option    */
8185 /*    _nx_dhcp_get_option_data              Get the string of an option   */
8186 /*                                                                        */
8187 /*  RELEASE HISTORY                                                       */
8188 /*                                                                        */
8189 /*    DATE              NAME                      DESCRIPTION             */
8190 /*                                                                        */
8191 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8192 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8193 /*                                            resulting in version 6.1    */
8194 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
8195 /*                                            improved internal logic,    */
8196 /*                                            resulting in version 6.1.12 */
8197 /*                                                                        */
8198 /**************************************************************************/
_nx_dhcp_search_buffer(UCHAR * option_message,UINT option,UINT length)8199 static UCHAR  *_nx_dhcp_search_buffer(UCHAR *option_message, UINT option, UINT length)
8200 {
8201 
8202 UCHAR   *data;
8203 UINT    i;
8204 UINT    size;
8205 
8206     /* Setup buffer pointer.  */
8207     data = option_message;
8208     i = 0;
8209 
8210     /* Search as long as there are valid options.   */
8211     while (i < length - 1)
8212     {
8213         /* Jump out when it reaches END option */
8214         if (*data == NX_DHCP_OPTION_END)
8215         {
8216             break;
8217         }
8218 
8219         /* Simply skip any padding */
8220         else if (*data == NX_DHCP_OPTION_PAD)
8221         {
8222 
8223             data++;
8224             i++;
8225         }
8226 
8227         /* On a match, return a pointer to the size.  */
8228         else if (*data == option)
8229         {
8230 
8231             size = *(data + 1);
8232 
8233             /* Check if the option data is in the packet.  */
8234             if ((i + size + 1) > length)
8235                 return(NX_NULL);
8236 
8237             /* Return a pointer to the option size byte.  */
8238             return(data + 1);
8239         }
8240 
8241         /* Otherwise skip the option by adding the size to the pointer.  */
8242         else
8243         {
8244 
8245             size = *(++data);
8246 
8247             /* skip the data plus the size byte */
8248             data += size + 1;
8249             i += size + 1;
8250         }
8251     }
8252 
8253     /* Return NULL to indicate the option was not found.  */
8254     return(NX_NULL);
8255 }
8256 
8257 
8258 /**************************************************************************/
8259 /*                                                                        */
8260 /*  FUNCTION                                               RELEASE        */
8261 /*                                                                        */
8262 /*    _nx_dhcp_get_data                                   PORTABLE C      */
8263 /*                                                           6.1          */
8264 /*  AUTHOR                                                                */
8265 /*                                                                        */
8266 /*    Yuxin Zhou, Microsoft Corporation                                   */
8267 /*                                                                        */
8268 /*  DESCRIPTION                                                           */
8269 /*                                                                        */
8270 /*    This routine gets a data value from a buffer, assuming the data is  */
8271 /*    stored in standard Network format (big endian). Up to 4 bytes of    */
8272 /*    data are used, if there are more than 4 bytes, only the lower 4     */
8273 /*    bytes are returned.                                                 */
8274 /*                                                                        */
8275 /*  INPUT                                                                 */
8276 /*                                                                        */
8277 /*    data                                  Pointer to buffer data        */
8278 /*    size                                  Size of data value            */
8279 /*                                                                        */
8280 /*  OUTPUT                                                                */
8281 /*                                                                        */
8282 /*    value                                 Data value retrieved          */
8283 /*                                                                        */
8284 /*  CALLS                                                                 */
8285 /*                                                                        */
8286 /*    None                                                                */
8287 /*                                                                        */
8288 /*  CALLED BY                                                             */
8289 /*                                                                        */
8290 /*    _nx_dhcp_get_response                 Get response from server      */
8291 /*    _nx_dhcp_extract_information          Extract server information    */
8292 /*    _nx_dhcp_get_option_value             Retrieve option value         */
8293 /*    _nx_dhcp_update_address_list          Update address list           */
8294 /*                                                                        */
8295 /*  RELEASE HISTORY                                                       */
8296 /*                                                                        */
8297 /*    DATE              NAME                      DESCRIPTION             */
8298 /*                                                                        */
8299 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8300 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8301 /*                                            resulting in version 6.1    */
8302 /*                                                                        */
8303 /**************************************************************************/
_nx_dhcp_get_data(UCHAR * data,UINT size)8304 static ULONG  _nx_dhcp_get_data(UCHAR *data, UINT size)
8305 {
8306 
8307 ULONG   value = 0;
8308 
8309 
8310     /* Process the data retrieval request.  */
8311     while (size-- > 0)
8312     {
8313 
8314         /* Build return value.  */
8315         value = (value << 8) | *data++;
8316     }
8317 
8318     /* Return value.  */
8319     return(value);
8320 }
8321 
8322 
8323 /**************************************************************************/
8324 /*                                                                        */
8325 /*  FUNCTION                                               RELEASE        */
8326 /*                                                                        */
8327 /*    _nx_dhcp_store_data                                 PORTABLE C      */
8328 /*                                                           6.1.12       */
8329 /*  AUTHOR                                                                */
8330 /*                                                                        */
8331 /*    Yuxin Zhou, Microsoft Corporation                                   */
8332 /*                                                                        */
8333 /*  DESCRIPTION                                                           */
8334 /*                                                                        */
8335 /*    This function stores a data value in a buffer in standard Network   */
8336 /*    format (big endian) where the destination may be unaligned. Up to   */
8337 /*    4 bytes of data are stored, if the size is larger than 4 bytes, the */
8338 /*    remaining bytes are set to zero.                                    */
8339 /*                                                                        */
8340 /*  INPUT                                                                 */
8341 /*                                                                        */
8342 /*    data                                  Pointer to buffer data        */
8343 /*    size                                  Size of data value            */
8344 /*    value                                 Value to store                */
8345 /*                                                                        */
8346 /*  OUTPUT                                                                */
8347 /*                                                                        */
8348 /*    None                                                                */
8349 /*                                                                        */
8350 /*  CALLS                                                                 */
8351 /*                                                                        */
8352 /*    None                                                                */
8353 /*                                                                        */
8354 /*  CALLED BY                                                             */
8355 /*                                                                        */
8356 /*    _nx_dhcp_send_request_internal        Send DHCP request             */
8357 /*    _nx_dhcp_add_option_value             Add a DHCP option             */
8358 /*                                                                        */
8359 /*  RELEASE HISTORY                                                       */
8360 /*                                                                        */
8361 /*    DATE              NAME                      DESCRIPTION             */
8362 /*                                                                        */
8363 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8364 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8365 /*                                            resulting in version 6.1    */
8366 /*  07-29-2022     Yuxin Zhou               Modified comment(s),          */
8367 /*                                            improved internal logic,    */
8368 /*                                            resulting in version 6.1.12 */
8369 /*                                                                        */
8370 /**************************************************************************/
_nx_dhcp_store_data(UCHAR * data,UINT size,ULONG value)8371 static VOID  _nx_dhcp_store_data(UCHAR *data, UINT size, ULONG value)
8372 {
8373     /* Store the value.  */
8374     while (size-- > 0)
8375     {
8376         *(data + size) = (UCHAR)(value & 0xff);
8377         value >>= 8;
8378     }
8379 }
8380 
8381 
8382 /**************************************************************************/
8383 /*                                                                        */
8384 /*  FUNCTION                                               RELEASE        */
8385 /*                                                                        */
8386 /*    _nx_dhcp_move_string                                PORTABLE C      */
8387 /*                                                           6.1          */
8388 /*  AUTHOR                                                                */
8389 /*                                                                        */
8390 /*    Yuxin Zhou, Microsoft Corporation                                   */
8391 /*                                                                        */
8392 /*  DESCRIPTION                                                           */
8393 /*                                                                        */
8394 /*    This function stores a sequence of data bytes to a buffer.          */
8395 /*                                                                        */
8396 /*  INPUT                                                                 */
8397 /*                                                                        */
8398 /*    dest                                  Pointer to destination buffer */
8399 /*    source                                Pointer to source buffer      */
8400 /*    size                                  Number of bytes to move       */
8401 /*                                                                        */
8402 /*  OUTPUT                                                                */
8403 /*                                                                        */
8404 /*    None                                                                */
8405 /*                                                                        */
8406 /*  CALLS                                                                 */
8407 /*                                                                        */
8408 /*    None                                                                */
8409 /*                                                                        */
8410 /*  CALLED BY                                                             */
8411 /*                                                                        */
8412 /*    _nx_dhcp_add_option_string            Add option string             */
8413 /*                                                                        */
8414 /*  RELEASE HISTORY                                                       */
8415 /*                                                                        */
8416 /*    DATE              NAME                      DESCRIPTION             */
8417 /*                                                                        */
8418 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8419 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8420 /*                                            resulting in version 6.1    */
8421 /*                                                                        */
8422 /**************************************************************************/
_nx_dhcp_move_string(UCHAR * dest,UCHAR * source,UINT size)8423 static VOID  _nx_dhcp_move_string(UCHAR *dest, UCHAR *source, UINT size)
8424 {
8425 
8426     /* Loop to copy all bytes.  */
8427     while (size-- > 0)
8428     {
8429 
8430         /* Copy a byte.  */
8431         *dest++ = *source++;
8432     }
8433 }
8434 
8435 
8436 /**************************************************************************/
8437 /*                                                                        */
8438 /*  FUNCTION                                               RELEASE        */
8439 /*                                                                        */
8440 /*    _nxe_dhcp_server_address_get                         PORTABLE C     */
8441 /*                                                           6.1          */
8442 /*  AUTHOR                                                                */
8443 /*                                                                        */
8444 /*    Yuxin Zhou, Microsoft Corporation                                   */
8445 /*                                                                        */
8446 /*  DESCRIPTION                                                           */
8447 /*                                                                        */
8448 /*    This function performs error checking for the DHCP server get       */
8449 /*    service.                                                            */
8450 /*                                                                        */
8451 /*  INPUT                                                                 */
8452 /*                                                                        */
8453 /*    dhcp_ptr                             Pointer to DHCP Client task    */
8454 /*    server_address                       Pointer to DHCP server address */
8455 /*                                                                        */
8456 /*  OUTPUT                                                                */
8457 /*                                                                        */
8458 /*    NX_PTR_ERROR                         Invalid pointer input          */
8459 /*    status                               Actual completion status       */
8460 /*                                                                        */
8461 /*  CALLS                                                                 */
8462 /*                                                                        */
8463 /*    _nx_dhcp_server_address_get         Actual get DHCP IP server       */
8464 /*                                           address service              */
8465 /*                                                                        */
8466 /*  CALLED BY                                                             */
8467 /*                                                                        */
8468 /*    Application code                                                    */
8469 /*                                                                        */
8470 /*  RELEASE HISTORY                                                       */
8471 /*                                                                        */
8472 /*    DATE              NAME                      DESCRIPTION             */
8473 /*                                                                        */
8474 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8475 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8476 /*                                            resulting in version 6.1    */
8477 /*                                                                        */
8478 /**************************************************************************/
_nxe_dhcp_server_address_get(NX_DHCP * dhcp_ptr,ULONG * server_address)8479 UINT _nxe_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_address)
8480 {
8481 
8482 UINT status ;
8483 
8484 
8485     if ((dhcp_ptr == NX_NULL) || (server_address == NX_NULL))
8486     {
8487         return NX_PTR_ERROR;
8488     }
8489 
8490     /* Check for appropriate caller.  */
8491     NX_THREADS_ONLY_CALLER_CHECKING
8492 
8493     status = _nx_dhcp_server_address_get(dhcp_ptr, server_address);
8494 
8495     return status;
8496 }
8497 
8498 /**************************************************************************/
8499 /*                                                                        */
8500 /*  FUNCTION                                               RELEASE        */
8501 /*                                                                        */
8502 /*    _nx_dhcp_server_address_get                         PORTABLE C      */
8503 /*                                                           6.1          */
8504 /*  AUTHOR                                                                */
8505 /*                                                                        */
8506 /*    Yuxin Zhou, Microsoft Corporation                                   */
8507 /*                                                                        */
8508 /*  DESCRIPTION                                                           */
8509 /*                                                                        */
8510 /*    This function retrieves the DHCP Client's DHCP server IP address on */
8511 /*    the first DHCP enabled interface found.                             */
8512 /*                                                                        */
8513 /*    Note that the caller should only call this service when the Client  */
8514 /*    is bound to an IP address from a DHCP server. See the               */
8515 /*    nx_dhcp_state_change_notify for notification of state changes.      */
8516 /*                                                                        */
8517 /*    If multiple interfaces are enabled for DHCP, use                    */
8518 /*    nx_dhcp_interface_server_address_get() to get the server IP address */
8519 /*    on a specified interface.                                           */
8520 /*                                                                        */
8521 /*                                                                        */
8522 /*  INPUT                                                                 */
8523 /*                                                                        */
8524 /*    dhcp_ptr                              Pointer to DHCP Client task   */
8525 /*    server_address                        Pointer to DHCP server address*/
8526 /*                                                                        */
8527 /*  OUTPUT                                                                */
8528 /*                                                                        */
8529 /*    status                                Actual completion status      */
8530 /*    NX_DHCP_NO_INTERFACES_ENABLED         No interfaces enabled for DHCP*/
8531 /*                                                                        */
8532 /*  CALLS                                                                 */
8533 /*                                                                        */
8534 /*    _nx_dhcp_interface_server_address_get Interface specific server IP  */
8535 /*                                            address get service         */
8536 /*    tx_mutex_get                          Obtain protection mutex       */
8537 /*    tx_mutex_put                          Release protection mutex      */
8538 /*                                                                        */
8539 /*  CALLED BY                                                             */
8540 /*                                                                        */
8541 /*    Application code                                                    */
8542 /*                                                                        */
8543 /*  RELEASE HISTORY                                                       */
8544 /*                                                                        */
8545 /*    DATE              NAME                      DESCRIPTION             */
8546 /*                                                                        */
8547 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8548 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8549 /*                                            resulting in version 6.1    */
8550 /*                                                                        */
8551 /**************************************************************************/
_nx_dhcp_server_address_get(NX_DHCP * dhcp_ptr,ULONG * server_address)8552 UINT _nx_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_address)
8553 {
8554 
8555 UINT i;
8556 UINT status;
8557 
8558     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
8559 
8560     /* Find the DHCP interface record.  */
8561     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
8562     {
8563 
8564         /* Check the interface record is valid.  */
8565         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
8566             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
8567         {
8568 
8569             /* Get the server address of first valid record.  */
8570             status = _nx_dhcp_interface_server_address_get(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index, server_address);
8571 
8572             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8573 
8574             return(status);
8575         }
8576     }
8577 
8578     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8579 
8580     return(NX_DHCP_NO_INTERFACES_ENABLED);
8581 }
8582 
8583 
8584 /**************************************************************************/
8585 /*                                                                        */
8586 /*  FUNCTION                                               RELEASE        */
8587 /*                                                                        */
8588 /*    _nxe_dhcp_interface_server_address_get              PORTABLE C      */
8589 /*                                                           6.1          */
8590 /*  AUTHOR                                                                */
8591 /*                                                                        */
8592 /*    Yuxin Zhou, Microsoft Corporation                                   */
8593 /*                                                                        */
8594 /*  DESCRIPTION                                                           */
8595 /*                                                                        */
8596 /*    This function performs error checking for the DHCP server get       */
8597 /*    service.                                                            */
8598 /*                                                                        */
8599 /*  INPUT                                                                 */
8600 /*                                                                        */
8601 /*    dhcp_ptr                             Pointer to DHCP Client task    */
8602 /*    iface_index                          Interface of the Server        */
8603 /*    server_address                       Pointer to DHCP server address */
8604 /*                                                                        */
8605 /*  OUTPUT                                                                */
8606 /*                                                                        */
8607 /*    status                                Completion status             */
8608 /*    NX_PTR_ERROR                          Invalid pointer input         */
8609 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
8610 /*                                                                        */
8611 /*  CALLS                                                                 */
8612 /*                                                                        */
8613 /*    _nx_dhcp_interface_server_address_get Actual get server IP address  */
8614 /*                                                                        */
8615 /*  CALLED BY                                                             */
8616 /*                                                                        */
8617 /*    Application code                                                    */
8618 /*                                                                        */
8619 /*  RELEASE HISTORY                                                       */
8620 /*                                                                        */
8621 /*    DATE              NAME                      DESCRIPTION             */
8622 /*                                                                        */
8623 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8624 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8625 /*                                            resulting in version 6.1    */
8626 /*                                                                        */
8627 /**************************************************************************/
8628 
_nxe_dhcp_interface_server_address_get(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG * server_address)8629 UINT _nxe_dhcp_interface_server_address_get(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG *server_address)
8630 {
8631 
8632 UINT status;
8633 
8634     if ((dhcp_ptr == NX_NULL) || (server_address == NX_NULL))
8635     {
8636         return NX_PTR_ERROR;
8637     }
8638 
8639     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
8640     {
8641         return NX_INVALID_INTERFACE;
8642     }
8643 
8644     /* Check for appropriate caller.  */
8645     NX_THREADS_ONLY_CALLER_CHECKING
8646 
8647     /* Call the actual reinitialize service.  */
8648     status = _nx_dhcp_interface_server_address_get(dhcp_ptr, iface_index, server_address);
8649 
8650     return status;
8651 }
8652 
8653 
8654 /**************************************************************************/
8655 /*                                                                        */
8656 /*  FUNCTION                                               RELEASE        */
8657 /*                                                                        */
8658 /*    _nx_dhcp_interface_server_address_get               PORTABLE C      */
8659 /*                                                           6.1          */
8660 /*  AUTHOR                                                                */
8661 /*                                                                        */
8662 /*    Yuxin Zhou, Microsoft Corporation                                   */
8663 /*                                                                        */
8664 /*  DESCRIPTION                                                           */
8665 /*                                                                        */
8666 /*    This function retrieves the DHCP Client's DHCP server IP address on */
8667 /*    the specified interface.                                            */
8668 /*                                                                        */
8669 /*    Note that the caller should only call this service when the Client  */
8670 /*    is in the bound state. See nx_dhcp_state_change_notify for          */
8671 /*    notification when the Client state changes.                         */
8672 /*                                                                        */
8673 /*  INPUT                                                                 */
8674 /*                                                                        */
8675 /*    dhcp_ptr                             Pointer to DHCP Client task    */
8676 /*    iface_index                          Interface of the DHCP server   */
8677 /*    server_address                       Pointer to DHCP server address */
8678 /*                                                                        */
8679 /*  OUTPUT                                                                */
8680 /*                                                                        */
8681 /*    status                               Actual completion status       */
8682 /*    NX_DHCP_NOT_BOUND                    Client state not Bound         */
8683 /*                                                                        */
8684 /*  CALLS                                                                 */
8685 /*                                                                        */
8686 /*    tx_mutex_get                          Obtain protection mutex       */
8687 /*    tx_mutex_put                          Release protection mutex      */
8688 /*    _nx_dhcp_interface_record_find        Find record for the interface */
8689 /*                                                                        */
8690 /*  CALLED BY                                                             */
8691 /*                                                                        */
8692 /*    Application code                                                    */
8693 /*                                                                        */
8694 /*  RELEASE HISTORY                                                       */
8695 /*                                                                        */
8696 /*    DATE              NAME                      DESCRIPTION             */
8697 /*                                                                        */
8698 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8699 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8700 /*                                            resulting in version 6.1    */
8701 /*                                                                        */
8702 /**************************************************************************/
_nx_dhcp_interface_server_address_get(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG * server_address)8703 UINT _nx_dhcp_interface_server_address_get(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG *server_address)
8704 {
8705 
8706 UINT    status;
8707 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
8708 
8709     /* Get the DHCP mutex.  */
8710     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
8711 
8712     /* Find the interface record.  */
8713     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
8714 
8715     /* Check status.  */
8716     if (status)
8717     {
8718 
8719         /* Release the DHCP mutex.  */
8720         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8721 
8722         return(status);
8723     }
8724 
8725     /* Check the record state.  */
8726     if (interface_record -> nx_dhcp_state >= NX_DHCP_STATE_BOUND)
8727     {
8728 
8729         /* Set the server IP address from the DHCP Client instance. */
8730         *server_address = interface_record -> nx_dhcp_server_ip;
8731         status = NX_SUCCESS;
8732     }
8733     else
8734         status = NX_DHCP_NOT_BOUND;
8735 
8736     /* Release the DHCP mutex.  */
8737     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8738 
8739     return status;
8740 }
8741 
8742 
8743 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
8744 /**************************************************************************/
8745 /*                                                                        */
8746 /*  FUNCTION                                               RELEASE        */
8747 /*                                                                        */
8748 /*    _nx_dhcp_ip_conflict                                PORTABLE C      */
8749 /*                                                           6.1.10       */
8750 /*  AUTHOR                                                                */
8751 /*                                                                        */
8752 /*    Yuxin Zhou, Microsoft Corporation                                   */
8753 /*                                                                        */
8754 /*  DESCRIPTION                                                           */
8755 /*                                                                        */
8756 /*    This function notifies the DHCP instance that a conflict was        */
8757 /*    detected by the NetX ARP receive packet handling routine.           */
8758 /*                                                                        */
8759 /*  INPUT                                                                 */
8760 /*                                                                        */
8761 /*    ip_ptr                                IP instance pointer           */
8762 /*    iface_index                           IP Interface Index            */
8763 /*    ip_address                            IP Address to bind to         */
8764 /*    physical_msw                          Physical address MSW          */
8765 /*    physical_lsw                          Physical address LSW          */
8766 /*                                                                        */
8767 /*  OUTPUT                                                                */
8768 /*                                                                        */
8769 /*    None                                                                */
8770 /*                                                                        */
8771 /*  CALLS                                                                 */
8772 /*                                                                        */
8773 /*    tx_event_flags_set                    Set event flags               */
8774 /*                                                                        */
8775 /*  CALLED BY                                                             */
8776 /*                                                                        */
8777 /*    NetX                                                                */
8778 /*                                                                        */
8779 /*  RELEASE HISTORY                                                       */
8780 /*                                                                        */
8781 /*    DATE              NAME                      DESCRIPTION             */
8782 /*                                                                        */
8783 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8784 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8785 /*                                            resulting in version 6.1    */
8786 /*  01-31-2022     Yuxin Zhou               Modified comment(s), supported*/
8787 /*                                            multiple client instances,  */
8788 /*                                            resulting in version 6.1.10 */
8789 /*                                                                        */
8790 /**************************************************************************/
_nx_dhcp_ip_conflict(NX_IP * ip_ptr,UINT iface_index,ULONG ip_address,ULONG physical_msw,ULONG physical_lsw)8791 VOID  _nx_dhcp_ip_conflict(NX_IP *ip_ptr, UINT iface_index, ULONG ip_address, ULONG physical_msw, ULONG physical_lsw)
8792 {
8793 
8794 TX_INTERRUPT_SAVE_AREA
8795 
8796 NX_DHCP *dhcp_ptr;
8797 
8798     NX_PARAMETER_NOT_USED(ip_address);
8799     NX_PARAMETER_NOT_USED(physical_msw);
8800     NX_PARAMETER_NOT_USED(physical_lsw);
8801 
8802     /* Disable interrupts.  */
8803     TX_DISABLE
8804 
8805     /* Find the DHCP client.  */
8806     for (dhcp_ptr = _nx_dhcp_created_ptr; dhcp_ptr; dhcp_ptr = dhcp_ptr -> nx_dhcp_created_next)
8807     {
8808         if (dhcp_ptr -> nx_dhcp_ip_ptr == ip_ptr)
8809         {
8810 
8811             /* Set the interface index.  */
8812             dhcp_ptr -> nx_dhcp_interface_conflict_flag |= (UINT)(1 << iface_index);
8813 
8814             /* Set the address conflict event flag.  */
8815             tx_event_flags_set(&(_nx_dhcp_created_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_CONFLICT_EVENT, TX_OR);
8816 
8817             break;
8818         }
8819     }
8820 
8821     /* Restore interrupts.  */
8822     TX_RESTORE
8823 
8824 }
8825 #endif
8826 
8827 
8828 /**************************************************************************/
8829 /*                                                                        */
8830 /*  FUNCTION                                               RELEASE        */
8831 /*                                                                        */
8832 /*    _nxe_dhcp_set_interface_index                       PORTABLE C      */
8833 /*                                                           6.1          */
8834 /*  AUTHOR                                                                */
8835 /*                                                                        */
8836 /*    Yuxin Zhou, Microsoft Corporation                                   */
8837 /*                                                                        */
8838 /*  DESCRIPTION                                                           */
8839 /*                                                                        */
8840 /*    This function does error checking for the set interface index call. */
8841 /*                                                                        */
8842 /*  INPUT                                                                 */
8843 /*                                                                        */
8844 /*    dhcp_ptr                              Pointer to DHCP instance      */
8845 /*    interface_index                       Interface the DHCP Client task*/
8846 /*                                                is associated with      */
8847 /*                                                                        */
8848 /*  OUTPUT                                                                */
8849 /*                                                                        */
8850 /*    status                                Completion status             */
8851 /*    NX_PTR_ERROR                          Invalid pointer input         */
8852 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
8853 /*                                                                        */
8854 /*  CALLS                                                                 */
8855 /*                                                                        */
8856 /*    _nx_dhcp_set_interface_index           Actual set interface index   */
8857 /*                                                                        */
8858 /*  CALLED BY                                                             */
8859 /*                                                                        */
8860 /*    Application Code                                                    */
8861 /*                                                                        */
8862 /*  RELEASE HISTORY                                                       */
8863 /*                                                                        */
8864 /*    DATE              NAME                      DESCRIPTION             */
8865 /*                                                                        */
8866 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8867 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8868 /*                                            resulting in version 6.1    */
8869 /*                                                                        */
8870 /**************************************************************************/
_nxe_dhcp_set_interface_index(NX_DHCP * dhcp_ptr,UINT interface_index)8871 UINT _nxe_dhcp_set_interface_index(NX_DHCP *dhcp_ptr, UINT interface_index)
8872 {
8873 
8874 UINT status;
8875 
8876 
8877     /* Check for invalid pointer input. */
8878     if (dhcp_ptr == NX_NULL)
8879     {
8880 
8881         return(NX_PTR_ERROR);
8882     }
8883     /* Check for invalid non pointer input. */
8884     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
8885     {
8886 
8887         return(NX_INVALID_INTERFACE);
8888     }
8889 
8890     /* Call the actual set DHCP Client interface service */
8891     status = _nx_dhcp_set_interface_index(dhcp_ptr,  interface_index);
8892 
8893     /* Return completion status. */
8894     return(status);
8895 }
8896 
8897 
8898 /**************************************************************************/
8899 /*                                                                        */
8900 /*  FUNCTION                                               RELEASE        */
8901 /*                                                                        */
8902 /*    _nx_dhcp_set_interface_index                        PORTABLE C      */
8903 /*                                                           6.1          */
8904 /*  AUTHOR                                                                */
8905 /*                                                                        */
8906 /*    Yuxin Zhou, Microsoft Corporation                                   */
8907 /*                                                                        */
8908 /*  DESCRIPTION                                                           */
8909 /*                                                                        */
8910 /*    This function enables DHCP on the specified interface. This function*/
8911 /*    should be called before the DHCP Client is started. The intended use*/
8912 /*    of this function is for DHCP to run on only one interface. To enable*/
8913 /*    multiple interfaces for DHCP, use the nx_dhcp_interface_enable      */
8914 /*    service.                                                            */
8915 /*                                                                        */
8916 /*  INPUT                                                                 */
8917 /*                                                                        */
8918 /*    dhcp_ptr                              Pointer to DHCP instance      */
8919 /*    iface_index                           Interface to enable DHCP on   */
8920 /*                                                                        */
8921 /*  OUTPUT                                                                */
8922 /*                                                                        */
8923 /*    NX_SUCCESS                            Successful Completion status  */
8924 /*                                                                        */
8925 /*  CALLS                                                                 */
8926 /*                                                                        */
8927 /*   _nx_dhcp_interface_enable              Enable DHCP on interface      */
8928 /*    tx_mutex_get                          Obtain protection mutex       */
8929 /*    tx_mutex_put                          Release protection mutex      */
8930 /*                                                                        */
8931 /*  CALLED BY                                                             */
8932 /*                                                                        */
8933 /*    Application Code                                                    */
8934 /*                                                                        */
8935 /*  RELEASE HISTORY                                                       */
8936 /*                                                                        */
8937 /*    DATE              NAME                      DESCRIPTION             */
8938 /*                                                                        */
8939 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8940 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8941 /*                                            resulting in version 6.1    */
8942 /*                                                                        */
8943 /**************************************************************************/
_nx_dhcp_set_interface_index(NX_DHCP * dhcp_ptr,UINT iface_index)8944 UINT _nx_dhcp_set_interface_index(NX_DHCP *dhcp_ptr, UINT iface_index)
8945 {
8946 
8947 UINT    i;
8948 UINT    status;
8949 
8950 
8951     /* Get the DHCP mutex.  */
8952     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
8953 
8954     /* Invalidate all the interfaces enabled for DHCP. */
8955     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
8956     {
8957 
8958         /* Invalidate this interface.  */
8959         dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid = NX_FALSE;
8960 
8961         /* Change the state.  */
8962         dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state = NX_DHCP_STATE_NOT_STARTED;
8963     }
8964 
8965     /* Enable DHCP on this interface.  */
8966     status = _nx_dhcp_interface_enable(dhcp_ptr, iface_index);
8967 
8968     /* Release the DHCP mutex.  */
8969     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8970 
8971     return(status);
8972 }
8973 
8974 
8975 /**************************************************************************/
8976 /*                                                                        */
8977 /*  FUNCTION                                               RELEASE        */
8978 /*                                                                        */
8979 /*    _nx_dhcp_interface_record_find                      PORTABLE C      */
8980 /*                                                           6.1          */
8981 /*  AUTHOR                                                                */
8982 /*                                                                        */
8983 /*    Yuxin Zhou, Microsoft Corporation                                   */
8984 /*                                                                        */
8985 /*  DESCRIPTION                                                           */
8986 /*                                                                        */
8987 /*    Find the Client record that is assigned to the input interface      */
8988 /*    index, and return a pointer to that record. The interface index must*/
8989 /*    match the interface index of the Client record, and the interface   */
8990 /*    must be enabled for DHCP.  If no matching records are found, an     */
8991 /*    error status is returned, and the interface record pointer is NULL. */
8992 /*                                                                        */
8993 /*  INPUT                                                                 */
8994 /*                                                                        */
8995 /*    dhcp_ptr                              Pointer to DHCP instance      */
8996 /*    interface_index                       Interface to find             */
8997 /*                                                                        */
8998 /*  OUTPUT                                                                */
8999 /*                                                                        */
9000 /*    NX_SUCCESS                            Successful completion         */
9001 /*    NX_DHCP_INTERFACE_NOT_ENABLED         No matching record found      */
9002 /*                                                                        */
9003 /*  CALLS                                                                 */
9004 /*       None                                                             */
9005 /*                                                                        */
9006 /*  CALLED BY                                                             */
9007 /*                                                                        */
9008 /*    Application Code                                                    */
9009 /*                                                                        */
9010 /*  RELEASE HISTORY                                                       */
9011 /*                                                                        */
9012 /*    DATE              NAME                      DESCRIPTION             */
9013 /*                                                                        */
9014 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9015 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9016 /*                                            resulting in version 6.1    */
9017 /*                                                                        */
9018 /**************************************************************************/
_nx_dhcp_interface_record_find(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_INTERFACE_RECORD ** interface_record)9019 static UINT _nx_dhcp_interface_record_find(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_INTERFACE_RECORD **interface_record)
9020 {
9021 
9022 UINT i;
9023 
9024     /* Find which DHCP Client interface record is assigned the input interface. */
9025     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
9026     {
9027 
9028         /* Check if this record is valid.  */
9029         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid == NX_FALSE)
9030             continue;
9031 
9032         /* Check if the interface index matches.  */
9033         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index == iface_index)
9034         {
9035 
9036             /* Yes, we found the record.  */
9037             *interface_record = &dhcp_ptr -> nx_dhcp_interface_record[i];
9038 
9039             /* Return.  */
9040             return (NX_SUCCESS);
9041         }
9042     }
9043 
9044     /* No matching record found.  */
9045     return (NX_DHCP_INTERFACE_NOT_ENABLED);
9046 }
9047 
9048 
9049 #ifdef NX_DHCP_CLIENT_RESTORE_STATE
9050 /**************************************************************************/
9051 /*                                                                        */
9052 /*  FUNCTION                                               RELEASE        */
9053 /*                                                                        */
9054 /*    _nxe_dhcp_client_get_record                          PORTABLE C     */
9055 /*                                                           6.1          */
9056 /*  AUTHOR                                                                */
9057 /*                                                                        */
9058 /*    Yuxin Zhou, Microsoft Corporation                                   */
9059 /*                                                                        */
9060 /*  DESCRIPTION                                                           */
9061 /*                                                                        */
9062 /*    This function performs error checking on the get DHCP Client record */
9063 /*    service.                                                            */
9064 /*                                                                        */
9065 /*  INPUT                                                                 */
9066 /*                                                                        */
9067 /*    dhcp_ptr                              Pointer to DHCP instance      */
9068 /*    client_record_ptr                     Pointer to memory to save     */
9069 /*                                             Client record to           */
9070 /*                                                                        */
9071 /*  OUTPUT                                                                */
9072 /*                                                                        */
9073 /*    NX_PTR_ERROR                          Invalid pointer input         */
9074 /*    status                                Completion status from        */
9075 /*                                            internal DHCP calls         */
9076 /*                                                                        */
9077 /*  CALLS                                                                 */
9078 /*                                                                        */
9079 /*   _nx_dhcp_client_create_record                                        */
9080 /*                                                                        */
9081 /*  CALLED BY                                                             */
9082 /*                                                                        */
9083 /*    Application code                                                    */
9084 /*                                                                        */
9085 /*  RELEASE HISTORY                                                       */
9086 /*                                                                        */
9087 /*    DATE              NAME                      DESCRIPTION             */
9088 /*                                                                        */
9089 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9090 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9091 /*                                            resulting in version 6.1    */
9092 /*                                                                        */
9093 /**************************************************************************/
_nxe_dhcp_client_get_record(NX_DHCP * dhcp_ptr,NX_DHCP_CLIENT_RECORD * client_record_ptr)9094 UINT  _nxe_dhcp_client_get_record(NX_DHCP *dhcp_ptr, NX_DHCP_CLIENT_RECORD *client_record_ptr)
9095 {
9096 
9097 UINT status;
9098 
9099     if ((dhcp_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
9100     {
9101         return NX_PTR_ERROR;
9102     }
9103 
9104     status = _nx_dhcp_client_get_record(dhcp_ptr, client_record_ptr);
9105 
9106     return status;
9107 }
9108 
9109 
9110 /**************************************************************************/
9111 /*                                                                        */
9112 /*  FUNCTION                                               RELEASE        */
9113 /*                                                                        */
9114 /*    _nx_dhcp_client_get_record                          PORTABLE C      */
9115 /*                                                           6.1          */
9116 /*  AUTHOR                                                                */
9117 /*                                                                        */
9118 /*    Yuxin Zhou, Microsoft Corporation                                   */
9119 /*                                                                        */
9120 /*  DESCRIPTION                                                           */
9121 /*                                                                        */
9122 /*    This function creates a DHCP Client record for restoring the Client */
9123 /*    state between power cycles or idle (sleep) mode.  It copies the     */
9124 /*    first DHCP enabled Client record found to the supplied client record*/
9125 /*    pointer. If DHCP is enabled on multiple interfaces, use             */
9126 /*    nx_dhcp_client_interface_record_get to get a record of a specific   */
9127 /*    interface.                                                          */
9128 /*                                                                        */
9129 /*  INPUT                                                                 */
9130 /*                                                                        */
9131 /*    dhcp_ptr                              Pointer to DHCP instance      */
9132 /*    client_record_ptr                     Pointer to Client record      */
9133 /*                                                                        */
9134 /*  OUTPUT                                                                */
9135 /*                                                                        */
9136 /*    status                                Completion status             */
9137 /*    NX_DHCP_NO_INTERFACES_ENABLED         No DHCP interface enabled     */
9138 /*                                                                        */
9139 /*  CALLS                                                                 */
9140 /*                                                                        */
9141 /*   _nx_dhcp_client_interface_get_record   Get record for specified index*/
9142 /*    tx_mutex_get                          Obtain protection mutex       */
9143 /*    tx_mutex_put                          Release protection mutex      */
9144 /*                                                                        */
9145 /*  CALLED BY                                                             */
9146 /*                                                                        */
9147 /*    Application code                                                    */
9148 /*                                                                        */
9149 /*  RELEASE HISTORY                                                       */
9150 /*                                                                        */
9151 /*    DATE              NAME                      DESCRIPTION             */
9152 /*                                                                        */
9153 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9154 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9155 /*                                            resulting in version 6.1    */
9156 /*                                                                        */
9157 /**************************************************************************/
_nx_dhcp_client_get_record(NX_DHCP * dhcp_ptr,NX_DHCP_CLIENT_RECORD * client_record_ptr)9158 UINT  _nx_dhcp_client_get_record(NX_DHCP *dhcp_ptr, NX_DHCP_CLIENT_RECORD *client_record_ptr)
9159 {
9160 
9161 UINT i;
9162 UINT status;
9163 
9164 
9165     /* Obtain DHCP Client protection mutex. */
9166     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9167 
9168     /* Find the DHCP interface record.  */
9169     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
9170     {
9171 
9172         /* Check if the interface record is valid.  */
9173         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
9174             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
9175         {
9176 
9177             /* Find a record of the current state of the DHCP CLient. */
9178             status = _nx_dhcp_client_interface_get_record(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index, client_record_ptr);
9179 
9180             /* Release the DHCP mutex.  */
9181             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9182             return(status);
9183         }
9184     }
9185 
9186     /* Release the DHCP mutex.  */
9187     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9188     return(NX_DHCP_NO_INTERFACES_ENABLED);
9189 }
9190 
9191 
9192 /**************************************************************************/
9193 /*                                                                        */
9194 /*  FUNCTION                                               RELEASE        */
9195 /*                                                                        */
9196 /*    _nxe_dhcp_client_interface_get_record               PORTABLE C      */
9197 /*                                                           6.1          */
9198 /*  AUTHOR                                                                */
9199 /*                                                                        */
9200 /*    Yuxin Zhou, Microsoft Corporation                                   */
9201 /*                                                                        */
9202 /*  DESCRIPTION                                                           */
9203 /*                                                                        */
9204 /*    This function performs error checking on the get DHCP Client        */
9205 /*    interface record service.                                           */
9206 /*                                                                        */
9207 /*  INPUT                                                                 */
9208 /*                                                                        */
9209 /*    dhcp_ptr                              Pointer to DHCP instance      */
9210 /*    iface_index                           Interface index               */
9211 /*    client_record_ptr                     Pointer to memory to save     */
9212 /*                                             Client record to           */
9213 /*                                                                        */
9214 /*  OUTPUT                                                                */
9215 /*                                                                        */
9216 /*    status                                Completion status             */
9217 /*    NX_PTR_ERROR                          Invalid pointer input         */
9218 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
9219 /*                                                                        */
9220 /*  CALLS                                                                 */
9221 /*                                                                        */
9222 /*   _nx_dhcp_client_interface_create_record                              */
9223 /*                                                                        */
9224 /*  CALLED BY                                                             */
9225 /*                                                                        */
9226 /*    Application code                                                    */
9227 /*                                                                        */
9228 /*  RELEASE HISTORY                                                       */
9229 /*                                                                        */
9230 /*    DATE              NAME                      DESCRIPTION             */
9231 /*                                                                        */
9232 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9233 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9234 /*                                            resulting in version 6.1    */
9235 /*                                                                        */
9236 /**************************************************************************/
_nxe_dhcp_client_interface_get_record(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_CLIENT_RECORD * client_record_ptr)9237 UINT  _nxe_dhcp_client_interface_get_record(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_CLIENT_RECORD *client_record_ptr)
9238 {
9239 
9240 UINT status;
9241 
9242     /* Check for invalid input pointers.  */
9243     if ((dhcp_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
9244     {
9245         return NX_PTR_ERROR;
9246     }
9247 
9248     /* Check interface index.  */
9249     if (iface_index >= NX_DHCP_CLIENT_MAX_RECORDS)
9250     {
9251         return NX_INVALID_INTERFACE;
9252     }
9253 
9254     status = _nx_dhcp_client_interface_get_record(dhcp_ptr, iface_index, client_record_ptr);
9255 
9256     return status;
9257 }
9258 
9259 
9260 /**************************************************************************/
9261 /*                                                                        */
9262 /*  FUNCTION                                               RELEASE        */
9263 /*                                                                        */
9264 /*    _nx_dhcp_client_interface_get_record                PORTABLE C      */
9265 /*                                                           6.1          */
9266 /*  AUTHOR                                                                */
9267 /*                                                                        */
9268 /*    Yuxin Zhou, Microsoft Corporation                                   */
9269 /*                                                                        */
9270 /*  DESCRIPTION                                                           */
9271 /*                                                                        */
9272 /*    This function creates a DHCP Client record for restoring the Client */
9273 /*    state between power cycles or idle (sleep) mode.  It then copies the*/
9274 /*    Client record to the supplied client record pointer.                */
9275 /*                                                                        */
9276 /*    The DHCP Client state should be restored from a Client record saved */
9277 /*    to memory (client_record_ptr).                                      */
9278 /*                                                                        */
9279 /*  INPUT                                                                 */
9280 /*                                                                        */
9281 /*    dhcp_ptr                              Pointer to DHCP instance      */
9282 /*    iface_index                           Interface index               */
9283 /*    client_record_ptr                     Pointer to memory to save     */
9284 /*                                             Client record to           */
9285 /*                                                                        */
9286 /*  OUTPUT                                                                */
9287 /*                                                                        */
9288 /*    NX_DHCP_NOT_BOUND                     Client not Bound to address   */
9289 /*    status                                Actual completion status      */
9290 /*                                                                        */
9291 /*  CALLS                                                                 */
9292 /*                                                                        */
9293 /*   _nx_dhcp_interface_record_find         Find interface record matching*/
9294 /*                                             the input interface        */
9295 /*    tx_mutex_get                          Obtain protection mutex       */
9296 /*    tx_mutex_put                          Release protection mutex      */
9297 /*                                                                        */
9298 /*  CALLED BY                                                             */
9299 /*                                                                        */
9300 /*    Application code                                                    */
9301 /*                                                                        */
9302 /*  RELEASE HISTORY                                                       */
9303 /*                                                                        */
9304 /*    DATE              NAME                      DESCRIPTION             */
9305 /*                                                                        */
9306 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9307 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9308 /*                                            resulting in version 6.1    */
9309 /*                                                                        */
9310 /**************************************************************************/
_nx_dhcp_client_interface_get_record(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_CLIENT_RECORD * client_record_ptr)9311 UINT  _nx_dhcp_client_interface_get_record(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_CLIENT_RECORD *client_record_ptr)
9312 {
9313 
9314 UINT                      status;
9315 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
9316 
9317 
9318     /* Obtain DHCP Client protection mutex. */
9319     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9320 
9321     /* Find the interface record.  */
9322     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
9323 
9324     /* Check status.  */
9325     if (status)
9326     {
9327 
9328         /* Release the DHCP mutex.  */
9329         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9330         return(status);
9331     }
9332 
9333     /* Check the state.  */
9334     if (interface_record -> nx_dhcp_state < NX_DHCP_STATE_BOUND)
9335     {
9336 
9337         /* The DHCP Client is not bound to an IP address. Cannot create a record for restoring Client
9338            state if the Client not bound to an IP address. */
9339 
9340         /* Release the DHCP mutex.  */
9341         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9342         return NX_DHCP_NOT_BOUND;
9343     }
9344 
9345     /* Clear memory before filling with data. */
9346     memset(client_record_ptr, 0, sizeof(NX_DHCP_CLIENT_RECORD));
9347 
9348     /* Set the record.  */
9349     client_record_ptr -> nx_dhcp_state = interface_record -> nx_dhcp_state;
9350     client_record_ptr -> nx_dhcp_ip_address = interface_record -> nx_dhcp_ip_address;           /* Server assigned IP Address                               */
9351     client_record_ptr -> nx_dhcp_network_mask = interface_record -> nx_dhcp_network_mask;       /* Server assigned network mask                             */
9352     client_record_ptr -> nx_dhcp_gateway_address = interface_record -> nx_dhcp_gateway_address;
9353     client_record_ptr -> nx_dhcp_server_ip = interface_record -> nx_dhcp_server_ip;
9354     client_record_ptr -> nx_dhcp_timeout = interface_record -> nx_dhcp_timeout;
9355     client_record_ptr -> nx_dhcp_lease_time = interface_record -> nx_dhcp_lease_time ;
9356     client_record_ptr -> nx_dhcp_renewal_time = interface_record -> nx_dhcp_renewal_time;
9357     client_record_ptr -> nx_dhcp_rebind_time = interface_record -> nx_dhcp_rebind_time;
9358     client_record_ptr -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_renewal_remain_time;
9359     client_record_ptr -> nx_dhcp_rebind_remain_time = interface_record -> nx_dhcp_rebind_remain_time;
9360     client_record_ptr -> nx_dhcp_interface_index = interface_record -> nx_dhcp_interface_index;
9361 
9362     /* Release the DHCP mutex.  */
9363     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9364 
9365     return(NX_SUCCESS);
9366 }
9367 
9368 
9369 /**************************************************************************/
9370 /*                                                                        */
9371 /*  FUNCTION                                               RELEASE        */
9372 /*                                                                        */
9373 /*    _nxe_dhcp_client_restore_record                     PORTABLE C      */
9374 /*                                                           6.1          */
9375 /*  AUTHOR                                                                */
9376 /*                                                                        */
9377 /*    Yuxin Zhou, Microsoft Corporation                                   */
9378 /*                                                                        */
9379 /*  DESCRIPTION                                                           */
9380 /*                                                                        */
9381 /*    This function performs error checking on the client restore service.*/
9382 /*                                                                        */
9383 /*  INPUT                                                                 */
9384 /*                                                                        */
9385 /*    dhcp_ptr                              Pointer to DHCP instance      */
9386 /*    client_record_ptr                     Pointer to previously saved   */
9387 /*                                             Client record              */
9388 /*    time_elapsed                          Time elapsed in timer ticks   */
9389 /*                                                                        */
9390 /*  OUTPUT                                                                */
9391 /*                                                                        */
9392 /*    NX_PTR_ERRPR                          Invalid pointer input         */
9393 /*    status                                NetX completion status        */
9394 /*                                                                        */
9395 /*  CALLS                                                                 */
9396 /*                                                                        */
9397 /*   _nx_dhcp_client_restore_record         Actual restore record service */
9398 /*                                                                        */
9399 /*  CALLED BY                                                             */
9400 /*                                                                        */
9401 /*    Application code                                                    */
9402 /*                                                                        */
9403 /*  RELEASE HISTORY                                                       */
9404 /*                                                                        */
9405 /*    DATE              NAME                      DESCRIPTION             */
9406 /*                                                                        */
9407 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9408 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9409 /*                                            resulting in version 6.1    */
9410 /*                                                                        */
9411 /**************************************************************************/
_nxe_dhcp_client_restore_record(NX_DHCP * dhcp_ptr,NX_DHCP_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)9412 UINT  _nxe_dhcp_client_restore_record(NX_DHCP *dhcp_ptr, NX_DHCP_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
9413 {
9414 
9415 UINT status;
9416 
9417 
9418     if ((dhcp_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
9419     {
9420         return NX_PTR_ERROR;
9421     }
9422 
9423     /* Note: zero time elapsed is an acceptable value. */
9424 
9425     status = _nx_dhcp_client_restore_record(dhcp_ptr, client_record_ptr, time_elapsed);
9426 
9427     return status;
9428 }
9429 
9430 
9431 /**************************************************************************/
9432 /*                                                                        */
9433 /*  FUNCTION                                               RELEASE        */
9434 /*                                                                        */
9435 /*    _nx_dhcp_client_restore_record                      PORTABLE C      */
9436 /*                                                           6.1          */
9437 /*  AUTHOR                                                                */
9438 /*                                                                        */
9439 /*    Yuxin Zhou, Microsoft Corporation                                   */
9440 /*                                                                        */
9441 /*  DESCRIPTION                                                           */
9442 /*                                                                        */
9443 /*    This function updates the DHCP Client state of the first DHCP       */
9444 /*    enabled interface found with the supplied DHCP Client record        */
9445 /*    pointed to by the client_record_ptr pointer. It then updates the    */
9446 /*    time out parameters of the DHCP Client with the time_elapsed        */
9447 /*    input (in timer ticks).                                             */
9448 /*                                                                        */
9449 /*    If DHCP is enabled on multiple interfaces, use                      */
9450 /*    nx_dhcp_client_interface_restore_record to restore a record to a    */
9451 /*    specific interface.                                                 */
9452 /*                                                                        */
9453 /*    This function is intended for restoring Client state between reboots*/
9454 /*    and assumes the DHCP Client state was previously obtained and stored*/
9455 /*    in non volatile memory before power down.                           */
9456 /*                                                                        */
9457 /*    Note: his should not be called in addition to _nx_dhcp_client_update*/
9458 /*    _time_remaining.  _nx_dhcp_client_restore_ calls that function,     */
9459 /*    so calling t_nx_dhcp_client_update_time_remaining separately would  */
9460 /*    effectively apply the time elapsed a second time.                   */
9461 /*                                                                        */
9462 /*  INPUT                                                                 */
9463 /*                                                                        */
9464 /*    dhcp_ptr                              Pointer to DHCP instance      */
9465 /*    client_record_ptr                     Pointer to previously saved   */
9466 /*                                             Client record              */
9467 /*    time_elapsed                          time input in timer ticks     */
9468 /*                                                                        */
9469 /*  OUTPUT                                                                */
9470 /*                                                                        */
9471 /*    NX_DHCP_NO_INTERFACES_ENABLED         No interfaces enabled for DHCP*/
9472 /*    status                                NetX completion status        */
9473 /*                                                                        */
9474 /*  CALLS                                                                 */
9475 /*                                                                        */
9476 /*   _nx_dhcp_client_interface_restore_record                             */
9477 /*                                          Interface specific restore    */
9478 /*    tx_mutex_get                          Obtain protection mutex       */
9479 /*    tx_mutex_put                          Release protection mutex      */
9480 /*                                                                        */
9481 /*  CALLED BY                                                             */
9482 /*                                                                        */
9483 /*    Application code                                                    */
9484 /*                                                                        */
9485 /*  RELEASE HISTORY                                                       */
9486 /*                                                                        */
9487 /*    DATE              NAME                      DESCRIPTION             */
9488 /*                                                                        */
9489 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9490 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9491 /*                                            resulting in version 6.1    */
9492 /*                                                                        */
9493 /**************************************************************************/
_nx_dhcp_client_restore_record(NX_DHCP * dhcp_ptr,NX_DHCP_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)9494 UINT  _nx_dhcp_client_restore_record(NX_DHCP *dhcp_ptr, NX_DHCP_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
9495 {
9496 
9497 UINT    i;
9498 UINT    status;
9499 
9500 
9501     /* Obtain DHCP Client protection mutex. */
9502     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9503 
9504     /* Find the DHCP interface record.  */
9505     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
9506     {
9507 
9508         /* Check which interface record is valid.  */
9509         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
9510         {
9511 
9512             /* Create a record of the current state of the DHCP Client. */
9513             status = _nx_dhcp_client_interface_restore_record(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index,
9514                                                               client_record_ptr, time_elapsed);
9515 
9516             /* Release the DHCP mutex.  */
9517             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9518             return(status);
9519         }
9520     }
9521 
9522     /* Release the DHCP mutex.  */
9523     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9524     return(NX_DHCP_NO_INTERFACES_ENABLED);
9525 }
9526 
9527 
9528 /**************************************************************************/
9529 /*                                                                        */
9530 /*  FUNCTION                                               RELEASE        */
9531 /*                                                                        */
9532 /*    _nxe_dhcp_client_interface_restore_record           PORTABLE C      */
9533 /*                                                           6.1          */
9534 /*  AUTHOR                                                                */
9535 /*                                                                        */
9536 /*    Yuxin Zhou, Microsoft Corporation                                   */
9537 /*                                                                        */
9538 /*  DESCRIPTION                                                           */
9539 /*                                                                        */
9540 /*    This function performs error checking on the client restore service.*/
9541 /*                                                                        */
9542 /*  INPUT                                                                 */
9543 /*                                                                        */
9544 /*    dhcp_ptr                              Pointer to DHCP instance      */
9545 /*    iface_index                           Interface index               */
9546 /*    client_record_ptr                     Pointer to previously saved   */
9547 /*                                             Client record              */
9548 /*    time_elapsed                          time input in timer ticks     */
9549 /*                                                                        */
9550 /*  OUTPUT                                                                */
9551 /*                                                                        */
9552 /*    NX_PTR_ERRPR                          Invalid pointer input         */
9553 /*    status                                NetX completion status        */
9554 /*                                                                        */
9555 /*  CALLS                                                                 */
9556 /*                                                                        */
9557 /*   _nx_dhcp_client_interface_restore_record                             */
9558 /*                                                                        */
9559 /*  CALLED BY                                                             */
9560 /*                                                                        */
9561 /*    Application code                                                    */
9562 /*                                                                        */
9563 /*  RELEASE HISTORY                                                       */
9564 /*                                                                        */
9565 /*    DATE              NAME                      DESCRIPTION             */
9566 /*                                                                        */
9567 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9568 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9569 /*                                            resulting in version 6.1    */
9570 /*                                                                        */
9571 /**************************************************************************/
_nxe_dhcp_client_interface_restore_record(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)9572 UINT  _nxe_dhcp_client_interface_restore_record(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
9573 {
9574 
9575 UINT status;
9576 
9577 
9578     /* Check for invalid input pointers.  */
9579     if ((dhcp_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
9580     {
9581         return NX_PTR_ERROR;
9582     }
9583 
9584     /* Check interface index.  */
9585     if (iface_index >= NX_DHCP_CLIENT_MAX_RECORDS)
9586     {
9587         return NX_INVALID_INTERFACE;
9588     }
9589 
9590     status = _nx_dhcp_client_interface_restore_record(dhcp_ptr, iface_index, client_record_ptr, time_elapsed);
9591 
9592     return status;
9593 }
9594 
9595 
9596 /**************************************************************************/
9597 /*                                                                        */
9598 /*  FUNCTION                                               RELEASE        */
9599 /*                                                                        */
9600 /*    _nx_dhcp_client_interface_restore_record            PORTABLE C      */
9601 /*                                                           6.1          */
9602 /*  AUTHOR                                                                */
9603 /*                                                                        */
9604 /*    Yuxin Zhou, Microsoft Corporation                                   */
9605 /*                                                                        */
9606 /*  DESCRIPTION                                                           */
9607 /*                                                                        */
9608 /*    This function updates the DHCP Client state with the input DHCP     */
9609 /*    Client record for the specified interface. It copies data from the  */
9610 /*    Client record to the interface racord, and updates the time out     */
9611 /*    parameters of the DHCP Client with the time_elapsed inpur (in timer */
9612 /*    ticks).                                                             */
9613 /*                                                                        */
9614 /*    This function is intended for restoring Client state between reboots*/
9615 /*    and assumes the DHCP Client record was previously obtained and      */
9616 /*    stored in non volatile memory before power down.                    */
9617 /*                                                                        */
9618 /*    Note: this should not be called in addition to                      */
9619 /*    nx_dhcp_client_update_time_remaining.                               */
9620 /*    nx_dhcp_client_interface_restore_record calls that function, so     */
9621 /*    calling nx_dhcp_client_update_time_remaining would apply the time   */
9622 /*    elapsed a second time.                                              */
9623 /*                                                                        */
9624 /*  INPUT                                                                 */
9625 /*                                                                        */
9626 /*    dhcp_ptr                              Pointer to DHCP instance      */
9627 /*    client_record_ptr                     Pointer to previously saved   */
9628 /*                                             Client record              */
9629 /*    time_elapsed                          time input in timer ticks     */
9630 /*                                                                        */
9631 /*  OUTPUT                                                                */
9632 /*                                                                        */
9633 /*    NX_SUCCESS                            Successful completion status  */
9634 /*    status                                NetX completion status        */
9635 /*                                                                        */
9636 /*  CALLS                                                                 */
9637 /*                                                                        */
9638 /*    tx_mutex_get                          Obtain protection mutex       */
9639 /*    tx_mutex_put                          Release protection mutex      */
9640 /*   _nx_dhcp_interface_record_find         Find client record for        */
9641 /*                                            specified interface         */
9642 /*    nx_ip_interface_address_set           Set IP interface address      */
9643 /*   _nx_dhcp_client_update_time_remaining  Update time remaining for time*/
9644 /*                                            elapsed while powered down  */
9645 /*                                                                        */
9646 /*  CALLED BY                                                             */
9647 /*                                                                        */
9648 /*    Application code                                                    */
9649 /*                                                                        */
9650 /*  RELEASE HISTORY                                                       */
9651 /*                                                                        */
9652 /*    DATE              NAME                      DESCRIPTION             */
9653 /*                                                                        */
9654 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9655 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
9656 /*                                            restored the gateway        */
9657 /*                                            address,                    */
9658 /*                                            resulting in version 6.1    */
9659 /*                                                                        */
9660 /**************************************************************************/
_nx_dhcp_client_interface_restore_record(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)9661 UINT  _nx_dhcp_client_interface_restore_record(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
9662 {
9663 
9664 UINT    status;
9665 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
9666 
9667     /* Obtain DHCP Client protection mutex. */
9668     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9669 
9670     /* Find the interface record.  */
9671     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
9672 
9673     /* Check status.  */
9674     if (status)
9675     {
9676 
9677         /* Release the DHCP mutex.  */
9678         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9679         return(status);
9680     }
9681 
9682     interface_record -> nx_dhcp_state = client_record_ptr -> nx_dhcp_state;
9683     interface_record -> nx_dhcp_gateway_address = client_record_ptr -> nx_dhcp_gateway_address;
9684     interface_record -> nx_dhcp_server_ip = client_record_ptr -> nx_dhcp_server_ip;
9685     interface_record -> nx_dhcp_timeout = client_record_ptr -> nx_dhcp_timeout;
9686     interface_record -> nx_dhcp_lease_time = client_record_ptr -> nx_dhcp_lease_time ;
9687     interface_record -> nx_dhcp_renewal_time = client_record_ptr -> nx_dhcp_renewal_time;
9688     interface_record -> nx_dhcp_rebind_time = client_record_ptr -> nx_dhcp_rebind_time;
9689     interface_record -> nx_dhcp_renewal_remain_time = client_record_ptr -> nx_dhcp_renewal_remain_time;
9690     interface_record -> nx_dhcp_rebind_remain_time = client_record_ptr -> nx_dhcp_rebind_remain_time;
9691 
9692     /* Restore directly from the client record. */
9693     interface_record -> nx_dhcp_ip_address = client_record_ptr -> nx_dhcp_ip_address;
9694     interface_record -> nx_dhcp_network_mask = client_record_ptr -> nx_dhcp_network_mask;
9695     interface_record -> nx_dhcp_interface_index = iface_index;
9696 
9697     /* Update the IP instance with saved network parameters.*/
9698     status = nx_ip_interface_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, iface_index, interface_record -> nx_dhcp_ip_address, interface_record -> nx_dhcp_network_mask);
9699 
9700     /* Check status.  */
9701     if (status != NX_SUCCESS)
9702     {
9703 
9704         /* Release the DHCP mutex.  */
9705         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9706         return status;
9707     }
9708 
9709     /* Check if the gateway address is valid.  */
9710     if (interface_record -> nx_dhcp_gateway_address)
9711     {
9712 
9713         /* Set the gateway address.  */
9714         status = nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
9715 
9716         /* Check status.  */
9717         if (status != NX_SUCCESS)
9718         {
9719 
9720             /* Release the DHCP mutex.  */
9721             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9722             return(status);
9723         }
9724     }
9725 
9726     /* Now apply the time elapsed to update the DHCP Client time remaining on its lease and current DHCP state. */
9727     status = _nx_dhcp_client_interface_update_time_remaining(dhcp_ptr, interface_record-> nx_dhcp_interface_index, time_elapsed);
9728 
9729     /* Release the DHCP mutex.  */
9730     tx_mutex_put(&(dhcp_ptr->nx_dhcp_mutex));
9731 
9732     return status;
9733 }
9734 
9735 
9736 /**************************************************************************/
9737 /*                                                                        */
9738 /*  FUNCTION                                               RELEASE        */
9739 /*                                                                        */
9740 /*    _nxe_dhcp_client_update_time_remaining              PORTABLE C      */
9741 /*                                                           6.1          */
9742 /*  AUTHOR                                                                */
9743 /*                                                                        */
9744 /*    Yuxin Zhou, Microsoft Corporation                                   */
9745 /*                                                                        */
9746 /*  DESCRIPTION                                                           */
9747 /*                                                                        */
9748 /*    This function performs error checking on the update time remaining  */
9749 /*    service.                                                            */
9750 /*                                                                        */
9751 /*  INPUT                                                                 */
9752 /*                                                                        */
9753 /*    dhcp_ptr                              Pointer to DHCP instance      */
9754 /*    time_elapsed                          time input in timer ticks     */
9755 /*                                                                        */
9756 /*  OUTPUT                                                                */
9757 /*                                                                        */
9758 /*    status                                Actual Completion status      */
9759 /*                                                                        */
9760 /*  CALLS                                                                 */
9761 /*                                                                        */
9762 /*   _nx_dhcp_client_update_time_remaining  Update DHCP timeout for time  */
9763 /*                                            elapsed while powered down  */
9764 /*                                                                        */
9765 /*  CALLED BY                                                             */
9766 /*                                                                        */
9767 /*    Application                                                         */
9768 /*                                                                        */
9769 /*  RELEASE HISTORY                                                       */
9770 /*                                                                        */
9771 /*    DATE              NAME                      DESCRIPTION             */
9772 /*                                                                        */
9773 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9774 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9775 /*                                            resulting in version 6.1    */
9776 /*                                                                        */
9777 /**************************************************************************/
_nxe_dhcp_client_update_time_remaining(NX_DHCP * dhcp_ptr,ULONG time_elapsed)9778 UINT  _nxe_dhcp_client_update_time_remaining(NX_DHCP *dhcp_ptr, ULONG time_elapsed)
9779 {
9780 
9781 UINT status;
9782 
9783 
9784     if (dhcp_ptr == NX_NULL)
9785     {
9786         return NX_PTR_ERROR;
9787     }
9788 
9789     status = _nx_dhcp_client_update_time_remaining(dhcp_ptr, time_elapsed);
9790 
9791     return status;
9792 }
9793 
9794 
9795 /**************************************************************************/
9796 /*                                                                        */
9797 /*  FUNCTION                                               RELEASE        */
9798 /*                                                                        */
9799 /*    _nx_dhcp_client_update_time_remaining               PORTABLE C      */
9800 /*                                                           6.1          */
9801 /*  AUTHOR                                                                */
9802 /*                                                                        */
9803 /*    Yuxin Zhou, Microsoft Corporation                                   */
9804 /*                                                                        */
9805 /*  DESCRIPTION                                                           */
9806 /*                                                                        */
9807 /*    This function applies the input time_elapsed to the DHCP Client     */
9808 /*    time remaining and determines if a state change occurred meanwhile. */
9809 /*    Note that time_elapsed is in timer ticks.                           */
9810 /*                                                                        */
9811 /*    There is no need to call this function if also calling              */
9812 /*    _nx_dhcp_client_restore_record which applies the elapsed time.      */
9813 /*                                                                        */
9814 /*  INPUT                                                                 */
9815 /*                                                                        */
9816 /*    dhcp_ptr                              Pointer to DHCP instance      */
9817 /*    time_elapsed                          time input in timer ticks     */
9818 /*                                                                        */
9819 /*  OUTPUT                                                                */
9820 /*                                                                        */
9821 /*    status                                Actual completion status      */
9822 /*    NX_DHCP_NO_INTERFACES_ENABLED         No interface enabled for DHCP */
9823 /*                                                                        */
9824 /*  CALLS                                                                 */
9825 /*                                                                        */
9826 /*   _nx_dhcp_client_interface_update_time_remaining                      */
9827 /*                                          Apply the elapsed time to the */
9828 /*                                            specified DHCP timeout      */
9829 /*    tx_mutex_get                          Obtain protection mutex       */
9830 /*    tx_mutex_put                          Release protection mutex      */
9831 /*                                                                        */
9832 /*  CALLED BY                                                             */
9833 /*                                                                        */
9834 /*    _nx_dhcp_client_restore_record                                      */
9835 /*                                                                        */
9836 /*  RELEASE HISTORY                                                       */
9837 /*                                                                        */
9838 /*    DATE              NAME                      DESCRIPTION             */
9839 /*                                                                        */
9840 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9841 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9842 /*                                            resulting in version 6.1    */
9843 /*                                                                        */
9844 /**************************************************************************/
_nx_dhcp_client_update_time_remaining(NX_DHCP * dhcp_ptr,ULONG time_elapsed)9845 UINT  _nx_dhcp_client_update_time_remaining(NX_DHCP *dhcp_ptr, ULONG time_elapsed)
9846 {
9847 
9848 UINT i;
9849 UINT status;
9850 
9851 
9852     /* Obtain DHCP Client protection mutex. */
9853     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9854 
9855     /* Find the DHCP interface record.  */
9856     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
9857     {
9858 
9859         /* Check which interface record is valid.  */
9860         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
9861         {
9862 
9863             /* Create a record of the current state of the DHCP CLient. */
9864             status = _nx_dhcp_client_interface_update_time_remaining(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index, time_elapsed);
9865 
9866             /* Release the DHCP mutex.  */
9867             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9868             return(status);
9869         }
9870     }
9871 
9872     /* Release the DHCP mutex.  */
9873     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9874     return(NX_DHCP_NO_INTERFACES_ENABLED);
9875 }
9876 
9877 
9878 /**************************************************************************/
9879 /*                                                                        */
9880 /*  FUNCTION                                               RELEASE        */
9881 /*                                                                        */
9882 /*    _nxe_dhcp_client_interface_update_time_remaining    PORTABLE C      */
9883 /*                                                           6.1          */
9884 /*  AUTHOR                                                                */
9885 /*                                                                        */
9886 /*    Yuxin Zhou, Microsoft Corporation                                   */
9887 /*                                                                        */
9888 /*  DESCRIPTION                                                           */
9889 /*                                                                        */
9890 /*    This function performs error checking on the update time remaining  */
9891 /*    service.                                                            */
9892 /*                                                                        */
9893 /*  INPUT                                                                 */
9894 /*                                                                        */
9895 /*    dhcp_ptr                              Pointer to DHCP instance      */
9896 /*    time_elapsed                          time input in timer ticks     */
9897 /*                                                                        */
9898 /*  OUTPUT                                                                */
9899 /*                                                                        */
9900 /*    status                                Completion status             */
9901 /*    NX_PTR_ERROR                          Invalid pointer input         */
9902 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
9903 /*                                                                        */
9904 /*  CALLS                                                                 */
9905 /*                                                                        */
9906 /*   _nx_dhcp_client_interface_update_time_remaining                      */
9907 /*                                          Actual update time service    */
9908 /*                                                                        */
9909 /*  CALLED BY                                                             */
9910 /*                                                                        */
9911 /*    Application code                                                    */
9912 /*                                                                        */
9913 /*  RELEASE HISTORY                                                       */
9914 /*                                                                        */
9915 /*    DATE              NAME                      DESCRIPTION             */
9916 /*                                                                        */
9917 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9918 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9919 /*                                            resulting in version 6.1    */
9920 /*                                                                        */
9921 /**************************************************************************/
_nxe_dhcp_client_interface_update_time_remaining(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG time_elapsed)9922 UINT  _nxe_dhcp_client_interface_update_time_remaining(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG time_elapsed)
9923 {
9924 
9925 UINT status;
9926 
9927 
9928     /* Check for invalid input pointers.  */
9929     if (dhcp_ptr == NX_NULL)
9930     {
9931         return NX_PTR_ERROR;
9932     }
9933 
9934     /* Check interface index.  */
9935     if (iface_index >= NX_DHCP_CLIENT_MAX_RECORDS)
9936     {
9937         return NX_INVALID_INTERFACE;
9938     }
9939 
9940     status = _nx_dhcp_client_interface_update_time_remaining(dhcp_ptr, iface_index, time_elapsed);
9941 
9942     return status;
9943 }
9944 
9945 
9946 /**************************************************************************/
9947 /*                                                                        */
9948 /*  FUNCTION                                               RELEASE        */
9949 /*                                                                        */
9950 /*    _nx_dhcp_client_interface_update_time_remaining     PORTABLE C      */
9951 /*                                                           6.1          */
9952 /*  AUTHOR                                                                */
9953 /*                                                                        */
9954 /*    Yuxin Zhou, Microsoft Corporation                                   */
9955 /*                                                                        */
9956 /*  DESCRIPTION                                                           */
9957 /*                                                                        */
9958 /*    This function applies the input time_elapsed data to the DHCP Client*/
9959 /*    state and determines what state it should be in (e.g. BOUND,        */
9960 /*    IP address. Note, time_elapsed is in timer ticks. If called from the*/
9961 /*    application it is assumed the application device is sleeping, not   */
9962 /*    powering up.  If the device is waking up from sleeping, it does not */
9963 /*    need to restore the DHCP client state but only to update the time   */
9964 /*    elapsed.                                                            */
9965 /*                                                                        */
9966 /*    Therefore this should not be called in addition to                  */
9967 /*    _nx_dhcp_client_restore_record.  The restore record service handles */
9968 /*    updating time remaining, such that calling this service would       */
9969 /*    effectively apply the time elapsed a second time.                   */
9970 /*                                                                        */
9971 /*  INPUT                                                                 */
9972 /*                                                                        */
9973 /*    dhcp_ptr                              Pointer to DHCP instance      */
9974 /*    time_elapsed                          time input in timer ticks     */
9975 /*                                                                        */
9976 /*  OUTPUT                                                                */
9977 /*                                                                        */
9978 /*    NX_SUCCESS                            Successful Completion status  */
9979 /*    status                                Actual completion status      */
9980 /*                                                                        */
9981 /*  CALLS                                                                 */
9982 /*                                                                        */
9983 /*    tx_mutex_get                          Obtain protection mutex       */
9984 /*    tx_mutex_put                          Release protection mutex      */
9985 /*   _nx_dhcp_update_renewal_timeout        Update time remaining on lease*/
9986 /*   _nx_dhcp_interface_record_find         Find record for the interface */
9987 /*   _nx_dhcp_interface_reinitialize        Clear DHCP and IP network     */
9988 /*                                            parameters                  */
9989 /*                                                                        */
9990 /*  CALLED BY                                                             */
9991 /*                                                                        */
9992 /*    Application code                                                    */
9993 /*                                                                        */
9994 /*  RELEASE HISTORY                                                       */
9995 /*                                                                        */
9996 /*    DATE              NAME                      DESCRIPTION             */
9997 /*                                                                        */
9998 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9999 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10000 /*                                            resulting in version 6.1    */
10001 /*                                                                        */
10002 /**************************************************************************/
_nx_dhcp_client_interface_update_time_remaining(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG time_elapsed)10003 UINT  _nx_dhcp_client_interface_update_time_remaining(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG time_elapsed)
10004 {
10005 
10006 UINT                      status;
10007 UINT                      accrued_time_adjusted = 0;
10008 UINT                      time_accrued;
10009 UINT                      original_state;
10010 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
10011 
10012 
10013     /* Obtain DHCP Client protection mutex. */
10014     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
10015 
10016     /* Find the interface record.  */
10017     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
10018 
10019     /* Check status.  */
10020     if (status)
10021     {
10022 
10023         /* Release the DHCP mutex.  */
10024         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10025         return(status);
10026     }
10027 
10028     /* Get the original state.  */
10029     original_state = interface_record -> nx_dhcp_state;
10030 
10031     /* Compute the time since the lease was assigned before we suspended the Client.  */
10032     if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_BOUND)
10033     {
10034         if (interface_record -> nx_dhcp_renewal_time >= interface_record -> nx_dhcp_timeout)
10035         {
10036             /* Since the Client is in a BOUND state, we know the timeout is less than T2
10037                or nx_dhcp_renew_time. */
10038             time_accrued = interface_record -> nx_dhcp_renewal_time - interface_record -> nx_dhcp_timeout;
10039         }
10040         else
10041         {
10042             /* Invalid DHCP timeout. If it is in the BOUND state, set to the renewal time. */
10043             time_accrued = interface_record -> nx_dhcp_renewal_time;
10044         }
10045     }
10046     else if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING)
10047     {
10048 
10049         /* Since the Client is in the RENEWING state, the total time on the lease is the
10050            lease rebind time - the time out in the RENEW state: */
10051         time_accrued = interface_record -> nx_dhcp_rebind_time - interface_record -> nx_dhcp_renewal_remain_time;
10052 
10053         /* Note if dhcp_ptr -> nx_dhcp_rebind_time < dhcp_ptr -> nx_dhcp_renewal_remain_time,
10054            the CLient either received invalid DHCP parameters or there is an internal error.
10055            The renewal time should never exceed the rebind time.  */
10056     }
10057     else if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_REBINDING)
10058     {
10059 
10060         /* Since the Client is in the REBINDING state, the total time on the lease is the
10061            lease  time - the  time remaining in the REBIND state: */
10062         time_accrued = interface_record -> nx_dhcp_lease_time - interface_record -> nx_dhcp_rebind_remain_time;
10063 
10064         /* Note if dhcp_ptr -> nx_dhcp_lease_time < dhcp_ptr -> nx_dhcp_rebind_remain_time,
10065            the CLient either received invalid DHCP parameters or there is an internal error.
10066            The rebind time should never exceed the lease time.  */
10067     }
10068     else
10069     {
10070         /* Expired! */
10071         accrued_time_adjusted = 0xFFFFFFFF;
10072     }
10073 
10074     /* Adjust the time accrued to include the interval while the Client was suspended. */
10075     if (accrued_time_adjusted != 0xFFFFFFFF)
10076     {
10077         accrued_time_adjusted = time_accrued + time_elapsed;
10078     }
10079 
10080     /* Determine if the DHCP Client needs to renew. */
10081     if (accrued_time_adjusted < interface_record -> nx_dhcp_renewal_time)
10082     {
10083 
10084         /* Not yet.  Update the nx_dhcp_timeout for the time elapsed and we're done. */
10085         interface_record -> nx_dhcp_timeout -= time_elapsed;
10086 
10087         /* Release the DHCP mutex.  */
10088         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10089 
10090         /* We are done. Ok to resume the Client. */
10091         return NX_SUCCESS;
10092     }
10093 
10094     /* Determine if the Client should renew. */
10095     else if (accrued_time_adjusted < interface_record -> nx_dhcp_rebind_time)
10096     {
10097 
10098         /* Yes; it has not reached the expiration on the renew period.  */
10099 
10100         /* Check if it is already in the RENEW state. */
10101         if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING)
10102         {
10103 
10104             /* Yes it is, so do nothing. Let the Client continue renewing. */
10105 
10106             /* Update the time remaining for the Client to renew its lease.   */
10107             interface_record -> nx_dhcp_renewal_remain_time -= time_elapsed;
10108 
10109             /* Reset the timeout based on the updated time remaining to renew. */
10110             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
10111 
10112             /* Record the retransmission interval.  */
10113             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10114         }
10115         else
10116         {
10117 
10118             /* No it wasn't so update the Client for the RENEW state. */
10119 
10120             /* Compute how many seconds into the renew period the Client is (total time on lease over and above
10121                the time to start renewing. */
10122             if (accrued_time_adjusted == interface_record -> nx_dhcp_renewal_time)
10123             {
10124 
10125                 interface_record -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_rebind_time - interface_record -> nx_dhcp_renewal_time;
10126             }
10127             else
10128             {
10129 
10130                 interface_record -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_rebind_time - accrued_time_adjusted;
10131             }
10132 
10133             /* Set the DHCP timeout for being in the RENEW phase. */
10134             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
10135 
10136             /* Record the retransmission interval.  */
10137             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10138 
10139             /* And change to the Renewing state. */
10140             interface_record -> nx_dhcp_state = NX_DHCP_STATE_RENEWING;
10141         }
10142 
10143         /* Release the DHCP mutex.  */
10144         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10145 
10146         /* We are done. Ok to resume the Client. */
10147         return NX_SUCCESS;
10148     }
10149 
10150     /* Determine if it is time for the Client to rebind (e.g. check the lease has not completely expired). */
10151     else if (accrued_time_adjusted < interface_record -> nx_dhcp_lease_time)
10152     {
10153 
10154         /* Check if it is already in the REBIND state. */
10155         if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_REBINDING)
10156         {
10157             /* Yes it is, so do nothing. Let the Client complete its rebind task*/
10158 
10159             /* Update the time remaining for the Client to rebind an IP address.   */
10160             interface_record -> nx_dhcp_rebind_remain_time -= time_elapsed;
10161 
10162             /* Reset the timeout based on the updated time remaining to rebind. */
10163             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_rebind_remain_time);
10164 
10165             /* Record the retransmission interval.  */
10166             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10167         }
10168         else
10169         {
10170 
10171             /* No it wasn't so update the Client for the REBIND state. */
10172 
10173             /* Compute how many seconds into the rebind period the Client is (total time on lease over and above
10174                the time to start rebinding. */
10175             if (accrued_time_adjusted == interface_record -> nx_dhcp_rebind_time)
10176             {
10177 
10178                 interface_record -> nx_dhcp_rebind_remain_time = interface_record -> nx_dhcp_lease_time - interface_record -> nx_dhcp_rebind_time;
10179             }
10180             else
10181             {
10182 
10183                 interface_record -> nx_dhcp_rebind_remain_time = interface_record -> nx_dhcp_lease_time - accrued_time_adjusted;
10184             }
10185 
10186             /* Set the DHCP timeout for being in the RENEW phase. */
10187             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_rebind_remain_time);
10188 
10189             /* Record the retransmission interval.  */
10190             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10191 
10192             /* Record the retransmission interval.  */
10193             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10194 
10195             /* And change to the Rebinding state. */
10196             interface_record -> nx_dhcp_state = NX_DHCP_STATE_REBINDING;
10197         }
10198 
10199         /* Release the DHCP mutex.  */
10200         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10201 
10202         /* We are done. Ok to resume the Client. */
10203         return NX_SUCCESS;
10204     }
10205     else
10206     {
10207 
10208         /* Clear the existing DHCP Client network parameters for restarting in the INIT state. */
10209         _nx_dhcp_interface_reinitialize(dhcp_ptr, iface_index);
10210 
10211         /* Start the DHCP protocol again by setting the state back to INIT. */
10212         interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
10213 
10214         /* The client begins in INIT state and forms a DHCPDISCOVER message.
10215            The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
10216            RFC2131, Section4.4.1, Page36.  */
10217 
10218         /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
10219         interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
10220         interface_record -> nx_dhcp_rtr_interval = 0;
10221     }
10222 
10223     /* Check if the state is changed.  */
10224     if (original_state != interface_record -> nx_dhcp_state)
10225     {
10226 
10227         /* Determine if the application has specified a routine for DHCP state change notification.  */
10228         if (dhcp_ptr -> nx_dhcp_state_change_callback)
10229         {
10230 
10231             /* Yes, call the application's state change notify function with the new state.  */
10232             (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
10233         }
10234 
10235         /* Determine if the application has specified a routine for DHCP interface state change notification.  */
10236         if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
10237         {
10238 
10239             /* Yes, call the application's state change notify function with the new state.  */
10240             (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
10241         }
10242     }
10243 
10244     /* Release the DHCP mutex.  */
10245     tx_mutex_put(&(dhcp_ptr->nx_dhcp_mutex));
10246 
10247     return NX_SUCCESS;
10248 }
10249 
10250 
10251 /**************************************************************************/
10252 /*                                                                        */
10253 /*  FUNCTION                                               RELEASE        */
10254 /*                                                                        */
10255 /*    _nxe_dhcp_resume                                    PORTABLE C      */
10256 /*                                                           6.1          */
10257 /*  AUTHOR                                                                */
10258 /*                                                                        */
10259 /*    Yuxin Zhou, Microsoft Corporation                                   */
10260 /*                                                                        */
10261 /*  DESCRIPTION                                                           */
10262 /*                                                                        */
10263 /*    This function performs error checking for the Client resume service.*/
10264 /*                                                                        */
10265 /*  INPUT                                                                 */
10266 /*                                                                        */
10267 /*    dhcp_ptr                              Pointer to DHCP instance      */
10268 /*                                                                        */
10269 /*  OUTPUT                                                                */
10270 /*                                                                        */
10271 /*    NX_PTR_ERROR                          Invalid pointer input         */
10272 /*    status                                Actual completion  status     */
10273 /*                                                                        */
10274 /*  CALLS                                                                 */
10275 /*                                                                        */
10276 /*   _nx_dhcp_resume                        Actual Client resume service  */
10277 /*                                                                        */
10278 /*  CALLED BY                                                             */
10279 /*                                                                        */
10280 /*    Application Code                                                    */
10281 /*                                                                        */
10282 /*  RELEASE HISTORY                                                       */
10283 /*                                                                        */
10284 /*    DATE              NAME                      DESCRIPTION             */
10285 /*                                                                        */
10286 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10287 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10288 /*                                            resulting in version 6.1    */
10289 /*                                                                        */
10290 /**************************************************************************/
_nxe_dhcp_resume(NX_DHCP * dhcp_ptr)10291 UINT  _nxe_dhcp_resume(NX_DHCP *dhcp_ptr)
10292 {
10293 
10294 UINT status;
10295 
10296 
10297     if (dhcp_ptr == NX_NULL)
10298     {
10299         return NX_PTR_ERROR;
10300     }
10301 
10302     status = _nx_dhcp_resume(dhcp_ptr);
10303 
10304     return status;
10305 }
10306 
10307 /**************************************************************************/
10308 /*                                                                        */
10309 /*  FUNCTION                                               RELEASE        */
10310 /*                                                                        */
10311 /*    _nx_dhcp_resume                                     PORTABLE C      */
10312 /*                                                           6.1          */
10313 /*  AUTHOR                                                                */
10314 /*                                                                        */
10315 /*    Yuxin Zhou, Microsoft Corporation                                   */
10316 /*                                                                        */
10317 /*  DESCRIPTION                                                           */
10318 /*                                                                        */
10319 /*    This function resumes the DHCP Client thread and timer.  It then    */
10320 /*    checks the state on all DHCP enabled interfaces if renewing or      */
10321 /*    rebinding.  If so it sends a REQUEST to the DHCP server.            */
10322 /*                                                                        */
10323 /*    The DHCP Client application can then call the                       */
10324 /*    nx_dhcp_client_udpate_remaining_time() service to update the time   */
10325 /*    remaining on the client lease, before calling nx_dhcp_resume.       */
10326 /*                                                                        */
10327 /*    This function does not change the Client state, lease timeout or    */
10328 /*    time remaining on the current lease.  It requires the               */
10329 /*    NX_DHCP_CLIENT_RESTORE_STATE option to be enabled.                  */
10330 /*                                                                        */
10331 /*  INPUT                                                                 */
10332 /*                                                                        */
10333 /*    dhcp_ptr                              Pointer to DHCP instance      */
10334 /*                                                                        */
10335 /*  OUTPUT                                                                */
10336 /*                                                                        */
10337 /*    NX_SUCCESS                            Successful Completion status  */
10338 /*    NX_DHCP_ALREADY_STARTED               DHCP Client thread started    */
10339 /*    status                                NetX or ThreadX completion    */
10340 /*                                             status                     */
10341 /*                                                                        */
10342 /*  CALLS                                                                 */
10343 /*                                                                        */
10344 /*   _nx_dhcp_send_request_internal         Send message to DHCP server   */
10345 /*   nx_udp_socket_bind                     Bind UDP socket to port       */
10346 /*   tx_thread_resume                       Resume the DHCP Client thread */
10347 /*   tx_mutex_get                           Obtain mutex protection       */
10348 /*   tx_mutex_put                           Release mutex protectiob      */
10349 /*                                                                        */
10350 /*  CALLED BY                                                             */
10351 /*                                                                        */
10352 /*    Application Code                                                    */
10353 /*                                                                        */
10354 /*  RELEASE HISTORY                                                       */
10355 /*                                                                        */
10356 /*    DATE              NAME                      DESCRIPTION             */
10357 /*                                                                        */
10358 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10359 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
10360 /*                                            fixed compiler warnings,    */
10361 /*                                            resulting in version 6.1    */
10362 /*                                                                        */
10363 /**************************************************************************/
_nx_dhcp_resume(NX_DHCP * dhcp_ptr)10364 UINT _nx_dhcp_resume(NX_DHCP *dhcp_ptr)
10365 {
10366 
10367 UINT    i;
10368 UINT    status;
10369 NX_IP   *ip_ptr;
10370 ULONG   client_physical_msw;
10371 ULONG   client_physical_lsw;
10372 UINT    iface_index;
10373 
10374 
10375     /* Get the DHCP mutex.  */
10376     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
10377 
10378     /* Resume the DHCP processing thread.  */
10379     status = tx_thread_resume(&(dhcp_ptr -> nx_dhcp_thread));
10380 
10381     /* Determine if the resume was successful.  */
10382     if ((status != TX_SUCCESS) && (status != TX_SUSPEND_LIFTED))
10383     {
10384 
10385         /* Release the DHCP mutex.  */
10386         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10387         return(status);
10388     }
10389 
10390     /* Active the timer.  */
10391     status = tx_timer_activate(&(dhcp_ptr -> nx_dhcp_timer));
10392 
10393     /* Check status.  */
10394     if (status)
10395     {
10396 
10397         /* Release the DHCP mutex.  */
10398         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10399         return(status);
10400     }
10401 
10402     /* Bind the UDP socket to the DHCP Client port.  */
10403     status =  nx_udp_socket_bind(&(dhcp_ptr -> nx_dhcp_socket), NX_DHCP_CLIENT_UDP_PORT, NX_WAIT_FOREVER);
10404 
10405     /* Check status.  */
10406     if (status)
10407     {
10408 
10409         /* Release the DHCP mutex.  */
10410         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10411         return(status);
10412     }
10413 
10414     /* Set IP pointer.  */
10415     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
10416 
10417     /* Loop to process interface records.  */
10418     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
10419     {
10420 
10421         /* Check which interface record is valid.  */
10422         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
10423         {
10424 
10425             /* Get the interface index.  */
10426             iface_index = dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index;
10427 
10428             /* Get the client MAC address from the device interface. */
10429             client_physical_msw = ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_msw;
10430             client_physical_lsw = ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_lsw;
10431 
10432             /* Generate a 'unique' client transaction ID from the MAC address for each message to the server. */
10433             dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_xid = client_physical_msw ^ client_physical_lsw ^ (ULONG)NX_RAND();
10434 
10435             /* If the DHCP Client is renewing or rebinding on being resumed, send a DHCP request. */
10436             if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state == NX_DHCP_STATE_RENEWING) ||
10437                 (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state == NX_DHCP_STATE_REBINDING))
10438             {
10439 
10440                 /* Transmit the request message.  */
10441                 _nx_dhcp_send_request_internal(dhcp_ptr, &dhcp_ptr -> nx_dhcp_interface_record[i], NX_DHCP_TYPE_DHCPREQUEST);
10442             }
10443         }
10444     }
10445 
10446     /* Release the DHCP mutex.  */
10447     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10448 
10449     /* Return completion status.  */
10450     return(NX_SUCCESS);
10451 }
10452 
10453 /**************************************************************************/
10454 /*                                                                        */
10455 /*  FUNCTION                                               RELEASE        */
10456 /*                                                                        */
10457 /*    _nxe_dhcp_suspend                                   PORTABLE C      */
10458 /*                                                           6.1          */
10459 /*  AUTHOR                                                                */
10460 /*                                                                        */
10461 /*    Yuxin Zhou, Microsoft Corporation                                   */
10462 /*                                                                        */
10463 /*  DESCRIPTION                                                           */
10464 /*                                                                        */
10465 /*    This function performs error checking for the Client suspend        */
10466 /*    service.                                                            */
10467 /*                                                                        */
10468 /*  INPUT                                                                 */
10469 /*                                                                        */
10470 /*    dhcp_ptr                              Pointer to DHCP instance      */
10471 /*                                                                        */
10472 /*  OUTPUT                                                                */
10473 /*                                                                        */
10474 /*    NX_SUCCESS                            Successful Completion status  */
10475 /*    status                                Actual completion  status     */
10476 /*                                                                        */
10477 /*  CALLS                                                                 */
10478 /*                                                                        */
10479 /*   _nx_dhcp_suspend                       Actual Client suspend service */
10480 /*                                                                        */
10481 /*  CALLED BY                                                             */
10482 /*                                                                        */
10483 /*    Application Code                                                    */
10484 /*                                                                        */
10485 /*  RELEASE HISTORY                                                       */
10486 /*                                                                        */
10487 /*    DATE              NAME                      DESCRIPTION             */
10488 /*                                                                        */
10489 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10490 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10491 /*                                            resulting in version 6.1    */
10492 /*                                                                        */
10493 /**************************************************************************/
_nxe_dhcp_suspend(NX_DHCP * dhcp_ptr)10494 UINT  _nxe_dhcp_suspend(NX_DHCP *dhcp_ptr)
10495 {
10496 
10497 UINT status;
10498 
10499 
10500     if (dhcp_ptr == NX_NULL)
10501     {
10502         return NX_PTR_ERROR;
10503     }
10504 
10505    status = _nx_dhcp_suspend(dhcp_ptr);
10506    return status;
10507 }
10508 
10509 
10510 /**************************************************************************/
10511 /*                                                                        */
10512 /*  FUNCTION                                               RELEASE        */
10513 /*                                                                        */
10514 /*    _nx_dhcp_suspend                                   PORTABLE C       */
10515 /*                                                           6.1          */
10516 /*  AUTHOR                                                                */
10517 /*                                                                        */
10518 /*    Yuxin Zhou, Microsoft Corporation                                   */
10519 /*                                                                        */
10520 /*  DESCRIPTION                                                           */
10521 /*                                                                        */
10522 /*    This function suspends the DHCP Client task thread and unbinds the  */
10523 /*    socket port. The intented use of this service is to combine with the*/
10524 /*    resume service such that the calling application can 'pause' the    */
10525 /*    DHCP Client for a certain amount of time, and resume it in the same */
10526 /*    state.  The DHCP Client application can then call the               */
10527 /*    nx_dhcp_client_udpate_remaining_time service to update the time     */
10528 /*    remaining on the client lease, then nx_dhcp_resume to actually      */
10529 /*    resume the DHCP Client task.                                        */
10530 /*                                                                        */
10531 /*    This function does not change the Client state, lease timeout or    */
10532 /*    time remaining on the current lease.  It requires the               */
10533 /*    NX_DHCP_CLIENT_RESTORE_STATE option to be enabled.                  */
10534 /*                                                                        */
10535 /*  INPUT                                                                 */
10536 /*                                                                        */
10537 /*    dhcp_ptr                              Pointer to DHCP instance      */
10538 /*                                                                        */
10539 /*  OUTPUT                                                                */
10540 /*                                                                        */
10541 /*    NX_SUCCESS                            Successful Completion status  */
10542 /*                                                                        */
10543 /*  CALLS                                                                 */
10544 /*                                                                        */
10545 /*   nx_udp_socket_unbind                   Unbind port from UDP socket   */
10546 /*   tx_timer_deactivate                    Stop the timer                */
10547 /*   tx_thread_suspend                      Suspend the DHCP Client thread*/
10548 /*   tx_mutex_get                           Obtain mutex protection       */
10549 /*   tx_mutex_put                           Release mutex protection      */
10550 /*                                                                        */
10551 /*  CALLED BY                                                             */
10552 /*                                                                        */
10553 /*    Application Code                                                    */
10554 /*                                                                        */
10555 /*  RELEASE HISTORY                                                       */
10556 /*                                                                        */
10557 /*    DATE              NAME                      DESCRIPTION             */
10558 /*                                                                        */
10559 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10560 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10561 /*                                            resulting in version 6.1    */
10562 /*                                                                        */
10563 /**************************************************************************/
_nx_dhcp_suspend(NX_DHCP * dhcp_ptr)10564 UINT  _nx_dhcp_suspend(NX_DHCP *dhcp_ptr)
10565 {
10566 
10567 
10568     /* Get the DHCP mutex.  */
10569     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
10570 
10571     /* Suspend the DHCP thread.  */
10572     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread));
10573 
10574     /* Deactive the timer.  */
10575     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer));
10576 
10577     /* Unbind the port.  */
10578     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
10579 
10580     /* Release the DHCP mutex.  */
10581     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10582 
10583     /* Return completion status.  */
10584     return(NX_SUCCESS);
10585 }
10586 
10587 #endif /* NX_DHCP_CLIENT_RESTORE_STATE */
10588 #endif /* NX_DISABLE_IPV4 */
10589