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