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.1          */
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 /*                                                                        */
3590 /**************************************************************************/
_nxe_dhcp_state_change_notify(NX_DHCP * dhcp_ptr,VOID (* dhcp_state_change_notify)(NX_DHCP * dhcp_ptr,UCHAR new_state))3591 UINT  _nxe_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state))
3592 {
3593 
3594 UINT    status;
3595 
3596 
3597     /* Check for invalid input pointer.  */
3598     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
3599         return(NX_PTR_ERROR);
3600 
3601     /* Check for appropriate caller.  */
3602     NX_THREADS_ONLY_CALLER_CHECKING
3603 
3604     /* Call actual DHCP notify service.  */
3605     status =  _nx_dhcp_state_change_notify(dhcp_ptr, dhcp_state_change_notify);
3606 
3607     /* Return status.  */
3608     return(status);
3609 }
3610 
3611 
3612 /**************************************************************************/
3613 /*                                                                        */
3614 /*  FUNCTION                                               RELEASE        */
3615 /*                                                                        */
3616 /*    _nx_dhcp_state_change_notify                        PORTABLE C      */
3617 /*                                                           6.1          */
3618 /*  AUTHOR                                                                */
3619 /*                                                                        */
3620 /*    Yuxin Zhou, Microsoft Corporation                                   */
3621 /*                                                                        */
3622 /*  DESCRIPTION                                                           */
3623 /*                                                                        */
3624 /*    This function sets up an application notification function that is  */
3625 /*    called whenever a DHCP interface enters a new state.  If a NULL     */
3626 /*    pointer is supplied, the notification is effectively cancelled.     */
3627 /*                                                                        */
3628 /*  INPUT                                                                 */
3629 /*                                                                        */
3630 /*    dhcp_ptr                              Pointer to DHCP instance      */
3631 /*    dchp_state_change_notify              Application function to call  */
3632 /*                                            upon DHCP state change      */
3633 /*                                                                        */
3634 /*  OUTPUT                                                                */
3635 /*                                                                        */
3636 /*    status                                Completion status             */
3637 /*                                                                        */
3638 /*  CALLS                                                                 */
3639 /*                                                                        */
3640 /*    tx_mutex_get                          Get the DHCP mutex            */
3641 /*    tx_mutex_put                          Release the DHCP mutex        */
3642 /*                                                                        */
3643 /*  CALLED BY                                                             */
3644 /*                                                                        */
3645 /*    Application Code                                                    */
3646 /*                                                                        */
3647 /*  RELEASE HISTORY                                                       */
3648 /*                                                                        */
3649 /*    DATE              NAME                      DESCRIPTION             */
3650 /*                                                                        */
3651 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3652 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3653 /*                                            resulting in version 6.1    */
3654 /*                                                                        */
3655 /**************************************************************************/
_nx_dhcp_state_change_notify(NX_DHCP * dhcp_ptr,VOID (* dhcp_state_change_notify)(NX_DHCP * dhcp_ptr,UCHAR new_state))3656 UINT  _nx_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state))
3657 {
3658 
3659 
3660     /* Get the DHCP mutex.  */
3661     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
3662 
3663     /* Setup the DHCP notify function.  */
3664     dhcp_ptr -> nx_dhcp_state_change_callback =  dhcp_state_change_notify;
3665 
3666     /* Release the DHCP mutex.  */
3667     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3668 
3669     /* Return completion status.  */
3670     return(NX_SUCCESS);
3671 }
3672 
3673 
3674 /**************************************************************************/
3675 /*                                                                        */
3676 /*  FUNCTION                                               RELEASE        */
3677 /*                                                                        */
3678 /*    _nxe_dhcp_interface_state_change_notify             PORTABLE C      */
3679 /*                                                           6.1          */
3680 /*  AUTHOR                                                                */
3681 /*                                                                        */
3682 /*    Yuxin Zhou, Microsoft Corporation                                   */
3683 /*                                                                        */
3684 /*  DESCRIPTION                                                           */
3685 /*                                                                        */
3686 /*    This function checks for errors in the state change notify call.    */
3687 /*                                                                        */
3688 /*  INPUT                                                                 */
3689 /*                                                                        */
3690 /*    dhcp_ptr                              Pointer to DHCP instance      */
3691 /*    dhcp_state_interface_change_notify    Application function to call  */
3692 /*                                            upon DHCP state change      */
3693 /*                                                                        */
3694 /*  OUTPUT                                                                */
3695 /*                                                                        */
3696 /*    NX_SUCCESS                            Successful completion status  */
3697 /*    NX_PTR_ERROR                          Invalid pointer input         */
3698 /*                                                                        */
3699 /*  CALLS                                                                 */
3700 /*                                                                        */
3701 /*    _nx_dhcp_interface_state_change_notify Actual DHCP notify function  */
3702 /*                                                                        */
3703 /*  CALLED BY                                                             */
3704 /*                                                                        */
3705 /*    Application Code                                                    */
3706 /*                                                                        */
3707 /*  RELEASE HISTORY                                                       */
3708 /*                                                                        */
3709 /*    DATE              NAME                      DESCRIPTION             */
3710 /*                                                                        */
3711 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3712 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3713 /*                                            resulting in version 6.1    */
3714 /*                                                                        */
3715 /**************************************************************************/
_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))3716 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))
3717 {
3718 
3719 UINT    status;
3720 
3721     /* Check for invalid input pointer.  */
3722     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
3723     {
3724         return(NX_PTR_ERROR);
3725     }
3726 
3727     /* Call actual DHCP notify service.  */
3728     status =  _nx_dhcp_interface_state_change_notify(dhcp_ptr, dhcp_state_interface_change_notify);
3729 
3730     /* Return status.  */
3731     return(status);
3732 }
3733 
3734 
3735 /**************************************************************************/
3736 /*                                                                        */
3737 /*  FUNCTION                                               RELEASE        */
3738 /*                                                                        */
3739 /*    _nx_dhcp_interface_state_change_notify              PORTABLE C      */
3740 /*                                                           6.1          */
3741 /*  AUTHOR                                                                */
3742 /*                                                                        */
3743 /*    Yuxin Zhou, Microsoft Corporation                                   */
3744 /*                                                                        */
3745 /*  DESCRIPTION                                                           */
3746 /*                                                                        */
3747 /*    This function sets up an application notification function that is  */
3748 /*    called whenever DHCP on the input interface enters a new state. If  */
3749 /*    NULL function pointer is supplied, the notification is  cancelled.  */
3750 /*    The interface on which the DHCP state changed is indicated by the   */
3751 /*    iface_index input.                                                  */
3752 /*                                                                        */
3753 /*  INPUT                                                                 */
3754 /*                                                                        */
3755 /*    dhcp_ptr                              Pointer to DHCP instance      */
3756 /*    dchp_state_change_notify              interface-specific callback   */
3757 /*                                            for DHCP state change       */
3758 /*                                                                        */
3759 /*  OUTPUT                                                                */
3760 /*                                                                        */
3761 /*    NX_SUCCESS                            Successful status             */
3762 /*                                                                        */
3763 /*  CALLS                                                                 */
3764 /*                                                                        */
3765 /*    tx_mutex_get                          Get the DHCP mutex            */
3766 /*    tx_mutex_put                          Release the DHCP mutex        */
3767 /*                                                                        */
3768 /*  CALLED BY                                                             */
3769 /*                                                                        */
3770 /*    Application Code                                                    */
3771 /*                                                                        */
3772 /*  RELEASE HISTORY                                                       */
3773 /*                                                                        */
3774 /*    DATE              NAME                      DESCRIPTION             */
3775 /*                                                                        */
3776 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3777 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3778 /*                                            resulting in version 6.1    */
3779 /*                                                                        */
3780 /**************************************************************************/
_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))3781 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))
3782 {
3783 
3784 
3785     /* Obtain the DHCP mutex.  */
3786     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
3787 
3788     /* Setup the DHCP notify function.  */
3789     dhcp_ptr -> nx_dhcp_interface_state_change_callback =  dhcp_interface_state_change_notify;
3790 
3791     /* Release the DHCP mutex.  */
3792     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3793 
3794     /* Return completion status.  */
3795     return(NX_SUCCESS);
3796 }
3797 
3798 
3799 /**************************************************************************/
3800 /*                                                                        */
3801 /*  FUNCTION                                               RELEASE        */
3802 /*                                                                        */
3803 /*    _nxe_dhcp_stop                                      PORTABLE C      */
3804 /*                                                           6.1          */
3805 /*  AUTHOR                                                                */
3806 /*                                                                        */
3807 /*    Yuxin Zhou, Microsoft Corporation                                   */
3808 /*                                                                        */
3809 /*  DESCRIPTION                                                           */
3810 /*                                                                        */
3811 /*    This function checks for errors in the DHCP stop function call.     */
3812 /*                                                                        */
3813 /*  INPUT                                                                 */
3814 /*                                                                        */
3815 /*    dhcp_ptr                              Pointer to DHCP instance      */
3816 /*                                                                        */
3817 /*  OUTPUT                                                                */
3818 /*                                                                        */
3819 /*    status                                Completion status             */
3820 /*    NX_PTR_ERROR                          Invalid pointer input         */
3821 /*                                                                        */
3822 /*  CALLS                                                                 */
3823 /*                                                                        */
3824 /*    _nx_dhcp_stop                         Actual DHCP stop function     */
3825 /*                                                                        */
3826 /*  CALLED BY                                                             */
3827 /*                                                                        */
3828 /*    Application Code                                                    */
3829 /*                                                                        */
3830 /*  RELEASE HISTORY                                                       */
3831 /*                                                                        */
3832 /*    DATE              NAME                      DESCRIPTION             */
3833 /*                                                                        */
3834 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3835 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3836 /*                                            resulting in version 6.1    */
3837 /*                                                                        */
3838 /**************************************************************************/
_nxe_dhcp_stop(NX_DHCP * dhcp_ptr)3839 UINT  _nxe_dhcp_stop(NX_DHCP *dhcp_ptr)
3840 {
3841 
3842 UINT    status;
3843 
3844 
3845     /* Check for invalid input pointer.  */
3846     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
3847         return(NX_PTR_ERROR);
3848 
3849     /* Check for appropriate caller.  */
3850     NX_THREADS_ONLY_CALLER_CHECKING
3851 
3852     /* Call actual DHCP stop service.  */
3853     status =  _nx_dhcp_stop(dhcp_ptr);
3854 
3855     /* Return status.  */
3856     return(status);
3857 }
3858 
3859 
3860 /**************************************************************************/
3861 /*                                                                        */
3862 /*  FUNCTION                                               RELEASE        */
3863 /*                                                                        */
3864 /*    _nx_dhcp_stop                                       PORTABLE C      */
3865 /*                                                           6.1          */
3866 /*  AUTHOR                                                                */
3867 /*                                                                        */
3868 /*    Yuxin Zhou, Microsoft Corporation                                   */
3869 /*                                                                        */
3870 /*  DESCRIPTION                                                           */
3871 /*                                                                        */
3872 /*    This function halts DHCP processing on all interfaces enabled for   */
3873 /*    DHCP.  The Client state is reset to NOT STARTED, and if no          */
3874 /*    interfaces are currently running DHCP, this function suspends the   */
3875 /*    DHCP Client thread, and unbinds the DHCP socket port.               */
3876 /*                                                                        */
3877 /*    To stop DHCP on a specific interface when multiple interfaces are   */
3878 /*    enabled for DHCP, use the nx_dhcp_interface_stop service.           */
3879 /*                                                                        */
3880 /*    To restart DHCP Client on a stopped interface, the interface must   */
3881 /*    be reinitialized using either nx_dhcp_reinitialize() to reinitialize*/
3882 /*    all enabled DHCP interfaces, or nx_dhcp_interface_reinitialize() for*/
3883 /*    a specific interface.                                               */
3884 /*                                                                        */
3885 /*  INPUT                                                                 */
3886 /*                                                                        */
3887 /*    dhcp_ptr                              Pointer to DHCP instance      */
3888 /*                                                                        */
3889 /*  OUTPUT                                                                */
3890 /*                                                                        */
3891 /*    NX_SUCCESS                            Completion status             */
3892 /*                                                                        */
3893 /*  CALLS                                                                 */
3894 /*                                                                        */
3895 /*    _nx_dhcp_interface_stop               Interface specific DHCP stop  */
3896 /*    tx_mutex_get                          Obtain protection mutex       */
3897 /*    tx_mutex_put                          Release protection mutex      */
3898 /*                                                                        */
3899 /*  CALLED BY                                                             */
3900 /*                                                                        */
3901 /*    Application Code                                                    */
3902 /*                                                                        */
3903 /*  RELEASE HISTORY                                                       */
3904 /*                                                                        */
3905 /*    DATE              NAME                      DESCRIPTION             */
3906 /*                                                                        */
3907 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3908 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3909 /*                                            resulting in version 6.1    */
3910 /*                                                                        */
3911 /**************************************************************************/
_nx_dhcp_stop(NX_DHCP * dhcp_ptr)3912 UINT  _nx_dhcp_stop(NX_DHCP *dhcp_ptr)
3913 {
3914 
3915 UINT i;
3916 
3917 
3918     /* Get the DHCP mutex.  */
3919     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
3920 
3921     /* Check all interfaces to find out which need to stop the DHCP protocol.  */
3922     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
3923     {
3924 
3925         /* Check if this record is valid.  */
3926         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
3927             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state != NX_DHCP_STATE_NOT_STARTED))
3928         {
3929 
3930             /* Stop DHCP.  */
3931             _nx_dhcp_interface_stop(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index);
3932        }
3933     }
3934 
3935     /* Stop DHCP Thread. */
3936     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread));
3937 
3938     /* Deactivate DHCP Timer.  */
3939     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer));
3940 
3941     /* Ubind UDP socket.  */
3942     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
3943 
3944     /* Release the DHCP mutex.  */
3945     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
3946     return(NX_SUCCESS);
3947 }
3948 
3949 
3950 /**************************************************************************/
3951 /*                                                                        */
3952 /*  FUNCTION                                               RELEASE        */
3953 /*                                                                        */
3954 /*    _nxe_dhcp_interface_stop                           PORTABLE C       */
3955 /*                                                           6.1          */
3956 /*  AUTHOR                                                                */
3957 /*                                                                        */
3958 /*    Yuxin Zhou, Microsoft Corporation                                   */
3959 /*                                                                        */
3960 /*  DESCRIPTION                                                           */
3961 /*                                                                        */
3962 /*    This function performs error checking for the interface specific    */
3963 /*    DHCP stop service.                                                  */
3964 /*                                                                        */
3965 /*  INPUT                                                                 */
3966 /*                                                                        */
3967 /*    dhcp_ptr                              Pointer to DHCP instance      */
3968 /*    iface_index                           Interface to stop DHCP        */
3969 /*                                                                        */
3970 /*  OUTPUT                                                                */
3971 /*                                                                        */
3972 /*    status                                Completion status             */
3973 /*    NX_PTR_ERROR                          Invalid pointer input         */
3974 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
3975 /*                                                                        */
3976 /*  CALLS                                                                 */
3977 /*                                                                        */
3978 /*    _nx_dhcp_interface_stop               Actual interface stop service */
3979 /*                                                                        */
3980 /*  CALLED BY                                                             */
3981 /*                                                                        */
3982 /*    Application Code                                                    */
3983 /*                                                                        */
3984 /*  RELEASE HISTORY                                                       */
3985 /*                                                                        */
3986 /*    DATE              NAME                      DESCRIPTION             */
3987 /*                                                                        */
3988 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3989 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3990 /*                                            resulting in version 6.1    */
3991 /*                                                                        */
3992 /**************************************************************************/
_nxe_dhcp_interface_stop(NX_DHCP * dhcp_ptr,UINT iface_index)3993 UINT  _nxe_dhcp_interface_stop(NX_DHCP *dhcp_ptr, UINT iface_index)
3994 {
3995 
3996 UINT status;
3997 
3998     if (dhcp_ptr == NX_NULL)
3999     {
4000         return NX_PTR_ERROR;
4001     }
4002 
4003     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
4004     {
4005         return NX_INVALID_INTERFACE;
4006     }
4007 
4008     /* Check for appropriate caller.  */
4009     NX_THREADS_ONLY_CALLER_CHECKING
4010 
4011     status =  _nx_dhcp_interface_stop(dhcp_ptr, iface_index);
4012 
4013     return status;
4014 }
4015 
4016 
4017 /**************************************************************************/
4018 /*                                                                        */
4019 /*  FUNCTION                                               RELEASE        */
4020 /*                                                                        */
4021 /*    _nx_dhcp_interface_stop                             PORTABLE C      */
4022 /*                                                           6.1.12       */
4023 /*  AUTHOR                                                                */
4024 /*                                                                        */
4025 /*    Yuxin Zhou, Microsoft Corporation                                   */
4026 /*                                                                        */
4027 /*  DESCRIPTION                                                           */
4028 /*                                                                        */
4029 /*    This function stops DHCP processing on the specified interface. It  */
4030 /*    sets the DHCP state to the unstarted status. If any state changes   */
4031 /*    occurred it calls the record state change callback.                 */
4032 /*                                                                        */
4033 /*    If DHCP is not started on any of the DHCP Client interfaces, this   */
4034 /*    function will suspend the thread, unbind the socket and stop the    */
4035 /*    timer.                                                              */
4036 /*                                                                        */
4037 /*    Note: before DHCP Client can be restarted on the interface, the     */
4038 /*    DHCP Client must be reinitialized by calling                        */
4039 /*    nx_dhcp_interface_reinitialize().                                   */
4040 /*                                                                        */
4041 /*  INPUT                                                                 */
4042 /*                                                                        */
4043 /*    dhcp_ptr                              Pointer to DHCP instance      */
4044 /*    iface_index                           Interface to stop DHCP on     */
4045 /*                                                                        */
4046 /*  OUTPUT                                                                */
4047 /*                                                                        */
4048 /*    status                                Completion status             */
4049 /*                                                                        */
4050 /*  CALLS                                                                 */
4051 /*                                                                        */
4052 /*    _nx_dhcp_interface_record_find        Find record assigned to  the  */
4053 /*                                            input interface             */
4054 /*    tx_mutex_get                          Get the DHCP mutex            */
4055 /*    tx_mutex_put                          Release the DHCP mutex        */
4056 /*                                                                        */
4057 /*  CALLED BY                                                             */
4058 /*                                                                        */
4059 /*    Application Code                                                    */
4060 /*                                                                        */
4061 /*  RELEASE HISTORY                                                       */
4062 /*                                                                        */
4063 /*    DATE              NAME                      DESCRIPTION             */
4064 /*                                                                        */
4065 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4066 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4067 /*                                            resulting in version 6.1    */
4068 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
4069 /*                                            improved internal logic,    */
4070 /*                                            resulting in version 6.1.12 */
4071 /*                                                                        */
4072 /**************************************************************************/
_nx_dhcp_interface_stop(NX_DHCP * dhcp_ptr,UINT iface_index)4073 UINT _nx_dhcp_interface_stop(NX_DHCP *dhcp_ptr, UINT iface_index)
4074 {
4075 
4076 UINT                     i;
4077 UINT                     status;
4078 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
4079 
4080 
4081     /* Obtain the DHCP mutex.  */
4082     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
4083 
4084     /* Find the interface record.  */
4085     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
4086 
4087     /* Check status.  */
4088     if (status)
4089     {
4090 
4091         /* Not found. Release the DHCP mutex.  */
4092         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4093         return(status);
4094     }
4095 
4096     /* Determine if DHCP is started.  */
4097     if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_NOT_STARTED)
4098     {
4099 
4100         /* Release the DHCP mutex.  */
4101         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4102 
4103         /* DHCP is not started so it can't be stopped.  */
4104         return(NX_DHCP_NOT_STARTED);
4105     }
4106 
4107     /* Set the state to NX_DHCP_STATE_NOT_STARTED.  */
4108     interface_record -> nx_dhcp_state = NX_DHCP_STATE_NOT_STARTED;
4109 
4110     /* Determine if the application has specified a routine for DHCP state change notification.  */
4111     if (dhcp_ptr -> nx_dhcp_state_change_callback)
4112     {
4113 
4114         /* Yes, call the application's state change notify function with the new state.  */
4115         (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
4116     }
4117 
4118     /* Determine if the application has specified a routine for DHCP interface state change notification.  */
4119     if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
4120     {
4121 
4122         /* Yes, call the application's state change notify function with the new state.  */
4123         (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record->nx_dhcp_state);
4124     }
4125 
4126     /* Check if other interfaces are running DHCP.  */
4127     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
4128     {
4129 
4130         /* Check which interface record is valid.  */
4131         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
4132             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state != NX_DHCP_STATE_NOT_STARTED))
4133         {
4134 
4135             /* Yes, other interfaces have started DHCP. We can assume Netx and ThreadX
4136                resources need to stay activated. */
4137 
4138             /* Release the DHCP mutex.  */
4139             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4140             return(NX_SUCCESS);
4141         }
4142     }
4143 
4144     /* Yes, stop DHCP Thread. */
4145     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread));
4146 
4147     /* Deactivate DHCP Timer.  */
4148     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer));
4149 
4150     /* Unbind UDP socket.  */
4151     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
4152 
4153     /* Release the DHCP mutex.  */
4154     tx_mutex_put(&(dhcp_ptr->nx_dhcp_mutex));
4155     return(NX_SUCCESS);
4156 
4157 }
4158 
4159 
4160 /**************************************************************************/
4161 /*                                                                        */
4162 /*  FUNCTION                                               RELEASE        */
4163 /*                                                                        */
4164 /*    _nxe_dhcp_user_option_retrieve                      PORTABLE C      */
4165 /*                                                           6.1          */
4166 /*  AUTHOR                                                                */
4167 /*                                                                        */
4168 /*    Yuxin Zhou, Microsoft Corporation                                   */
4169 /*                                                                        */
4170 /*  DESCRIPTION                                                           */
4171 /*                                                                        */
4172 /*    This function checks for errors in the DHCP user option function    */
4173 /*    call.                                                               */
4174 /*                                                                        */
4175 /*  INPUT                                                                 */
4176 /*                                                                        */
4177 /*    dhcp_ptr                              Pointer to DHCP instance      */
4178 /*    option_request                        Option request                */
4179 /*    destination_ptr                       Pointer to return buffer      */
4180 /*    destination_size                      Size of return buffer (and    */
4181 /*                                            modified to reflect how     */
4182 /*                                            much information is in the  */
4183 /*                                            response)                   */
4184 /*                                                                        */
4185 /*  OUTPUT                                                                */
4186 /*                                                                        */
4187 /*    status                                Completion status             */
4188 /*    NX_PTR_ERROR                          Invalid pointer input         */
4189 /*                                                                        */
4190 /*  CALLS                                                                 */
4191 /*                                                                        */
4192 /*    _nx_dhcp_user_option_request          Actual DHCP user option       */
4193 /*                                            function call               */
4194 /*                                                                        */
4195 /*  CALLED BY                                                             */
4196 /*                                                                        */
4197 /*    Application Code                                                    */
4198 /*                                                                        */
4199 /*  RELEASE HISTORY                                                       */
4200 /*                                                                        */
4201 /*    DATE              NAME                      DESCRIPTION             */
4202 /*                                                                        */
4203 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4204 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4205 /*                                            resulting in version 6.1    */
4206 /*                                                                        */
4207 /**************************************************************************/
_nxe_dhcp_user_option_retrieve(NX_DHCP * dhcp_ptr,UINT option_request,UCHAR * destination_ptr,UINT * destination_size)4208 UINT  _nxe_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT option_request, UCHAR *destination_ptr, UINT *destination_size)
4209 {
4210 
4211 UINT    status;
4212 
4213 
4214     /* Check for invalid input pointer.  */
4215     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID) ||
4216         (destination_ptr == NX_NULL) || (destination_size == NX_NULL))
4217         return(NX_PTR_ERROR);
4218 
4219     /* Check for appropriate caller.  */
4220     NX_THREADS_ONLY_CALLER_CHECKING
4221 
4222     /* Call actual DHCP user option request service.  */
4223     status =  _nx_dhcp_user_option_retrieve(dhcp_ptr, option_request, destination_ptr, destination_size);
4224 
4225     /* Return status.  */
4226     return(status);
4227 }
4228 
4229 
4230 /**************************************************************************/
4231 /*                                                                        */
4232 /*  FUNCTION                                               RELEASE        */
4233 /*                                                                        */
4234 /*    _nx_dhcp_user_option_retrieve                       PORTABLE C      */
4235 /*                                                           6.1          */
4236 /*  AUTHOR                                                                */
4237 /*                                                                        */
4238 /*    Yuxin Zhou, Microsoft Corporation                                   */
4239 /*                                                                        */
4240 /*  DESCRIPTION                                                           */
4241 /*                                                                        */
4242 /*    This function searches the DHCP options buffer to obtain the        */
4243 /*    specified option. If successful, the option is placed in the        */
4244 /*    supplied destination string.                                        */
4245 /*                                                                        */
4246 /*  INPUT                                                                 */
4247 /*                                                                        */
4248 /*    dhcp_ptr                              Pointer to DHCP instance      */
4249 /*    option_request                        Option request                */
4250 /*    destination_ptr                       Pointer to return buffer      */
4251 /*    destination_size                      Size of return buffer (and    */
4252 /*                                            modified to reflect how     */
4253 /*                                            much information is in the  */
4254 /*                                            response)                   */
4255 /*                                                                        */
4256 /*  OUTPUT                                                                */
4257 /*                                                                        */
4258 /*    status                                Completion status             */
4259 /*    NX_DHCP_NO_INTERFACES_ENABLED         No DHCP interfaces enabled    */
4260 /*                                                                        */
4261 /*  CALLS                                                                 */
4262 /*                                                                        */
4263 /*    _nx_dhcp_interface_user_option_retrieve                             */
4264 /*                                          Search DHCP interface options */
4265 /*    tx_mutex_get                          Get the DHCP mutex            */
4266 /*    tx_mutex_put                          Release the DHCP mutex        */
4267 /*                                                                        */
4268 /*  CALLED BY                                                             */
4269 /*                                                                        */
4270 /*    Application Code                                                    */
4271 /*                                                                        */
4272 /*  RELEASE HISTORY                                                       */
4273 /*                                                                        */
4274 /*    DATE              NAME                      DESCRIPTION             */
4275 /*                                                                        */
4276 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4277 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4278 /*                                            resulting in version 6.1    */
4279 /*                                                                        */
4280 /**************************************************************************/
_nx_dhcp_user_option_retrieve(NX_DHCP * dhcp_ptr,UINT option_request,UCHAR * destination_ptr,UINT * destination_size)4281 UINT  _nx_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT option_request, UCHAR *destination_ptr, UINT *destination_size)
4282 {
4283 
4284 UINT    i;
4285 UINT    status;
4286 
4287     /* Obtain the DHCP mutex.  */
4288     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
4289 
4290     /* Find the DHCP interface record.  */
4291     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
4292     {
4293 
4294         /* Check which interface record is valid.  */
4295         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
4296             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
4297         {
4298 
4299             /* Retrieve the user option.  */
4300             status = _nx_dhcp_interface_user_option_retrieve(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index,
4301                                                              option_request, destination_ptr, destination_size);
4302 
4303             /* Release the DHCP mutex.  */
4304             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4305             return(status);
4306         }
4307     }
4308 
4309     /* Release the DHCP mutex.  */
4310     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4311     return(NX_DHCP_NO_INTERFACES_ENABLED);
4312 }
4313 
4314 
4315 /**************************************************************************/
4316 /*                                                                        */
4317 /*  FUNCTION                                               RELEASE        */
4318 /*                                                                        */
4319 /*    _nxe_dhcp_user_option_request                       PORTABLE C      */
4320 /*                                                           6.1.8        */
4321 /*  AUTHOR                                                                */
4322 /*                                                                        */
4323 /*    Yuxin Zhou, Microsoft Corporation                                   */
4324 /*                                                                        */
4325 /*  DESCRIPTION                                                           */
4326 /*                                                                        */
4327 /*    This function checks for errors in the DHCP user option function    */
4328 /*    call.                                                               */
4329 /*                                                                        */
4330 /*  INPUT                                                                 */
4331 /*                                                                        */
4332 /*    dhcp_ptr                              Pointer to DHCP instance      */
4333 /*    option_code                           Option code                   */
4334 /*                                                                        */
4335 /*  OUTPUT                                                                */
4336 /*                                                                        */
4337 /*    status                                Completion status             */
4338 /*    NX_PTR_ERROR                          Invalid pointer input         */
4339 /*                                                                        */
4340 /*  CALLS                                                                 */
4341 /*                                                                        */
4342 /*    _nx_dhcp_user_option_request          Actual DHCP user option       */
4343 /*                                            request function call       */
4344 /*                                                                        */
4345 /*  CALLED BY                                                             */
4346 /*                                                                        */
4347 /*    Application Code                                                    */
4348 /*                                                                        */
4349 /*  RELEASE HISTORY                                                       */
4350 /*                                                                        */
4351 /*    DATE              NAME                      DESCRIPTION             */
4352 /*                                                                        */
4353 /*  08-02-2021     Yuxin Zhou               Initial Version 6.1.8         */
4354 /*                                                                        */
4355 /**************************************************************************/
_nxe_dhcp_user_option_request(NX_DHCP * dhcp_ptr,UINT option_code)4356 UINT  _nxe_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code)
4357 {
4358 
4359 UINT    status;
4360 
4361 
4362     /* Check for invalid input pointer.  */
4363     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
4364         return(NX_PTR_ERROR);
4365 
4366     /* Check for appropriate caller.  */
4367     NX_THREADS_ONLY_CALLER_CHECKING
4368 
4369     /* Call actual DHCP interface user option request service.  */
4370     status =  _nx_dhcp_user_option_request(dhcp_ptr, option_code);
4371 
4372     /* Return status.  */
4373     return(status);
4374 }
4375 
4376 
4377 /**************************************************************************/
4378 /*                                                                        */
4379 /*  FUNCTION                                               RELEASE        */
4380 /*                                                                        */
4381 /*    _nx_dhcp_user_option_request                        PORTABLE C      */
4382 /*                                                           6.1.8        */
4383 /*  AUTHOR                                                                */
4384 /*                                                                        */
4385 /*    Yuxin Zhou, Microsoft Corporation                                   */
4386 /*                                                                        */
4387 /*  DESCRIPTION                                                           */
4388 /*                                                                        */
4389 /*    This function requests the additional user option.                  */
4390 /*                                                                        */
4391 /*  INPUT                                                                 */
4392 /*                                                                        */
4393 /*    dhcp_ptr                              Pointer to DHCP instance      */
4394 /*    option_code                           Option code                   */
4395 /*                                                                        */
4396 /*  OUTPUT                                                                */
4397 /*                                                                        */
4398 /*    status                                Completion status             */
4399 /*                                                                        */
4400 /*  CALLS                                                                 */
4401 /*                                                                        */
4402 /*    tx_mutex_get                          Get the DHCP mutex            */
4403 /*    tx_mutex_put                          Release the DHCP mutex        */
4404 /*                                                                        */
4405 /*  CALLED BY                                                             */
4406 /*                                                                        */
4407 /*    Application Code                                                    */
4408 /*                                                                        */
4409 /*  RELEASE HISTORY                                                       */
4410 /*                                                                        */
4411 /*    DATE              NAME                      DESCRIPTION             */
4412 /*                                                                        */
4413 /*  08-02-2021     Yuxin Zhou               Initial Version 6.1.8         */
4414 /*                                                                        */
4415 /**************************************************************************/
_nx_dhcp_user_option_request(NX_DHCP * dhcp_ptr,UINT option_code)4416 UINT  _nx_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code)
4417 {
4418 UINT i;
4419 
4420 
4421     /* Obtain DHCP Client protection mutex. */
4422     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
4423 
4424     /* Check if the default option array already has it.  */
4425     for (i = 0; i < NX_DHCP_REQUEST_PARAMETER_SIZE; i++)
4426     {
4427         if (_nx_dhcp_request_parameters[i] == option_code)
4428         {
4429             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4430             return(NX_DUPLICATED_ENTRY);
4431         }
4432     }
4433 
4434     /* Check if the user option array already has it.  */
4435     for (i = 0; i < dhcp_ptr -> nx_dhcp_user_request_parameter_size; i++)
4436     {
4437         if (dhcp_ptr -> nx_dhcp_user_request_parameter[i] == option_code)
4438         {
4439             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4440             return(NX_DUPLICATED_ENTRY);
4441         }
4442     }
4443 
4444     /* Check if there is space to add option.  */
4445     if (dhcp_ptr -> nx_dhcp_user_request_parameter_size >= NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER)
4446     {
4447         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4448         return(NX_NO_MORE_ENTRIES);
4449     }
4450 
4451     /* Add the option.  */
4452     dhcp_ptr -> nx_dhcp_user_request_parameter[dhcp_ptr -> nx_dhcp_user_request_parameter_size++] = (UCHAR)option_code;
4453 
4454     /* Release the DHCP mutex.  */
4455     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4456 
4457     /* Return success.  */
4458     return(NX_SUCCESS);
4459 }
4460 
4461 
4462 /**************************************************************************/
4463 /*                                                                        */
4464 /*  FUNCTION                                               RELEASE        */
4465 /*                                                                        */
4466 /*    _nxe_dhcp_interface_user_option_retrieve            PORTABLE C      */
4467 /*                                                           6.1          */
4468 /*  AUTHOR                                                                */
4469 /*                                                                        */
4470 /*    Yuxin Zhou, Microsoft Corporation                                   */
4471 /*                                                                        */
4472 /*  DESCRIPTION                                                           */
4473 /*                                                                        */
4474 /*    This function checks for errors in the DHCP user option function    */
4475 /*    call.                                                               */
4476 /*                                                                        */
4477 /*  INPUT                                                                 */
4478 /*                                                                        */
4479 /*    dhcp_ptr                              Pointer to DHCP instance      */
4480 /*    iface_index                           Interface index               */
4481 /*    option_request                        Option request                */
4482 /*    destination_ptr                       Pointer to return buffer      */
4483 /*    destination_size                      Size of return buffer (and    */
4484 /*                                            modified to reflect how     */
4485 /*                                            much information is in the  */
4486 /*                                            response)                   */
4487 /*                                                                        */
4488 /*  OUTPUT                                                                */
4489 /*                                                                        */
4490 /*    status                                Completion status             */
4491 /*    NX_PTR_ERROR                          Invalid pointer input         */
4492 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
4493 /*                                                                        */
4494 /*  CALLS                                                                 */
4495 /*                                                                        */
4496 /*    _nx_dhcp_user_option_request          Actual DHCP user option       */
4497 /*                                            function call               */
4498 /*                                                                        */
4499 /*  CALLED BY                                                             */
4500 /*                                                                        */
4501 /*    Application Code                                                    */
4502 /*                                                                        */
4503 /*  RELEASE HISTORY                                                       */
4504 /*                                                                        */
4505 /*    DATE              NAME                      DESCRIPTION             */
4506 /*                                                                        */
4507 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4508 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4509 /*                                            resulting in version 6.1    */
4510 /*                                                                        */
4511 /**************************************************************************/
_nxe_dhcp_interface_user_option_retrieve(NX_DHCP * dhcp_ptr,UINT iface_index,UINT option_request,UCHAR * destination_ptr,UINT * destination_size)4512 UINT  _nxe_dhcp_interface_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT iface_index, UINT option_request, UCHAR *destination_ptr, UINT *destination_size)
4513 {
4514 
4515 UINT    status;
4516 
4517 
4518     /* Check for invalid input pointer.  */
4519     if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID) ||
4520         (destination_ptr == NX_NULL) || (destination_size == NX_NULL))
4521         return(NX_PTR_ERROR);
4522 
4523     /* Check interface index.  */
4524     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
4525     {
4526         return(NX_INVALID_INTERFACE);
4527     }
4528 
4529     /* Check for appropriate caller.  */
4530     NX_THREADS_ONLY_CALLER_CHECKING
4531 
4532     /* Call actual DHCP interface user option request service.  */
4533     status =  _nx_dhcp_interface_user_option_retrieve(dhcp_ptr, iface_index, option_request, destination_ptr, destination_size);
4534 
4535     /* Return status.  */
4536     return(status);
4537 }
4538 
4539 
4540 /**************************************************************************/
4541 /*                                                                        */
4542 /*  FUNCTION                                               RELEASE        */
4543 /*                                                                        */
4544 /*    _nx_dhcp_interface_user_option_retrieve             PORTABLE C      */
4545 /*                                                           6.1          */
4546 /*  AUTHOR                                                                */
4547 /*                                                                        */
4548 /*    Yuxin Zhou, Microsoft Corporation                                   */
4549 /*                                                                        */
4550 /*  DESCRIPTION                                                           */
4551 /*                                                                        */
4552 /*    This function searches the DHCP options buffer to obtain the        */
4553 /*    specified option. If successful, the option is placed in the        */
4554 /*    supplied destination string.                                        */
4555 /*                                                                        */
4556 /*  INPUT                                                                 */
4557 /*                                                                        */
4558 /*    dhcp_ptr                              Pointer to DHCP instance      */
4559 /*    iface_index                           Interface index               */
4560 /*    option_request                        Option request                */
4561 /*    destination_ptr                       Pointer to return buffer      */
4562 /*    destination_size                      Size of return buffer (and    */
4563 /*                                            modified to reflect how     */
4564 /*                                            much information is in the  */
4565 /*                                            response)                   */
4566 /*    memcpy                                Copy specified area of memory */
4567 /*                                                                        */
4568 /*  OUTPUT                                                                */
4569 /*                                                                        */
4570 /*    destination_size                      Size of returned option       */
4571 /*    status                                Completion status             */
4572 /*                                                                        */
4573 /*  CALLS                                                                 */
4574 /*                                                                        */
4575 /*    _nx_dhcp_search_buffer                Search the buffer             */
4576 /*    _nx_dhcp_interface_record_find        Find record of input interface*/
4577 /*    tx_mutex_get                          Get the DHCP mutex            */
4578 /*    tx_mutex_put                          Release the DHCP mutex        */
4579 /*                                                                        */
4580 /*  CALLED BY                                                             */
4581 /*                                                                        */
4582 /*    Application Code                                                    */
4583 /*                                                                        */
4584 /*  RELEASE HISTORY                                                       */
4585 /*                                                                        */
4586 /*    DATE              NAME                      DESCRIPTION             */
4587 /*                                                                        */
4588 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4589 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
4590 /*                                            buffer length verification, */
4591 /*                                            verified memcpy use cases,  */
4592 /*                                            resulting in version 6.1    */
4593 /*                                                                        */
4594 /**************************************************************************/
_nx_dhcp_interface_user_option_retrieve(NX_DHCP * dhcp_ptr,UINT iface_index,UINT option_request,UCHAR * destination_ptr,UINT * destination_size)4595 UINT  _nx_dhcp_interface_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT iface_index, UINT option_request, UCHAR *destination_ptr, UINT *destination_size)
4596 {
4597 
4598 UCHAR                    *buffer_ptr;
4599 UINT                      size;
4600 UINT                      status;
4601 UINT                      i;
4602 ULONG                    *long_ptr;
4603 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
4604 
4605 
4606     /* Obtain DHCP Client protection mutex. */
4607     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
4608 
4609     /* Find the interface record.  */
4610     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
4611 
4612     /* Check status.  */
4613     if (status)
4614     {
4615 
4616         /* Release the mutex.  */
4617         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4618         return(status);
4619     }
4620 
4621     /* Check state.  */
4622     if (interface_record -> nx_dhcp_state < NX_DHCP_STATE_BOUND)
4623     {
4624 
4625         /* Release the DHCP mutex.  */
4626         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4627 
4628         /* Return an error.  */
4629         return(NX_DHCP_NOT_BOUND);
4630     }
4631 
4632     /* Setup a pointer to the previous buffer.  */
4633     buffer_ptr =  _nx_dhcp_search_buffer(interface_record -> nx_dhcp_options_buffer,
4634                                          option_request, interface_record -> nx_dhcp_options_size);
4635 
4636     /* Determine if the option was found.  */
4637     if (!buffer_ptr)
4638     {
4639 
4640         /* Release the DHCP mutex.  */
4641         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4642 
4643         /* Return an error.  */
4644         return(NX_DHCP_PARSE_ERROR);
4645     }
4646 
4647     /* Calculate the size of the option.  */
4648     size =  (UINT) *buffer_ptr;
4649 
4650     /* Determine if the destination is large enough.  */
4651     if (size > *destination_size)
4652     {
4653 
4654         /* Release the DHCP mutex.  */
4655         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4656 
4657         /* Server did not respond.  */
4658         return(NX_DHCP_DEST_TO_SMALL);
4659     }
4660 
4661     /* Skip the option size field.  */
4662     buffer_ptr++;
4663 
4664     /* Check to see which option data is requested: */
4665     switch (option_request)
4666     {
4667         case NX_DHCP_OPTION_SUBNET_MASK:
4668         case NX_DHCP_OPTION_TIME_OFFSET:
4669         case NX_DHCP_OPTION_GATEWAYS:
4670         case NX_DHCP_OPTION_TIMESVR:
4671         case NX_DHCP_OPTION_DNS_SVR:
4672         case NX_DHCP_OPTION_NTP_SVR:
4673         case NX_DHCP_OPTION_DHCP_LEASE:
4674         case NX_DHCP_OPTION_DHCP_SERVER:
4675         case NX_DHCP_OPTION_RENEWAL:
4676         case NX_DHCP_OPTION_REBIND:
4677         {
4678 
4679             /* The length of these options must always be a multiple of 4 octets.  */
4680             /* Store the value as host byte order.  */
4681             long_ptr = (ULONG *) destination_ptr;
4682 
4683             /* Loop to set the long value.  */
4684             for (i = 0; i + 4 <= size;)
4685             {
4686 
4687                 /* Set the long value.  */
4688                 *long_ptr = _nx_dhcp_get_data(buffer_ptr + i, 4);
4689 
4690                 /* Update the pointer.  */
4691                 long_ptr ++;
4692                 i += 4;
4693             }
4694             break;
4695         }
4696         default:
4697         {
4698 
4699             /* Directly copy the data into destination buffer.  */
4700             memcpy(destination_ptr, buffer_ptr, size); /* Use case of memcpy is verified. */
4701             break;
4702         }
4703     }
4704 
4705     /* Return the actual option size.  */
4706     *destination_size =  size;
4707 
4708     /* Release the DHCP mutex.  */
4709     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4710 
4711     /* Return success.  */
4712     return(NX_SUCCESS);
4713 }
4714 
4715 
4716 /**************************************************************************/
4717 /*                                                                        */
4718 /*  FUNCTION                                               RELEASE        */
4719 /*                                                                        */
4720 /*    _nxe_dhcp_user_option_convert                        PORTABLE C     */
4721 /*                                                           6.1          */
4722 /*  AUTHOR                                                                */
4723 /*                                                                        */
4724 /*    Yuxin Zhou, Microsoft Corporation                                   */
4725 /*                                                                        */
4726 /*  DESCRIPTION                                                           */
4727 /*                                                                        */
4728 /*    This function performs error checking on the option convert service.*/
4729 /*                                                                        */
4730 /*  INPUT                                                                 */
4731 /*                                                                        */
4732 /*    source_ptr                            Source of string area         */
4733 /*                                                                        */
4734 /*  OUTPUT                                                                */
4735 /*                                                                        */
4736 /*    value                                 Pointer to conversion value   */
4737 /*    NULL                                  Invalid pointer input         */
4738 /*                                                                        */
4739 /*  CALLS                                                                 */
4740 /*                                                                        */
4741 /*    _nx_dhcp_user_option_convert         Actual option convert service  */
4742 /*                                                                        */
4743 /*  CALLED BY                                                             */
4744 /*                                                                        */
4745 /*    Application Code                                                    */
4746 /*                                                                        */
4747 /*  RELEASE HISTORY                                                       */
4748 /*                                                                        */
4749 /*    DATE              NAME                      DESCRIPTION             */
4750 /*                                                                        */
4751 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4752 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4753 /*                                            resulting in version 6.1    */
4754 /*                                                                        */
4755 /**************************************************************************/
_nxe_dhcp_user_option_convert(UCHAR * source_ptr)4756 ULONG  _nxe_dhcp_user_option_convert(UCHAR *source_ptr)
4757 {
4758 
4759 ULONG   temp;
4760 
4761     /* Check for invalid input. */
4762     if (source_ptr == NX_NULL)
4763     {
4764         return NX_NULL;
4765     }
4766 
4767     /* Pickup the ULONG.  */
4768     temp =  _nx_dhcp_user_option_convert(source_ptr);
4769 
4770     /* Return the ULONG.  */
4771     return(temp);
4772 }
4773 
4774 
4775 /**************************************************************************/
4776 /*                                                                        */
4777 /*  FUNCTION                                               RELEASE        */
4778 /*                                                                        */
4779 /*    _nx_dhcp_user_option_convert                        PORTABLE C      */
4780 /*                                                           6.1          */
4781 /*  AUTHOR                                                                */
4782 /*                                                                        */
4783 /*    Yuxin Zhou, Microsoft Corporation                                   */
4784 /*                                                                        */
4785 /*  DESCRIPTION                                                           */
4786 /*                                                                        */
4787 /*    This function converts the four bytes pointed to by the input       */
4788 /*    string pointer to an ULONG and returns the value.                   */
4789 /*                                                                        */
4790 /*  INPUT                                                                 */
4791 /*                                                                        */
4792 /*    source_ptr                            Source of string area         */
4793 /*                                                                        */
4794 /*  OUTPUT                                                                */
4795 /*                                                                        */
4796 /*    value                                 Pointer to conversion value   */
4797 /*                                                                        */
4798 /*  CALLS                                                                 */
4799 /*                                                                        */
4800 /*    None                                                                */
4801 /*                                                                        */
4802 /*  CALLED BY                                                             */
4803 /*                                                                        */
4804 /*    Application Code                                                    */
4805 /*                                                                        */
4806 /*  RELEASE HISTORY                                                       */
4807 /*                                                                        */
4808 /*    DATE              NAME                      DESCRIPTION             */
4809 /*                                                                        */
4810 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4811 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4812 /*                                            resulting in version 6.1    */
4813 /*                                                                        */
4814 /**************************************************************************/
_nx_dhcp_user_option_convert(UCHAR * source_ptr)4815 ULONG  _nx_dhcp_user_option_convert(UCHAR *source_ptr)
4816 {
4817 
4818 ULONG   temp;
4819 
4820 
4821     /* Pickup the ULONG.  */
4822     temp =  (((ULONG) *(source_ptr))   << 24) |
4823             (((ULONG) *(source_ptr+1)) << 16) |
4824             (((ULONG) *(source_ptr+2)) << 8)  |
4825              ((ULONG) *(source_ptr+3));
4826 
4827     /* Return the ULONG.  */
4828     return(temp);
4829 }
4830 
4831 
4832 /**************************************************************************/
4833 /*                                                                        */
4834 /*  FUNCTION                                               RELEASE        */
4835 /*                                                                        */
4836 /*    _nxe_dhcp_user_option_add_callback_set               PORTABLE C     */
4837 /*                                                           6.1          */
4838 /*  AUTHOR                                                                */
4839 /*                                                                        */
4840 /*    Yuxin Zhou, Microsoft Corporation                                   */
4841 /*                                                                        */
4842 /*  DESCRIPTION                                                           */
4843 /*                                                                        */
4844 /*    This function performs error checking on the user option add        */
4845 /*    callback set service.                                               */
4846 /*                                                                        */
4847 /*  INPUT                                                                 */
4848 /*                                                                        */
4849 /*    dhcp_ptr                              Pointer to DHCP instance      */
4850 /*    dhcp_user_option_add                  Pointer to application's      */
4851 /*                                            option add function         */
4852 /*                                                                        */
4853 /*  OUTPUT                                                                */
4854 /*                                                                        */
4855 /*    status                                Completion status             */
4856 /*                                                                        */
4857 /*  CALLS                                                                 */
4858 /*                                                                        */
4859 /*    _nx_dhcp_user_option_add_callback_set Actual user option callback   */
4860 /*                                            set service                 */
4861 /*                                                                        */
4862 /*  CALLED BY                                                             */
4863 /*                                                                        */
4864 /*    Application Code                                                    */
4865 /*                                                                        */
4866 /*  RELEASE HISTORY                                                       */
4867 /*                                                                        */
4868 /*    DATE              NAME                      DESCRIPTION             */
4869 /*                                                                        */
4870 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4871 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4872 /*                                            resulting in version 6.1    */
4873 /*                                                                        */
4874 /**************************************************************************/
_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))4875 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,
4876                                                                                              UCHAR *user_option_ptr, UINT *user_option_length))
4877 {
4878 
4879 UINT    status;
4880 
4881     /* Check for invalid input. */
4882     if ((dhcp_ptr == NX_NULL) || (dhcp_user_option_add == NX_NULL))
4883     {
4884         return(NX_PTR_ERROR);
4885     }
4886 
4887     /* Call actual DHCP user option callback set service.  */
4888     status =  _nx_dhcp_user_option_add_callback_set(dhcp_ptr, dhcp_user_option_add);
4889 
4890     /* Return status.  */
4891     return(status);
4892 }
4893 
4894 
4895 /**************************************************************************/
4896 /*                                                                        */
4897 /*  FUNCTION                                               RELEASE        */
4898 /*                                                                        */
4899 /*    _nx_dhcp_user_option_add_callback_set               PORTABLE C      */
4900 /*                                                           6.1          */
4901 /*  AUTHOR                                                                */
4902 /*                                                                        */
4903 /*    Yuxin Zhou, Microsoft Corporation                                   */
4904 /*                                                                        */
4905 /*  DESCRIPTION                                                           */
4906 /*                                                                        */
4907 /*    This function sets the user option add callback.                    */
4908 /*                                                                        */
4909 /*  INPUT                                                                 */
4910 /*                                                                        */
4911 /*    dhcp_ptr                              Pointer to DHCP instance      */
4912 /*    dhcp_user_option_add                  Pointer to application's      */
4913 /*                                            option add function         */
4914 /*                                                                        */
4915 /*  OUTPUT                                                                */
4916 /*                                                                        */
4917 /*    status                                Completion status             */
4918 /*                                                                        */
4919 /*  CALLS                                                                 */
4920 /*                                                                        */
4921 /*    None                                                                */
4922 /*                                                                        */
4923 /*  CALLED BY                                                             */
4924 /*                                                                        */
4925 /*    Application Code                                                    */
4926 /*                                                                        */
4927 /*  RELEASE HISTORY                                                       */
4928 /*                                                                        */
4929 /*    DATE              NAME                      DESCRIPTION             */
4930 /*                                                                        */
4931 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4932 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4933 /*                                            resulting in version 6.1    */
4934 /*                                                                        */
4935 /**************************************************************************/
_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))4936 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,
4937                                                                                              UCHAR *user_option_ptr, UINT *user_option_length))
4938 {
4939 
4940     /* Obtain DHCP Client protection mutex. */
4941     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
4942 
4943     /* Set the callback.  */
4944     dhcp_ptr -> nx_dhcp_user_option_add = dhcp_user_option_add;
4945 
4946     /* Release the mutex.  */
4947     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
4948 
4949     /* Return a successful status.  */
4950     return(NX_SUCCESS);
4951 }
4952 
4953 
4954 /**************************************************************************/
4955 /*                                                                        */
4956 /*  FUNCTION                                               RELEASE        */
4957 /*                                                                        */
4958 /*    _nx_dhcp_udp_receive_notify                         PORTABLE C      */
4959 /*                                                           6.1.10       */
4960 /*  AUTHOR                                                                */
4961 /*                                                                        */
4962 /*    Yuxin Zhou, Microsoft Corporation                                   */
4963 /*                                                                        */
4964 /*  DESCRIPTION                                                           */
4965 /*                                                                        */
4966 /*    This function is called when the IP thread task detects a UDP packet*/
4967 /*    has been received on this socket. It allows the DHCP Client to make */
4968 /*    a non blocking nx_udp_socket_receive call.                          */
4969 /*                                                                        */
4970 /*  INPUT                                                                 */
4971 /*                                                                        */
4972 /*    socket_ptr                            Pointer to DHCP socket        */
4973 /*                                                                        */
4974 /*  OUTPUT                                                                */
4975 /*                                                                        */
4976 /*    None                                                                */
4977 /*                                                                        */
4978 /*  CALLS                                                                 */
4979 /*                                                                        */
4980 /*   tx_event_flags_set                    Set event packet is received   */
4981 /*                                                                        */
4982 /*  CALLED BY                                                             */
4983 /*                                                                        */
4984 /*    IP thread task                                                      */
4985 /*                                                                        */
4986 /*  RELEASE HISTORY                                                       */
4987 /*                                                                        */
4988 /*    DATE              NAME                      DESCRIPTION             */
4989 /*                                                                        */
4990 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4991 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4992 /*                                            resulting in version 6.1    */
4993 /*  01-31-2022     Yuxin Zhou               Modified comment(s), supported*/
4994 /*                                            multiple client instances,  */
4995 /*                                            resulting in version 6.1.10 */
4996 /*                                                                        */
4997 /**************************************************************************/
_nx_dhcp_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)4998 VOID _nx_dhcp_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
4999 {
5000 
5001 NX_DHCP *dhcp_ptr;
5002 
5003     dhcp_ptr = (NX_DHCP *)(socket_ptr -> nx_udp_socket_reserved_ptr);
5004 
5005     /* Set the data received event flag.  */
5006     tx_event_flags_set(&(dhcp_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_RECEIVE_EVENT, TX_OR);
5007 }
5008 
5009 
5010 /**************************************************************************/
5011 /*                                                                        */
5012 /*  FUNCTION                                               RELEASE        */
5013 /*                                                                        */
5014 /*    _nx_dhcp_timeout_entry                              PORTABLE C      */
5015 /*                                                           6.1          */
5016 /*  AUTHOR                                                                */
5017 /*                                                                        */
5018 /*    Yuxin Zhou, Microsoft Corporation                                   */
5019 /*                                                                        */
5020 /*  DESCRIPTION                                                           */
5021 /*                                                                        */
5022 /*    This function is called when the DHCP Client timer expires. It      */
5023 /*    loops through all valid interfaces that have started DHCP, and      */
5024 /*    updates their DHCP timeout.  If an interface timeout has expired, it*/
5025 /*    processes that interface depending on which DHCP state it is in.    */
5026 /*                                                                        */
5027 /*  INPUT                                                                 */
5028 /*                                                                        */
5029 /*    dhcp_ptr                              Pointer to DHCP instance      */
5030 /*                                                                        */
5031 /*  OUTPUT                                                                */
5032 /*                                                                        */
5033 /*    None                                                                */
5034 /*                                                                        */
5035 /*  CALLS                                                                 */
5036 /*                                                                        */
5037 /*   tx_event_flags_set                    Set an event that timer expired*/
5038 /*                                                                        */
5039 /*  CALLED BY                                                             */
5040 /*                                                                        */
5041 /*    ThreadX timer                                                       */
5042 /*                                                                        */
5043 /*  RELEASE HISTORY                                                       */
5044 /*                                                                        */
5045 /*    DATE              NAME                      DESCRIPTION             */
5046 /*                                                                        */
5047 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5048 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5049 /*                                            resulting in version 6.1    */
5050 /*                                                                        */
5051 /**************************************************************************/
_nx_dhcp_timeout_entry(ULONG dhcp)5052 VOID _nx_dhcp_timeout_entry(ULONG dhcp)
5053 {
5054 
5055 NX_DHCP     *dhcp_ptr;
5056 
5057 
5058     /* Setup DHCP pointer.  */
5059     NX_TIMER_EXTENSION_PTR_GET(dhcp_ptr, NX_DHCP, dhcp)
5060 
5061     /* Set the data event flag.  */
5062     tx_event_flags_set(&(dhcp_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_TIMER_EVENT, TX_OR);
5063 }
5064 
5065 
5066 
5067 /**************************************************************************/
5068 /*                                                                        */
5069 /*  FUNCTION                                               RELEASE        */
5070 /*                                                                        */
5071 /*    _nx_dhcp_thread_entry                               PORTABLE C      */
5072 /*                                                           6.1          */
5073 /*  AUTHOR                                                                */
5074 /*                                                                        */
5075 /*    Yuxin Zhou, Microsoft Corporation                                   */
5076 /*                                                                        */
5077 /*  DESCRIPTION                                                           */
5078 /*                                                                        */
5079 /*    This function is the processing thread for the DHCP Client.         */
5080 /*    Its processing consists of executing a while-forever loop that      */
5081 /*    checks for events (e.g. packet receive, timer expiration). For      */
5082 /*    received packets, some initial packet validation is done before     */
5083 /*    calling _nx_dhcp_packet_process.                                    */
5084 /*                                                                        */
5085 /*  INPUT                                                                 */
5086 /*                                                                        */
5087 /*    dhcp_instance                         Pointer to DHCP instance      */
5088 /*                                                                        */
5089 /*  OUTPUT                                                                */
5090 /*                                                                        */
5091 /*    status                                Completion status             */
5092 /*                                                                        */
5093 /*  CALLS                                                                 */
5094 /*                                                                        */
5095 /*    tx_event_flags_get                    Check for events              */
5096 /*    _nx_udp_socket_receive                Retrieve packet from socket   */
5097 /*    _nx_dhcp_interface_record_find        Find record of this interface */
5098 /*    tx_mutex_get                          Get the DHCP mutex            */
5099 /*    tx_mutex_put                          Release the DHCP mutex        */
5100 /*    _nx_dhcp_packet_process               Process received packet       */
5101 /*    _nx_dhcp_timout_entry                 Process timer expiration      */
5102 /*                                                                        */
5103 /*  CALLED BY                                                             */
5104 /*                                                                        */
5105 /*    ThreadX                                                             */
5106 /*                                                                        */
5107 /*  RELEASE HISTORY                                                       */
5108 /*                                                                        */
5109 /*    DATE              NAME                      DESCRIPTION             */
5110 /*                                                                        */
5111 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5112 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5113 /*                                            resulting in version 6.1    */
5114 /*                                                                        */
5115 /**************************************************************************/
_nx_dhcp_thread_entry(ULONG dhcp_instance)5116 static VOID  _nx_dhcp_thread_entry(ULONG dhcp_instance)
5117 {
5118 
5119 NX_DHCP                  *dhcp_ptr;
5120 NX_PACKET                *packet_ptr;
5121 ULONG                     events;
5122 UINT                      status;
5123 UINT                      iface_index;
5124 UINT                      source_port;
5125 ULONG                     source_ip_address;
5126 UINT                      protocol;
5127 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
5128 
5129     /* Setup the DHCP pointer.  */
5130     NX_THREAD_EXTENSION_PTR_GET(dhcp_ptr, NX_DHCP, dhcp_instance)
5131 
5132     /* Obtain the DHCP mutex before processing an.  */
5133     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
5134 
5135     /* Enter the DHCP Client task loop.  */
5136     do
5137     {
5138 
5139         /* Release the DHCP mutex.  */
5140         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
5141 
5142         /* Wait for a DHCP client activity.  */
5143         tx_event_flags_get(&(dhcp_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_ALL_EVENTS,
5144                            TX_OR_CLEAR, &events, TX_WAIT_FOREVER);
5145 
5146         /* Obtain the DHCP mutex before processing an.  */
5147         tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
5148 
5149         /* Check for DHCP data received event.  */
5150         if  (events & NX_DHCP_CLIENT_RECEIVE_EVENT)
5151         {
5152 
5153             /* Loop to receive DHCP message.  */
5154             while(1)
5155             {
5156 
5157                 /* Check for an incoming DHCP packet with non blocking option. */
5158                 status = _nx_udp_socket_receive(&dhcp_ptr -> nx_dhcp_socket, &packet_ptr, NX_NO_WAIT);
5159 
5160                 /* Check for packet receive errors. */
5161                 if (status != NX_SUCCESS)
5162                 {
5163                     break;
5164                 }
5165 
5166                 /* Find the source IP address, port, interface this packet is on. */
5167                 status = nx_udp_packet_info_extract(packet_ptr, &source_ip_address, &protocol, &source_port, &iface_index);
5168 
5169                 /* Check status.  */
5170                 if (status != NX_SUCCESS)
5171                 {
5172 
5173                     nx_packet_release(packet_ptr);
5174                     continue;
5175                 }
5176 
5177                 /* Find the interface record.  */
5178                 status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
5179 
5180                 /* Check status.  */
5181                 if (status != NX_SUCCESS)
5182                 {
5183 
5184                     /* Release the original packet . */
5185                     nx_packet_release(packet_ptr);
5186                     continue;
5187                 }
5188 
5189                 /* Process DHCP packet.  */
5190                 _nx_dhcp_packet_process(dhcp_ptr, interface_record, packet_ptr);
5191             }
5192         }
5193 
5194         /* Timer event.  */
5195         if (events & NX_DHCP_CLIENT_TIMER_EVENT)
5196         {
5197             _nx_dhcp_timeout_process(dhcp_ptr);
5198         }
5199 
5200 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5201 
5202         /* IP address conflict event.  */
5203         if (events & NX_DHCP_CLIENT_CONFLICT_EVENT)
5204         {
5205 
5206             /* Loop to check the interface.  */
5207             for (iface_index = 0; iface_index < NX_MAX_PHYSICAL_INTERFACES; iface_index++)
5208             {
5209 
5210                 /* Check the flag.  */
5211                 if (dhcp_ptr -> nx_dhcp_interface_conflict_flag == 0)
5212                 {
5213                     break;
5214                 }
5215 
5216                 /* Check if IP address conflict for this interface.  */
5217                 if (dhcp_ptr -> nx_dhcp_interface_conflict_flag & ((UINT)(1 << iface_index)))
5218                 {
5219 
5220                     /* Handle notice of address conflict event. Let the server know we
5221                        did not get assigned a unique IP address. */
5222                     _nx_dhcp_interface_decline(dhcp_ptr, iface_index);
5223 
5224                     /* Clear the flag.  */
5225                     dhcp_ptr -> nx_dhcp_interface_conflict_flag &= (UINT)(~(1 << iface_index));
5226                 }
5227             }
5228         }
5229 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE  */
5230 
5231     } while (1);
5232 }
5233 
5234 
5235 /**************************************************************************/
5236 /*                                                                        */
5237 /*  FUNCTION                                               RELEASE        */
5238 /*                                                                        */
5239 /*    _nx_dhcp_packet_process                             PORTABLE C      */
5240 /*                                                           6.1.12       */
5241 /*  AUTHOR                                                                */
5242 /*                                                                        */
5243 /*    Yuxin Zhou, Microsoft Corporation                                   */
5244 /*                                                                        */
5245 /*  DESCRIPTION                                                           */
5246 /*                                                                        */
5247 /*    This function is called when the DHCP Client thread is notified of a*/
5248 /*    receive event. If verifies the packet is intended for this host,    */
5249 /*    and checks the transaction ID from the Server to match its ID,      */
5250 /*    processing the packet based on DHCP state.                          */
5251 /*                                                                        */
5252 /*  INPUT                                                                 */
5253 /*                                                                        */
5254 /*    dhcp_ptr                              Pointer to DHCP instance      */
5255 /*    interface_record                      Pointer to DHCP interface     */
5256 /*    packet_ptr                            Pointer to received packet    */
5257 /*                                                                        */
5258 /*  OUTPUT                                                                */
5259 /*                                                                        */
5260 /*    None                                                                */
5261 /*                                                                        */
5262 /*  CALLS                                                                 */
5263 /*                                                                        */
5264 /*   _nx_dhcp_find_matching_record          Find Client record matching   */
5265 /*                                            the packet interface        */
5266 /*   nx_packet_allocate                     Allocate new packet from DHCP */
5267 /*                                            Client packet pool          */
5268 /*   nx_packet_release                      Release packet back to DHCP   */
5269 /*                                            Client packet pool          */
5270 /*   nx_packet_data_extract_offset          Copy data to new packet buffer*/
5271 /*   _nx_dhcp_get_option_value              Get data for input option     */
5272 /*   _nx_dhcp_extract_information           Extract basic info from packet*/
5273 /*   _nx_dhcp_send_request_internal         Send DHCP message             */
5274 /*   nx_ip_interface_address_set            Set IP interface address      */
5275 /*   nx_ip_gateway_address_set              Set IP gateway address        */
5276 /*   _nx_dhcp_interface_reinitialize        Clear DHCP interface data     */
5277 /*                                            for restarting DHCP         */
5278 /*                                                                        */
5279 /*  CALLED BY                                                             */
5280 /*                                                                        */
5281 /*    nx_dhcp_thread_entry                  DHCP Client thread entry fcn  */
5282 /*                                                                        */
5283 /*  RELEASE HISTORY                                                       */
5284 /*                                                                        */
5285 /*    DATE              NAME                      DESCRIPTION             */
5286 /*                                                                        */
5287 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5288 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5289 /*                                            resulting in version 6.1    */
5290 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
5291 /*                                            improved internal logic,    */
5292 /*                                            resulting in version 6.1.12 */
5293 /*                                                                        */
5294 /**************************************************************************/
_nx_dhcp_packet_process(NX_DHCP * dhcp_ptr,NX_DHCP_INTERFACE_RECORD * interface_record,NX_PACKET * packet_ptr)5295 VOID  _nx_dhcp_packet_process(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, NX_PACKET *packet_ptr)
5296 {
5297 
5298 UINT        status;
5299 NX_PACKET   *new_packet_ptr;
5300 ULONG       dhcp_type;
5301 UCHAR       *work_ptr;
5302 ULONG       bytes_copied;
5303 UINT        offset;
5304 NX_IP       *ip_ptr;
5305 UINT        iface_index;
5306 ULONG       packet_client_mac_msw, packet_client_mac_lsw;
5307 ULONG       dhcp_client_mac_msw, dhcp_client_mac_lsw;
5308 UINT        original_state;
5309 UCHAR       *buffer;
5310 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5311 ULONG       probing_delay;
5312 #endif
5313 
5314     /* Set the IP pointer and interface index.  */
5315     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
5316     iface_index = interface_record -> nx_dhcp_interface_index;
5317 
5318     /* Check for valid packet length.  */
5319     if (packet_ptr -> nx_packet_length <= NX_BOOTP_OFFSET_OPTIONS)
5320     {
5321 
5322         /* Release the packet. */
5323         nx_packet_release(packet_ptr);
5324 
5325         /* Return.  */
5326         return;
5327     }
5328 
5329     /* Copy the received packet (datagram) over to a packet from the DHCP Client pool and release
5330        the packet back to receive packet pool as soon as possible. */
5331     status =  nx_packet_allocate(dhcp_ptr -> nx_dhcp_packet_pool_ptr, &new_packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
5332 
5333     /* Check status.  */
5334     if (status != NX_SUCCESS)
5335     {
5336 
5337         /* Release the original packet. */
5338         nx_packet_release(packet_ptr);
5339 
5340         /* Error allocating packet, return error status.  */
5341         return;
5342     }
5343 
5344     /* Verify the incoming packet does not exceed our DHCP Client packet payload. */
5345     if ((ULONG)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr) < ((packet_ptr) -> nx_packet_length))
5346     {
5347 
5348         /* Release the newly allocated packet . */
5349         nx_packet_release(new_packet_ptr);
5350 
5351         /* Release the original packet. */
5352         nx_packet_release(packet_ptr);
5353 
5354         return;
5355     }
5356 
5357     /* Initialize the offset to the beginning of the packet buffer. */
5358     offset = 0;
5359     status = nx_packet_data_extract_offset(packet_ptr, offset, (VOID *)new_packet_ptr -> nx_packet_prepend_ptr, (packet_ptr) -> nx_packet_length, &bytes_copied);
5360     NX_ASSERT((status == NX_SUCCESS) && (bytes_copied > 0));
5361 
5362     /* Update the new packet with the bytes copied.  For chained packets, this will reflect the total
5363        'datagram' length. */
5364     new_packet_ptr -> nx_packet_length = bytes_copied;
5365 
5366 
5367     /* Now we can release the original packet. */
5368     nx_packet_release(packet_ptr);
5369 
5370     /* Set the interface index and MAC address.  */
5371     dhcp_client_mac_msw = ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_msw;
5372     dhcp_client_mac_lsw = ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_lsw;
5373 
5374     /* Set work_ptr.  */
5375     work_ptr = new_packet_ptr -> nx_packet_prepend_ptr + NX_BOOTP_OFFSET_CLIENT_HW;
5376 
5377     /* Pickup the target MAC address in the DHCP message.  */
5378     packet_client_mac_msw = (((ULONG)work_ptr[0]) << 8) | ((ULONG)work_ptr[1]);
5379     packet_client_mac_lsw = (((ULONG)work_ptr[2]) << 24) |
5380                             (((ULONG)work_ptr[3]) << 16) |
5381                             (((ULONG)work_ptr[4]) << 8) |
5382                             ((ULONG)work_ptr[5]);
5383 
5384     /* Determine if the  MAC address matches ours.  */
5385     if ((packet_client_mac_msw != dhcp_client_mac_msw) || (packet_client_mac_lsw != dhcp_client_mac_lsw))
5386     {
5387 
5388         /* Release the allocated packet. */
5389         nx_packet_release(new_packet_ptr);
5390         return;
5391     }
5392 
5393     /* Check if XIDs match.  */
5394     if (_nx_dhcp_get_data(new_packet_ptr -> nx_packet_prepend_ptr + NX_BOOTP_OFFSET_XID, 4) != interface_record -> nx_dhcp_xid)
5395     {
5396 
5397         /* Release the original packet . */
5398         nx_packet_release(new_packet_ptr);
5399 
5400         /* Error with XID data, return error status.  */
5401         return;
5402     }
5403 
5404     /* Save the original state for the state change callback; after this point we will likely change it. */
5405     original_state  = interface_record -> nx_dhcp_state;
5406 
5407     /* The action depends on the current state of the dhcp client. */
5408     switch (interface_record -> nx_dhcp_state)
5409     {
5410 
5411         case NX_DHCP_STATE_SELECTING:
5412         {
5413 
5414             /* Set up a buffer pointer.  */
5415             buffer =  new_packet_ptr -> nx_packet_prepend_ptr;
5416 
5417             /* Get what type of DHCP message it is. */
5418             status = _nx_dhcp_get_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, &dhcp_type, new_packet_ptr -> nx_packet_length);
5419 
5420             /* Determine if it is an Offer.  */
5421             if ((status == NX_SUCCESS) && (dhcp_type == NX_DHCP_TYPE_DHCPOFFER))
5422             {
5423 
5424                 /* Yes, a valid Offer is received!  */
5425 
5426                 /* Increment the number of offers received.  */
5427                 interface_record -> nx_dhcp_offers_received++;
5428 
5429                 /* Update the DHCP Client interface parameters (IP address, server IP, lease, renewal and rebind times */
5430                 if (_nx_dhcp_extract_information(dhcp_ptr, interface_record, buffer, new_packet_ptr -> nx_packet_length))
5431                     break;
5432 
5433                 /* Send the DHCP Request to accept the offer.  */
5434                 _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
5435 
5436                 /* Reset the initial timeout to NX_DHCP_MIN_RETRANS_TIMEOUT seconds  */
5437                 interface_record -> nx_dhcp_rtr_interval = NX_DHCP_MIN_RETRANS_TIMEOUT;
5438                 interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_rtr_interval;
5439 
5440                 /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */
5441                 interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout);
5442 
5443                 /* Update the state to Requesting state.  */
5444                 interface_record -> nx_dhcp_state = NX_DHCP_STATE_REQUESTING;
5445            }
5446 
5447            /* Let the timeout processing handle retransmissions. We're done here */
5448            break;
5449         }
5450 
5451         case NX_DHCP_STATE_REQUESTING:
5452         {
5453 
5454 #ifdef NX_DHCP_ENABLE_BOOTP
5455 
5456             /* Initialize the value of dhcp type since we do not care for BOOTP. */
5457             dhcp_type = NX_DHCP_TYPE_DHCPACK;
5458 
5459             /* Also initialize status to success since we won't make the get option call. */
5460             status = NX_SUCCESS;
5461 #endif
5462 
5463             /* Setup buffer pointer.  */
5464             buffer = new_packet_ptr -> nx_packet_prepend_ptr;
5465 
5466 #ifndef NX_DHCP_ENABLE_BOOTP
5467             /* There is a valid DHCP response, see if it is an ACK.  */
5468             status = _nx_dhcp_get_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, &dhcp_type, new_packet_ptr ->nx_packet_length);
5469 #endif
5470             /* Proceed to processing the server response?   */
5471             if (status == NX_SUCCESS)
5472             {
5473 
5474                 /* Yes, check and see if it is an ACK back to our previous request.  */
5475                 if (dhcp_type == NX_DHCP_TYPE_DHCPACK)
5476                 {
5477 
5478                     /* Increment the number of ACKs received.  */
5479                     interface_record -> nx_dhcp_acks_received++;
5480 
5481                     /* Either we got an ACK or we are using BOOTP.  */
5482 
5483                     /* Update the parameters (IP address, server IP, lease, renewal and rebind times */
5484                     if (_nx_dhcp_extract_information(dhcp_ptr, interface_record, buffer, new_packet_ptr -> nx_packet_length))
5485                         break;
5486 
5487                     /* If the host is configured to send an ARP probe to verify Client address is
5488                        not in use, do so now. */
5489 
5490 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5491 
5492                     /* Change to the Address Probing state.  */
5493                     interface_record -> nx_dhcp_state =  NX_DHCP_STATE_ADDRESS_PROBING;
5494 
5495                     /* Initalize the time for probing.  */
5496                     probing_delay = (ULONG)NX_RAND() % (NX_DHCP_ARP_PROBE_WAIT);
5497 
5498                     /* Check the probing_delay for timer interval.  */
5499                     if (probing_delay)
5500                         interface_record -> nx_dhcp_timeout = probing_delay;
5501                     else
5502                         interface_record -> nx_dhcp_timeout = 1;
5503 
5504                     /* Set the probing count.  */
5505                     interface_record -> nx_dhcp_probe_count = NX_DHCP_ARP_PROBE_NUM;
5506 
5507                     /* Setup the handler to indicate the we want collision notification.  */
5508                     ip_ptr -> nx_ip_interface[iface_index].nx_interface_ip_conflict_notify_handler = _nx_dhcp_ip_conflict;
5509 
5510 #else    /* NX_DHCP_CLIENT_SEND_ARP_PROBE not defined: */
5511 
5512                     nx_ip_interface_address_set(ip_ptr, iface_index,
5513                                                 interface_record -> nx_dhcp_ip_address,
5514                                                 interface_record -> nx_dhcp_network_mask);
5515 
5516                     /* Check if the gateway address is valid.  */
5517                     if (interface_record -> nx_dhcp_gateway_address)
5518                     {
5519 
5520                         /* Set the gateway address.  */
5521                         nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
5522                     }
5523 
5524                     /* No ARP probe performed. OK to change to the Bound state.  */
5525                     interface_record -> nx_dhcp_state =  NX_DHCP_STATE_BOUND;
5526 
5527 #ifdef NX_DHCP_ENABLE_BOOTP
5528                     /* BOOTP does not use timeouts.  For the life of this DHCP Client application, keep the same IP address. */
5529                     interface_record -> nx_dhcp_timeout = NX_WAIT_FOREVER;
5530 #else
5531                     /* Set the renewal time received from the server.  */
5532                     interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_renewal_time;
5533 #endif /* NX_DHCP_ENABLE_BOOTP  */
5534 
5535 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE*/
5536 
5537                     break;
5538                 }
5539                 else if (dhcp_type == NX_DHCP_TYPE_DHCPNACK)
5540                 {
5541 
5542                     /* Increment the number of NACKs received.  */
5543                     interface_record -> nx_dhcp_nacks_received++;
5544 
5545                     /* Reinitialize DHCP.  */
5546                     _nx_dhcp_interface_reinitialize(dhcp_ptr, interface_record -> nx_dhcp_interface_index);
5547 
5548                     /* Restart DHCP service for this interface record.  */
5549 
5550                     /* Start the DHCP protocol again by setting the state back to INIT. */
5551                     interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
5552 
5553                     /* The client begins in INIT state and forms a DHCPDISCOVER message.
5554                        The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
5555                        RFC2131, Section4.4.1, Page36.  */
5556 
5557                     /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
5558                     interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
5559                     interface_record -> nx_dhcp_rtr_interval = 0;
5560                 }
5561             }
5562             break;
5563         }
5564 
5565         case NX_DHCP_STATE_BOUND:
5566         {
5567 
5568             /* Silently discard all received packets in the BOUND state, RFC2131, Section 4.4 Figure 5  */
5569 
5570             break;
5571         }
5572 
5573         case NX_DHCP_STATE_RENEWING:
5574         {
5575 
5576             /* Setup the buffer pointer.  */
5577             buffer =  new_packet_ptr -> nx_packet_prepend_ptr;
5578 
5579             /* Check the server response if it accepts are renewal.  */
5580             status = _nx_dhcp_get_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, &dhcp_type, new_packet_ptr ->nx_packet_length);
5581 
5582             /* Was the option retrieved?  */
5583             if (status == NX_SUCCESS)
5584             {
5585 
5586                 /* Yes, Check for an ACK.  */
5587                 if (dhcp_type == NX_DHCP_TYPE_DHCPACK)
5588                 {
5589 
5590                     /* Increment the number of ACKs received.  */
5591                     interface_record -> nx_dhcp_acks_received++;
5592 
5593                     /* Update the parameters (IP address, server IP, lease, renewal and rebind times */
5594                     if (_nx_dhcp_extract_information(dhcp_ptr, interface_record, buffer, new_packet_ptr -> nx_packet_length))
5595                         break;
5596 
5597                     /* Set the IP address and gateway address from the value extracted from the Server's DHCP response. */
5598                     nx_ip_interface_address_set(ip_ptr, iface_index,
5599                                                 interface_record -> nx_dhcp_ip_address,
5600                                                 interface_record -> nx_dhcp_network_mask);
5601 
5602                     /* Check if the gateway address is valid.  */
5603                     if (interface_record -> nx_dhcp_gateway_address)
5604                     {
5605 
5606                         /* Set the gateway address.  */
5607                         nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
5608                     }
5609 
5610                     /* Lease has been renewed, set the countdown timer back to the renewal time and go back
5611                        to the Bound state*/
5612                     interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_renewal_time;
5613 
5614                     /* Change the state back to bound.  */
5615                     interface_record -> nx_dhcp_state =  NX_DHCP_STATE_BOUND;
5616 
5617                 }
5618                 else if (dhcp_type == NX_DHCP_TYPE_DHCPNACK)
5619                 {
5620 
5621                     /* Increment the number of NACKs received.  */
5622                     interface_record -> nx_dhcp_nacks_received++;
5623 
5624                     /* Reinitialize DHCP.  */
5625                     _nx_dhcp_interface_reinitialize(dhcp_ptr, interface_record -> nx_dhcp_interface_index);
5626 
5627                     /* Restart DHCP service for this interface record.  */
5628 
5629                     /* Start the DHCP protocol again by setting the state back to INIT. */
5630                     interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
5631 
5632                     /* The client begins in INIT state and forms a DHCPDISCOVER message.
5633                        The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
5634                        RFC2131, Section4.4.1, Page36.  */
5635 
5636                     /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
5637                     interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
5638                     interface_record -> nx_dhcp_rtr_interval = 0;
5639                 }
5640             }
5641             break;
5642         }
5643 
5644         case NX_DHCP_STATE_REBINDING:
5645         {
5646 
5647             /* Setup buffer pointer.  */
5648             buffer =  new_packet_ptr -> nx_packet_prepend_ptr;
5649 
5650             /* There is a valid DHCP response, pickup the type of response.  */
5651             status = _nx_dhcp_get_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, &dhcp_type, new_packet_ptr ->nx_packet_length);
5652 
5653             /* Valid response?  */
5654             if (status == NX_SUCCESS)
5655             {
5656 
5657                 /* Is it an ACK response?  */
5658                 if (dhcp_type == NX_DHCP_TYPE_DHCPACK)
5659                 {
5660 
5661                     /* Increment the number of ACKs received.  */
5662                     interface_record -> nx_dhcp_acks_received++;
5663 
5664                     /* Update the parameters (IP address, server IP, lease, renewal and rebind times */
5665                     if (_nx_dhcp_extract_information(dhcp_ptr, interface_record, buffer, new_packet_ptr -> nx_packet_length))
5666                         break;
5667 
5668                     /* Set the IP address and gateway address from the value extracted from the Server's DHCP response. */
5669                     nx_ip_interface_address_set(ip_ptr, iface_index,
5670                                                 interface_record -> nx_dhcp_ip_address,
5671                                                 interface_record -> nx_dhcp_network_mask);
5672 
5673                     /* Check if the gateway address is valid.  */
5674                     if (interface_record -> nx_dhcp_gateway_address)
5675                     {
5676 
5677                         /* Set the gateway address.  */
5678                         nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
5679                     }
5680 
5681                     /* Lease has been renewed, set the countdown timer back to the renewal time and go back
5682                        to the Bound state.  */
5683                     interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_renewal_time;
5684 
5685                     /* Change to bound state.  */
5686                     interface_record -> nx_dhcp_state = NX_DHCP_STATE_BOUND;
5687                 }
5688                 else if (dhcp_type == NX_DHCP_TYPE_DHCPNACK)
5689                 {
5690 
5691                     /* Increment the number of NACKs received.  */
5692                     interface_record -> nx_dhcp_nacks_received++;
5693 
5694                     /* Reinitialize DHCP.  */
5695                     _nx_dhcp_interface_reinitialize(dhcp_ptr, interface_record -> nx_dhcp_interface_index);
5696 
5697                     /* Restart DHCP service for this interface record.  */
5698 
5699                     /* Start the DHCP protocol again by setting the state back to INIT. */
5700                     interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
5701 
5702                     /* The client begins in INIT state and forms a DHCPDISCOVER message.
5703                        The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
5704                        RFC2131, Section4.4.1, Page36.  */
5705 
5706                     /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
5707                     interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
5708                     interface_record -> nx_dhcp_rtr_interval = 0;
5709                 }
5710             }
5711             break;
5712         }
5713 
5714         default:
5715             break;
5716 
5717     } /* End of switch case */
5718 
5719     /* Release the packet.  */
5720     nx_packet_release(new_packet_ptr);
5721 
5722     /* Check if the state is changed.  */
5723     if (original_state != interface_record -> nx_dhcp_state)
5724     {
5725 
5726         /* Determine if the application has specified a routine for DHCP state change notification.  */
5727         if (dhcp_ptr -> nx_dhcp_state_change_callback)
5728         {
5729 
5730             /* Yes, call the application's state change notify function with the new state.  */
5731             (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
5732         }
5733 
5734         /* Determine if the application has specified a routine for DHCP interface state change notification.  */
5735         if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
5736         {
5737 
5738             /* Yes, call the application's state change notify function with the new state.  */
5739             (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
5740         }
5741     }
5742 
5743     return;
5744 }
5745 
5746 
5747 /**************************************************************************/
5748 /*                                                                        */
5749 /*  FUNCTION                                               RELEASE        */
5750 /*                                                                        */
5751 /*    _nx_dhcp_timeout_process                            PORTABLE C      */
5752 /*                                                           6.1.12       */
5753 /*  AUTHOR                                                                */
5754 /*                                                                        */
5755 /*    Yuxin Zhou, Microsoft Corporation                                   */
5756 /*                                                                        */
5757 /*  DESCRIPTION                                                           */
5758 /*                                                                        */
5759 /*    This function is by the DHCP Client when it checks for a timer      */
5760 /*    expiration event. It checks all the DHCP interface records who have */
5761 /*    started DHCP and updates the time remaining on their timeout.       */
5762 /*    If a timeout has expired, this function then processes it according */
5763 /*    to the DHCP state it is in.                                         */
5764 /*                                                                        */
5765 /*  INPUT                                                                 */
5766 /*                                                                        */
5767 /*    dhcp_ptr                              Pointer to DHCP instance      */
5768 /*                                                                        */
5769 /*  OUTPUT                                                                */
5770 /*                                                                        */
5771 /*    None                                                                */
5772 /*                                                                        */
5773 /*  CALLS                                                                 */
5774 /*                                                                        */
5775 /*   _nx_dhcp_send_request_internal         Send a request to DHCP server */
5776 /*   _nx_dhcp_update_timeout                Reset the DHCP timeout        */
5777 /*   _nx_dhcp_add_randomize                 Modify timeout by random value*/
5778 /*   _nx_dhcp_update_renewal_timeout        Set the retransmission timeout*/
5779 /*   _nx_arp_probe_send                     Send ARP probe for IP address */
5780 /*                                            uniqueness if ARP probe     */
5781 /*                                            enabled                     */
5782 /*   nx_ip_interface_address_set            Set the IP interface address  */
5783 /*   nx_ip_gateway_address_set              Set the IP gateway address    */
5784 /*                                                                        */
5785 /*  CALLED BY                                                             */
5786 /*                                                                        */
5787 /*    _nx_dhcp_thread_entry                                               */
5788 /*                                                                        */
5789 /*  RELEASE HISTORY                                                       */
5790 /*                                                                        */
5791 /*    DATE              NAME                      DESCRIPTION             */
5792 /*                                                                        */
5793 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5794 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5795 /*                                            resulting in version 6.1    */
5796 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
5797 /*                                            improved internal logic,    */
5798 /*                                            resulting in version 6.1.12 */
5799 /*                                                                        */
5800 /**************************************************************************/
_nx_dhcp_timeout_process(NX_DHCP * dhcp_ptr)5801 VOID _nx_dhcp_timeout_process(NX_DHCP *dhcp_ptr)
5802 {
5803 
5804 UINT            i;
5805 UINT            original_state;
5806 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
5807 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5808 ULONG            probing_delay;
5809 NX_IP           *ip_ptr;
5810 
5811 
5812     /* Pickup the associated IP pointer.  */
5813     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
5814 
5815 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE  */
5816 
5817     /* Update the timeout on both interfaces. Check what needs to be done
5818        if a timeout expires, based on Client state. */
5819     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
5820     {
5821 
5822          /* Check if the DHCP Client is active on this interface. */
5823          if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid == NX_FALSE)
5824              continue;
5825 
5826          /* Set the interface reocrd pointer.  */
5827          interface_record = &dhcp_ptr -> nx_dhcp_interface_record[i];
5828 
5829          /* Update the count.  */
5830          interface_record -> nx_dhcp_seconds ++;
5831 
5832         /* Check the timer.  */
5833         if (interface_record -> nx_dhcp_timeout != 0)
5834         {
5835 
5836             /* Apply the timer interval to the current DHCP Client timeout.  */
5837             if (interface_record -> nx_dhcp_timeout > NX_DHCP_TIME_INTERVAL)
5838             {
5839 
5840                 /* Update the timeout.  */
5841                 interface_record -> nx_dhcp_timeout -= (ULONG)NX_DHCP_TIME_INTERVAL;
5842             }
5843             else
5844             {
5845 
5846                 /* The DHCP Client timeout has expired. */
5847                 interface_record -> nx_dhcp_timeout = 0;
5848 
5849                 /* Save the current state for state change callback. */
5850                 original_state = interface_record -> nx_dhcp_state;
5851 
5852                 /* Process according to what state the Client is in. */
5853                 switch (interface_record -> nx_dhcp_state)
5854                 {
5855 
5856                     case NX_DHCP_STATE_INIT:
5857                     {
5858 
5859                         /* Reset the seconds field for starting the DHCP address acquistiion. */
5860                         interface_record -> nx_dhcp_seconds = 0;
5861 
5862                         /* Initial state when there is no address.  Send a DHCPDISCOVER message
5863                            to find a DHCP server and switch to the SELECTING state.
5864                            Initial timeout is NX_DHCP_MIN_RETRANS_TIMEOUT seconds. */
5865 #ifndef NX_DHCP_ENABLE_BOOTP
5866                         /* Only if the DHCP Client is requesting an IP address and is configured to skip the Discovery message. */
5867                         if ((interface_record -> nx_dhcp_ip_address != NX_BOOTP_NO_ADDRESS) &&
5868                             (interface_record -> nx_dhcp_skip_discovery))
5869                         {
5870 
5871                             /* Send out the DHCP request.  */
5872                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
5873 
5874                             /* And change to the Requesting state. */
5875                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_REQUESTING;
5876                         }
5877                         else
5878                         {
5879 
5880                             /* Send out the DHCP request.  */
5881                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPDISCOVER);
5882 
5883                             /* And change to the Selecting state. */
5884                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_SELECTING;
5885                         }
5886 #else
5887                         /* Send the BOOTP Request message.  */
5888                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_BOOT_REQUEST);
5889 
5890                         /* And change to the Requesting state. */
5891                         interface_record -> nx_dhcp_state = NX_DHCP_STATE_REQUESTING;
5892 #endif
5893 
5894                         /* Check if the retransmission interval is zero.  */
5895                         if (interface_record -> nx_dhcp_rtr_interval == 0)
5896                         {
5897 
5898                             /* Set the interval to min retransmission timeout.  */
5899                             interface_record -> nx_dhcp_rtr_interval = NX_DHCP_MIN_RETRANS_TIMEOUT;
5900                         }
5901                         else
5902                         {
5903 
5904                             /* Record the retransmission interval for next retransmission.  */
5905                             interface_record -> nx_dhcp_rtr_interval = _nx_dhcp_update_timeout(interface_record -> nx_dhcp_rtr_interval);
5906                         }
5907 
5908                         /* Update the timeout for next retransmission.  */
5909                         interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_rtr_interval;
5910 
5911                         /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */
5912                         interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout);
5913 
5914                         break;
5915                     }
5916 
5917                     case NX_DHCP_STATE_SELECTING:
5918                     {
5919 
5920 #ifndef NX_DHCP_ENABLE_BOOTP
5921                         /* Retransmit the Discover message.  */
5922                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPDISCOVER);
5923 #else
5924                         /* Retransmit the BOOTP Request message.  */
5925                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_BOOT_REQUEST);
5926 #endif
5927 
5928                         /* Update the retransmision interval.   */
5929                         interface_record -> nx_dhcp_rtr_interval = _nx_dhcp_update_timeout(interface_record -> nx_dhcp_rtr_interval);
5930 
5931                         /* Update the timeout for next retransmission.  */
5932                         interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_rtr_interval;
5933 
5934                         /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */
5935                         interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout);
5936 
5937                         break;
5938                     }
5939 
5940                     case NX_DHCP_STATE_REQUESTING:
5941                     {
5942 
5943 #ifndef NX_DHCP_ENABLE_BOOTP
5944                         /* Send a DHCP request. */
5945                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
5946 #else
5947                         /* Send a BOOTP request. */
5948                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_BOOT_REQUEST);
5949 #endif
5950 
5951                         /* Update the retransmision interval.   */
5952                         interface_record->nx_dhcp_rtr_interval = _nx_dhcp_update_timeout(interface_record -> nx_dhcp_rtr_interval);
5953 
5954                         /* Reset the timeout for next retransmision. */
5955                         interface_record -> nx_dhcp_timeout = interface_record->nx_dhcp_rtr_interval;
5956 
5957                         /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */
5958                         interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout);
5959 
5960                         break;
5961                     }
5962 
5963                     case NX_DHCP_STATE_ADDRESS_PROBING:
5964                     {
5965 
5966 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
5967 
5968                         /* Send the ARP probe.  */
5969                         _nx_arp_probe_send(ip_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_ip_address);
5970 
5971                         /* Decrease the probe count.  */
5972                         interface_record -> nx_dhcp_probe_count--;
5973 
5974                         /* Check the probe count.  */
5975                         if (interface_record -> nx_dhcp_probe_count)
5976                         {
5977 
5978                             /* Calculate the delay time.  */
5979                             probing_delay = (ULONG)NX_RAND() % (NX_DHCP_ARP_PROBE_MAX);
5980 
5981                             /* Determine if this is less than the minimum.  */
5982                             if (probing_delay < NX_DHCP_ARP_PROBE_MIN)
5983                             {
5984 
5985                                 /* Set the delay to the minimum.  */
5986                                 probing_delay = NX_DHCP_ARP_PROBE_MIN;
5987                             }
5988 
5989                             /* Check the probing_delay for timer interval.  */
5990                             if (probing_delay)
5991                                 interface_record -> nx_dhcp_timeout = probing_delay;
5992                             else
5993                                 interface_record -> nx_dhcp_timeout = 1;
5994                         }
5995                         else
5996                         {
5997 
5998                             /* No address conflict.  */
5999                             ip_ptr -> nx_ip_interface[interface_record -> nx_dhcp_interface_index].nx_interface_ip_conflict_notify_handler = NX_NULL;
6000 
6001                             /* Set the IP address.  */
6002                             nx_ip_interface_address_set(ip_ptr, interface_record -> nx_dhcp_interface_index,
6003                                                         interface_record -> nx_dhcp_ip_address, interface_record -> nx_dhcp_network_mask);
6004 
6005                             /* Check if the gateway address is valid.  */
6006                             if (interface_record -> nx_dhcp_gateway_address)
6007                             {
6008 
6009                                 /* Set the gateway address.  */
6010                                 nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
6011                             }
6012 
6013                             /* Change to the Bound state.  */
6014                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_BOUND;
6015 
6016  #ifdef NX_DHCP_ENABLE_BOOTP
6017                             /* BOOTP does not use timeouts.  For the life of this DHCP Client application, keep the same IP address. */
6018                             interface_record -> nx_dhcp_timeout = NX_WAIT_FOREVER;
6019 #else
6020                             /* Set the renewal time received from the server.  */
6021                             interface_record -> nx_dhcp_timeout = interface_record -> nx_dhcp_renewal_time;
6022 #endif /* NX_DHCP_ENABLE_BOOTP  */
6023                         }
6024 
6025 #endif /* NX_DHCP_CLIENT_SEND_ARP_PROBE */
6026 
6027                         break;
6028                     }
6029 
6030                     case NX_DHCP_STATE_BOUND:
6031                     {
6032 
6033                         /* Reset the seconds field for starting the DHCP request process. */
6034                         interface_record -> nx_dhcp_seconds = 0;
6035 
6036                         /* The lease has timed out. Time to renew.  */
6037 
6038                         /* And change to the Renewing state. */
6039                         interface_record -> nx_dhcp_state = NX_DHCP_STATE_RENEWING;
6040 
6041                         /* Send the renewal request.  */
6042                         _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
6043 
6044                         /* Set the time remaining based on RFC 2131 when T1 expires. */
6045                         interface_record -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_rebind_time - interface_record -> nx_dhcp_renewal_time;
6046                         interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
6047 
6048                         /* Record the retransmission interval.  */
6049                         interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
6050 
6051                         break;
6052                     }
6053 
6054                     case NX_DHCP_STATE_RENEWING:
6055                     {
6056 
6057                         /* Check if we have reached the end of the renewal time.  */
6058                         if (interface_record -> nx_dhcp_renewal_remain_time >= interface_record -> nx_dhcp_rtr_interval)
6059                         {
6060                             interface_record -> nx_dhcp_renewal_remain_time -= interface_record -> nx_dhcp_rtr_interval;
6061                         }
6062                         else
6063                         {
6064                             interface_record -> nx_dhcp_renewal_remain_time = 0;
6065                         }
6066 
6067                         /* Update the timeout for renew retranmission.  */
6068                         interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
6069 
6070                         /* Check if we are at the limit on retransmission.  */
6071                         if (interface_record -> nx_dhcp_timeout == 0)
6072                         {
6073 
6074                             /* And change to the Rebinding state. */
6075                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_REBINDING;
6076 
6077                             /* Send the rebind request.  */
6078                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
6079 
6080                             /* Calculate the rebind time based on the RFC 2131. */
6081                             interface_record -> nx_dhcp_rebind_remain_time = interface_record -> nx_dhcp_lease_time - interface_record -> nx_dhcp_rebind_time;
6082 
6083                             /* Calculate the timeout for the response.  */
6084                             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_rebind_remain_time);
6085 
6086                             /* Record the retransmission interval.  */
6087                             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
6088                         }
6089                         else
6090                         {
6091 
6092                             /* Retransmit the Renewing message and wait again */
6093                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
6094 
6095                             /* Record the retransmission interval.  */
6096                             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
6097                         }
6098 
6099                         break;
6100                     }
6101 
6102                     case NX_DHCP_STATE_REBINDING:
6103                     {
6104 
6105                         /* No response yet, the response must have timed out,
6106                             update the timeout and check if we have reached the
6107                             end of the rebinding time.  */
6108                         if (interface_record -> nx_dhcp_rebind_remain_time >= interface_record -> nx_dhcp_rtr_interval)
6109                         {
6110                             interface_record -> nx_dhcp_rebind_remain_time -= interface_record -> nx_dhcp_rtr_interval;
6111                         }
6112                         else
6113                         {
6114                             interface_record -> nx_dhcp_rebind_remain_time = 0;
6115                         }
6116 
6117                         /* Update the timeout for renew retranmission.  */
6118                         interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_rebind_remain_time);
6119 
6120                         /* Check if we are at the limit on retransmission.  */
6121                         if (interface_record -> nx_dhcp_timeout == 0)
6122                         {
6123 
6124                             /* Timeout. Restart DHCP service for this interface record.  */
6125 
6126                             /* Reinitialize DHCP.  */
6127                             _nx_dhcp_interface_reinitialize(dhcp_ptr, interface_record -> nx_dhcp_interface_index);
6128 
6129                             /* Start the DHCP protocol again by setting the state back to INIT. */
6130                             interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
6131 
6132                             /* The client begins in INIT state and forms a DHCPDISCOVER message.
6133                                The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
6134                                RFC2131, Section4.4.1, Page36.  */
6135 
6136                             /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
6137                             interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
6138                             interface_record -> nx_dhcp_rtr_interval = 0;
6139                         }
6140                         else
6141                         {
6142 
6143                             /* Retransmit the Renewing message and wait again */
6144                             _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPREQUEST);
6145 
6146                             /* Record the retransmission interval.  */
6147                             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
6148                         }
6149                         break;
6150                     }
6151 
6152                     default:
6153                     {
6154 
6155                         break;
6156                     }
6157                 }
6158 
6159                 /* Check if the state is changed.  */
6160                 if (original_state != interface_record -> nx_dhcp_state)
6161                 {
6162 
6163                     /* Determine if the application has specified a routine for DHCP state change notification.  */
6164                     if (dhcp_ptr -> nx_dhcp_state_change_callback)
6165                     {
6166 
6167                         /* Yes, call the application's state change notify function with the new state.  */
6168                         (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
6169                     }
6170 
6171                     /* Determine if the application has specified a routine for DHCP interface state change notification.  */
6172                     if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
6173                     {
6174 
6175                         /* Yes, call the application's state change notify function with the new state.  */
6176                         (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
6177                     }
6178                 }
6179 
6180             } /* End of switch statement. */
6181         }
6182 
6183     } /* Try the next interface record.  */
6184 }
6185 
6186 
6187 /**************************************************************************/
6188 /*                                                                        */
6189 /*  FUNCTION                                               RELEASE        */
6190 /*                                                                        */
6191 /*    _nxe_dhcp_send_request                              PORTABLE C      */
6192 /*                                                           6.1          */
6193 /*  AUTHOR                                                                */
6194 /*                                                                        */
6195 /*    Yuxin Zhou, Microsoft Corporation                                   */
6196 /*                                                                        */
6197 /*  DESCRIPTION                                                           */
6198 /*                                                                        */
6199 /*    This function performs error checking for the DHCP client send      */
6200 /*    request service.                                                    */
6201 /*                                                                        */
6202 /*  INPUT                                                                 */
6203 /*                                                                        */
6204 /*    dhcp_ptr                              Pointer to DHCP instance      */
6205 /*    dhcp_message_type                     Type of DHCP message to send , */
6206 /*                                                                        */
6207 /*  OUTPUT                                                                */
6208 /*    NX_PTR_ERROR                          Invalid pointer input         */
6209 /*    status                                Completion status             */
6210 /*                                                                        */
6211 /*  CALLS                                                                 */
6212 /*                                                                        */
6213 /*    _nxe_dhcp_send_request                Actual send request service   */
6214 /*                                                                        */
6215 /*  CALLED BY                                                             */
6216 /*                                                                        */
6217 /*    Application thread                                                  */
6218 /*                                                                        */
6219 /*  RELEASE HISTORY                                                       */
6220 /*                                                                        */
6221 /*    DATE              NAME                      DESCRIPTION             */
6222 /*                                                                        */
6223 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6224 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6225 /*                                            resulting in version 6.1    */
6226 /*                                                                        */
6227 /**************************************************************************/
_nxe_dhcp_send_request(NX_DHCP * dhcp_ptr,UINT dhcp_message_type)6228 UINT  _nxe_dhcp_send_request(NX_DHCP *dhcp_ptr, UINT dhcp_message_type)
6229 {
6230 
6231 UINT status;
6232 
6233 
6234     /* Check for invalid input. */
6235     if (!dhcp_ptr || (dhcp_message_type == 0) || (dhcp_message_type > NX_DHCP_TYPE_DHCPFORCERENEW))
6236     {
6237         return (NX_PTR_ERROR);
6238     }
6239 
6240     /* Call the actual service and return completion status. */
6241     status = _nx_dhcp_send_request(dhcp_ptr, dhcp_message_type);
6242 
6243     return(status);
6244 
6245 }
6246 
6247 
6248 /**************************************************************************/
6249 /*                                                                        */
6250 /*  FUNCTION                                               RELEASE        */
6251 /*                                                                        */
6252 /*    _nx_dhcp_send_request                               PORTABLE C      */
6253 /*                                                           6.1          */
6254 /*  AUTHOR                                                                */
6255 /*                                                                        */
6256 /*    Yuxin Zhou, Microsoft Corporation                                   */
6257 /*                                                                        */
6258 /*  DESCRIPTION                                                           */
6259 /*                                                                        */
6260 /*    This function sends the specified request to the first DHCP enabled */
6261 /*    interface found. To send a RELEASE or DECLINE message, use the      */
6262 /*    nx_dhcp_release/nx_dhcp_interface_release or nx_dhcp_decline/       */
6263 /*    nx_dhcp_interface_decline respectively.                             */
6264 /*                                                                        */
6265 /*    To send a request on a specific DHCP interface if multiple          */
6266 /*    interfaces are DHCP enabled, use the                                */
6267 /*    nx_dhcp_interface_send_request service.                             */
6268 /*                                                                        */
6269 /*    Note: Except for an INFORM REQUEST message, the application should  */
6270 /*    not need to send DHCP messages out independently of the DHCP Client */
6271 /*    processing thread. It is not recommended to use this function once  */
6272 /*    the DHCP Client has started until it is BOUND.                      */
6273 /*                                                                        */
6274 /*  INPUT                                                                 */
6275 /*                                                                        */
6276 /*    dhcp_ptr                              Pointer to DHCP instance      */
6277 /*    dhcp_message_type                     Type of DHCP message to send  */
6278 /*                                                                        */
6279 /*  OUTPUT                                                                */
6280 /*                                                                        */
6281 /*    status                                Actual completion status      */
6282 /*    NX_DHCP_NO_INTERFACES_ENABLED         No DHCP interface enabled     */
6283 /*                                                                        */
6284 /*  CALLS                                                                 */
6285 /*                                                                        */
6286 /*    _nx_dhcp_interface_send_request       Send DHCP request to server   */
6287 /*    tx_mutex_get                          Obtain protection mutex       */
6288 /*    tx_mutex_put                          Release protection mutex      */
6289 /*                                                                        */
6290 /*  CALLED BY                                                             */
6291 /*                                                                        */
6292 /*    Application code                                                    */
6293 /*                                                                        */
6294 /*  RELEASE HISTORY                                                       */
6295 /*                                                                        */
6296 /*    DATE              NAME                      DESCRIPTION             */
6297 /*                                                                        */
6298 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6299 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6300 /*                                            resulting in version 6.1    */
6301 /*                                                                        */
6302 /**************************************************************************/
_nx_dhcp_send_request(NX_DHCP * dhcp_ptr,UINT dhcp_message_type)6303 UINT  _nx_dhcp_send_request(NX_DHCP *dhcp_ptr, UINT dhcp_message_type)
6304 {
6305 
6306 UINT  status;
6307 UINT  i;
6308 
6309     /* Obtain the DHCP mutex.  */
6310     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
6311 
6312     /* Find the DHCP interface record.  */
6313     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
6314     {
6315 
6316         /* Check which interface record is valid.  */
6317         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
6318         {
6319 
6320             /* Set the request on only the first (only) valid interface.  */
6321             status = _nx_dhcp_interface_send_request(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index,  dhcp_message_type);
6322 
6323             /* Release the DHCP mutex.  */
6324             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6325             return(status);
6326         }
6327     }
6328 
6329     /* Release the DHCP mutex.  */
6330     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6331     return(NX_DHCP_NO_INTERFACES_ENABLED);
6332 
6333 }
6334 
6335 
6336 /**************************************************************************/
6337 /*                                                                        */
6338 /*  FUNCTION                                               RELEASE        */
6339 /*                                                                        */
6340 /*    _nxe_dhcp_interface_send_request                    PORTABLE C      */
6341 /*                                                           6.1          */
6342 /*  AUTHOR                                                                */
6343 /*                                                                        */
6344 /*    Yuxin Zhou, Microsoft Corporation                                   */
6345 /*                                                                        */
6346 /*  DESCRIPTION                                                           */
6347 /*                                                                        */
6348 /*    This function performs error checking on the send request service.  */
6349 /*                                                                        */
6350 /*  INPUT                                                                 */
6351 /*                                                                        */
6352 /*    dhcp_ptr                              Pointer to DHCP instance      */
6353 /*    iface_index                           Interface to send message on  */
6354 /*    dhcp_message_type                     DHCP messages to send:        */
6355 /*                                              NX_DHCP_TYPE_DHCPDECLINE  */
6356 /*                                              NX_DHCP_TYPE_DHCPRELEASE  */
6357 /*                                                                        */
6358 /*  OUTPUT                                                                */
6359 /*                                                                        */
6360 /*    status                                Completion status             */
6361 /*    NX_PTR_ERROR                          Invalid pointer input         */
6362 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
6363 /*                                                                        */
6364 /*  CALLS                                                                 */
6365 /*                                                                        */
6366 /*    _nx_dhcp_interface_send_request       Actual send the DHCP request  */
6367 /*                                                                        */
6368 /*  CALLED BY                                                             */
6369 /*                                                                        */
6370 /*    Application code                                                    */
6371 /*                                                                        */
6372 /*  RELEASE HISTORY                                                       */
6373 /*                                                                        */
6374 /*    DATE              NAME                      DESCRIPTION             */
6375 /*                                                                        */
6376 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6377 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6378 /*                                            resulting in version 6.1    */
6379 /*                                                                        */
6380 /**************************************************************************/
_nxe_dhcp_interface_send_request(NX_DHCP * dhcp_ptr,UINT iface_index,UINT dhcp_message_type)6381 UINT  _nxe_dhcp_interface_send_request(NX_DHCP *dhcp_ptr, UINT iface_index, UINT dhcp_message_type)
6382 {
6383 
6384 UINT status;
6385 
6386 
6387     if (dhcp_ptr == NX_NULL)
6388     {
6389         return(NX_PTR_ERROR);
6390     }
6391 
6392     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
6393     {
6394         return(NX_INVALID_INTERFACE);
6395     }
6396 
6397     /* Check for appropriate caller.  */
6398     NX_THREADS_ONLY_CALLER_CHECKING
6399 
6400     status = _nx_dhcp_interface_send_request(dhcp_ptr, iface_index, dhcp_message_type);
6401 
6402     return status;
6403 }
6404 
6405 
6406 /**************************************************************************/
6407 /*                                                                        */
6408 /*  FUNCTION                                               RELEASE        */
6409 /*                                                                        */
6410 /*    _nx_dhcp_interface_send_request                     PORTABLE C      */
6411 /*                                                           6.1          */
6412 /*  AUTHOR                                                                */
6413 /*                                                                        */
6414 /*    Yuxin Zhou, Microsoft Corporation                                   */
6415 /*                                                                        */
6416 /*  DESCRIPTION                                                           */
6417 /*                                                                        */
6418 /*    This function allows the host application to send a specific request*/
6419 /*    on the specified interface. The interface must be enabled for DHCP. */
6420 /*                                                                        */
6421 /*    To send a RELEASE or DECLINE message on a specific interface, use   */
6422 /*    the nx_dhcp_interface_release or nx_dhcp_interface_decline          */
6423 /*    respectively.                                                       */
6424 /*                                                                        */
6425 /*    Note: Except for an INFORM REQUEST message, the application should  */
6426 /*    not need to send DHCP messages out independently of the DHCP Client */
6427 /*    processing thread. It is not recommended to use this function once  */
6428 /*    the DHCP Client has started until it is BOUND.                      */
6429 /*                                                                        */
6430 /*  INPUT                                                                 */
6431 /*                                                                        */
6432 /*    dhcp_ptr                              Pointer to DHCP instance      */
6433 /*    iface_index                           Interface to send message on  */
6434 /*    dhcp_message_type                     Type of DHCP message to send, */
6435 /*                                              NX_DHCP_TYPE_DHCPDECLINE  */
6436 /*                                              NX_DHCP_TYPE_DHCPRELEASE  */
6437 /*                                                                        */
6438 /*  OUTPUT                                                                */
6439 /*                                                                        */
6440 /*    NX_DHCP_INVALID_MESSAGE               Message type not allowed      */
6441 /*    status                                Actual completion status      */
6442 /*                                                                        */
6443 /*  CALLS                                                                 */
6444 /*                                                                        */
6445 /*    _nx_dhcp_interface_record_find        Find Client record for the    */
6446 /*                                            specified interface         */
6447 /*    _nx_dhcp_send_request_internal        Send the DHCP request         */
6448 /*    tx_mutex_get                          Obtain protection mutex       */
6449 /*    tx_mutex_put                          Release protection mutex      */
6450 /*                                                                        */
6451 /*  CALLED BY                                                             */
6452 /*                                                                        */
6453 /*    Application code                                                    */
6454 /*                                                                        */
6455 /*  RELEASE HISTORY                                                       */
6456 /*                                                                        */
6457 /*    DATE              NAME                      DESCRIPTION             */
6458 /*                                                                        */
6459 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6460 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6461 /*                                            resulting in version 6.1    */
6462 /*                                                                        */
6463 /**************************************************************************/
_nx_dhcp_interface_send_request(NX_DHCP * dhcp_ptr,UINT iface_index,UINT dhcp_message_type)6464 UINT  _nx_dhcp_interface_send_request(NX_DHCP *dhcp_ptr, UINT iface_index, UINT dhcp_message_type)
6465 {
6466 
6467 UINT                      status;
6468 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
6469 
6470 
6471     /* Get the DHCP mutex.  */
6472     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
6473 
6474     /* Find the interface record.  */
6475     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
6476 
6477     /* Check status.  */
6478     if (status)
6479     {
6480 
6481         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6482 
6483         return(status);
6484     }
6485 
6486     /* If the message is a RELEASE or DECLINE request, the host should call nx_dhcp_release
6487        or nx_dhcp_decline respectively. */
6488     if ((dhcp_message_type == NX_DHCP_TYPE_DHCPRELEASE) || (dhcp_message_type == NX_DHCP_TYPE_DHCPDECLINE))
6489     {
6490 
6491         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6492 
6493         return NX_DHCP_INVALID_MESSAGE;
6494     }
6495 
6496     /* The DHCP INFORM message is independent of the Client thread task activity. */
6497     if (dhcp_message_type != NX_DHCP_TYPE_DHCPINFORM)
6498     {
6499 
6500         /* Determine if DHCP is started.  */
6501         if (dhcp_ptr -> nx_dhcp_interface_record[iface_index].nx_dhcp_state == NX_DHCP_STATE_NOT_STARTED)
6502         {
6503 
6504             /* Release the DHCP mutex.  */
6505             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
6506 
6507             /* DHCP is not started so it should not 'send' a request to the server.  */
6508             return(NX_DHCP_NOT_STARTED);
6509         }
6510     }
6511 
6512 
6513     status = _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, dhcp_message_type);
6514 
6515     /* Release the DHCP mutex.  */
6516     tx_mutex_put(&dhcp_ptr -> nx_dhcp_mutex);
6517 
6518     return status;
6519 
6520 }
6521 
6522 /**************************************************************************/
6523 /*                                                                        */
6524 /*  FUNCTION                                               RELEASE        */
6525 /*                                                                        */
6526 /*    _nx_dhcp_send_request_internal                      PORTABLE C      */
6527 /*                                                           6.1.12       */
6528 /*  AUTHOR                                                                */
6529 /*                                                                        */
6530 /*    Yuxin Zhou, Microsoft Corporation                                   */
6531 /*                                                                        */
6532 /*  DESCRIPTION                                                           */
6533 /*                                                                        */
6534 /*    This function sends a DHCP request to the server.  Any additional   */
6535 /*    options are appended to the request structure for certain types of  */
6536 /*    DHCP requests.                                                      */
6537 /*                                                                        */
6538 /*  INPUT                                                                 */
6539 /*                                                                        */
6540 /*    dhcp_ptr                              Pointer to DHCP instance      */
6541 /*    iface_index                           Interface to send message on  */
6542 /*    dhcp_message_type                     Type of DHCP message to send  */
6543 /*                                                                        */
6544 /*  OUTPUT                                                                */
6545 /*                                                                        */
6546 /*    status                                Completion status             */
6547 /*                                                                        */
6548 /*  CALLS                                                                 */
6549 /*                                                                        */
6550 /*    nx_packet_allocate                    Allocate a DHCP packet        */
6551 /*    nx_packet_release                     Release DHCP packet           */
6552 /*    nx_udp_socket_send                    Send DHCP packet              */
6553 /*    _nx_dhcp_store_data                   Write data into message       */
6554 /*    _nx_dhcp_add_option_value             Add an option to the request  */
6555 /*    _nx_dhcp_add_option_string            Add an option string to the   */
6556 /*                                            request                     */
6557 /*    _nx_dhcp_add_option_parameter_request Add a parameter request option*/
6558 /*    nx_udp_socket_interface_send          Send packet out on interface  */
6559 /*    _nx_dhcp_client_send_with_zero_source_address                       */
6560 /*                                          Send broadcast packet with    */
6561 /*                                            zero source IP address      */
6562 /*                                                                        */
6563 /*  CALLED BY                                                             */
6564 /*                                                                        */
6565 /*    _nx_dhcp_interface_send_request       Send request on specified     */
6566 /*                                             interface                  */
6567 /*    _nx_dhcp_interface_force_renew        Send Force Renew message      */
6568 /*    _nx_dhcp_interface_decline            Send DECLINE message          */
6569 /*    _nx_dhcp_interface_release            Send RELEASE message          */
6570 /*    _nx_dhcp_packet_process               Process received packets      */
6571 /*    _nx_dhcp_timeout_process              Process timer expirations     */
6572 #ifdef NX_DHCP_CLIENT_RESTORE_STATE
6573 /*    _nx_dhcp_resume                       Resume the DHCP Client thread */
6574 #endif
6575 /*                                                                        */
6576 /*  RELEASE HISTORY                                                       */
6577 /*                                                                        */
6578 /*    DATE              NAME                      DESCRIPTION             */
6579 /*                                                                        */
6580 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6581 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6582 /*                                            resulting in version 6.1    */
6583 /*  08-02-2021     Yuxin Zhou               Modified comment(s), supported*/
6584 /*                                            adding additional request   */
6585 /*                                            option in parameter request,*/
6586 /*                                            resulting in version 6.1.8  */
6587 /*  07-29-2022     Yuxin Zhou               Modified comment(s), corrected*/
6588 /*                                            the logic of adding server  */
6589 /*                                            identifier option,          */
6590 /*                                            resulting in version 6.1.12 */
6591 /*                                                                        */
6592 /**************************************************************************/
_nx_dhcp_send_request_internal(NX_DHCP * dhcp_ptr,NX_DHCP_INTERFACE_RECORD * interface_record,UINT dhcp_message_type)6593 static UINT  _nx_dhcp_send_request_internal(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, UINT dhcp_message_type)
6594 {
6595 
6596 NX_PACKET       *packet_ptr;
6597 UCHAR           *buffer;
6598 ULONG           targetIP;
6599 UINT            status;
6600 ULONG           dhcp_client_mac_msw;
6601 ULONG           dhcp_client_mac_lsw;
6602 UINT            iface_index;
6603 UINT            index = 0;
6604 UCHAR          *user_option_ptr;
6605 UINT            user_option_length;
6606 UINT            name_length;
6607 
6608 
6609     /* Set the interface idnex.  */
6610     iface_index = interface_record -> nx_dhcp_interface_index;
6611 
6612     /* Allocate a DHCP packet.  */
6613     status =  nx_packet_allocate(dhcp_ptr -> nx_dhcp_packet_pool_ptr, &packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
6614 
6615     /* Was the packet allocation successful?  */
6616     if (status != NX_SUCCESS)
6617     {
6618 
6619         /* Increment the DHCP internal error counter.  */
6620         interface_record -> nx_dhcp_internal_errors++;
6621 
6622         /* Return status.  */
6623         return(status);
6624     }
6625 
6626     /* Set the interface index and MAC address.  */
6627     dhcp_client_mac_msw = dhcp_ptr -> nx_dhcp_ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_msw;
6628     dhcp_client_mac_lsw = dhcp_ptr -> nx_dhcp_ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_lsw;
6629 
6630     /* Setup the buffer pointer.  */
6631     buffer =  packet_ptr -> nx_packet_prepend_ptr;
6632 
6633     /* Clear the buffer out... just in case.  */
6634     memset((void *) buffer, 0, NX_BOOTP_OFFSET_END);
6635 
6636     /* Setup the standard BootP fields.  */
6637     buffer[NX_BOOTP_OFFSET_OP] =        NX_BOOTP_OP_REQUEST;
6638     buffer[NX_BOOTP_OFFSET_HTYPE] =     NX_BOOTP_TYPE_ETHERNET;
6639     buffer[NX_BOOTP_OFFSET_HLEN] =      NX_BOOTP_HLEN_ETHERNET;
6640     buffer[NX_BOOTP_OFFSET_HOPS] =      0;
6641     buffer[NX_BOOTP_OFFSET_SERVER_NM] = 0;
6642     buffer[NX_BOOTP_OFFSET_BOOT_FILE] = 0;
6643 
6644     /* Setup the 'Xid' field.  */
6645     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_XID, 4, interface_record -> nx_dhcp_xid);
6646 
6647     /* Set the 'secs' field according to RFC2131, Secion4.4.1, Page37, Table5. */
6648     if ((dhcp_message_type == NX_DHCP_TYPE_DHCPDECLINE) || (dhcp_message_type == NX_DHCP_TYPE_DHCPRELEASE))
6649     {
6650         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_SECS, 2, 0);
6651     }
6652     else
6653     {
6654         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_SECS, 2, interface_record -> nx_dhcp_seconds);
6655     }
6656 
6657     /* Set the broadcast flag according to RFC2131, Secion4.4.1, Page38, Table5.  */
6658 
6659     /* Set the broadcast flag to 0 for DHCP Decline and DHCP Release.  */
6660     if ((dhcp_message_type == NX_DHCP_TYPE_DHCPDECLINE) || (dhcp_message_type == NX_DHCP_TYPE_DHCPRELEASE))
6661     {
6662 
6663         /* Request the response be sent unicast.  */
6664         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_FLAGS, 1, NX_BOOTP_FLAGS_UNICAST);
6665     }
6666 
6667     /* Set the 'broadcast' flag according to user requirement for DHCP Discover, DHCP Request and DHCP Inform.  */
6668     else if (interface_record -> nx_dhcp_clear_broadcast == NX_TRUE)
6669     {
6670 
6671         /* Request the response be sent unicast.  */
6672         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_FLAGS, 1, NX_BOOTP_FLAGS_UNICAST);
6673     }
6674     else
6675     {
6676 
6677         /* Request the response be sent broadcast.  */
6678         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_FLAGS, 1, NX_BOOTP_FLAGS_BROADCAST);
6679     }
6680 
6681     /* RFC 2131 4.4.1: Do not set the Client IP ("ciaddr" field) address...*/
6682     if (dhcp_message_type != NX_DHCP_TYPE_DHCPINFORM)
6683     {
6684         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, NX_BOOTP_NO_ADDRESS);
6685     }
6686     /* ...unless this is an INFORM REQUEST message. */
6687     else
6688     {
6689         _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
6690     }
6691 
6692     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_YOUR_IP, 4, NX_BOOTP_NO_ADDRESS);
6693     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_SERVER_IP, 4, NX_BOOTP_NO_ADDRESS);
6694     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_GATEWAY_IP, 4, NX_BOOTP_NO_ADDRESS);
6695     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_HW, 2, dhcp_client_mac_msw);
6696     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_HW + 2, 4, dhcp_client_mac_lsw);
6697 
6698 #ifndef NX_DHCP_ENABLE_BOOTP
6699     /* Update the index.  */
6700     index = NX_BOOTP_OFFSET_OPTIONS;
6701 
6702     /*  A BOOTP Client should not request DHCP option data. */
6703     _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_VENDOR, 4, NX_BOOTP_MAGIC_COOKIE);
6704 
6705     /* Add the actual DHCP request.  */
6706     _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_TYPE, NX_DHCP_OPTION_DHCP_TYPE_SIZE, dhcp_message_type, &index);
6707 #endif
6708 
6709     /* Determine if any additional options need to be added relative to the DHCP message type.
6710        RFC 2131, Table 5: Fields and options used by DHCP Clients.  */
6711     switch (dhcp_message_type)
6712     {
6713 
6714 #ifdef NX_DHCP_ENABLE_BOOTP
6715 
6716         case NX_DHCP_TYPE_BOOT_REQUEST:
6717 
6718             _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
6719             _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_SERVER_IP, 4, interface_record -> nx_dhcp_server_ip);
6720 
6721             break;
6722 #endif
6723 
6724         case NX_DHCP_TYPE_DHCPDISCOVER:
6725 
6726 
6727             /* Determine if we have a valid IP address.  */
6728             if ((interface_record -> nx_dhcp_ip_address != NX_BOOTP_NO_ADDRESS) &&
6729                 (interface_record -> nx_dhcp_ip_address != NX_BOOTP_BC_ADDRESS))
6730             {
6731 
6732                 /* Add a IP request option if we have a valid IP address */
6733                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_IP_REQ, NX_DHCP_OPTION_DHCP_IP_REQ_SIZE,
6734                                           interface_record -> nx_dhcp_ip_address, &index);
6735             }
6736 
6737             /* Add an option request for an infinite lease.  */
6738             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_LEASE, NX_DHCP_OPTION_DHCP_LEASE_SIZE, NX_DHCP_INFINITE_LEASE, &index);
6739 
6740             /* Add the system name */
6741             if (dhcp_ptr -> nx_dhcp_name)
6742             {
6743 
6744                 /* Check name length.  */
6745                 if (_nx_utility_string_length_check(dhcp_ptr -> nx_dhcp_name, &name_length, 255))
6746                 {
6747                     nx_packet_release(packet_ptr);
6748                     return(NX_DHCP_INVALID_NAME);
6749                 }
6750 
6751                 _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_HOST_NAME, name_length,
6752                                            (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index);
6753             }
6754 
6755             /* Add parameter request option.  */
6756             _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
6757 
6758 #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
6759 
6760             /* Add an option to specify the maximum length DHCP message that DHCP Client is willing to accept.
6761                RFC2132, Section9.10, Page28.  */
6762             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_MAX_DHCP_MESSAGE, 2, dhcp_ptr -> nx_dhcp_max_dhcp_message_size, &index);
6763 #endif
6764 
6765             /* Increment the number of Discovery messages sent.  */
6766             interface_record -> nx_dhcp_discoveries_sent++;
6767             break;
6768 
6769         case NX_DHCP_TYPE_DHCPREQUEST:
6770 
6771             /* Add the system name */
6772             if (dhcp_ptr -> nx_dhcp_name)
6773             {
6774 
6775                 /* Check name length.  */
6776                 if (_nx_utility_string_length_check(dhcp_ptr -> nx_dhcp_name, &name_length, 255))
6777                 {
6778                     nx_packet_release(packet_ptr);
6779                     return(NX_DHCP_INVALID_NAME);
6780                 }
6781 
6782                 _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_HOST_NAME, name_length, (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index);
6783             }
6784 
6785             /* Determine if we have a valid IP address. Must not include if Renewing or Rebinding RCV 2131 4.3.2.  */
6786             if ((interface_record -> nx_dhcp_ip_address != NX_BOOTP_NO_ADDRESS) &&
6787                 (interface_record -> nx_dhcp_ip_address != NX_BOOTP_BC_ADDRESS) &&
6788                 (interface_record -> nx_dhcp_state != NX_DHCP_STATE_RENEWING) &&
6789                 (interface_record -> nx_dhcp_state != NX_DHCP_STATE_REBINDING))
6790             {
6791 
6792                 /* Add an IP request option if we have a valid IP address.  */
6793                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_IP_REQ, NX_DHCP_OPTION_DHCP_IP_REQ_SIZE,
6794                                           interface_record -> nx_dhcp_ip_address, &index);
6795             }
6796 
6797             /* Add a request for an infinite lease if we haven't already set the timers.  */
6798             if ((interface_record -> nx_dhcp_rebind_time == 0) ||
6799                 (interface_record -> nx_dhcp_renewal_time == 0))
6800             {
6801 
6802                 /* Add the infinite lease option.  */
6803                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_LEASE, NX_DHCP_OPTION_DHCP_LEASE_SIZE, NX_DHCP_INFINITE_LEASE, &index);
6804             }
6805 
6806             /* Should add server ID if not renewing.  */
6807             if ((interface_record -> nx_dhcp_state != NX_DHCP_STATE_RENEWING) &&
6808                 (interface_record -> nx_dhcp_state != NX_DHCP_STATE_REBINDING) &&
6809                 (interface_record -> nx_dhcp_server_ip != NX_BOOTP_BC_ADDRESS) &&
6810                 (interface_record -> nx_dhcp_server_ip != NX_BOOTP_NO_ADDRESS)
6811                )
6812             {
6813 
6814                 /* Add Server identifier option.  */
6815                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_SERVER, NX_DHCP_OPTION_DHCP_SERVER_SIZE,
6816                                           interface_record -> nx_dhcp_server_ip, &index);
6817             }
6818             else if ((interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING) ||
6819                      (interface_record -> nx_dhcp_state == NX_DHCP_STATE_REBINDING))
6820 
6821             {
6822 
6823                 /* Ensure the renewal message fields are correct.  */
6824                 _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
6825             }
6826 
6827             /* Add parameter request option.  */
6828             _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
6829 
6830 #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
6831 
6832             /* Add an option to specify the maximum length DHCP message that DHCP Client is willing to accept.
6833                RFC2132, Section9.10, Page28.  */
6834             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_MAX_DHCP_MESSAGE, 2, dhcp_ptr -> nx_dhcp_max_dhcp_message_size, &index);
6835 #endif
6836 
6837             /* Increment the number of Request messages sent.  */
6838             interface_record -> nx_dhcp_requests_sent++;
6839             break;
6840 
6841         case NX_DHCP_TYPE_DHCPDECLINE:
6842 
6843             /* Does the Client have a nonzero requested address it is declining? */
6844             if ((interface_record -> nx_dhcp_ip_address != NX_BOOTP_NO_ADDRESS) &&
6845                 (interface_record -> nx_dhcp_ip_address != NX_BOOTP_BC_ADDRESS))
6846             {
6847 
6848                 /* Yes; add Request IP address option.  */
6849                 _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_IP_REQ, NX_DHCP_OPTION_DHCP_IP_REQ_SIZE,
6850                                           interface_record -> nx_dhcp_ip_address, &index);
6851             }
6852 
6853             /* Add Server identifier option.  */
6854             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_SERVER, NX_DHCP_OPTION_DHCP_SERVER_SIZE,
6855                                       interface_record -> nx_dhcp_server_ip, &index);
6856 
6857             break;
6858 
6859         case NX_DHCP_TYPE_DHCPRELEASE:
6860 
6861             /* Added the 'ciaddr', Indicate the IP address being released.  */
6862             _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
6863 
6864             /* Add Server identifier option.  */
6865             _nx_dhcp_add_option_value(buffer, NX_DHCP_OPTION_DHCP_SERVER, NX_DHCP_OPTION_DHCP_SERVER_SIZE,
6866                                       interface_record -> nx_dhcp_server_ip, &index);
6867 
6868             /* Increment the number of Release messages sent.  */
6869             interface_record -> nx_dhcp_releases_sent++;
6870             break;
6871 
6872         case NX_DHCP_TYPE_DHCPINFORM:
6873 
6874             /* Add the system name */
6875             if (dhcp_ptr -> nx_dhcp_name)
6876             {
6877 
6878                 /* Check name length.  */
6879                 if (_nx_utility_string_length_check(dhcp_ptr -> nx_dhcp_name, &name_length, 255))
6880                 {
6881                     nx_packet_release(packet_ptr);
6882                     return(NX_DHCP_INVALID_NAME);
6883                 }
6884 
6885                 _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_HOST_NAME, name_length, (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index);
6886             }
6887 
6888             /* Add parameter request option.  */
6889             _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
6890 
6891             /* Increment the number of Inform messages sent.  */
6892             interface_record -> nx_dhcp_informs_sent++;
6893 
6894             break;
6895 
6896         default:
6897             break;
6898     }
6899 
6900     /* Add any user supplied options to the buffer.  */
6901     if (dhcp_ptr -> nx_dhcp_user_option_add)
6902     {
6903 
6904         /* Set the pointer for adding user option.  */
6905         user_option_ptr = buffer + index;
6906 
6907         /* Calculate the available length for user options. Minus 1 to add the END option.  */
6908         user_option_length = (UINT)(packet_ptr -> nx_packet_data_end - user_option_ptr - 1);
6909 
6910         /* Add the specific DHCP option user wanted.  */
6911         if (dhcp_ptr -> nx_dhcp_user_option_add(dhcp_ptr, iface_index, dhcp_message_type, user_option_ptr, &user_option_length) == NX_TRUE)
6912         {
6913 
6914             /* Update the index to include the user options.  */
6915             index += user_option_length;
6916         }
6917         else
6918         {
6919 
6920             /* Invalid user options. Release the packet.  */
6921             nx_packet_release(packet_ptr);
6922             return(NX_DHCP_UNKNOWN_OPTION);
6923         }
6924     }
6925 
6926     /* Setup the packet pointers.  */
6927     packet_ptr -> nx_packet_length =      NX_BOOTP_OFFSET_END;
6928     packet_ptr -> nx_packet_append_ptr =  packet_ptr -> nx_packet_prepend_ptr + NX_BOOTP_OFFSET_END;
6929 
6930 #ifndef NX_DHCP_ENABLE_BOOTP
6931 
6932     /* Added the END option.  */
6933     *(buffer + index) = NX_DHCP_OPTION_END;
6934     index ++;
6935 
6936     /* Check the option length.  */
6937     if (index > NX_BOOTP_OFFSET_END)
6938     {
6939         packet_ptr -> nx_packet_length = index;
6940         packet_ptr -> nx_packet_append_ptr =  packet_ptr -> nx_packet_prepend_ptr + index;
6941     }
6942 #endif
6943 
6944     /* Set the target address according to RFC2131, Section4.3.6, Page33, Table4 and Section4.4.4, Page40.
6945        DHCP Request for renewing and DHCP Release message must be unicast.  */
6946     if (((dhcp_message_type == NX_DHCP_TYPE_DHCPREQUEST) && (interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING)) ||
6947         (dhcp_message_type == NX_DHCP_TYPE_DHCPRELEASE))
6948     {
6949 
6950         /* Use the current server's IP address.  */
6951         targetIP = interface_record -> nx_dhcp_server_ip;
6952     }
6953     else
6954     {
6955 
6956         /* Set the server target IP address to broadcast.  */
6957         targetIP = NX_BOOTP_BC_ADDRESS;
6958     }
6959 
6960     /* DHCP messages broadcast by a client prior to that client obtaining
6961        its IP address must have the source address field in the IP header
6962        set to 0. RFC2131, Section4.1, Page23.  */
6963     if ((dhcp_message_type == NX_DHCP_TYPE_DHCPDISCOVER) ||
6964         ((dhcp_message_type == NX_DHCP_TYPE_DHCPREQUEST) && (interface_record -> nx_dhcp_state < NX_DHCP_STATE_BOUND)))
6965     {
6966 
6967         /* Call function to send the special packet with zero source address.*/
6968         status = _nx_dhcp_client_send_with_zero_source_address(dhcp_ptr, iface_index, packet_ptr);
6969     }
6970     else
6971     {
6972 
6973         /* Send the packet.  */
6974         status = nx_udp_socket_interface_send(&(dhcp_ptr -> nx_dhcp_socket), packet_ptr, targetIP, NX_DHCP_SERVER_UDP_PORT, iface_index);
6975     }
6976 
6977     /* If an error is detected, release the packet. */
6978     if (status != NX_SUCCESS)
6979     {
6980 
6981         /* Release the packet.  */
6982         nx_packet_release(packet_ptr);
6983     }
6984 
6985     /* Return completion status.  */
6986     return(status);
6987 }
6988 
6989 
6990 /**************************************************************************/
6991 /*                                                                        */
6992 /*  FUNCTION                                               RELEASE        */
6993 /*                                                                        */
6994 /*    _nx_dhcp_client_send_with_zero_source_address       PORTABLE C      */
6995 /*                                                           6.1.12       */
6996 /*  AUTHOR                                                                */
6997 /*                                                                        */
6998 /*    Yuxin Zhou, Microsoft Corporation                                   */
6999 /*                                                                        */
7000 /*  DESCRIPTION                                                           */
7001 /*                                                                        */
7002 /*    This function builds the UDP and IP header with zero source address,*/
7003 /*    then sends the packet to the appropriate link driver.               */
7004 /*                                                                        */
7005 /*  INPUT                                                                 */
7006 /*                                                                        */
7007 /*    dhcp_ptr                              Pointer to DHCP instance      */
7008 /*    iface_index                           Interface to send message on  */
7009 /*    packet_ptr                            Pointer to packet to send     */
7010 /*                                                                        */
7011 /*  OUTPUT                                                                */
7012 /*                                                                        */
7013 /*    status                                Completion status             */
7014 /*                                                                        */
7015 /*  CALLS                                                                 */
7016 /*                                                                        */
7017 /*    (ip_link_driver)                      User supplied link driver     */
7018 /*                                                                        */
7019 /*  CALLED BY                                                             */
7020 /*                                                                        */
7021 /*    _nx_dhcp_send_request_internal        Send DHCP Request             */
7022 /*                                                                        */
7023 /*  RELEASE HISTORY                                                       */
7024 /*                                                                        */
7025 /*    DATE              NAME                      DESCRIPTION             */
7026 /*                                                                        */
7027 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7028 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7029 /*                                            resulting in version 6.1    */
7030 /*  08-02-2021     Yuxin Zhou               Modified comment(s), and      */
7031 /*                                            supported new ip filter,    */
7032 /*                                            resulting in version 6.1.8  */
7033 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
7034 /*                                            set the IP header pointer,  */
7035 /*                                            resulting in version 6.1.11 */
7036 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
7037 /*                                            improved internal logic,    */
7038 /*                                            and solve inconformity with */
7039 /*                                            udp socket send and ip      */
7040 /*                                            header add,                 */
7041 /*                                            resulting in version 6.1.12 */
7042 /*                                                                        */
7043 /**************************************************************************/
_nx_dhcp_client_send_with_zero_source_address(NX_DHCP * dhcp_ptr,UINT iface_index,NX_PACKET * packet_ptr)7044 static UINT  _nx_dhcp_client_send_with_zero_source_address(NX_DHCP *dhcp_ptr, UINT iface_index, NX_PACKET *packet_ptr)
7045 {
7046 
7047 NX_IP          *ip_ptr;
7048 NX_UDP_SOCKET  *socket_ptr;
7049 NX_UDP_HEADER  *udp_header_ptr;
7050 NX_IPV4_HEADER *ip_header_ptr;
7051 NX_INTERFACE   *interface_ptr;
7052 ULONG           ip_src_addr, ip_dest_addr;
7053 #if defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY)
7054 UINT            compute_checksum = 1;
7055 #endif /* defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */
7056 ULONG           checksum;
7057 ULONG           val;
7058 NX_IP_DRIVER    driver_request;
7059 
7060     /* Set up the pointer to the associated IP instance.  */
7061     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
7062 
7063     /* Set up the pointer to the associated socket.  */
7064     socket_ptr = &dhcp_ptr -> nx_dhcp_socket;
7065 
7066     /* Set up the pointer to the interface.  */
7067     interface_ptr = &(ip_ptr -> nx_ip_interface[iface_index]);
7068     packet_ptr -> nx_packet_ip_interface = interface_ptr;
7069 
7070     /* Set up the address.  */
7071     ip_src_addr = NX_BOOTP_NO_ADDRESS;
7072     ip_dest_addr = NX_BOOTP_BC_ADDRESS;
7073 
7074     /* Check the interface.  */
7075     if ((!interface_ptr -> nx_interface_valid) || (!interface_ptr -> nx_interface_link_up))
7076     {
7077 
7078         /* None found; return the error status. */
7079         return(NX_INVALID_INTERFACE);
7080     }
7081 
7082     /* Build UDP header.  */
7083 
7084     /* Prepend the UDP header to the packet.  First, make room for the UDP header.  */
7085     packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER);
7086 
7087     /* Set the correct IP version. */
7088     packet_ptr -> nx_packet_ip_version = NX_IP_VERSION_V4;
7089 
7090 #ifndef NX_DISABLE_UDP_INFO
7091     /* Increment the total UDP packets sent count.  */
7092     ip_ptr -> nx_ip_udp_packets_sent++;
7093 
7094     /* Increment the total UDP bytes sent.  */
7095     ip_ptr -> nx_ip_udp_bytes_sent +=  packet_ptr -> nx_packet_length;
7096 
7097     /* Increment the total UDP packets sent count for this socket.  */
7098     socket_ptr -> nx_udp_socket_packets_sent++;
7099 
7100     /* Increment the total UDP bytes sent for this socket.  */
7101     socket_ptr -> nx_udp_socket_bytes_sent +=  packet_ptr -> nx_packet_length;
7102 #endif
7103 
7104     /* Increase the packet length.  */
7105     packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_UDP_HEADER);
7106 
7107     /* Setup the UDP header pointer.  */
7108     udp_header_ptr =  (NX_UDP_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
7109 
7110     /* Build the first 32-bit word of the UDP header.  */
7111     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;
7112 
7113     /* Build the second 32-bit word of the UDP header.  */
7114     udp_header_ptr -> nx_udp_header_word_1 =  (packet_ptr -> nx_packet_length << NX_SHIFT_BY_16);
7115 
7116     /* Endian swapping logic.  If NX_LITTLE_ENDIAN is specified, these macros will
7117        swap the endian of the UDP header.  */
7118     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0);
7119     NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
7120 
7121 #ifdef NX_DISABLE_UDP_TX_CHECKSUM
7122     compute_checksum = 0;
7123 #endif /* NX_DISABLE_UDP_TX_CHECKSUM */
7124 
7125 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
7126     if (interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM)
7127         compute_checksum = 0;
7128 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
7129 
7130 #if defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY)
7131     if (compute_checksum)
7132 #endif /* defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */
7133     {
7134         /* Yes, we need to compute the UDP checksum.  */
7135         checksum = _nx_ip_checksum_compute(packet_ptr,
7136                                            NX_PROTOCOL_UDP,
7137                                            (UINT)packet_ptr -> nx_packet_length,
7138                                            &ip_src_addr,
7139                                            &ip_dest_addr);
7140 
7141         checksum = ~checksum & NX_LOWER_16_MASK;
7142 
7143         /* If the computed checksum is zero, it will be transmitted as all ones. */
7144         /* RFC 768, page 2. */
7145         if (checksum == 0)
7146             checksum = 0xFFFF;
7147 
7148         NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
7149 
7150         udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 | checksum;
7151 
7152         NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
7153     }
7154 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
7155     else
7156         /* Set CHECKSUM flag so the driver would invoke the HW checksum. */
7157         packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM;
7158 #endif /* NX_ENABLE_INTERFACE_CAPABILITY  */
7159 
7160     /* Get mutex protection.  */
7161     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
7162 
7163     /* Build the IP header.  */
7164 
7165     /* Prepend the IP header to the packet.  First, make room for the IP header.  */
7166     packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - 20;
7167 
7168     /* Increase the packet length.  */
7169     packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + 20;
7170 
7171     /* Setup the IP header pointer.  */
7172     ip_header_ptr =  (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
7173     packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr;
7174     packet_ptr -> nx_packet_ip_header_length = sizeof(NX_IPV4_HEADER);
7175 
7176     /* Build the first 32-bit word of the IP header.  */
7177     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));
7178 
7179     /* Build the second 32-bit word of the IP header.  */
7180     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;
7181 
7182     /* Build the third 32-bit word of the IP header.  */
7183     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);
7184 
7185     /* Place the source IP address in the IP header.  */
7186     ip_header_ptr -> nx_ip_header_source_ip =  ip_src_addr;
7187 
7188     /* Place the destination IP address in the IP header.  */
7189     ip_header_ptr -> nx_ip_header_destination_ip =  ip_dest_addr;
7190 
7191     /* Endian swapping logic.  If NX_LITTLE_ENDIAN is specified, these macros will
7192        swap the endian of the IP header.  */
7193     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_0);
7194     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_1);
7195     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_2);
7196     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip);
7197     NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip);
7198 
7199 #ifdef NX_DISABLE_IP_TX_CHECKSUM
7200     compute_checksum = 0;
7201 #elif defined(NX_ENABLE_INTERFACE_CAPABILITY)
7202     /* Re-initialize the value back to the default initial value (i.e. 1) */
7203     compute_checksum = 1;
7204 #endif /* defined(NX_DISABLE_IP_TX_CHECKSUM) */
7205 
7206 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
7207     if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM)
7208         compute_checksum = 0;
7209 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
7210 
7211 #if defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY)
7212     if (compute_checksum)
7213 #endif /* defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */
7214     {
7215         checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_VERSION_V4, 20, NULL, NULL);
7216 
7217         val = (ULONG)(~checksum);
7218         val = val & NX_LOWER_16_MASK;
7219 
7220         /* Convert to network byte order. */
7221         NX_CHANGE_ULONG_ENDIAN(val);
7222 
7223         /* Now store the checksum in the IP header.  */
7224         ip_header_ptr -> nx_ip_header_word_2 =  ip_header_ptr -> nx_ip_header_word_2 | val;
7225     }
7226 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
7227     else
7228     {
7229         packet_ptr -> nx_packet_interface_capability_flag |= NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM;
7230     }
7231 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
7232 
7233 #ifdef NX_ENABLE_IP_PACKET_FILTER
7234     /* Check if the IP packet filter is set.  */
7235     if (ip_ptr -> nx_ip_packet_filter)
7236     {
7237 
7238         /* Yes, call the IP packet filter routine.  */
7239         if ((ip_ptr -> nx_ip_packet_filter((VOID *)(ip_header_ptr), NX_IP_PACKET_OUT)) != NX_SUCCESS)
7240         {
7241 
7242             /* Release mutex protection.  */
7243             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7244 
7245             /* Return a not successful status.  */
7246             return(NX_NOT_SUCCESSFUL);
7247         }
7248     }
7249 
7250     /* Check if the IP packet filter extended is set. */
7251     if (ip_ptr -> nx_ip_packet_filter_extended)
7252     {
7253 
7254         /* Yes, call the IP packet filter extended routine. */
7255         if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS)
7256         {
7257 
7258             /* Release mutex protection.  */
7259             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7260 
7261             /* Return a not successful status.  */
7262             return(NX_NOT_SUCCESSFUL);
7263         }
7264     }
7265 #endif /* NX_ENABLE_IP_PACKET_FILTER */
7266 
7267     /* Build the driver request.  */
7268     driver_request.nx_ip_driver_ptr =                   ip_ptr;
7269     driver_request.nx_ip_driver_packet =                packet_ptr;
7270     driver_request.nx_ip_driver_interface =             packet_ptr -> nx_packet_ip_interface;
7271     driver_request.nx_ip_driver_command =               NX_LINK_PACKET_BROADCAST;
7272     driver_request.nx_ip_driver_physical_address_msw =  0xFFFFUL;
7273     driver_request.nx_ip_driver_physical_address_lsw =  0xFFFFFFFFUL;
7274 
7275     /* Determine if fragmentation is needed.  */
7276     if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_mtu_size)
7277     {
7278 
7279 #ifndef NX_DISABLE_FRAGMENTATION
7280         /* Check the DF bit flag.  */
7281         if ((ip_ptr -> nx_ip_fragment_processing) && (socket_ptr -> nx_udp_socket_fragment_enable != NX_DONT_FRAGMENT))
7282         {
7283 
7284             /* Fragmentation is needed, call the IP fragment processing routine.  */
7285             (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
7286 
7287             /* Release mutex protection.  */
7288             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7289 
7290             /* Return a successful status.  */
7291             return(NX_SUCCESS);
7292         }
7293         else
7294 #endif /* NX_DISABLE_FRAGMENTATION */
7295         {
7296 
7297 #ifndef NX_DISABLE_IP_INFO
7298 
7299             /* Increment the IP send packets dropped count.  */
7300             ip_ptr -> nx_ip_send_packets_dropped++;
7301 #endif
7302 
7303             /* Release mutex protection.  */
7304             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7305 
7306             /* Return a not successful status.  */
7307             return(NX_NOT_SUCCESSFUL);
7308         }
7309     }
7310 
7311 #ifndef NX_DISABLE_IP_INFO
7312 
7313     /* Increment the IP packet sent count.  */
7314     ip_ptr -> nx_ip_total_packets_sent++;
7315 
7316     /* Increment the IP bytes sent count.  */
7317     ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - 20;
7318 #endif
7319 
7320     /* Broadcast packet.  */
7321     (packet_ptr -> nx_packet_ip_interface -> nx_interface_link_driver_entry) (&driver_request);
7322 
7323     /* Release mutex protection.  */
7324     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
7325 
7326     /* Return a successful status.  */
7327     return(NX_SUCCESS);
7328 }
7329 
7330 
7331 
7332 
7333 /**************************************************************************/
7334 /*                                                                        */
7335 /*  FUNCTION                                               RELEASE        */
7336 /*                                                                        */
7337 /*    _nx_dhcp_extract_information                        PORTABLE C      */
7338 /*                                                           6.1          */
7339 /*  AUTHOR                                                                */
7340 /*                                                                        */
7341 /*    Yuxin Zhou, Microsoft Corporation                                   */
7342 /*                                                                        */
7343 /*  DESCRIPTION                                                           */
7344 /*                                                                        */
7345 /*    This function extracts important information from the server's      */
7346 /*    response DHCP message.                                              */
7347 /*                                                                        */
7348 /*  INPUT                                                                 */
7349 /*                                                                        */
7350 /*    dhcp_ptr                              Pointer to DHCP instance      */
7351 /*    interface_record                      Pointer to DHCP interface     */
7352 /*    dhcp_message                          Pointer to DHCP message       */
7353 /*    length                                Size of DHCP message buffer   */
7354 /*                                                                        */
7355 /*  OUTPUT                                                                */
7356 /*                                                                        */
7357 /*    status                                Completion status             */
7358 /*                                                                        */
7359 /*  CALLS                                                                 */
7360 /*                                                                        */
7361 /*    _nx_dhcp_ip_address_set               Set the DHCP IP address       */
7362 /*    nx_ip_gateway_address_set             Set the Gateway address       */
7363 /*    _nx_dhcp_get_option_value             Get DHCP option from buffer   */
7364 /*    _nx_dhcp_get_data                     Get data from buffer          */
7365 /*    memcpy                                Copy specified area of memory */
7366 /*                                                                        */
7367 /*  CALLED BY                                                             */
7368 /*                                                                        */
7369 /*    _nx_dhcp_packet_process               Data received handler         */
7370 /*                                                                        */
7371 /*  RELEASE HISTORY                                                       */
7372 /*                                                                        */
7373 /*    DATE              NAME                      DESCRIPTION             */
7374 /*                                                                        */
7375 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7376 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
7377 /*                                            verified memcpy use cases,  */
7378 /*                                            resulting in version 6.1    */
7379 /*                                                                        */
7380 /**************************************************************************/
_nx_dhcp_extract_information(NX_DHCP * dhcp_ptr,NX_DHCP_INTERFACE_RECORD * interface_record,UCHAR * dhcp_message,UINT length)7381 static UINT  _nx_dhcp_extract_information(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, UCHAR *dhcp_message, UINT length)
7382 {
7383 
7384 ULONG       value;
7385 
7386 
7387     /* Extract the IP address.  */
7388     value =  _nx_dhcp_get_data(dhcp_message + NX_BOOTP_OFFSET_YOUR_IP, 4);
7389 
7390     /* Determine if it is valid.  */
7391     if ((value != NX_BOOTP_NO_ADDRESS) &&
7392         (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7393          ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7394          ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7395     {
7396 
7397         /* Store the IP address.  */
7398         interface_record -> nx_dhcp_ip_address =  value;
7399     }
7400     else
7401     {
7402         return(NX_DHCP_BAD_IP_ADDRESS);
7403     }
7404 
7405     /* Determine if there is a subnet mask. Note a DHCP Server receiving a BOOTP request
7406        may send DHCP option data for subnet masks as per RFC 1534 Section 2.  */
7407     if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_SUBNET_MASK, &value, length) == NX_SUCCESS)
7408     {
7409 
7410         /* Make sure there is a valid IP address too.  */
7411         if (value != NX_BOOTP_NO_ADDRESS)
7412         {
7413 
7414             interface_record -> nx_dhcp_network_mask =  value;
7415         }
7416         else
7417         {
7418             ULONG ip_address;
7419 
7420             /* No valid network mask info supplied; use the current network mask if any. Don't
7421                care about current IP address for now. */
7422             nx_ip_interface_address_get(dhcp_ptr -> nx_dhcp_ip_ptr,
7423                                         interface_record -> nx_dhcp_interface_index,
7424                                         &ip_address,
7425                                         &(interface_record -> nx_dhcp_network_mask));
7426         }
7427     }
7428 
7429 #ifdef NX_DHCP_ENABLE_BOOTP
7430 
7431     /* Update the IP address.  */
7432     value =  _nx_dhcp_get_data(dhcp_message + NX_BOOTP_OFFSET_SERVER_IP, 4);
7433 
7434     /* Determine if it is valid.  */
7435     if (value != NX_BOOTP_NO_ADDRESS)
7436     {
7437 
7438         /* Store the IP address.  */
7439         interface_record -> nx_dhcp_server_ip =  value;
7440     }
7441 
7442     /* Update the  IP address.  */
7443     value =  _nx_dhcp_get_data(dhcp_message + NX_BOOTP_OFFSET_GATEWAY_IP, 4);
7444 
7445     /* Determine if it is valid.  */
7446     if ((value != NX_BOOTP_NO_ADDRESS) &&
7447         (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7448          ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7449          ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7450     {
7451 
7452         /* Store the gateway/Router IP address to the Client record.  */
7453         interface_record -> nx_dhcp_gateway_address = value;
7454     }
7455     else
7456     {
7457 
7458         /* The gateway may be sent as an option: See note above about BOOTP Clients
7459            parsing DHCP option data. */
7460 
7461         /* Determine if the IP gateway/router IP address is present.  */
7462         if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_GATEWAYS, &value, length) == NX_SUCCESS)
7463         {
7464 
7465             /* Determine if it is valid.  */
7466             if ((value != NX_BOOTP_NO_ADDRESS) &&
7467                 (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7468                  ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7469                  ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7470             {
7471 
7472                 /* Store the gateway/Router IP address to the Client record.  */
7473                 interface_record -> nx_dhcp_gateway_address = value;
7474             }
7475             else
7476             {
7477                 return(NX_DHCP_BAD_IP_ADDRESS);
7478             }
7479         }
7480     }
7481 
7482 #else
7483 
7484     /* NX_DHCP_ENABLE_BOOTP  not defined */
7485 
7486     /* Overwrite the server ID if there is a DHCP option for Server ID */
7487     if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_DHCP_SERVER, &value, length) == NX_SUCCESS)
7488     {
7489 
7490         /* Determine if it is valid.  */
7491         if ((value != NX_BOOTP_NO_ADDRESS) &&
7492             (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7493              ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7494              ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7495         {
7496 
7497             /* Store the server IP address.  */
7498             interface_record -> nx_dhcp_server_ip = value;
7499         }
7500         else
7501         {
7502             return(NX_DHCP_BAD_IP_ADDRESS);
7503         }
7504     }
7505 
7506     /* Get the lease time.  */
7507     if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_DHCP_LEASE, &value, length) == NX_SUCCESS)
7508     {
7509 
7510         /* Check for an infinite lease. */
7511         if (value == 0xFFFFFFFF)
7512         {
7513             /* Store the 'infinite' lease time . */
7514             interface_record -> nx_dhcp_lease_time = value;
7515             interface_record -> nx_dhcp_renewal_time = value;
7516             interface_record -> nx_dhcp_rebind_time = value;
7517         }
7518         else
7519         {
7520 
7521             /* Store the lease time in timer ticks.  */
7522             interface_record -> nx_dhcp_lease_time =  value * (ULONG)NX_IP_PERIODIC_RATE;
7523 
7524             /* Set the renew and rebind times.  */
7525             interface_record -> nx_dhcp_renewal_time = interface_record -> nx_dhcp_lease_time / 2;
7526             interface_record -> nx_dhcp_rebind_time =  interface_record -> nx_dhcp_lease_time - (interface_record -> nx_dhcp_lease_time / 8);
7527         }
7528     }
7529 
7530     /* Overwrite the renew and rebind times with the specified values if the options are present.  */
7531     if ((_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_RENEWAL, &value, length) == NX_SUCCESS) &&
7532         (value <= interface_record -> nx_dhcp_lease_time))
7533     {
7534 
7535         /* Check for an infinite lease. */
7536         if (value == 0xFFFFFFFF)
7537         {
7538             /* Set the 'infinite least time.  */
7539             interface_record -> nx_dhcp_renewal_time = value;
7540         }
7541         else
7542         {
7543 
7544             /* Store the renewal time in timer ticks  */
7545             interface_record -> nx_dhcp_renewal_time =  value * (ULONG)NX_IP_PERIODIC_RATE;
7546         }
7547     }
7548 
7549     /* Determine if there is a rebind time.  */
7550     if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_REBIND, &value, length) == NX_SUCCESS)
7551     {
7552 
7553         /* Check for an infinite lease. */
7554         if (value == 0xFFFFFFFF)
7555         {
7556 
7557             /* Set the 'infinite least time.  */
7558             interface_record -> nx_dhcp_rebind_time = value;
7559         }
7560         else
7561         {
7562 
7563             /* Convert to timer ticks. */
7564             value = value * (ULONG)NX_IP_PERIODIC_RATE;
7565 
7566             /* Sanity check*/
7567             if ((value <= interface_record -> nx_dhcp_lease_time) &&
7568                 (value >= interface_record -> nx_dhcp_renewal_time))
7569             {
7570 
7571                 /* Store the rebind time.  */
7572                 interface_record -> nx_dhcp_rebind_time =  value;
7573             }
7574         }
7575     }
7576 
7577     /* Determine if this is an ACK from a server response, which can only happen from a handful of states.  */
7578     if ((interface_record -> nx_dhcp_state == NX_DHCP_STATE_REQUESTING) ||
7579         (interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING) ||
7580         (interface_record -> nx_dhcp_state == NX_DHCP_STATE_REBINDING))
7581     {
7582 
7583         /* Determine if the IP gateway/router IP address is present.  */
7584         if (_nx_dhcp_get_option_value(dhcp_message, NX_DHCP_OPTION_GATEWAYS, &value, length) == NX_SUCCESS)
7585         {
7586 
7587             /* Determine if it is valid.  */
7588             if ((value != NX_BOOTP_NO_ADDRESS) &&
7589                 (((value & NX_IP_CLASS_A_MASK) == NX_IP_CLASS_A_TYPE) ||
7590                  ((value & NX_IP_CLASS_B_MASK) == NX_IP_CLASS_B_TYPE) ||
7591                  ((value & NX_IP_CLASS_C_MASK) == NX_IP_CLASS_C_TYPE)))
7592             {
7593 
7594                 /* Store the gateway/Router IP address to the Client record.  */
7595                 interface_record -> nx_dhcp_gateway_address = value;
7596             }
7597             else
7598             {
7599                 return(NX_DHCP_BAD_IP_ADDRESS);
7600             }
7601         }
7602     }
7603 
7604      /* Check the DHCP options size.  */
7605      if ((length - NX_BOOTP_OFFSET_OPTIONS) > NX_DHCP_OPTIONS_BUFFER_SIZE)
7606          interface_record -> nx_dhcp_options_size = NX_DHCP_OPTIONS_BUFFER_SIZE;
7607      else
7608          interface_record -> nx_dhcp_options_size = length - NX_BOOTP_OFFSET_OPTIONS;
7609 
7610      /* Copy the DHCP options into DHCP Client options buffer.  */
7611      memcpy(interface_record -> nx_dhcp_options_buffer, /* Use case of memcpy is verified. */
7612             &dhcp_message[NX_BOOTP_OFFSET_OPTIONS], interface_record -> nx_dhcp_options_size);
7613 
7614 #endif  /* NX_DHCP_ENABLE_BOOTP */
7615 
7616     return (NX_SUCCESS);
7617 }
7618 
7619 
7620 /**************************************************************************/
7621 /*                                                                        */
7622 /*  FUNCTION                                               RELEASE        */
7623 /*                                                                        */
7624 /*    _nx_dhcp_get_option_value                           PORTABLE C      */
7625 /*                                                           6.1.12       */
7626 /*  AUTHOR                                                                */
7627 /*                                                                        */
7628 /*    Yuxin Zhou, Microsoft Corporation                                   */
7629 /*                                                                        */
7630 /*  DESCRIPTION                                                           */
7631 /*                                                                        */
7632 /*    This function searches through a buffer containing a BootP message  */
7633 /*    for a DHCP option parameter and gets the value of that option if    */
7634 /*    it exists. The function is restricted to options that are less      */
7635 /*    than 4 octets (bytes) in size.                                      */
7636 /*                                                                        */
7637 /*  INPUT                                                                 */
7638 /*                                                                        */
7639 /*    bootp_message                         Pointer to option buffer      */
7640 /*    option                                Option requested              */
7641 /*    value                                 Pointer to return value var   */
7642 /*    length                                Size of option buffer         */
7643 /*                                                                        */
7644 /*  OUTPUT                                                                */
7645 /*                                                                        */
7646 /*    status                                Completion status             */
7647 /*                                                                        */
7648 /*  CALLS                                                                 */
7649 /*                                                                        */
7650 /*    _nx_dhcp_search_buffer                Search the buffer             */
7651 /*    _nx_dhcp_get_data                     Get data from buffer          */
7652 /*                                                                        */
7653 /*  CALLED BY                                                             */
7654 /*                                                                        */
7655 /*    _nx_dhcp_packet_process               Data received handler         */
7656 /*    _nx_dhcp_extract_information          Extract info from server      */
7657 /*                                                                        */
7658 /*  RELEASE HISTORY                                                       */
7659 /*                                                                        */
7660 /*    DATE              NAME                      DESCRIPTION             */
7661 /*                                                                        */
7662 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7663 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7664 /*                                            resulting in version 6.1    */
7665 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
7666 /*                                            improved internal logic,    */
7667 /*                                            resulting in version 6.1.12 */
7668 /*                                                                        */
7669 /**************************************************************************/
_nx_dhcp_get_option_value(UCHAR * bootp_message,UINT option,ULONG * value,UINT length)7670 static UINT  _nx_dhcp_get_option_value(UCHAR *bootp_message, UINT option, ULONG *value, UINT length)
7671 {
7672 
7673 UCHAR *data;
7674 UCHAR *option_message;
7675 UINT   option_length;
7676 
7677 
7678     /* Setup buffer pointer.  */
7679     option_message = &bootp_message[NX_BOOTP_OFFSET_OPTIONS];
7680     option_length = length - NX_BOOTP_OFFSET_OPTIONS;
7681 
7682     /* There is no need to check whether the option is PAD or END here since no caller will pass these 2 options
7683        and for denfensive purpose, the function below could check them and guarantee appropriate behaviour */
7684 
7685     /* Search the buffer for the option.  */
7686     data =  _nx_dhcp_search_buffer(option_message, option, option_length);
7687 
7688     /* Check to see if the option was found.  */
7689     if (data != NX_NULL)
7690     {
7691 
7692         /* Check for the proper size.  */
7693         if (*data > 4)
7694         {
7695 
7696             /* Check for the gateway option.  */
7697             if (option == NX_DHCP_OPTION_GATEWAYS)
7698             {
7699 
7700                 /* Pickup the first gateway address.  */
7701                 *value =  _nx_dhcp_get_data(data + 1, 4);
7702 
7703                 /* For now, just disregard any additional gateway addresses.  */
7704                 return(NX_SUCCESS);
7705             }
7706             else
7707             {
7708 
7709                 /* Invalid size, return error.  */
7710                 return(NX_SIZE_ERROR);
7711             }
7712         }
7713         else
7714         {
7715 
7716             /* Get the actual value.  */
7717             *value = _nx_dhcp_get_data(data + 1, *data);
7718             return(NX_SUCCESS);
7719         }
7720     }
7721 
7722     /* Return an error if not found.  */
7723     return(NX_OPTION_ERROR);
7724 }
7725 
7726 
7727 /**************************************************************************/
7728 /*                                                                        */
7729 /*  FUNCTION                                               RELEASE        */
7730 /*                                                                        */
7731 /*    _nx_dhcp_add_option_value                           PORTABLE C      */
7732 /*                                                           6.1          */
7733 /*  AUTHOR                                                                */
7734 /*                                                                        */
7735 /*    Yuxin Zhou, Microsoft Corporation                                   */
7736 /*                                                                        */
7737 /*  DESCRIPTION                                                           */
7738 /*                                                                        */
7739 /*    This routine adds a DHCP vendor option value to the BootP message   */
7740 /*    in the supplied buffer.  Adding the option includes adding the      */
7741 /*    option code, length and option data value.                          */
7742 /*                                                                        */
7743 /*  INPUT                                                                 */
7744 /*                                                                        */
7745 /*    bootp_message                         Pointer to message buffer     */
7746 /*    option                                Option to add                 */
7747 /*    value                                 Value of Option to add        */
7748 /*                                                                        */
7749 /*  OUTPUT                                                                */
7750 /*                                                                        */
7751 /*    status                                Completion status             */
7752 /*                                                                        */
7753 /*  CALLS                                                                 */
7754 /*                                                                        */
7755 /*    _nx_dhcp_store_data                   Store data value              */
7756 /*                                                                        */
7757 /*  CALLED BY                                                             */
7758 /*                                                                        */
7759 /*    _nx_dhcp_send_request_internal        Send DHCP request             */
7760 /*                                                                        */
7761 /*  RELEASE HISTORY                                                       */
7762 /*                                                                        */
7763 /*    DATE              NAME                      DESCRIPTION             */
7764 /*                                                                        */
7765 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7766 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7767 /*                                            resulting in version 6.1    */
7768 /*                                                                        */
7769 /**************************************************************************/
_nx_dhcp_add_option_value(UCHAR * bootp_message,UINT option,UINT size,ULONG value,UINT * index)7770 UINT  _nx_dhcp_add_option_value(UCHAR *bootp_message, UINT option, UINT size, ULONG value, UINT *index)
7771 {
7772 
7773 
7774     /* Store the option.  */
7775     *(bootp_message + (*index)) = (UCHAR)option;
7776     (*index) ++;
7777 
7778     /* Store the option size.  */
7779     *(bootp_message + (*index)) = (UCHAR)size;
7780     (*index) ++;
7781 
7782     /* Store the option value.  */
7783     _nx_dhcp_store_data(bootp_message + (*index), size, value);
7784     (*index) += size;
7785 
7786     /* Return a successful completion.  */
7787     return(NX_SUCCESS);
7788 }
7789 
7790 
7791 /**************************************************************************/
7792 /*                                                                        */
7793 /*  FUNCTION                                               RELEASE        */
7794 /*                                                                        */
7795 /*    _nx_dhcp_add_option_string                          PORTABLE C      */
7796 /*                                                           6.1          */
7797 /*  AUTHOR                                                                */
7798 /*                                                                        */
7799 /*    Yuxin Zhou, Microsoft Corporation                                   */
7800 /*                                                                        */
7801 /*  DESCRIPTION                                                           */
7802 /*                                                                        */
7803 /*    This routine adds a DHCP option string to the BootP message in      */
7804 /*    supplied buffer.  Adding the option includes adding the option      */
7805 /*    code, length and option string.                                     */
7806 /*                                                                        */
7807 /*  INPUT                                                                 */
7808 /*                                                                        */
7809 /*    bootp_message                         Pointer to message buffer     */
7810 /*    option                                Option to add                 */
7811 /*    size                                  Size of option string         */
7812 /*    value                                 Option string pointer         */
7813 /*                                                                        */
7814 /*  OUTPUT                                                                */
7815 /*                                                                        */
7816 /*    status                                Completion status             */
7817 /*                                                                        */
7818 /*  CALLS                                                                 */
7819 /*                                                                        */
7820 /*    _nx_dhcp_move_string                  Store option string           */
7821 /*                                                                        */
7822 /*  CALLED BY                                                             */
7823 /*                                                                        */
7824 /*    _nx_dhcp_send_request_internal       Internal DHCP message send     */
7825 /*                                                                        */
7826 /*  RELEASE HISTORY                                                       */
7827 /*                                                                        */
7828 /*    DATE              NAME                      DESCRIPTION             */
7829 /*                                                                        */
7830 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7831 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7832 /*                                            resulting in version 6.1    */
7833 /*                                                                        */
7834 /**************************************************************************/
_nx_dhcp_add_option_string(UCHAR * bootp_message,UINT option,UINT size,UCHAR * value,UINT * index)7835 static UINT  _nx_dhcp_add_option_string(UCHAR *bootp_message, UINT option, UINT size, UCHAR *value, UINT *index)
7836 {
7837 
7838     /* Store the option.  */
7839     *(bootp_message + (*index)) = (UCHAR)option;
7840     (*index) ++;
7841 
7842     /* Store the option size.  */
7843     *(bootp_message + (*index)) = (UCHAR)size;
7844     (*index) ++;
7845 
7846     /* Store the option value.  */
7847     _nx_dhcp_move_string(bootp_message + (*index), value, size);
7848     (*index) += size;
7849 
7850     /* Return a successful completion.  */
7851     return(NX_SUCCESS);
7852 }
7853 
7854 
7855 /**************************************************************************/
7856 /*                                                                        */
7857 /*  FUNCTION                                               RELEASE        */
7858 /*                                                                        */
7859 /*    _nx_dhcp_add_option_parameter_request               PORTABLE C      */
7860 /*                                                           6.1.8        */
7861 /*  AUTHOR                                                                */
7862 /*                                                                        */
7863 /*    Yuxin Zhou, Microsoft Corporation                                   */
7864 /*                                                                        */
7865 /*  DESCRIPTION                                                           */
7866 /*                                                                        */
7867 /*    This routine adds a DHCP parameter request option to the BootP      */
7868 /*    message in supplied buffer. Adding the option includes adding the   */
7869 /*    option code, length and option value.                               */
7870 /*                                                                        */
7871 /*  INPUT                                                                 */
7872 /*                                                                        */
7873 /*    dhcp_ptr                              Pointer to DHCP instance      */
7874 /*    bootp_message                         Pointer to message buffer     */
7875 /*    index                                 Index to write data           */
7876 /*                                                                        */
7877 /*  OUTPUT                                                                */
7878 /*                                                                        */
7879 /*    status                                Completion status             */
7880 /*                                                                        */
7881 /*  CALLS                                                                 */
7882 /*                                                                        */
7883 /*    _nx_dhcp_move_string                  Store option string           */
7884 /*                                                                        */
7885 /*  CALLED BY                                                             */
7886 /*                                                                        */
7887 /*    _nx_dhcp_send_request_internal       Internal DHCP message send     */
7888 /*                                                                        */
7889 /*  RELEASE HISTORY                                                       */
7890 /*                                                                        */
7891 /*    DATE              NAME                      DESCRIPTION             */
7892 /*                                                                        */
7893 /*  08-02-2021     Yuxin Zhou               Initial Version 6.1.8         */
7894 /*                                                                        */
7895 /**************************************************************************/
_nx_dhcp_add_option_parameter_request(NX_DHCP * dhcp_ptr,UCHAR * bootp_message,UINT * index)7896 static UINT  _nx_dhcp_add_option_parameter_request(NX_DHCP *dhcp_ptr, UCHAR *bootp_message, UINT *index)
7897 {
7898 
7899     /* Store the option.  */
7900     *(bootp_message + (*index)) = NX_DHCP_OPTION_DHCP_PARAMETERS;
7901     (*index) ++;
7902 
7903     /* Store the option size.  */
7904     *(bootp_message + (*index)) = (UCHAR)(NX_DHCP_REQUEST_PARAMETER_SIZE + dhcp_ptr -> nx_dhcp_user_request_parameter_size);
7905     (*index) ++;
7906 
7907     /* Store the option value.  */
7908     _nx_dhcp_move_string(bootp_message + (*index), _nx_dhcp_request_parameters, NX_DHCP_REQUEST_PARAMETER_SIZE);
7909     (*index) += (UINT)NX_DHCP_REQUEST_PARAMETER_SIZE;
7910 
7911     /* Check if there are additional user options.  */
7912     if (dhcp_ptr -> nx_dhcp_user_request_parameter_size)
7913     {
7914         _nx_dhcp_move_string(bootp_message + (*index), dhcp_ptr -> nx_dhcp_user_request_parameter, dhcp_ptr -> nx_dhcp_user_request_parameter_size);
7915         (*index) += (UCHAR)dhcp_ptr -> nx_dhcp_user_request_parameter_size;
7916     }
7917 
7918     /* Return a successful completion.  */
7919     return(NX_SUCCESS);
7920 }
7921 
7922 
7923 /**************************************************************************/
7924 /*                                                                        */
7925 /*  FUNCTION                                               RELEASE        */
7926 /*                                                                        */
7927 /*    _nx_dhcp_add_randomize                              PORTABLE C      */
7928 /*                                                           6.1.12       */
7929 /*  AUTHOR                                                                */
7930 /*                                                                        */
7931 /*    Yuxin Zhou, Microsoft Corporation                                   */
7932 /*                                                                        */
7933 /*  DESCRIPTION                                                           */
7934 /*                                                                        */
7935 /*    This routine adds randomized variance to the input timeout up to    */
7936 /*    +/- one second.                                                     */
7937 /*                                                                        */
7938 /*  INPUT                                                                 */
7939 /*                                                                        */
7940 /*    timeout                               Timeout to randomize          */
7941 /*                                                                        */
7942 /*  OUTPUT                                                                */
7943 /*                                                                        */
7944 /*    ULONG                                 Modified timeout value        */
7945 /*                                                                        */
7946 /*  CALLS                                                                 */
7947 /*                                                                        */
7948 /*    None                                                                */
7949 /*                                                                        */
7950 /*  CALLED BY                                                             */
7951 /*                                                                        */
7952 /*    nx_dhcp_process                       Process the current state of  */
7953 /*                                           the DHCP Client state machine*/
7954 /*                                                                        */
7955 /*  RELEASE HISTORY                                                       */
7956 /*                                                                        */
7957 /*    DATE              NAME                      DESCRIPTION             */
7958 /*                                                                        */
7959 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7960 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7961 /*                                            resulting in version 6.1    */
7962 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
7963 /*                                            improved internal logic,    */
7964 /*                                            resulting in version 6.1.12 */
7965 /*                                                                        */
7966 /**************************************************************************/
_nx_dhcp_add_randomize(ULONG timeout)7967 static ULONG _nx_dhcp_add_randomize(ULONG timeout)
7968 {
7969 
7970 ULONG adjustment;
7971 
7972     /* Uniform random number chosen from the range -1 to +1 second as recommended by RFC2131, Section4.1, Page24. */
7973 
7974     /* Calculate random time adjustment in timer ticks from the range 0 to NX_IP_PERIODIC_RATE * 2.  */
7975     adjustment = (ULONG)NX_RAND() % ((NX_IP_PERIODIC_RATE << 1) + 1);
7976 
7977     /* Check for adjustment.  */
7978     if (adjustment < NX_IP_PERIODIC_RATE)
7979     {
7980 
7981         /* Updated timeout, minus NX_IP_PERIODIC_RATE - adjustment.  */
7982 
7983         /* Check for timeout.  */
7984         if (timeout > (NX_IP_PERIODIC_RATE - adjustment))
7985             timeout -= (ULONG)(NX_IP_PERIODIC_RATE - adjustment);
7986         else
7987             timeout = 1; /* Set 1 here since the minmum tick for timeout shall be larger than 0 */
7988     }
7989     else
7990     {
7991 
7992         /* Updated timeout, add adjustment- NX_IP_PERIODIC_RATE.  */
7993         timeout += (ULONG)(adjustment - NX_IP_PERIODIC_RATE);
7994     }
7995 
7996     return timeout;
7997 }
7998 
7999 
8000 /**************************************************************************/
8001 /*                                                                        */
8002 /*  FUNCTION                                               RELEASE        */
8003 /*                                                                        */
8004 /*    _nx_dhcp_update_timeout                             PORTABLE C      */
8005 /*                                                           6.1          */
8006 /*  AUTHOR                                                                */
8007 /*                                                                        */
8008 /*    Yuxin Zhou, Microsoft Corporation                                   */
8009 /*                                                                        */
8010 /*  DESCRIPTION                                                           */
8011 /*                                                                        */
8012 /*    This function updates the DHCP timeout for retransmission. When the */
8013 /*    current timeout expires, this function doubles the timeout, but     */
8014 /*    limits the timeout value to NX_DHCP_MAX_RETRANS_TIMEOUT (seconds).  */
8015 /*                                                                        */
8016 /*  INPUT                                                                 */
8017 /*                                                                        */
8018 /*    timeout                               The current Timeout value     */
8019 /*                                                                        */
8020 /*  OUTPUT                                                                */
8021 /*                                                                        */
8022 /*    timeout                               The updated timeout           */
8023 /*                                                                        */
8024 /*  CALLS                                                                 */
8025 /*                                                                        */
8026 /*    _nx_dhcp_convert_delay_to_ticks       Convert the delay to ticks    */
8027 /*                                                                        */
8028 /*  CALLED BY                                                             */
8029 /*                                                                        */
8030 /*    _nx_dhcp_timeout_process               Timer expiration handler     */
8031 /*                                                                        */
8032 /*  RELEASE HISTORY                                                       */
8033 /*                                                                        */
8034 /*    DATE              NAME                      DESCRIPTION             */
8035 /*                                                                        */
8036 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8037 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8038 /*                                            resulting in version 6.1    */
8039 /*                                                                        */
8040 /**************************************************************************/
_nx_dhcp_update_timeout(ULONG timeout)8041 static ULONG _nx_dhcp_update_timeout(ULONG timeout)
8042 {
8043 
8044     /* Timed out, double the timeout, limited to NX_DHCP_MAX_RETRANS_TIMEOUT */
8045     if ((2 * timeout) >= NX_DHCP_MAX_RETRANS_TIMEOUT)
8046     {
8047 
8048         /* Set the timeout as NX_DHCP_MAX_RETRANS_TIMEOUT.  */
8049         timeout = NX_DHCP_MAX_RETRANS_TIMEOUT;
8050     }
8051     else
8052     {
8053 
8054         /* Double timeout value.  */
8055         timeout = timeout * 2;
8056     }
8057 
8058     /* Return the sequence timeout.  */
8059     return(timeout);
8060 }
8061 
8062 /**************************************************************************/
8063 /*                                                                        */
8064 /*  FUNCTION                                               RELEASE        */
8065 /*                                                                        */
8066 /*    _nx_dhcp_update_renewal_timeout                     PORTABLE C      */
8067 /*                                                           6.1          */
8068 /*  AUTHOR                                                                */
8069 /*                                                                        */
8070 /*    Yuxin Zhou, Microsoft Corporation                                   */
8071 /*                                                                        */
8072 /*  DESCRIPTION                                                           */
8073 /*                                                                        */
8074 /*    This function updates the DHCP timeout when trying to renew a       */
8075 /*    lease according to the RFC. When the current period has timed out,  */
8076 /*    this function halves the timeout, limiting the minimum timeout      */
8077 /*    value to NX_DHCP_MIN_RENEW_TIMEOUT seconds.                         */
8078 /*                                                                        */
8079 /*  INPUT                                                                 */
8080 /*                                                                        */
8081 /*    timeout                               The current Timeout value     */
8082 /*                                                                        */
8083 /*  OUTPUT                                                                */
8084 /*                                                                        */
8085 /*    timeout                               Renewal time remaining        */
8086 /*                                                                        */
8087 /*  CALLS                                                                 */
8088 /*                                                                        */
8089 /*                                                                        */
8090 /*  CALLED BY                                                             */
8091 /*                                                                        */
8092 /*    _nx_dhcp_client_interface_update_time_remaining                     */
8093 /*                                          Apply input time elapsed to   */
8094 /*                                            the DHCP Client record      */
8095 /*    _nx_dhcp_timeout_process              Timer expiration handler      */
8096 /*                                                                        */
8097 /*  RELEASE HISTORY                                                       */
8098 /*                                                                        */
8099 /*    DATE              NAME                      DESCRIPTION             */
8100 /*                                                                        */
8101 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8102 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8103 /*                                            resulting in version 6.1    */
8104 /*                                                                        */
8105 /**************************************************************************/
_nx_dhcp_update_renewal_timeout(ULONG timeout)8106 static ULONG _nx_dhcp_update_renewal_timeout(ULONG timeout)
8107 {
8108 
8109     /* check if the timeout is non zero */
8110     if (timeout != 0)
8111     {
8112 
8113         /* Timed out, halve the timeout, limited to NX_DHCP_MIN_RENEW_TIMEOUT or
8114           the remaining timeout if it is less than NX_DHCP_MIN_RENEW_TIMEOUT */
8115         if (timeout > NX_DHCP_MIN_RENEW_TIMEOUT)
8116         {
8117 
8118             /* Timeout can still decrease, either
8119                force it to the minimum or halve it */
8120             if (timeout > (2 * NX_DHCP_MIN_RENEW_TIMEOUT ))
8121             {
8122 
8123                 /* Halve timeout.  */
8124                 timeout = timeout / 2;
8125             }
8126             else
8127             {
8128 
8129                 /* set timeout to minimum.  */
8130                 timeout =  NX_DHCP_MIN_RENEW_TIMEOUT ;
8131             }
8132         }
8133     }
8134 
8135     /* Return the sequence timeout.  */
8136     return(timeout);
8137 }
8138 
8139 
8140 /**************************************************************************/
8141 /*                                                                        */
8142 /*  FUNCTION                                               RELEASE        */
8143 /*                                                                        */
8144 /*    _nx_dhcp_search_buffer                              PORTABLE C      */
8145 /*                                                           6.1.12       */
8146 /*  AUTHOR                                                                */
8147 /*                                                                        */
8148 /*    Yuxin Zhou, Microsoft Corporation                                   */
8149 /*                                                                        */
8150 /*  DESCRIPTION                                                           */
8151 /*                                                                        */
8152 /*    This routine searches through a buffer containing a BootP message   */
8153 /*    for a DHCP option parameter and returns a pointer to the byte       */
8154 /*    containing the size of the data section of that option if it        */
8155 /*    exists. If the option cannot be found then function returns NULL.   */
8156 /*    If the option has no data (PAD and END) then the pointer is not     */
8157 /*    usable.                                                             */
8158 /*                                                                        */
8159 /*  INPUT                                                                 */
8160 /*                                                                        */
8161 /*    option_message                        Pointer to option buffer area */
8162 /*    option                                Option to search for          */
8163 /*    length                                Length of search buffer       */
8164 /*                                                                        */
8165 /*  OUTPUT                                                                */
8166 /*                                                                        */
8167 /*    pointer                               Pointer to found option       */
8168 /*                                                                        */
8169 /*  CALLS                                                                 */
8170 /*                                                                        */
8171 /*    None                                                                */
8172 /*                                                                        */
8173 /*  CALLED BY                                                             */
8174 /*                                                                        */
8175 /*    _nx_dhcp_get_option_value             Get the value of an option    */
8176 /*    _nx_dhcp_get_option_data              Get the string of an option   */
8177 /*                                                                        */
8178 /*  RELEASE HISTORY                                                       */
8179 /*                                                                        */
8180 /*    DATE              NAME                      DESCRIPTION             */
8181 /*                                                                        */
8182 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8183 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8184 /*                                            resulting in version 6.1    */
8185 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
8186 /*                                            improved internal logic,    */
8187 /*                                            resulting in version 6.1.12 */
8188 /*                                                                        */
8189 /**************************************************************************/
_nx_dhcp_search_buffer(UCHAR * option_message,UINT option,UINT length)8190 static UCHAR  *_nx_dhcp_search_buffer(UCHAR *option_message, UINT option, UINT length)
8191 {
8192 
8193 UCHAR   *data;
8194 UINT    i;
8195 UINT    size;
8196 
8197     /* Setup buffer pointer.  */
8198     data = option_message;
8199     i = 0;
8200 
8201     /* Search as long as there are valid options.   */
8202     while (i < length - 1)
8203     {
8204         /* Jump out when it reaches END option */
8205         if (*data == NX_DHCP_OPTION_END)
8206         {
8207             break;
8208         }
8209 
8210         /* Simply skip any padding */
8211         else if (*data == NX_DHCP_OPTION_PAD)
8212         {
8213 
8214             data++;
8215             i++;
8216         }
8217 
8218         /* On a match, return a pointer to the size.  */
8219         else if (*data == option)
8220         {
8221 
8222             size = *(data + 1);
8223 
8224             /* Check if the option data is in the packet.  */
8225             if ((i + size + 1) > length)
8226                 return(NX_NULL);
8227 
8228             /* Return a pointer to the option size byte.  */
8229             return(data + 1);
8230         }
8231 
8232         /* Otherwise skip the option by adding the size to the pointer.  */
8233         else
8234         {
8235 
8236             size = *(++data);
8237 
8238             /* skip the data plus the size byte */
8239             data += size + 1;
8240             i += size + 1;
8241         }
8242     }
8243 
8244     /* Return NULL to indicate the option was not found.  */
8245     return(NX_NULL);
8246 }
8247 
8248 
8249 /**************************************************************************/
8250 /*                                                                        */
8251 /*  FUNCTION                                               RELEASE        */
8252 /*                                                                        */
8253 /*    _nx_dhcp_get_data                                   PORTABLE C      */
8254 /*                                                           6.1          */
8255 /*  AUTHOR                                                                */
8256 /*                                                                        */
8257 /*    Yuxin Zhou, Microsoft Corporation                                   */
8258 /*                                                                        */
8259 /*  DESCRIPTION                                                           */
8260 /*                                                                        */
8261 /*    This routine gets a data value from a buffer, assuming the data is  */
8262 /*    stored in standard Network format (big endian). Up to 4 bytes of    */
8263 /*    data are used, if there are more than 4 bytes, only the lower 4     */
8264 /*    bytes are returned.                                                 */
8265 /*                                                                        */
8266 /*  INPUT                                                                 */
8267 /*                                                                        */
8268 /*    data                                  Pointer to buffer data        */
8269 /*    size                                  Size of data value            */
8270 /*                                                                        */
8271 /*  OUTPUT                                                                */
8272 /*                                                                        */
8273 /*    value                                 Data value retrieved          */
8274 /*                                                                        */
8275 /*  CALLS                                                                 */
8276 /*                                                                        */
8277 /*    None                                                                */
8278 /*                                                                        */
8279 /*  CALLED BY                                                             */
8280 /*                                                                        */
8281 /*    _nx_dhcp_get_response                 Get response from server      */
8282 /*    _nx_dhcp_extract_information          Extract server information    */
8283 /*    _nx_dhcp_get_option_value             Retrieve option value         */
8284 /*    _nx_dhcp_update_address_list          Update address list           */
8285 /*                                                                        */
8286 /*  RELEASE HISTORY                                                       */
8287 /*                                                                        */
8288 /*    DATE              NAME                      DESCRIPTION             */
8289 /*                                                                        */
8290 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8291 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8292 /*                                            resulting in version 6.1    */
8293 /*                                                                        */
8294 /**************************************************************************/
_nx_dhcp_get_data(UCHAR * data,UINT size)8295 static ULONG  _nx_dhcp_get_data(UCHAR *data, UINT size)
8296 {
8297 
8298 ULONG   value = 0;
8299 
8300 
8301     /* Process the data retrieval request.  */
8302     while (size-- > 0)
8303     {
8304 
8305         /* Build return value.  */
8306         value = (value << 8) | *data++;
8307     }
8308 
8309     /* Return value.  */
8310     return(value);
8311 }
8312 
8313 
8314 /**************************************************************************/
8315 /*                                                                        */
8316 /*  FUNCTION                                               RELEASE        */
8317 /*                                                                        */
8318 /*    _nx_dhcp_store_data                                 PORTABLE C      */
8319 /*                                                           6.1.12       */
8320 /*  AUTHOR                                                                */
8321 /*                                                                        */
8322 /*    Yuxin Zhou, Microsoft Corporation                                   */
8323 /*                                                                        */
8324 /*  DESCRIPTION                                                           */
8325 /*                                                                        */
8326 /*    This function stores a data value in a buffer in standard Network   */
8327 /*    format (big endian) where the destination may be unaligned. Up to   */
8328 /*    4 bytes of data are stored, if the size is larger than 4 bytes, the */
8329 /*    remaining bytes are set to zero.                                    */
8330 /*                                                                        */
8331 /*  INPUT                                                                 */
8332 /*                                                                        */
8333 /*    data                                  Pointer to buffer data        */
8334 /*    size                                  Size of data value            */
8335 /*    value                                 Value to store                */
8336 /*                                                                        */
8337 /*  OUTPUT                                                                */
8338 /*                                                                        */
8339 /*    None                                                                */
8340 /*                                                                        */
8341 /*  CALLS                                                                 */
8342 /*                                                                        */
8343 /*    None                                                                */
8344 /*                                                                        */
8345 /*  CALLED BY                                                             */
8346 /*                                                                        */
8347 /*    _nx_dhcp_send_request_internal        Send DHCP request             */
8348 /*    _nx_dhcp_add_option_value             Add a DHCP option             */
8349 /*                                                                        */
8350 /*  RELEASE HISTORY                                                       */
8351 /*                                                                        */
8352 /*    DATE              NAME                      DESCRIPTION             */
8353 /*                                                                        */
8354 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8355 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8356 /*                                            resulting in version 6.1    */
8357 /*  07-29-2022     Yuxin Zhou               Modified comment(s),          */
8358 /*                                            improved internal logic,    */
8359 /*                                            resulting in version 6.1.12 */
8360 /*                                                                        */
8361 /**************************************************************************/
_nx_dhcp_store_data(UCHAR * data,UINT size,ULONG value)8362 static VOID  _nx_dhcp_store_data(UCHAR *data, UINT size, ULONG value)
8363 {
8364     /* Store the value.  */
8365     while (size-- > 0)
8366     {
8367         *(data + size) = (UCHAR)(value & 0xff);
8368         value >>= 8;
8369     }
8370 }
8371 
8372 
8373 /**************************************************************************/
8374 /*                                                                        */
8375 /*  FUNCTION                                               RELEASE        */
8376 /*                                                                        */
8377 /*    _nx_dhcp_move_string                                PORTABLE C      */
8378 /*                                                           6.1          */
8379 /*  AUTHOR                                                                */
8380 /*                                                                        */
8381 /*    Yuxin Zhou, Microsoft Corporation                                   */
8382 /*                                                                        */
8383 /*  DESCRIPTION                                                           */
8384 /*                                                                        */
8385 /*    This function stores a sequence of data bytes to a buffer.          */
8386 /*                                                                        */
8387 /*  INPUT                                                                 */
8388 /*                                                                        */
8389 /*    dest                                  Pointer to destination buffer */
8390 /*    source                                Pointer to source buffer      */
8391 /*    size                                  Number of bytes to move       */
8392 /*                                                                        */
8393 /*  OUTPUT                                                                */
8394 /*                                                                        */
8395 /*    None                                                                */
8396 /*                                                                        */
8397 /*  CALLS                                                                 */
8398 /*                                                                        */
8399 /*    None                                                                */
8400 /*                                                                        */
8401 /*  CALLED BY                                                             */
8402 /*                                                                        */
8403 /*    _nx_dhcp_add_option_string            Add option string             */
8404 /*                                                                        */
8405 /*  RELEASE HISTORY                                                       */
8406 /*                                                                        */
8407 /*    DATE              NAME                      DESCRIPTION             */
8408 /*                                                                        */
8409 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8410 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8411 /*                                            resulting in version 6.1    */
8412 /*                                                                        */
8413 /**************************************************************************/
_nx_dhcp_move_string(UCHAR * dest,UCHAR * source,UINT size)8414 static VOID  _nx_dhcp_move_string(UCHAR *dest, UCHAR *source, UINT size)
8415 {
8416 
8417     /* Loop to copy all bytes.  */
8418     while (size-- > 0)
8419     {
8420 
8421         /* Copy a byte.  */
8422         *dest++ = *source++;
8423     }
8424 }
8425 
8426 
8427 /**************************************************************************/
8428 /*                                                                        */
8429 /*  FUNCTION                                               RELEASE        */
8430 /*                                                                        */
8431 /*    _nxe_dhcp_server_address_get                         PORTABLE C     */
8432 /*                                                           6.1          */
8433 /*  AUTHOR                                                                */
8434 /*                                                                        */
8435 /*    Yuxin Zhou, Microsoft Corporation                                   */
8436 /*                                                                        */
8437 /*  DESCRIPTION                                                           */
8438 /*                                                                        */
8439 /*    This function performs error checking for the DHCP server get       */
8440 /*    service.                                                            */
8441 /*                                                                        */
8442 /*  INPUT                                                                 */
8443 /*                                                                        */
8444 /*    dhcp_ptr                             Pointer to DHCP Client task    */
8445 /*    server_address                       Pointer to DHCP server address */
8446 /*                                                                        */
8447 /*  OUTPUT                                                                */
8448 /*                                                                        */
8449 /*    NX_PTR_ERROR                         Invalid pointer input          */
8450 /*    status                               Actual completion status       */
8451 /*                                                                        */
8452 /*  CALLS                                                                 */
8453 /*                                                                        */
8454 /*    _nx_dhcp_server_address_get         Actual get DHCP IP server       */
8455 /*                                           address service              */
8456 /*                                                                        */
8457 /*  CALLED BY                                                             */
8458 /*                                                                        */
8459 /*    Application code                                                    */
8460 /*                                                                        */
8461 /*  RELEASE HISTORY                                                       */
8462 /*                                                                        */
8463 /*    DATE              NAME                      DESCRIPTION             */
8464 /*                                                                        */
8465 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8466 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8467 /*                                            resulting in version 6.1    */
8468 /*                                                                        */
8469 /**************************************************************************/
_nxe_dhcp_server_address_get(NX_DHCP * dhcp_ptr,ULONG * server_address)8470 UINT _nxe_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_address)
8471 {
8472 
8473 UINT status ;
8474 
8475 
8476     if ((dhcp_ptr == NX_NULL) || (server_address == NX_NULL))
8477     {
8478         return NX_PTR_ERROR;
8479     }
8480 
8481     /* Check for appropriate caller.  */
8482     NX_THREADS_ONLY_CALLER_CHECKING
8483 
8484     status = _nx_dhcp_server_address_get(dhcp_ptr, server_address);
8485 
8486     return status;
8487 }
8488 
8489 /**************************************************************************/
8490 /*                                                                        */
8491 /*  FUNCTION                                               RELEASE        */
8492 /*                                                                        */
8493 /*    _nx_dhcp_server_address_get                         PORTABLE C      */
8494 /*                                                           6.1          */
8495 /*  AUTHOR                                                                */
8496 /*                                                                        */
8497 /*    Yuxin Zhou, Microsoft Corporation                                   */
8498 /*                                                                        */
8499 /*  DESCRIPTION                                                           */
8500 /*                                                                        */
8501 /*    This function retrieves the DHCP Client's DHCP server IP address on */
8502 /*    the first DHCP enabled interface found.                             */
8503 /*                                                                        */
8504 /*    Note that the caller should only call this service when the Client  */
8505 /*    is bound to an IP address from a DHCP server. See the               */
8506 /*    nx_dhcp_state_change_notify for notification of state changes.      */
8507 /*                                                                        */
8508 /*    If multiple interfaces are enabled for DHCP, use                    */
8509 /*    nx_dhcp_interface_server_address_get() to get the server IP address */
8510 /*    on a specified interface.                                           */
8511 /*                                                                        */
8512 /*                                                                        */
8513 /*  INPUT                                                                 */
8514 /*                                                                        */
8515 /*    dhcp_ptr                              Pointer to DHCP Client task   */
8516 /*    server_address                        Pointer to DHCP server address*/
8517 /*                                                                        */
8518 /*  OUTPUT                                                                */
8519 /*                                                                        */
8520 /*    status                                Actual completion status      */
8521 /*    NX_DHCP_NO_INTERFACES_ENABLED         No interfaces enabled for DHCP*/
8522 /*                                                                        */
8523 /*  CALLS                                                                 */
8524 /*                                                                        */
8525 /*    _nx_dhcp_interface_server_address_get Interface specific server IP  */
8526 /*                                            address get service         */
8527 /*    tx_mutex_get                          Obtain protection mutex       */
8528 /*    tx_mutex_put                          Release protection mutex      */
8529 /*                                                                        */
8530 /*  CALLED BY                                                             */
8531 /*                                                                        */
8532 /*    Application code                                                    */
8533 /*                                                                        */
8534 /*  RELEASE HISTORY                                                       */
8535 /*                                                                        */
8536 /*    DATE              NAME                      DESCRIPTION             */
8537 /*                                                                        */
8538 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8539 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8540 /*                                            resulting in version 6.1    */
8541 /*                                                                        */
8542 /**************************************************************************/
_nx_dhcp_server_address_get(NX_DHCP * dhcp_ptr,ULONG * server_address)8543 UINT _nx_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_address)
8544 {
8545 
8546 UINT i;
8547 UINT status;
8548 
8549     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
8550 
8551     /* Find the DHCP interface record.  */
8552     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
8553     {
8554 
8555         /* Check the interface record is valid.  */
8556         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
8557             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
8558         {
8559 
8560             /* Get the server address of first valid record.  */
8561             status = _nx_dhcp_interface_server_address_get(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index, server_address);
8562 
8563             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8564 
8565             return(status);
8566         }
8567     }
8568 
8569     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8570 
8571     return(NX_DHCP_NO_INTERFACES_ENABLED);
8572 }
8573 
8574 
8575 /**************************************************************************/
8576 /*                                                                        */
8577 /*  FUNCTION                                               RELEASE        */
8578 /*                                                                        */
8579 /*    _nxe_dhcp_interface_server_address_get              PORTABLE C      */
8580 /*                                                           6.1          */
8581 /*  AUTHOR                                                                */
8582 /*                                                                        */
8583 /*    Yuxin Zhou, Microsoft Corporation                                   */
8584 /*                                                                        */
8585 /*  DESCRIPTION                                                           */
8586 /*                                                                        */
8587 /*    This function performs error checking for the DHCP server get       */
8588 /*    service.                                                            */
8589 /*                                                                        */
8590 /*  INPUT                                                                 */
8591 /*                                                                        */
8592 /*    dhcp_ptr                             Pointer to DHCP Client task    */
8593 /*    iface_index                          Interface of the Server        */
8594 /*    server_address                       Pointer to DHCP server address */
8595 /*                                                                        */
8596 /*  OUTPUT                                                                */
8597 /*                                                                        */
8598 /*    status                                Completion status             */
8599 /*    NX_PTR_ERROR                          Invalid pointer input         */
8600 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
8601 /*                                                                        */
8602 /*  CALLS                                                                 */
8603 /*                                                                        */
8604 /*    _nx_dhcp_interface_server_address_get Actual get server IP address  */
8605 /*                                                                        */
8606 /*  CALLED BY                                                             */
8607 /*                                                                        */
8608 /*    Application code                                                    */
8609 /*                                                                        */
8610 /*  RELEASE HISTORY                                                       */
8611 /*                                                                        */
8612 /*    DATE              NAME                      DESCRIPTION             */
8613 /*                                                                        */
8614 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8615 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8616 /*                                            resulting in version 6.1    */
8617 /*                                                                        */
8618 /**************************************************************************/
8619 
_nxe_dhcp_interface_server_address_get(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG * server_address)8620 UINT _nxe_dhcp_interface_server_address_get(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG *server_address)
8621 {
8622 
8623 UINT status;
8624 
8625     if ((dhcp_ptr == NX_NULL) || (server_address == NX_NULL))
8626     {
8627         return NX_PTR_ERROR;
8628     }
8629 
8630     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
8631     {
8632         return NX_INVALID_INTERFACE;
8633     }
8634 
8635     /* Check for appropriate caller.  */
8636     NX_THREADS_ONLY_CALLER_CHECKING
8637 
8638     /* Call the actual reinitialize service.  */
8639     status = _nx_dhcp_interface_server_address_get(dhcp_ptr, iface_index, server_address);
8640 
8641     return status;
8642 }
8643 
8644 
8645 /**************************************************************************/
8646 /*                                                                        */
8647 /*  FUNCTION                                               RELEASE        */
8648 /*                                                                        */
8649 /*    _nx_dhcp_interface_server_address_get               PORTABLE C      */
8650 /*                                                           6.1          */
8651 /*  AUTHOR                                                                */
8652 /*                                                                        */
8653 /*    Yuxin Zhou, Microsoft Corporation                                   */
8654 /*                                                                        */
8655 /*  DESCRIPTION                                                           */
8656 /*                                                                        */
8657 /*    This function retrieves the DHCP Client's DHCP server IP address on */
8658 /*    the specified interface.                                            */
8659 /*                                                                        */
8660 /*    Note that the caller should only call this service when the Client  */
8661 /*    is in the bound state. See nx_dhcp_state_change_notify for          */
8662 /*    notification when the Client state changes.                         */
8663 /*                                                                        */
8664 /*  INPUT                                                                 */
8665 /*                                                                        */
8666 /*    dhcp_ptr                             Pointer to DHCP Client task    */
8667 /*    iface_index                          Interface of the DHCP server   */
8668 /*    server_address                       Pointer to DHCP server address */
8669 /*                                                                        */
8670 /*  OUTPUT                                                                */
8671 /*                                                                        */
8672 /*    status                               Actual completion status       */
8673 /*    NX_DHCP_NOT_BOUND                    Client state not Bound         */
8674 /*                                                                        */
8675 /*  CALLS                                                                 */
8676 /*                                                                        */
8677 /*    tx_mutex_get                          Obtain protection mutex       */
8678 /*    tx_mutex_put                          Release protection mutex      */
8679 /*    _nx_dhcp_interface_record_find        Find record for the interface */
8680 /*                                                                        */
8681 /*  CALLED BY                                                             */
8682 /*                                                                        */
8683 /*    Application code                                                    */
8684 /*                                                                        */
8685 /*  RELEASE HISTORY                                                       */
8686 /*                                                                        */
8687 /*    DATE              NAME                      DESCRIPTION             */
8688 /*                                                                        */
8689 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8690 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8691 /*                                            resulting in version 6.1    */
8692 /*                                                                        */
8693 /**************************************************************************/
_nx_dhcp_interface_server_address_get(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG * server_address)8694 UINT _nx_dhcp_interface_server_address_get(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG *server_address)
8695 {
8696 
8697 UINT    status;
8698 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
8699 
8700     /* Get the DHCP mutex.  */
8701     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
8702 
8703     /* Find the interface record.  */
8704     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
8705 
8706     /* Check status.  */
8707     if (status)
8708     {
8709 
8710         /* Release the DHCP mutex.  */
8711         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8712 
8713         return(status);
8714     }
8715 
8716     /* Check the record state.  */
8717     if (interface_record -> nx_dhcp_state >= NX_DHCP_STATE_BOUND)
8718     {
8719 
8720         /* Set the server IP address from the DHCP Client instance. */
8721         *server_address = interface_record -> nx_dhcp_server_ip;
8722         status = NX_SUCCESS;
8723     }
8724     else
8725         status = NX_DHCP_NOT_BOUND;
8726 
8727     /* Release the DHCP mutex.  */
8728     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8729 
8730     return status;
8731 }
8732 
8733 
8734 #ifdef NX_DHCP_CLIENT_SEND_ARP_PROBE
8735 /**************************************************************************/
8736 /*                                                                        */
8737 /*  FUNCTION                                               RELEASE        */
8738 /*                                                                        */
8739 /*    _nx_dhcp_ip_conflict                                PORTABLE C      */
8740 /*                                                           6.1.10       */
8741 /*  AUTHOR                                                                */
8742 /*                                                                        */
8743 /*    Yuxin Zhou, Microsoft Corporation                                   */
8744 /*                                                                        */
8745 /*  DESCRIPTION                                                           */
8746 /*                                                                        */
8747 /*    This function notifies the DHCP instance that a conflict was        */
8748 /*    detected by the NetX ARP receive packet handling routine.           */
8749 /*                                                                        */
8750 /*  INPUT                                                                 */
8751 /*                                                                        */
8752 /*    ip_ptr                                IP instance pointer           */
8753 /*    iface_index                           IP Interface Index            */
8754 /*    ip_address                            IP Address to bind to         */
8755 /*    physical_msw                          Physical address MSW          */
8756 /*    physical_lsw                          Physical address LSW          */
8757 /*                                                                        */
8758 /*  OUTPUT                                                                */
8759 /*                                                                        */
8760 /*    None                                                                */
8761 /*                                                                        */
8762 /*  CALLS                                                                 */
8763 /*                                                                        */
8764 /*    tx_event_flags_set                    Set event flags               */
8765 /*                                                                        */
8766 /*  CALLED BY                                                             */
8767 /*                                                                        */
8768 /*    NetX                                                                */
8769 /*                                                                        */
8770 /*  RELEASE HISTORY                                                       */
8771 /*                                                                        */
8772 /*    DATE              NAME                      DESCRIPTION             */
8773 /*                                                                        */
8774 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8775 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8776 /*                                            resulting in version 6.1    */
8777 /*  01-31-2022     Yuxin Zhou               Modified comment(s), supported*/
8778 /*                                            multiple client instances,  */
8779 /*                                            resulting in version 6.1.10 */
8780 /*                                                                        */
8781 /**************************************************************************/
_nx_dhcp_ip_conflict(NX_IP * ip_ptr,UINT iface_index,ULONG ip_address,ULONG physical_msw,ULONG physical_lsw)8782 VOID  _nx_dhcp_ip_conflict(NX_IP *ip_ptr, UINT iface_index, ULONG ip_address, ULONG physical_msw, ULONG physical_lsw)
8783 {
8784 
8785 TX_INTERRUPT_SAVE_AREA
8786 
8787 NX_DHCP *dhcp_ptr;
8788 
8789     NX_PARAMETER_NOT_USED(ip_address);
8790     NX_PARAMETER_NOT_USED(physical_msw);
8791     NX_PARAMETER_NOT_USED(physical_lsw);
8792 
8793     /* Disable interrupts.  */
8794     TX_DISABLE
8795 
8796     /* Find the DHCP client.  */
8797     for (dhcp_ptr = _nx_dhcp_created_ptr; dhcp_ptr; dhcp_ptr = dhcp_ptr -> nx_dhcp_created_next)
8798     {
8799         if (dhcp_ptr -> nx_dhcp_ip_ptr == ip_ptr)
8800         {
8801 
8802             /* Set the interface index.  */
8803             dhcp_ptr -> nx_dhcp_interface_conflict_flag |= (UINT)(1 << iface_index);
8804 
8805             /* Set the address conflict event flag.  */
8806             tx_event_flags_set(&(_nx_dhcp_created_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_CONFLICT_EVENT, TX_OR);
8807 
8808             break;
8809         }
8810     }
8811 
8812     /* Restore interrupts.  */
8813     TX_RESTORE
8814 
8815 }
8816 #endif
8817 
8818 
8819 /**************************************************************************/
8820 /*                                                                        */
8821 /*  FUNCTION                                               RELEASE        */
8822 /*                                                                        */
8823 /*    _nxe_dhcp_set_interface_index                       PORTABLE C      */
8824 /*                                                           6.1          */
8825 /*  AUTHOR                                                                */
8826 /*                                                                        */
8827 /*    Yuxin Zhou, Microsoft Corporation                                   */
8828 /*                                                                        */
8829 /*  DESCRIPTION                                                           */
8830 /*                                                                        */
8831 /*    This function does error checking for the set interface index call. */
8832 /*                                                                        */
8833 /*  INPUT                                                                 */
8834 /*                                                                        */
8835 /*    dhcp_ptr                              Pointer to DHCP instance      */
8836 /*    interface_index                       Interface the DHCP Client task*/
8837 /*                                                is associated with      */
8838 /*                                                                        */
8839 /*  OUTPUT                                                                */
8840 /*                                                                        */
8841 /*    status                                Completion status             */
8842 /*    NX_PTR_ERROR                          Invalid pointer input         */
8843 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
8844 /*                                                                        */
8845 /*  CALLS                                                                 */
8846 /*                                                                        */
8847 /*    _nx_dhcp_set_interface_index           Actual set interface index   */
8848 /*                                                                        */
8849 /*  CALLED BY                                                             */
8850 /*                                                                        */
8851 /*    Application Code                                                    */
8852 /*                                                                        */
8853 /*  RELEASE HISTORY                                                       */
8854 /*                                                                        */
8855 /*    DATE              NAME                      DESCRIPTION             */
8856 /*                                                                        */
8857 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8858 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8859 /*                                            resulting in version 6.1    */
8860 /*                                                                        */
8861 /**************************************************************************/
_nxe_dhcp_set_interface_index(NX_DHCP * dhcp_ptr,UINT interface_index)8862 UINT _nxe_dhcp_set_interface_index(NX_DHCP *dhcp_ptr, UINT interface_index)
8863 {
8864 
8865 UINT status;
8866 
8867 
8868     /* Check for invalid pointer input. */
8869     if (dhcp_ptr == NX_NULL)
8870     {
8871 
8872         return(NX_PTR_ERROR);
8873     }
8874     /* Check for invalid non pointer input. */
8875     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
8876     {
8877 
8878         return(NX_INVALID_INTERFACE);
8879     }
8880 
8881     /* Call the actual set DHCP Client interface service */
8882     status = _nx_dhcp_set_interface_index(dhcp_ptr,  interface_index);
8883 
8884     /* Return completion status. */
8885     return(status);
8886 }
8887 
8888 
8889 /**************************************************************************/
8890 /*                                                                        */
8891 /*  FUNCTION                                               RELEASE        */
8892 /*                                                                        */
8893 /*    _nx_dhcp_set_interface_index                        PORTABLE C      */
8894 /*                                                           6.1          */
8895 /*  AUTHOR                                                                */
8896 /*                                                                        */
8897 /*    Yuxin Zhou, Microsoft Corporation                                   */
8898 /*                                                                        */
8899 /*  DESCRIPTION                                                           */
8900 /*                                                                        */
8901 /*    This function enables DHCP on the specified interface. This function*/
8902 /*    should be called before the DHCP Client is started. The intended use*/
8903 /*    of this function is for DHCP to run on only one interface. To enable*/
8904 /*    multiple interfaces for DHCP, use the nx_dhcp_interface_enable      */
8905 /*    service.                                                            */
8906 /*                                                                        */
8907 /*  INPUT                                                                 */
8908 /*                                                                        */
8909 /*    dhcp_ptr                              Pointer to DHCP instance      */
8910 /*    iface_index                           Interface to enable DHCP on   */
8911 /*                                                                        */
8912 /*  OUTPUT                                                                */
8913 /*                                                                        */
8914 /*    NX_SUCCESS                            Successful Completion status  */
8915 /*                                                                        */
8916 /*  CALLS                                                                 */
8917 /*                                                                        */
8918 /*   _nx_dhcp_interface_enable              Enable DHCP on interface      */
8919 /*    tx_mutex_get                          Obtain protection mutex       */
8920 /*    tx_mutex_put                          Release protection mutex      */
8921 /*                                                                        */
8922 /*  CALLED BY                                                             */
8923 /*                                                                        */
8924 /*    Application Code                                                    */
8925 /*                                                                        */
8926 /*  RELEASE HISTORY                                                       */
8927 /*                                                                        */
8928 /*    DATE              NAME                      DESCRIPTION             */
8929 /*                                                                        */
8930 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8931 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8932 /*                                            resulting in version 6.1    */
8933 /*                                                                        */
8934 /**************************************************************************/
_nx_dhcp_set_interface_index(NX_DHCP * dhcp_ptr,UINT iface_index)8935 UINT _nx_dhcp_set_interface_index(NX_DHCP *dhcp_ptr, UINT iface_index)
8936 {
8937 
8938 UINT    i;
8939 UINT    status;
8940 
8941 
8942     /* Get the DHCP mutex.  */
8943     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), NX_WAIT_FOREVER);
8944 
8945     /* Invalidate all the interfaces enabled for DHCP. */
8946     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
8947     {
8948 
8949         /* Invalidate this interface.  */
8950         dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid = NX_FALSE;
8951 
8952         /* Change the state.  */
8953         dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state = NX_DHCP_STATE_NOT_STARTED;
8954     }
8955 
8956     /* Enable DHCP on this interface.  */
8957     status = _nx_dhcp_interface_enable(dhcp_ptr, iface_index);
8958 
8959     /* Release the DHCP mutex.  */
8960     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
8961 
8962     return(status);
8963 }
8964 
8965 
8966 /**************************************************************************/
8967 /*                                                                        */
8968 /*  FUNCTION                                               RELEASE        */
8969 /*                                                                        */
8970 /*    _nx_dhcp_interface_record_find                      PORTABLE C      */
8971 /*                                                           6.1          */
8972 /*  AUTHOR                                                                */
8973 /*                                                                        */
8974 /*    Yuxin Zhou, Microsoft Corporation                                   */
8975 /*                                                                        */
8976 /*  DESCRIPTION                                                           */
8977 /*                                                                        */
8978 /*    Find the Client record that is assigned to the input interface      */
8979 /*    index, and return a pointer to that record. The interface index must*/
8980 /*    match the interface index of the Client record, and the interface   */
8981 /*    must be enabled for DHCP.  If no matching records are found, an     */
8982 /*    error status is returned, and the interface record pointer is NULL. */
8983 /*                                                                        */
8984 /*  INPUT                                                                 */
8985 /*                                                                        */
8986 /*    dhcp_ptr                              Pointer to DHCP instance      */
8987 /*    interface_index                       Interface to find             */
8988 /*                                                                        */
8989 /*  OUTPUT                                                                */
8990 /*                                                                        */
8991 /*    NX_SUCCESS                            Successful completion         */
8992 /*    NX_DHCP_INTERFACE_NOT_ENABLED         No matching record found      */
8993 /*                                                                        */
8994 /*  CALLS                                                                 */
8995 /*       None                                                             */
8996 /*                                                                        */
8997 /*  CALLED BY                                                             */
8998 /*                                                                        */
8999 /*    Application Code                                                    */
9000 /*                                                                        */
9001 /*  RELEASE HISTORY                                                       */
9002 /*                                                                        */
9003 /*    DATE              NAME                      DESCRIPTION             */
9004 /*                                                                        */
9005 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9006 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9007 /*                                            resulting in version 6.1    */
9008 /*                                                                        */
9009 /**************************************************************************/
_nx_dhcp_interface_record_find(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_INTERFACE_RECORD ** interface_record)9010 static UINT _nx_dhcp_interface_record_find(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_INTERFACE_RECORD **interface_record)
9011 {
9012 
9013 UINT i;
9014 
9015     /* Find which DHCP Client interface record is assigned the input interface. */
9016     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
9017     {
9018 
9019         /* Check if this record is valid.  */
9020         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid == NX_FALSE)
9021             continue;
9022 
9023         /* Check if the interface index matches.  */
9024         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index == iface_index)
9025         {
9026 
9027             /* Yes, we found the record.  */
9028             *interface_record = &dhcp_ptr -> nx_dhcp_interface_record[i];
9029 
9030             /* Return.  */
9031             return (NX_SUCCESS);
9032         }
9033     }
9034 
9035     /* No matching record found.  */
9036     return (NX_DHCP_INTERFACE_NOT_ENABLED);
9037 }
9038 
9039 
9040 #ifdef NX_DHCP_CLIENT_RESTORE_STATE
9041 /**************************************************************************/
9042 /*                                                                        */
9043 /*  FUNCTION                                               RELEASE        */
9044 /*                                                                        */
9045 /*    _nxe_dhcp_client_get_record                          PORTABLE C     */
9046 /*                                                           6.1          */
9047 /*  AUTHOR                                                                */
9048 /*                                                                        */
9049 /*    Yuxin Zhou, Microsoft Corporation                                   */
9050 /*                                                                        */
9051 /*  DESCRIPTION                                                           */
9052 /*                                                                        */
9053 /*    This function performs error checking on the get DHCP Client record */
9054 /*    service.                                                            */
9055 /*                                                                        */
9056 /*  INPUT                                                                 */
9057 /*                                                                        */
9058 /*    dhcp_ptr                              Pointer to DHCP instance      */
9059 /*    client_record_ptr                     Pointer to memory to save     */
9060 /*                                             Client record to           */
9061 /*                                                                        */
9062 /*  OUTPUT                                                                */
9063 /*                                                                        */
9064 /*    NX_PTR_ERROR                          Invalid pointer input         */
9065 /*    status                                Completion status from        */
9066 /*                                            internal DHCP calls         */
9067 /*                                                                        */
9068 /*  CALLS                                                                 */
9069 /*                                                                        */
9070 /*   _nx_dhcp_client_create_record                                        */
9071 /*                                                                        */
9072 /*  CALLED BY                                                             */
9073 /*                                                                        */
9074 /*    Application code                                                    */
9075 /*                                                                        */
9076 /*  RELEASE HISTORY                                                       */
9077 /*                                                                        */
9078 /*    DATE              NAME                      DESCRIPTION             */
9079 /*                                                                        */
9080 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9081 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9082 /*                                            resulting in version 6.1    */
9083 /*                                                                        */
9084 /**************************************************************************/
_nxe_dhcp_client_get_record(NX_DHCP * dhcp_ptr,NX_DHCP_CLIENT_RECORD * client_record_ptr)9085 UINT  _nxe_dhcp_client_get_record(NX_DHCP *dhcp_ptr, NX_DHCP_CLIENT_RECORD *client_record_ptr)
9086 {
9087 
9088 UINT status;
9089 
9090     if ((dhcp_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
9091     {
9092         return NX_PTR_ERROR;
9093     }
9094 
9095     status = _nx_dhcp_client_get_record(dhcp_ptr, client_record_ptr);
9096 
9097     return status;
9098 }
9099 
9100 
9101 /**************************************************************************/
9102 /*                                                                        */
9103 /*  FUNCTION                                               RELEASE        */
9104 /*                                                                        */
9105 /*    _nx_dhcp_client_get_record                          PORTABLE C      */
9106 /*                                                           6.1          */
9107 /*  AUTHOR                                                                */
9108 /*                                                                        */
9109 /*    Yuxin Zhou, Microsoft Corporation                                   */
9110 /*                                                                        */
9111 /*  DESCRIPTION                                                           */
9112 /*                                                                        */
9113 /*    This function creates a DHCP Client record for restoring the Client */
9114 /*    state between power cycles or idle (sleep) mode.  It copies the     */
9115 /*    first DHCP enabled Client record found to the supplied client record*/
9116 /*    pointer. If DHCP is enabled on multiple interfaces, use             */
9117 /*    nx_dhcp_client_interface_record_get to get a record of a specific   */
9118 /*    interface.                                                          */
9119 /*                                                                        */
9120 /*  INPUT                                                                 */
9121 /*                                                                        */
9122 /*    dhcp_ptr                              Pointer to DHCP instance      */
9123 /*    client_record_ptr                     Pointer to Client record      */
9124 /*                                                                        */
9125 /*  OUTPUT                                                                */
9126 /*                                                                        */
9127 /*    status                                Completion status             */
9128 /*    NX_DHCP_NO_INTERFACES_ENABLED         No DHCP interface enabled     */
9129 /*                                                                        */
9130 /*  CALLS                                                                 */
9131 /*                                                                        */
9132 /*   _nx_dhcp_client_interface_get_record   Get record for specified index*/
9133 /*    tx_mutex_get                          Obtain protection mutex       */
9134 /*    tx_mutex_put                          Release protection mutex      */
9135 /*                                                                        */
9136 /*  CALLED BY                                                             */
9137 /*                                                                        */
9138 /*    Application code                                                    */
9139 /*                                                                        */
9140 /*  RELEASE HISTORY                                                       */
9141 /*                                                                        */
9142 /*    DATE              NAME                      DESCRIPTION             */
9143 /*                                                                        */
9144 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9145 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9146 /*                                            resulting in version 6.1    */
9147 /*                                                                        */
9148 /**************************************************************************/
_nx_dhcp_client_get_record(NX_DHCP * dhcp_ptr,NX_DHCP_CLIENT_RECORD * client_record_ptr)9149 UINT  _nx_dhcp_client_get_record(NX_DHCP *dhcp_ptr, NX_DHCP_CLIENT_RECORD *client_record_ptr)
9150 {
9151 
9152 UINT i;
9153 UINT status;
9154 
9155 
9156     /* Obtain DHCP Client protection mutex. */
9157     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9158 
9159     /* Find the DHCP interface record.  */
9160     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
9161     {
9162 
9163         /* Check if the interface record is valid.  */
9164         if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid) &&
9165             (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state >= NX_DHCP_STATE_BOUND))
9166         {
9167 
9168             /* Find a record of the current state of the DHCP CLient. */
9169             status = _nx_dhcp_client_interface_get_record(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index, client_record_ptr);
9170 
9171             /* Release the DHCP mutex.  */
9172             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9173             return(status);
9174         }
9175     }
9176 
9177     /* Release the DHCP mutex.  */
9178     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9179     return(NX_DHCP_NO_INTERFACES_ENABLED);
9180 }
9181 
9182 
9183 /**************************************************************************/
9184 /*                                                                        */
9185 /*  FUNCTION                                               RELEASE        */
9186 /*                                                                        */
9187 /*    _nxe_dhcp_client_interface_get_record               PORTABLE C      */
9188 /*                                                           6.1          */
9189 /*  AUTHOR                                                                */
9190 /*                                                                        */
9191 /*    Yuxin Zhou, Microsoft Corporation                                   */
9192 /*                                                                        */
9193 /*  DESCRIPTION                                                           */
9194 /*                                                                        */
9195 /*    This function performs error checking on the get DHCP Client        */
9196 /*    interface record service.                                           */
9197 /*                                                                        */
9198 /*  INPUT                                                                 */
9199 /*                                                                        */
9200 /*    dhcp_ptr                              Pointer to DHCP instance      */
9201 /*    iface_index                           Interface index               */
9202 /*    client_record_ptr                     Pointer to memory to save     */
9203 /*                                             Client record to           */
9204 /*                                                                        */
9205 /*  OUTPUT                                                                */
9206 /*                                                                        */
9207 /*    status                                Completion status             */
9208 /*    NX_PTR_ERROR                          Invalid pointer input         */
9209 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
9210 /*                                                                        */
9211 /*  CALLS                                                                 */
9212 /*                                                                        */
9213 /*   _nx_dhcp_client_interface_create_record                              */
9214 /*                                                                        */
9215 /*  CALLED BY                                                             */
9216 /*                                                                        */
9217 /*    Application code                                                    */
9218 /*                                                                        */
9219 /*  RELEASE HISTORY                                                       */
9220 /*                                                                        */
9221 /*    DATE              NAME                      DESCRIPTION             */
9222 /*                                                                        */
9223 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9224 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9225 /*                                            resulting in version 6.1    */
9226 /*                                                                        */
9227 /**************************************************************************/
_nxe_dhcp_client_interface_get_record(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_CLIENT_RECORD * client_record_ptr)9228 UINT  _nxe_dhcp_client_interface_get_record(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_CLIENT_RECORD *client_record_ptr)
9229 {
9230 
9231 UINT status;
9232 
9233     /* Check for invalid input pointers.  */
9234     if ((dhcp_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
9235     {
9236         return NX_PTR_ERROR;
9237     }
9238 
9239     /* Check interface index.  */
9240     if (iface_index >= NX_DHCP_CLIENT_MAX_RECORDS)
9241     {
9242         return NX_INVALID_INTERFACE;
9243     }
9244 
9245     status = _nx_dhcp_client_interface_get_record(dhcp_ptr, iface_index, client_record_ptr);
9246 
9247     return status;
9248 }
9249 
9250 
9251 /**************************************************************************/
9252 /*                                                                        */
9253 /*  FUNCTION                                               RELEASE        */
9254 /*                                                                        */
9255 /*    _nx_dhcp_client_interface_get_record                PORTABLE C      */
9256 /*                                                           6.1          */
9257 /*  AUTHOR                                                                */
9258 /*                                                                        */
9259 /*    Yuxin Zhou, Microsoft Corporation                                   */
9260 /*                                                                        */
9261 /*  DESCRIPTION                                                           */
9262 /*                                                                        */
9263 /*    This function creates a DHCP Client record for restoring the Client */
9264 /*    state between power cycles or idle (sleep) mode.  It then copies the*/
9265 /*    Client record to the supplied client record pointer.                */
9266 /*                                                                        */
9267 /*    The DHCP Client state should be restored from a Client record saved */
9268 /*    to memory (client_record_ptr).                                      */
9269 /*                                                                        */
9270 /*  INPUT                                                                 */
9271 /*                                                                        */
9272 /*    dhcp_ptr                              Pointer to DHCP instance      */
9273 /*    iface_index                           Interface index               */
9274 /*    client_record_ptr                     Pointer to memory to save     */
9275 /*                                             Client record to           */
9276 /*                                                                        */
9277 /*  OUTPUT                                                                */
9278 /*                                                                        */
9279 /*    NX_DHCP_NOT_BOUND                     Client not Bound to address   */
9280 /*    status                                Actual completion status      */
9281 /*                                                                        */
9282 /*  CALLS                                                                 */
9283 /*                                                                        */
9284 /*   _nx_dhcp_interface_record_find         Find interface record matching*/
9285 /*                                             the input interface        */
9286 /*    tx_mutex_get                          Obtain protection mutex       */
9287 /*    tx_mutex_put                          Release protection mutex      */
9288 /*                                                                        */
9289 /*  CALLED BY                                                             */
9290 /*                                                                        */
9291 /*    Application code                                                    */
9292 /*                                                                        */
9293 /*  RELEASE HISTORY                                                       */
9294 /*                                                                        */
9295 /*    DATE              NAME                      DESCRIPTION             */
9296 /*                                                                        */
9297 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9298 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9299 /*                                            resulting in version 6.1    */
9300 /*                                                                        */
9301 /**************************************************************************/
_nx_dhcp_client_interface_get_record(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_CLIENT_RECORD * client_record_ptr)9302 UINT  _nx_dhcp_client_interface_get_record(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_CLIENT_RECORD *client_record_ptr)
9303 {
9304 
9305 UINT                      status;
9306 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
9307 
9308 
9309     /* Obtain DHCP Client protection mutex. */
9310     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9311 
9312     /* Find the interface record.  */
9313     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
9314 
9315     /* Check status.  */
9316     if (status)
9317     {
9318 
9319         /* Release the DHCP mutex.  */
9320         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9321         return(status);
9322     }
9323 
9324     /* Check the state.  */
9325     if (interface_record -> nx_dhcp_state < NX_DHCP_STATE_BOUND)
9326     {
9327 
9328         /* The DHCP Client is not bound to an IP address. Cannot create a record for restoring Client
9329            state if the Client not bound to an IP address. */
9330 
9331         /* Release the DHCP mutex.  */
9332         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9333         return NX_DHCP_NOT_BOUND;
9334     }
9335 
9336     /* Clear memory before filling with data. */
9337     memset(client_record_ptr, 0, sizeof(NX_DHCP_CLIENT_RECORD));
9338 
9339     /* Set the record.  */
9340     client_record_ptr -> nx_dhcp_state = interface_record -> nx_dhcp_state;
9341     client_record_ptr -> nx_dhcp_ip_address = interface_record -> nx_dhcp_ip_address;           /* Server assigned IP Address                               */
9342     client_record_ptr -> nx_dhcp_network_mask = interface_record -> nx_dhcp_network_mask;       /* Server assigned network mask                             */
9343     client_record_ptr -> nx_dhcp_gateway_address = interface_record -> nx_dhcp_gateway_address;
9344     client_record_ptr -> nx_dhcp_server_ip = interface_record -> nx_dhcp_server_ip;
9345     client_record_ptr -> nx_dhcp_timeout = interface_record -> nx_dhcp_timeout;
9346     client_record_ptr -> nx_dhcp_lease_time = interface_record -> nx_dhcp_lease_time ;
9347     client_record_ptr -> nx_dhcp_renewal_time = interface_record -> nx_dhcp_renewal_time;
9348     client_record_ptr -> nx_dhcp_rebind_time = interface_record -> nx_dhcp_rebind_time;
9349     client_record_ptr -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_renewal_remain_time;
9350     client_record_ptr -> nx_dhcp_rebind_remain_time = interface_record -> nx_dhcp_rebind_remain_time;
9351     client_record_ptr -> nx_dhcp_interface_index = interface_record -> nx_dhcp_interface_index;
9352 
9353     /* Release the DHCP mutex.  */
9354     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9355 
9356     return(NX_SUCCESS);
9357 }
9358 
9359 
9360 /**************************************************************************/
9361 /*                                                                        */
9362 /*  FUNCTION                                               RELEASE        */
9363 /*                                                                        */
9364 /*    _nxe_dhcp_client_restore_record                     PORTABLE C      */
9365 /*                                                           6.1          */
9366 /*  AUTHOR                                                                */
9367 /*                                                                        */
9368 /*    Yuxin Zhou, Microsoft Corporation                                   */
9369 /*                                                                        */
9370 /*  DESCRIPTION                                                           */
9371 /*                                                                        */
9372 /*    This function performs error checking on the client restore service.*/
9373 /*                                                                        */
9374 /*  INPUT                                                                 */
9375 /*                                                                        */
9376 /*    dhcp_ptr                              Pointer to DHCP instance      */
9377 /*    client_record_ptr                     Pointer to previously saved   */
9378 /*                                             Client record              */
9379 /*    time_elapsed                          Time elapsed in timer ticks   */
9380 /*                                                                        */
9381 /*  OUTPUT                                                                */
9382 /*                                                                        */
9383 /*    NX_PTR_ERRPR                          Invalid pointer input         */
9384 /*    status                                NetX completion status        */
9385 /*                                                                        */
9386 /*  CALLS                                                                 */
9387 /*                                                                        */
9388 /*   _nx_dhcp_client_restore_record         Actual restore record service */
9389 /*                                                                        */
9390 /*  CALLED BY                                                             */
9391 /*                                                                        */
9392 /*    Application code                                                    */
9393 /*                                                                        */
9394 /*  RELEASE HISTORY                                                       */
9395 /*                                                                        */
9396 /*    DATE              NAME                      DESCRIPTION             */
9397 /*                                                                        */
9398 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9399 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9400 /*                                            resulting in version 6.1    */
9401 /*                                                                        */
9402 /**************************************************************************/
_nxe_dhcp_client_restore_record(NX_DHCP * dhcp_ptr,NX_DHCP_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)9403 UINT  _nxe_dhcp_client_restore_record(NX_DHCP *dhcp_ptr, NX_DHCP_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
9404 {
9405 
9406 UINT status;
9407 
9408 
9409     if ((dhcp_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
9410     {
9411         return NX_PTR_ERROR;
9412     }
9413 
9414     /* Note: zero time elapsed is an acceptable value. */
9415 
9416     status = _nx_dhcp_client_restore_record(dhcp_ptr, client_record_ptr, time_elapsed);
9417 
9418     return status;
9419 }
9420 
9421 
9422 /**************************************************************************/
9423 /*                                                                        */
9424 /*  FUNCTION                                               RELEASE        */
9425 /*                                                                        */
9426 /*    _nx_dhcp_client_restore_record                      PORTABLE C      */
9427 /*                                                           6.1          */
9428 /*  AUTHOR                                                                */
9429 /*                                                                        */
9430 /*    Yuxin Zhou, Microsoft Corporation                                   */
9431 /*                                                                        */
9432 /*  DESCRIPTION                                                           */
9433 /*                                                                        */
9434 /*    This function updates the DHCP Client state of the first DHCP       */
9435 /*    enabled interface found with the supplied DHCP Client record        */
9436 /*    pointed to by the client_record_ptr pointer. It then updates the    */
9437 /*    time out parameters of the DHCP Client with the time_elapsed        */
9438 /*    input (in timer ticks).                                             */
9439 /*                                                                        */
9440 /*    If DHCP is enabled on multiple interfaces, use                      */
9441 /*    nx_dhcp_client_interface_restore_record to restore a record to a    */
9442 /*    specific interface.                                                 */
9443 /*                                                                        */
9444 /*    This function is intended for restoring Client state between reboots*/
9445 /*    and assumes the DHCP Client state was previously obtained and stored*/
9446 /*    in non volatile memory before power down.                           */
9447 /*                                                                        */
9448 /*    Note: his should not be called in addition to _nx_dhcp_client_update*/
9449 /*    _time_remaining.  _nx_dhcp_client_restore_ calls that function,     */
9450 /*    so calling t_nx_dhcp_client_update_time_remaining separately would  */
9451 /*    effectively apply the time elapsed a second time.                   */
9452 /*                                                                        */
9453 /*  INPUT                                                                 */
9454 /*                                                                        */
9455 /*    dhcp_ptr                              Pointer to DHCP instance      */
9456 /*    client_record_ptr                     Pointer to previously saved   */
9457 /*                                             Client record              */
9458 /*    time_elapsed                          time input in timer ticks     */
9459 /*                                                                        */
9460 /*  OUTPUT                                                                */
9461 /*                                                                        */
9462 /*    NX_DHCP_NO_INTERFACES_ENABLED         No interfaces enabled for DHCP*/
9463 /*    status                                NetX completion status        */
9464 /*                                                                        */
9465 /*  CALLS                                                                 */
9466 /*                                                                        */
9467 /*   _nx_dhcp_client_interface_restore_record                             */
9468 /*                                          Interface specific restore    */
9469 /*    tx_mutex_get                          Obtain protection mutex       */
9470 /*    tx_mutex_put                          Release protection mutex      */
9471 /*                                                                        */
9472 /*  CALLED BY                                                             */
9473 /*                                                                        */
9474 /*    Application code                                                    */
9475 /*                                                                        */
9476 /*  RELEASE HISTORY                                                       */
9477 /*                                                                        */
9478 /*    DATE              NAME                      DESCRIPTION             */
9479 /*                                                                        */
9480 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9481 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9482 /*                                            resulting in version 6.1    */
9483 /*                                                                        */
9484 /**************************************************************************/
_nx_dhcp_client_restore_record(NX_DHCP * dhcp_ptr,NX_DHCP_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)9485 UINT  _nx_dhcp_client_restore_record(NX_DHCP *dhcp_ptr, NX_DHCP_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
9486 {
9487 
9488 UINT    i;
9489 UINT    status;
9490 
9491 
9492     /* Obtain DHCP Client protection mutex. */
9493     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9494 
9495     /* Find the DHCP interface record.  */
9496     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
9497     {
9498 
9499         /* Check which interface record is valid.  */
9500         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
9501         {
9502 
9503             /* Create a record of the current state of the DHCP Client. */
9504             status = _nx_dhcp_client_interface_restore_record(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index,
9505                                                               client_record_ptr, time_elapsed);
9506 
9507             /* Release the DHCP mutex.  */
9508             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9509             return(status);
9510         }
9511     }
9512 
9513     /* Release the DHCP mutex.  */
9514     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9515     return(NX_DHCP_NO_INTERFACES_ENABLED);
9516 }
9517 
9518 
9519 /**************************************************************************/
9520 /*                                                                        */
9521 /*  FUNCTION                                               RELEASE        */
9522 /*                                                                        */
9523 /*    _nxe_dhcp_client_interface_restore_record           PORTABLE C      */
9524 /*                                                           6.1          */
9525 /*  AUTHOR                                                                */
9526 /*                                                                        */
9527 /*    Yuxin Zhou, Microsoft Corporation                                   */
9528 /*                                                                        */
9529 /*  DESCRIPTION                                                           */
9530 /*                                                                        */
9531 /*    This function performs error checking on the client restore service.*/
9532 /*                                                                        */
9533 /*  INPUT                                                                 */
9534 /*                                                                        */
9535 /*    dhcp_ptr                              Pointer to DHCP instance      */
9536 /*    iface_index                           Interface index               */
9537 /*    client_record_ptr                     Pointer to previously saved   */
9538 /*                                             Client record              */
9539 /*    time_elapsed                          time input in timer ticks     */
9540 /*                                                                        */
9541 /*  OUTPUT                                                                */
9542 /*                                                                        */
9543 /*    NX_PTR_ERRPR                          Invalid pointer input         */
9544 /*    status                                NetX completion status        */
9545 /*                                                                        */
9546 /*  CALLS                                                                 */
9547 /*                                                                        */
9548 /*   _nx_dhcp_client_interface_restore_record                             */
9549 /*                                                                        */
9550 /*  CALLED BY                                                             */
9551 /*                                                                        */
9552 /*    Application code                                                    */
9553 /*                                                                        */
9554 /*  RELEASE HISTORY                                                       */
9555 /*                                                                        */
9556 /*    DATE              NAME                      DESCRIPTION             */
9557 /*                                                                        */
9558 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9559 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9560 /*                                            resulting in version 6.1    */
9561 /*                                                                        */
9562 /**************************************************************************/
_nxe_dhcp_client_interface_restore_record(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)9563 UINT  _nxe_dhcp_client_interface_restore_record(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
9564 {
9565 
9566 UINT status;
9567 
9568 
9569     /* Check for invalid input pointers.  */
9570     if ((dhcp_ptr == NX_NULL) || (client_record_ptr == NX_NULL))
9571     {
9572         return NX_PTR_ERROR;
9573     }
9574 
9575     /* Check interface index.  */
9576     if (iface_index >= NX_DHCP_CLIENT_MAX_RECORDS)
9577     {
9578         return NX_INVALID_INTERFACE;
9579     }
9580 
9581     status = _nx_dhcp_client_interface_restore_record(dhcp_ptr, iface_index, client_record_ptr, time_elapsed);
9582 
9583     return status;
9584 }
9585 
9586 
9587 /**************************************************************************/
9588 /*                                                                        */
9589 /*  FUNCTION                                               RELEASE        */
9590 /*                                                                        */
9591 /*    _nx_dhcp_client_interface_restore_record            PORTABLE C      */
9592 /*                                                           6.1          */
9593 /*  AUTHOR                                                                */
9594 /*                                                                        */
9595 /*    Yuxin Zhou, Microsoft Corporation                                   */
9596 /*                                                                        */
9597 /*  DESCRIPTION                                                           */
9598 /*                                                                        */
9599 /*    This function updates the DHCP Client state with the input DHCP     */
9600 /*    Client record for the specified interface. It copies data from the  */
9601 /*    Client record to the interface racord, and updates the time out     */
9602 /*    parameters of the DHCP Client with the time_elapsed inpur (in timer */
9603 /*    ticks).                                                             */
9604 /*                                                                        */
9605 /*    This function is intended for restoring Client state between reboots*/
9606 /*    and assumes the DHCP Client record was previously obtained and      */
9607 /*    stored in non volatile memory before power down.                    */
9608 /*                                                                        */
9609 /*    Note: this should not be called in addition to                      */
9610 /*    nx_dhcp_client_update_time_remaining.                               */
9611 /*    nx_dhcp_client_interface_restore_record calls that function, so     */
9612 /*    calling nx_dhcp_client_update_time_remaining would apply the time   */
9613 /*    elapsed a second time.                                              */
9614 /*                                                                        */
9615 /*  INPUT                                                                 */
9616 /*                                                                        */
9617 /*    dhcp_ptr                              Pointer to DHCP instance      */
9618 /*    client_record_ptr                     Pointer to previously saved   */
9619 /*                                             Client record              */
9620 /*    time_elapsed                          time input in timer ticks     */
9621 /*                                                                        */
9622 /*  OUTPUT                                                                */
9623 /*                                                                        */
9624 /*    NX_SUCCESS                            Successful completion status  */
9625 /*    status                                NetX completion status        */
9626 /*                                                                        */
9627 /*  CALLS                                                                 */
9628 /*                                                                        */
9629 /*    tx_mutex_get                          Obtain protection mutex       */
9630 /*    tx_mutex_put                          Release protection mutex      */
9631 /*   _nx_dhcp_interface_record_find         Find client record for        */
9632 /*                                            specified interface         */
9633 /*    nx_ip_interface_address_set           Set IP interface address      */
9634 /*   _nx_dhcp_client_update_time_remaining  Update time remaining for time*/
9635 /*                                            elapsed while powered down  */
9636 /*                                                                        */
9637 /*  CALLED BY                                                             */
9638 /*                                                                        */
9639 /*    Application code                                                    */
9640 /*                                                                        */
9641 /*  RELEASE HISTORY                                                       */
9642 /*                                                                        */
9643 /*    DATE              NAME                      DESCRIPTION             */
9644 /*                                                                        */
9645 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9646 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
9647 /*                                            restored the gateway        */
9648 /*                                            address,                    */
9649 /*                                            resulting in version 6.1    */
9650 /*                                                                        */
9651 /**************************************************************************/
_nx_dhcp_client_interface_restore_record(NX_DHCP * dhcp_ptr,UINT iface_index,NX_DHCP_CLIENT_RECORD * client_record_ptr,ULONG time_elapsed)9652 UINT  _nx_dhcp_client_interface_restore_record(NX_DHCP *dhcp_ptr, UINT iface_index, NX_DHCP_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed)
9653 {
9654 
9655 UINT    status;
9656 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
9657 
9658     /* Obtain DHCP Client protection mutex. */
9659     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9660 
9661     /* Find the interface record.  */
9662     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
9663 
9664     /* Check status.  */
9665     if (status)
9666     {
9667 
9668         /* Release the DHCP mutex.  */
9669         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9670         return(status);
9671     }
9672 
9673     interface_record -> nx_dhcp_state = client_record_ptr -> nx_dhcp_state;
9674     interface_record -> nx_dhcp_gateway_address = client_record_ptr -> nx_dhcp_gateway_address;
9675     interface_record -> nx_dhcp_server_ip = client_record_ptr -> nx_dhcp_server_ip;
9676     interface_record -> nx_dhcp_timeout = client_record_ptr -> nx_dhcp_timeout;
9677     interface_record -> nx_dhcp_lease_time = client_record_ptr -> nx_dhcp_lease_time ;
9678     interface_record -> nx_dhcp_renewal_time = client_record_ptr -> nx_dhcp_renewal_time;
9679     interface_record -> nx_dhcp_rebind_time = client_record_ptr -> nx_dhcp_rebind_time;
9680     interface_record -> nx_dhcp_renewal_remain_time = client_record_ptr -> nx_dhcp_renewal_remain_time;
9681     interface_record -> nx_dhcp_rebind_remain_time = client_record_ptr -> nx_dhcp_rebind_remain_time;
9682 
9683     /* Restore directly from the client record. */
9684     interface_record -> nx_dhcp_ip_address = client_record_ptr -> nx_dhcp_ip_address;
9685     interface_record -> nx_dhcp_network_mask = client_record_ptr -> nx_dhcp_network_mask;
9686     interface_record -> nx_dhcp_interface_index = iface_index;
9687 
9688     /* Update the IP instance with saved network parameters.*/
9689     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);
9690 
9691     /* Check status.  */
9692     if (status != NX_SUCCESS)
9693     {
9694 
9695         /* Release the DHCP mutex.  */
9696         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9697         return status;
9698     }
9699 
9700     /* Check if the gateway address is valid.  */
9701     if (interface_record -> nx_dhcp_gateway_address)
9702     {
9703 
9704         /* Set the gateway address.  */
9705         status = nx_ip_gateway_address_set(dhcp_ptr -> nx_dhcp_ip_ptr, interface_record -> nx_dhcp_gateway_address);
9706 
9707         /* Check status.  */
9708         if (status != NX_SUCCESS)
9709         {
9710 
9711             /* Release the DHCP mutex.  */
9712             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9713             return(status);
9714         }
9715     }
9716 
9717     /* Now apply the time elapsed to update the DHCP Client time remaining on its lease and current DHCP state. */
9718     status = _nx_dhcp_client_interface_update_time_remaining(dhcp_ptr, interface_record-> nx_dhcp_interface_index, time_elapsed);
9719 
9720     /* Release the DHCP mutex.  */
9721     tx_mutex_put(&(dhcp_ptr->nx_dhcp_mutex));
9722 
9723     return status;
9724 }
9725 
9726 
9727 /**************************************************************************/
9728 /*                                                                        */
9729 /*  FUNCTION                                               RELEASE        */
9730 /*                                                                        */
9731 /*    _nxe_dhcp_client_update_time_remaining              PORTABLE C      */
9732 /*                                                           6.1          */
9733 /*  AUTHOR                                                                */
9734 /*                                                                        */
9735 /*    Yuxin Zhou, Microsoft Corporation                                   */
9736 /*                                                                        */
9737 /*  DESCRIPTION                                                           */
9738 /*                                                                        */
9739 /*    This function performs error checking on the update time remaining  */
9740 /*    service.                                                            */
9741 /*                                                                        */
9742 /*  INPUT                                                                 */
9743 /*                                                                        */
9744 /*    dhcp_ptr                              Pointer to DHCP instance      */
9745 /*    time_elapsed                          time input in timer ticks     */
9746 /*                                                                        */
9747 /*  OUTPUT                                                                */
9748 /*                                                                        */
9749 /*    status                                Actual Completion status      */
9750 /*                                                                        */
9751 /*  CALLS                                                                 */
9752 /*                                                                        */
9753 /*   _nx_dhcp_client_update_time_remaining  Update DHCP timeout for time  */
9754 /*                                            elapsed while powered down  */
9755 /*                                                                        */
9756 /*  CALLED BY                                                             */
9757 /*                                                                        */
9758 /*    Application                                                         */
9759 /*                                                                        */
9760 /*  RELEASE HISTORY                                                       */
9761 /*                                                                        */
9762 /*    DATE              NAME                      DESCRIPTION             */
9763 /*                                                                        */
9764 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9765 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9766 /*                                            resulting in version 6.1    */
9767 /*                                                                        */
9768 /**************************************************************************/
_nxe_dhcp_client_update_time_remaining(NX_DHCP * dhcp_ptr,ULONG time_elapsed)9769 UINT  _nxe_dhcp_client_update_time_remaining(NX_DHCP *dhcp_ptr, ULONG time_elapsed)
9770 {
9771 
9772 UINT status;
9773 
9774 
9775     if (dhcp_ptr == NX_NULL)
9776     {
9777         return NX_PTR_ERROR;
9778     }
9779 
9780     status = _nx_dhcp_client_update_time_remaining(dhcp_ptr, time_elapsed);
9781 
9782     return status;
9783 }
9784 
9785 
9786 /**************************************************************************/
9787 /*                                                                        */
9788 /*  FUNCTION                                               RELEASE        */
9789 /*                                                                        */
9790 /*    _nx_dhcp_client_update_time_remaining               PORTABLE C      */
9791 /*                                                           6.1          */
9792 /*  AUTHOR                                                                */
9793 /*                                                                        */
9794 /*    Yuxin Zhou, Microsoft Corporation                                   */
9795 /*                                                                        */
9796 /*  DESCRIPTION                                                           */
9797 /*                                                                        */
9798 /*    This function applies the input time_elapsed to the DHCP Client     */
9799 /*    time remaining and determines if a state change occurred meanwhile. */
9800 /*    Note that time_elapsed is in timer ticks.                           */
9801 /*                                                                        */
9802 /*    There is no need to call this function if also calling              */
9803 /*    _nx_dhcp_client_restore_record which applies the elapsed time.      */
9804 /*                                                                        */
9805 /*  INPUT                                                                 */
9806 /*                                                                        */
9807 /*    dhcp_ptr                              Pointer to DHCP instance      */
9808 /*    time_elapsed                          time input in timer ticks     */
9809 /*                                                                        */
9810 /*  OUTPUT                                                                */
9811 /*                                                                        */
9812 /*    status                                Actual completion status      */
9813 /*    NX_DHCP_NO_INTERFACES_ENABLED         No interface enabled for DHCP */
9814 /*                                                                        */
9815 /*  CALLS                                                                 */
9816 /*                                                                        */
9817 /*   _nx_dhcp_client_interface_update_time_remaining                      */
9818 /*                                          Apply the elapsed time to the */
9819 /*                                            specified DHCP timeout      */
9820 /*    tx_mutex_get                          Obtain protection mutex       */
9821 /*    tx_mutex_put                          Release protection mutex      */
9822 /*                                                                        */
9823 /*  CALLED BY                                                             */
9824 /*                                                                        */
9825 /*    _nx_dhcp_client_restore_record                                      */
9826 /*                                                                        */
9827 /*  RELEASE HISTORY                                                       */
9828 /*                                                                        */
9829 /*    DATE              NAME                      DESCRIPTION             */
9830 /*                                                                        */
9831 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9832 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9833 /*                                            resulting in version 6.1    */
9834 /*                                                                        */
9835 /**************************************************************************/
_nx_dhcp_client_update_time_remaining(NX_DHCP * dhcp_ptr,ULONG time_elapsed)9836 UINT  _nx_dhcp_client_update_time_remaining(NX_DHCP *dhcp_ptr, ULONG time_elapsed)
9837 {
9838 
9839 UINT i;
9840 UINT status;
9841 
9842 
9843     /* Obtain DHCP Client protection mutex. */
9844     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
9845 
9846     /* Find the DHCP interface record.  */
9847     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
9848     {
9849 
9850         /* Check which interface record is valid.  */
9851         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
9852         {
9853 
9854             /* Create a record of the current state of the DHCP CLient. */
9855             status = _nx_dhcp_client_interface_update_time_remaining(dhcp_ptr, dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index, time_elapsed);
9856 
9857             /* Release the DHCP mutex.  */
9858             tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9859             return(status);
9860         }
9861     }
9862 
9863     /* Release the DHCP mutex.  */
9864     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
9865     return(NX_DHCP_NO_INTERFACES_ENABLED);
9866 }
9867 
9868 
9869 /**************************************************************************/
9870 /*                                                                        */
9871 /*  FUNCTION                                               RELEASE        */
9872 /*                                                                        */
9873 /*    _nxe_dhcp_client_interface_update_time_remaining    PORTABLE C      */
9874 /*                                                           6.1          */
9875 /*  AUTHOR                                                                */
9876 /*                                                                        */
9877 /*    Yuxin Zhou, Microsoft Corporation                                   */
9878 /*                                                                        */
9879 /*  DESCRIPTION                                                           */
9880 /*                                                                        */
9881 /*    This function performs error checking on the update time remaining  */
9882 /*    service.                                                            */
9883 /*                                                                        */
9884 /*  INPUT                                                                 */
9885 /*                                                                        */
9886 /*    dhcp_ptr                              Pointer to DHCP instance      */
9887 /*    time_elapsed                          time input in timer ticks     */
9888 /*                                                                        */
9889 /*  OUTPUT                                                                */
9890 /*                                                                        */
9891 /*    status                                Completion status             */
9892 /*    NX_PTR_ERROR                          Invalid pointer input         */
9893 /*    NX_INVALID_INTERFACE                  Invalid interface index       */
9894 /*                                                                        */
9895 /*  CALLS                                                                 */
9896 /*                                                                        */
9897 /*   _nx_dhcp_client_interface_update_time_remaining                      */
9898 /*                                          Actual update time service    */
9899 /*                                                                        */
9900 /*  CALLED BY                                                             */
9901 /*                                                                        */
9902 /*    Application code                                                    */
9903 /*                                                                        */
9904 /*  RELEASE HISTORY                                                       */
9905 /*                                                                        */
9906 /*    DATE              NAME                      DESCRIPTION             */
9907 /*                                                                        */
9908 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9909 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9910 /*                                            resulting in version 6.1    */
9911 /*                                                                        */
9912 /**************************************************************************/
_nxe_dhcp_client_interface_update_time_remaining(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG time_elapsed)9913 UINT  _nxe_dhcp_client_interface_update_time_remaining(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG time_elapsed)
9914 {
9915 
9916 UINT status;
9917 
9918 
9919     /* Check for invalid input pointers.  */
9920     if (dhcp_ptr == NX_NULL)
9921     {
9922         return NX_PTR_ERROR;
9923     }
9924 
9925     /* Check interface index.  */
9926     if (iface_index >= NX_DHCP_CLIENT_MAX_RECORDS)
9927     {
9928         return NX_INVALID_INTERFACE;
9929     }
9930 
9931     status = _nx_dhcp_client_interface_update_time_remaining(dhcp_ptr, iface_index, time_elapsed);
9932 
9933     return status;
9934 }
9935 
9936 
9937 /**************************************************************************/
9938 /*                                                                        */
9939 /*  FUNCTION                                               RELEASE        */
9940 /*                                                                        */
9941 /*    _nx_dhcp_client_interface_update_time_remaining     PORTABLE C      */
9942 /*                                                           6.1          */
9943 /*  AUTHOR                                                                */
9944 /*                                                                        */
9945 /*    Yuxin Zhou, Microsoft Corporation                                   */
9946 /*                                                                        */
9947 /*  DESCRIPTION                                                           */
9948 /*                                                                        */
9949 /*    This function applies the input time_elapsed data to the DHCP Client*/
9950 /*    state and determines what state it should be in (e.g. BOUND,        */
9951 /*    IP address. Note, time_elapsed is in timer ticks. If called from the*/
9952 /*    application it is assumed the application device is sleeping, not   */
9953 /*    powering up.  If the device is waking up from sleeping, it does not */
9954 /*    need to restore the DHCP client state but only to update the time   */
9955 /*    elapsed.                                                            */
9956 /*                                                                        */
9957 /*    Therefore this should not be called in addition to                  */
9958 /*    _nx_dhcp_client_restore_record.  The restore record service handles */
9959 /*    updating time remaining, such that calling this service would       */
9960 /*    effectively apply the time elapsed a second time.                   */
9961 /*                                                                        */
9962 /*  INPUT                                                                 */
9963 /*                                                                        */
9964 /*    dhcp_ptr                              Pointer to DHCP instance      */
9965 /*    time_elapsed                          time input in timer ticks     */
9966 /*                                                                        */
9967 /*  OUTPUT                                                                */
9968 /*                                                                        */
9969 /*    NX_SUCCESS                            Successful Completion status  */
9970 /*    status                                Actual completion status      */
9971 /*                                                                        */
9972 /*  CALLS                                                                 */
9973 /*                                                                        */
9974 /*    tx_mutex_get                          Obtain protection mutex       */
9975 /*    tx_mutex_put                          Release protection mutex      */
9976 /*   _nx_dhcp_update_renewal_timeout        Update time remaining on lease*/
9977 /*   _nx_dhcp_interface_record_find         Find record for the interface */
9978 /*   _nx_dhcp_interface_reinitialize        Clear DHCP and IP network     */
9979 /*                                            parameters                  */
9980 /*                                                                        */
9981 /*  CALLED BY                                                             */
9982 /*                                                                        */
9983 /*    Application code                                                    */
9984 /*                                                                        */
9985 /*  RELEASE HISTORY                                                       */
9986 /*                                                                        */
9987 /*    DATE              NAME                      DESCRIPTION             */
9988 /*                                                                        */
9989 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9990 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9991 /*                                            resulting in version 6.1    */
9992 /*                                                                        */
9993 /**************************************************************************/
_nx_dhcp_client_interface_update_time_remaining(NX_DHCP * dhcp_ptr,UINT iface_index,ULONG time_elapsed)9994 UINT  _nx_dhcp_client_interface_update_time_remaining(NX_DHCP *dhcp_ptr, UINT iface_index, ULONG time_elapsed)
9995 {
9996 
9997 UINT                      status;
9998 UINT                      accrued_time_adjusted = 0;
9999 UINT                      time_accrued;
10000 UINT                      original_state;
10001 NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
10002 
10003 
10004     /* Obtain DHCP Client protection mutex. */
10005     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
10006 
10007     /* Find the interface record.  */
10008     status = _nx_dhcp_interface_record_find(dhcp_ptr, iface_index, &interface_record);
10009 
10010     /* Check status.  */
10011     if (status)
10012     {
10013 
10014         /* Release the DHCP mutex.  */
10015         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10016         return(status);
10017     }
10018 
10019     /* Get the original state.  */
10020     original_state = interface_record -> nx_dhcp_state;
10021 
10022     /* Compute the time since the lease was assigned before we suspended the Client.  */
10023     if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_BOUND)
10024     {
10025         if (interface_record -> nx_dhcp_renewal_time >= interface_record -> nx_dhcp_timeout)
10026         {
10027             /* Since the Client is in a BOUND state, we know the timeout is less than T2
10028                or nx_dhcp_renew_time. */
10029             time_accrued = interface_record -> nx_dhcp_renewal_time - interface_record -> nx_dhcp_timeout;
10030         }
10031         else
10032         {
10033             /* Invalid DHCP timeout. If it is in the BOUND state, set to the renewal time. */
10034             time_accrued = interface_record -> nx_dhcp_renewal_time;
10035         }
10036     }
10037     else if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING)
10038     {
10039 
10040         /* Since the Client is in the RENEWING state, the total time on the lease is the
10041            lease rebind time - the time out in the RENEW state: */
10042         time_accrued = interface_record -> nx_dhcp_rebind_time - interface_record -> nx_dhcp_renewal_remain_time;
10043 
10044         /* Note if dhcp_ptr -> nx_dhcp_rebind_time < dhcp_ptr -> nx_dhcp_renewal_remain_time,
10045            the CLient either received invalid DHCP parameters or there is an internal error.
10046            The renewal time should never exceed the rebind time.  */
10047     }
10048     else if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_REBINDING)
10049     {
10050 
10051         /* Since the Client is in the REBINDING state, the total time on the lease is the
10052            lease  time - the  time remaining in the REBIND state: */
10053         time_accrued = interface_record -> nx_dhcp_lease_time - interface_record -> nx_dhcp_rebind_remain_time;
10054 
10055         /* Note if dhcp_ptr -> nx_dhcp_lease_time < dhcp_ptr -> nx_dhcp_rebind_remain_time,
10056            the CLient either received invalid DHCP parameters or there is an internal error.
10057            The rebind time should never exceed the lease time.  */
10058     }
10059     else
10060     {
10061         /* Expired! */
10062         accrued_time_adjusted = 0xFFFFFFFF;
10063     }
10064 
10065     /* Adjust the time accrued to include the interval while the Client was suspended. */
10066     if (accrued_time_adjusted != 0xFFFFFFFF)
10067     {
10068         accrued_time_adjusted = time_accrued + time_elapsed;
10069     }
10070 
10071     /* Determine if the DHCP Client needs to renew. */
10072     if (accrued_time_adjusted < interface_record -> nx_dhcp_renewal_time)
10073     {
10074 
10075         /* Not yet.  Update the nx_dhcp_timeout for the time elapsed and we're done. */
10076         interface_record -> nx_dhcp_timeout -= time_elapsed;
10077 
10078         /* Release the DHCP mutex.  */
10079         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10080 
10081         /* We are done. Ok to resume the Client. */
10082         return NX_SUCCESS;
10083     }
10084 
10085     /* Determine if the Client should renew. */
10086     else if (accrued_time_adjusted < interface_record -> nx_dhcp_rebind_time)
10087     {
10088 
10089         /* Yes; it has not reached the expiration on the renew period.  */
10090 
10091         /* Check if it is already in the RENEW state. */
10092         if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_RENEWING)
10093         {
10094 
10095             /* Yes it is, so do nothing. Let the Client continue renewing. */
10096 
10097             /* Update the time remaining for the Client to renew its lease.   */
10098             interface_record -> nx_dhcp_renewal_remain_time -= time_elapsed;
10099 
10100             /* Reset the timeout based on the updated time remaining to renew. */
10101             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
10102 
10103             /* Record the retransmission interval.  */
10104             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10105         }
10106         else
10107         {
10108 
10109             /* No it wasn't so update the Client for the RENEW state. */
10110 
10111             /* Compute how many seconds into the renew period the Client is (total time on lease over and above
10112                the time to start renewing. */
10113             if (accrued_time_adjusted == interface_record -> nx_dhcp_renewal_time)
10114             {
10115 
10116                 interface_record -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_rebind_time - interface_record -> nx_dhcp_renewal_time;
10117             }
10118             else
10119             {
10120 
10121                 interface_record -> nx_dhcp_renewal_remain_time = interface_record -> nx_dhcp_rebind_time - accrued_time_adjusted;
10122             }
10123 
10124             /* Set the DHCP timeout for being in the RENEW phase. */
10125             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_renewal_remain_time);
10126 
10127             /* Record the retransmission interval.  */
10128             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10129 
10130             /* And change to the Renewing state. */
10131             interface_record -> nx_dhcp_state = NX_DHCP_STATE_RENEWING;
10132         }
10133 
10134         /* Release the DHCP mutex.  */
10135         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10136 
10137         /* We are done. Ok to resume the Client. */
10138         return NX_SUCCESS;
10139     }
10140 
10141     /* Determine if it is time for the Client to rebind (e.g. check the lease has not completely expired). */
10142     else if (accrued_time_adjusted < interface_record -> nx_dhcp_lease_time)
10143     {
10144 
10145         /* Check if it is already in the REBIND state. */
10146         if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_REBINDING)
10147         {
10148             /* Yes it is, so do nothing. Let the Client complete its rebind task*/
10149 
10150             /* Update the time remaining for the Client to rebind an IP address.   */
10151             interface_record -> nx_dhcp_rebind_remain_time -= time_elapsed;
10152 
10153             /* Reset the timeout based on the updated time remaining to rebind. */
10154             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_rebind_remain_time);
10155 
10156             /* Record the retransmission interval.  */
10157             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10158         }
10159         else
10160         {
10161 
10162             /* No it wasn't so update the Client for the REBIND state. */
10163 
10164             /* Compute how many seconds into the rebind period the Client is (total time on lease over and above
10165                the time to start rebinding. */
10166             if (accrued_time_adjusted == interface_record -> nx_dhcp_rebind_time)
10167             {
10168 
10169                 interface_record -> nx_dhcp_rebind_remain_time = interface_record -> nx_dhcp_lease_time - interface_record -> nx_dhcp_rebind_time;
10170             }
10171             else
10172             {
10173 
10174                 interface_record -> nx_dhcp_rebind_remain_time = interface_record -> nx_dhcp_lease_time - accrued_time_adjusted;
10175             }
10176 
10177             /* Set the DHCP timeout for being in the RENEW phase. */
10178             interface_record -> nx_dhcp_timeout = _nx_dhcp_update_renewal_timeout(interface_record -> nx_dhcp_rebind_remain_time);
10179 
10180             /* Record the retransmission interval.  */
10181             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10182 
10183             /* Record the retransmission interval.  */
10184             interface_record -> nx_dhcp_rtr_interval = interface_record -> nx_dhcp_timeout;
10185 
10186             /* And change to the Rebinding state. */
10187             interface_record -> nx_dhcp_state = NX_DHCP_STATE_REBINDING;
10188         }
10189 
10190         /* Release the DHCP mutex.  */
10191         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10192 
10193         /* We are done. Ok to resume the Client. */
10194         return NX_SUCCESS;
10195     }
10196     else
10197     {
10198 
10199         /* Clear the existing DHCP Client network parameters for restarting in the INIT state. */
10200         _nx_dhcp_interface_reinitialize(dhcp_ptr, iface_index);
10201 
10202         /* Start the DHCP protocol again by setting the state back to INIT. */
10203         interface_record -> nx_dhcp_state = NX_DHCP_STATE_INIT;
10204 
10205         /* The client begins in INIT state and forms a DHCPDISCOVER message.
10206            The client should wait a random time between one and ten seconds to desynchronize the use of DHCP at startup.
10207            RFC2131, Section4.4.1, Page36.  */
10208 
10209         /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message.  */
10210         interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE;
10211         interface_record -> nx_dhcp_rtr_interval = 0;
10212     }
10213 
10214     /* Check if the state is changed.  */
10215     if (original_state != interface_record -> nx_dhcp_state)
10216     {
10217 
10218         /* Determine if the application has specified a routine for DHCP state change notification.  */
10219         if (dhcp_ptr -> nx_dhcp_state_change_callback)
10220         {
10221 
10222             /* Yes, call the application's state change notify function with the new state.  */
10223             (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state);
10224         }
10225 
10226         /* Determine if the application has specified a routine for DHCP interface state change notification.  */
10227         if (dhcp_ptr -> nx_dhcp_interface_state_change_callback)
10228         {
10229 
10230             /* Yes, call the application's state change notify function with the new state.  */
10231             (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state);
10232         }
10233     }
10234 
10235     /* Release the DHCP mutex.  */
10236     tx_mutex_put(&(dhcp_ptr->nx_dhcp_mutex));
10237 
10238     return NX_SUCCESS;
10239 }
10240 
10241 
10242 /**************************************************************************/
10243 /*                                                                        */
10244 /*  FUNCTION                                               RELEASE        */
10245 /*                                                                        */
10246 /*    _nxe_dhcp_resume                                    PORTABLE C      */
10247 /*                                                           6.1          */
10248 /*  AUTHOR                                                                */
10249 /*                                                                        */
10250 /*    Yuxin Zhou, Microsoft Corporation                                   */
10251 /*                                                                        */
10252 /*  DESCRIPTION                                                           */
10253 /*                                                                        */
10254 /*    This function performs error checking for the Client resume service.*/
10255 /*                                                                        */
10256 /*  INPUT                                                                 */
10257 /*                                                                        */
10258 /*    dhcp_ptr                              Pointer to DHCP instance      */
10259 /*                                                                        */
10260 /*  OUTPUT                                                                */
10261 /*                                                                        */
10262 /*    NX_PTR_ERROR                          Invalid pointer input         */
10263 /*    status                                Actual completion  status     */
10264 /*                                                                        */
10265 /*  CALLS                                                                 */
10266 /*                                                                        */
10267 /*   _nx_dhcp_resume                        Actual Client resume service  */
10268 /*                                                                        */
10269 /*  CALLED BY                                                             */
10270 /*                                                                        */
10271 /*    Application Code                                                    */
10272 /*                                                                        */
10273 /*  RELEASE HISTORY                                                       */
10274 /*                                                                        */
10275 /*    DATE              NAME                      DESCRIPTION             */
10276 /*                                                                        */
10277 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10278 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10279 /*                                            resulting in version 6.1    */
10280 /*                                                                        */
10281 /**************************************************************************/
_nxe_dhcp_resume(NX_DHCP * dhcp_ptr)10282 UINT  _nxe_dhcp_resume(NX_DHCP *dhcp_ptr)
10283 {
10284 
10285 UINT status;
10286 
10287 
10288     if (dhcp_ptr == NX_NULL)
10289     {
10290         return NX_PTR_ERROR;
10291     }
10292 
10293     status = _nx_dhcp_resume(dhcp_ptr);
10294 
10295     return status;
10296 }
10297 
10298 /**************************************************************************/
10299 /*                                                                        */
10300 /*  FUNCTION                                               RELEASE        */
10301 /*                                                                        */
10302 /*    _nx_dhcp_resume                                     PORTABLE C      */
10303 /*                                                           6.1          */
10304 /*  AUTHOR                                                                */
10305 /*                                                                        */
10306 /*    Yuxin Zhou, Microsoft Corporation                                   */
10307 /*                                                                        */
10308 /*  DESCRIPTION                                                           */
10309 /*                                                                        */
10310 /*    This function resumes the DHCP Client thread and timer.  It then    */
10311 /*    checks the state on all DHCP enabled interfaces if renewing or      */
10312 /*    rebinding.  If so it sends a REQUEST to the DHCP server.            */
10313 /*                                                                        */
10314 /*    The DHCP Client application can then call the                       */
10315 /*    nx_dhcp_client_udpate_remaining_time() service to update the time   */
10316 /*    remaining on the client lease, before calling nx_dhcp_resume.       */
10317 /*                                                                        */
10318 /*    This function does not change the Client state, lease timeout or    */
10319 /*    time remaining on the current lease.  It requires the               */
10320 /*    NX_DHCP_CLIENT_RESTORE_STATE option to be enabled.                  */
10321 /*                                                                        */
10322 /*  INPUT                                                                 */
10323 /*                                                                        */
10324 /*    dhcp_ptr                              Pointer to DHCP instance      */
10325 /*                                                                        */
10326 /*  OUTPUT                                                                */
10327 /*                                                                        */
10328 /*    NX_SUCCESS                            Successful Completion status  */
10329 /*    NX_DHCP_ALREADY_STARTED               DHCP Client thread started    */
10330 /*    status                                NetX or ThreadX completion    */
10331 /*                                             status                     */
10332 /*                                                                        */
10333 /*  CALLS                                                                 */
10334 /*                                                                        */
10335 /*   _nx_dhcp_send_request_internal         Send message to DHCP server   */
10336 /*   nx_udp_socket_bind                     Bind UDP socket to port       */
10337 /*   tx_thread_resume                       Resume the DHCP Client thread */
10338 /*   tx_mutex_get                           Obtain mutex protection       */
10339 /*   tx_mutex_put                           Release mutex protectiob      */
10340 /*                                                                        */
10341 /*  CALLED BY                                                             */
10342 /*                                                                        */
10343 /*    Application Code                                                    */
10344 /*                                                                        */
10345 /*  RELEASE HISTORY                                                       */
10346 /*                                                                        */
10347 /*    DATE              NAME                      DESCRIPTION             */
10348 /*                                                                        */
10349 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10350 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
10351 /*                                            fixed compiler warnings,    */
10352 /*                                            resulting in version 6.1    */
10353 /*                                                                        */
10354 /**************************************************************************/
_nx_dhcp_resume(NX_DHCP * dhcp_ptr)10355 UINT _nx_dhcp_resume(NX_DHCP *dhcp_ptr)
10356 {
10357 
10358 UINT    i;
10359 UINT    status;
10360 NX_IP   *ip_ptr;
10361 ULONG   client_physical_msw;
10362 ULONG   client_physical_lsw;
10363 UINT    iface_index;
10364 
10365 
10366     /* Get the DHCP mutex.  */
10367     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
10368 
10369     /* Resume the DHCP processing thread.  */
10370     status = tx_thread_resume(&(dhcp_ptr -> nx_dhcp_thread));
10371 
10372     /* Determine if the resume was successful.  */
10373     if ((status != TX_SUCCESS) && (status != TX_SUSPEND_LIFTED))
10374     {
10375 
10376         /* Release the DHCP mutex.  */
10377         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10378         return(status);
10379     }
10380 
10381     /* Active the timer.  */
10382     status = tx_timer_activate(&(dhcp_ptr -> nx_dhcp_timer));
10383 
10384     /* Check status.  */
10385     if (status)
10386     {
10387 
10388         /* Release the DHCP mutex.  */
10389         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10390         return(status);
10391     }
10392 
10393     /* Bind the UDP socket to the DHCP Client port.  */
10394     status =  nx_udp_socket_bind(&(dhcp_ptr -> nx_dhcp_socket), NX_DHCP_CLIENT_UDP_PORT, NX_WAIT_FOREVER);
10395 
10396     /* Check status.  */
10397     if (status)
10398     {
10399 
10400         /* Release the DHCP mutex.  */
10401         tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10402         return(status);
10403     }
10404 
10405     /* Set IP pointer.  */
10406     ip_ptr = dhcp_ptr -> nx_dhcp_ip_ptr;
10407 
10408     /* Loop to process interface records.  */
10409     for (i = 0; i < NX_DHCP_CLIENT_MAX_RECORDS; i++)
10410     {
10411 
10412         /* Check which interface record is valid.  */
10413         if (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_record_valid)
10414         {
10415 
10416             /* Get the interface index.  */
10417             iface_index = dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_interface_index;
10418 
10419             /* Get the client MAC address from the device interface. */
10420             client_physical_msw = ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_msw;
10421             client_physical_lsw = ip_ptr -> nx_ip_interface[iface_index].nx_interface_physical_address_lsw;
10422 
10423             /* Generate a 'unique' client transaction ID from the MAC address for each message to the server. */
10424             dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_xid = client_physical_msw ^ client_physical_lsw ^ (ULONG)NX_RAND();
10425 
10426             /* If the DHCP Client is renewing or rebinding on being resumed, send a DHCP request. */
10427             if ((dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state == NX_DHCP_STATE_RENEWING) ||
10428                 (dhcp_ptr -> nx_dhcp_interface_record[i].nx_dhcp_state == NX_DHCP_STATE_REBINDING))
10429             {
10430 
10431                 /* Transmit the request message.  */
10432                 _nx_dhcp_send_request_internal(dhcp_ptr, &dhcp_ptr -> nx_dhcp_interface_record[i], NX_DHCP_TYPE_DHCPREQUEST);
10433             }
10434         }
10435     }
10436 
10437     /* Release the DHCP mutex.  */
10438     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10439 
10440     /* Return completion status.  */
10441     return(NX_SUCCESS);
10442 }
10443 
10444 /**************************************************************************/
10445 /*                                                                        */
10446 /*  FUNCTION                                               RELEASE        */
10447 /*                                                                        */
10448 /*    _nxe_dhcp_suspend                                   PORTABLE C      */
10449 /*                                                           6.1          */
10450 /*  AUTHOR                                                                */
10451 /*                                                                        */
10452 /*    Yuxin Zhou, Microsoft Corporation                                   */
10453 /*                                                                        */
10454 /*  DESCRIPTION                                                           */
10455 /*                                                                        */
10456 /*    This function performs error checking for the Client suspend        */
10457 /*    service.                                                            */
10458 /*                                                                        */
10459 /*  INPUT                                                                 */
10460 /*                                                                        */
10461 /*    dhcp_ptr                              Pointer to DHCP instance      */
10462 /*                                                                        */
10463 /*  OUTPUT                                                                */
10464 /*                                                                        */
10465 /*    NX_SUCCESS                            Successful Completion status  */
10466 /*    status                                Actual completion  status     */
10467 /*                                                                        */
10468 /*  CALLS                                                                 */
10469 /*                                                                        */
10470 /*   _nx_dhcp_suspend                       Actual Client suspend service */
10471 /*                                                                        */
10472 /*  CALLED BY                                                             */
10473 /*                                                                        */
10474 /*    Application Code                                                    */
10475 /*                                                                        */
10476 /*  RELEASE HISTORY                                                       */
10477 /*                                                                        */
10478 /*    DATE              NAME                      DESCRIPTION             */
10479 /*                                                                        */
10480 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10481 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10482 /*                                            resulting in version 6.1    */
10483 /*                                                                        */
10484 /**************************************************************************/
_nxe_dhcp_suspend(NX_DHCP * dhcp_ptr)10485 UINT  _nxe_dhcp_suspend(NX_DHCP *dhcp_ptr)
10486 {
10487 
10488 UINT status;
10489 
10490 
10491     if (dhcp_ptr == NX_NULL)
10492     {
10493         return NX_PTR_ERROR;
10494     }
10495 
10496    status = _nx_dhcp_suspend(dhcp_ptr);
10497    return status;
10498 }
10499 
10500 
10501 /**************************************************************************/
10502 /*                                                                        */
10503 /*  FUNCTION                                               RELEASE        */
10504 /*                                                                        */
10505 /*    _nx_dhcp_suspend                                   PORTABLE C       */
10506 /*                                                           6.1          */
10507 /*  AUTHOR                                                                */
10508 /*                                                                        */
10509 /*    Yuxin Zhou, Microsoft Corporation                                   */
10510 /*                                                                        */
10511 /*  DESCRIPTION                                                           */
10512 /*                                                                        */
10513 /*    This function suspends the DHCP Client task thread and unbinds the  */
10514 /*    socket port. The intented use of this service is to combine with the*/
10515 /*    resume service such that the calling application can 'pause' the    */
10516 /*    DHCP Client for a certain amount of time, and resume it in the same */
10517 /*    state.  The DHCP Client application can then call the               */
10518 /*    nx_dhcp_client_udpate_remaining_time service to update the time     */
10519 /*    remaining on the client lease, then nx_dhcp_resume to actually      */
10520 /*    resume the DHCP Client task.                                        */
10521 /*                                                                        */
10522 /*    This function does not change the Client state, lease timeout or    */
10523 /*    time remaining on the current lease.  It requires the               */
10524 /*    NX_DHCP_CLIENT_RESTORE_STATE option to be enabled.                  */
10525 /*                                                                        */
10526 /*  INPUT                                                                 */
10527 /*                                                                        */
10528 /*    dhcp_ptr                              Pointer to DHCP instance      */
10529 /*                                                                        */
10530 /*  OUTPUT                                                                */
10531 /*                                                                        */
10532 /*    NX_SUCCESS                            Successful Completion status  */
10533 /*                                                                        */
10534 /*  CALLS                                                                 */
10535 /*                                                                        */
10536 /*   nx_udp_socket_unbind                   Unbind port from UDP socket   */
10537 /*   tx_timer_deactivate                    Stop the timer                */
10538 /*   tx_thread_suspend                      Suspend the DHCP Client thread*/
10539 /*   tx_mutex_get                           Obtain mutex protection       */
10540 /*   tx_mutex_put                           Release mutex protection      */
10541 /*                                                                        */
10542 /*  CALLED BY                                                             */
10543 /*                                                                        */
10544 /*    Application Code                                                    */
10545 /*                                                                        */
10546 /*  RELEASE HISTORY                                                       */
10547 /*                                                                        */
10548 /*    DATE              NAME                      DESCRIPTION             */
10549 /*                                                                        */
10550 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10551 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10552 /*                                            resulting in version 6.1    */
10553 /*                                                                        */
10554 /**************************************************************************/
_nx_dhcp_suspend(NX_DHCP * dhcp_ptr)10555 UINT  _nx_dhcp_suspend(NX_DHCP *dhcp_ptr)
10556 {
10557 
10558 
10559     /* Get the DHCP mutex.  */
10560     tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
10561 
10562     /* Suspend the DHCP thread.  */
10563     tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread));
10564 
10565     /* Deactive the timer.  */
10566     tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer));
10567 
10568     /* Unbind the port.  */
10569     nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket));
10570 
10571     /* Release the DHCP mutex.  */
10572     tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
10573 
10574     /* Return completion status.  */
10575     return(NX_SUCCESS);
10576 }
10577 
10578 #endif /* NX_DHCP_CLIENT_RESTORE_STATE */
10579 #endif /* NX_DISABLE_IPV4 */
10580