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