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