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