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 /** AutoIP (AutoIP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_AUTO_IP_SOURCE_CODE
23
24
25 /* Force error checking to be disabled in this module */
26 #include "tx_port.h"
27
28 #ifndef NX_DISABLE_ERROR_CHECKING
29 #define NX_DISABLE_ERROR_CHECKING
30 #endif
31
32 #ifndef TX_SAFETY_CRITICAL
33 #ifndef TX_DISABLE_ERROR_CHECKING
34 #define TX_DISABLE_ERROR_CHECKING
35 #endif
36 #endif
37
38
39 /* Include necessary system files. */
40
41 #include "nx_api.h"
42 #ifndef NX_DISABLE_IPV4
43 #include "nx_ip.h"
44 #include "nx_arp.h"
45 #include "tx_thread.h"
46 #include "tx_timer.h"
47 #include "nx_auto_ip.h"
48
49 /* Keep the AutoIP instance for callback notify. */
50 static NX_AUTO_IP *_nx_auto_ip_ptr;
51
52 /**************************************************************************/
53 /* */
54 /* FUNCTION RELEASE */
55 /* */
56 /* _nxe_auto_ip_create PORTABLE C */
57 /* 6.1 */
58 /* AUTHOR */
59 /* */
60 /* Yuxin Zhou, Microsoft Corporation */
61 /* */
62 /* DESCRIPTION */
63 /* */
64 /* This function checks for errors in the AutoIP create function */
65 /* call. */
66 /* */
67 /* INPUT */
68 /* */
69 /* auto_ip_ptr Pointer to AutoIP instance */
70 /* name Pointer to AutoIP name */
71 /* ip_ptr Pointer to IP instance */
72 /* stack_ptr Pointer to start of stack */
73 /* stack_size Size of stack in bytes */
74 /* priority Priority of AutoIP thread */
75 /* */
76 /* OUTPUT */
77 /* */
78 /* status Completion status */
79 /* */
80 /* CALLS */
81 /* */
82 /* _nx_auto_ip_create AutoIP create function */
83 /* */
84 /* CALLED BY */
85 /* */
86 /* Application Code */
87 /* */
88 /* RELEASE HISTORY */
89 /* */
90 /* DATE NAME DESCRIPTION */
91 /* */
92 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
93 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
94 /* resulting in version 6.1 */
95 /* */
96 /**************************************************************************/
_nxe_auto_ip_create(NX_AUTO_IP * auto_ip_ptr,CHAR * name,NX_IP * ip_ptr,VOID * stack_ptr,ULONG stack_size,UINT priority)97 UINT _nxe_auto_ip_create(NX_AUTO_IP *auto_ip_ptr, CHAR *name, NX_IP *ip_ptr, VOID *stack_ptr, ULONG stack_size, UINT priority)
98 {
99
100 UINT status;
101
102
103 /* Check for invalid input pointers. */
104 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
105 (auto_ip_ptr == NX_NULL) || (auto_ip_ptr -> nx_auto_ip_id == NX_AUTO_IP_ID))
106 return(NX_PTR_ERROR);
107
108 /* Check for appropriate caller. */
109 NX_INIT_AND_THREADS_CALLER_CHECKING
110
111 /* Call actual AutoIP create routine. */
112 status = _nx_auto_ip_create(auto_ip_ptr, name, ip_ptr, stack_ptr, stack_size, priority);
113
114 /* Return status. */
115 return(status);
116 }
117
118
119 /**************************************************************************/
120 /* */
121 /* FUNCTION RELEASE */
122 /* */
123 /* _nx_auto_ip_create PORTABLE C */
124 /* 6.1 */
125 /* AUTHOR */
126 /* */
127 /* Yuxin Zhou, Microsoft Corporation */
128 /* */
129 /* DESCRIPTION */
130 /* */
131 /* This function creates an AutoIP instance for the associated IP */
132 /* instance. There must be only one AutoIP instance per IP instance. */
133 /* */
134 /* INPUT */
135 /* */
136 /* auto_ip_ptr Pointer to AutoIP instance */
137 /* name Pointer to AutoIP name */
138 /* ip_ptr Pointer to IP instance */
139 /* stack_ptr Pointer to start of stack */
140 /* stack_size Size of stack in bytes */
141 /* priority Priority of AutoIP thread */
142 /* */
143 /* OUTPUT */
144 /* */
145 /* Completion Status */
146 /* */
147 /* CALLS */
148 /* */
149 /* tx_thread_create Create AutoIP thread */
150 /* tx_event_flags_create Create event flags group */
151 /* tx_event_flags_delete Delete event flags group */
152 /* */
153 /* CALLED BY */
154 /* */
155 /* Application */
156 /* */
157 /* RELEASE HISTORY */
158 /* */
159 /* DATE NAME DESCRIPTION */
160 /* */
161 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
162 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
163 /* resulting in version 6.1 */
164 /* */
165 /**************************************************************************/
_nx_auto_ip_create(NX_AUTO_IP * auto_ip_ptr,CHAR * name,NX_IP * ip_ptr,VOID * stack_ptr,ULONG stack_size,UINT priority)166 UINT _nx_auto_ip_create(NX_AUTO_IP *auto_ip_ptr, CHAR *name, NX_IP *ip_ptr, VOID *stack_ptr, ULONG stack_size, UINT priority)
167 {
168
169 UINT status;
170
171
172 /* Initialize the AutoIP control block to zero. */
173 memset((void *) auto_ip_ptr, 0, sizeof(NX_AUTO_IP));
174
175 /* Create the AutoIP event flags. */
176 status = tx_event_flags_create(&(auto_ip_ptr -> nx_auto_ip_conflict_event), "NetX AutoIP Collision Event");
177
178 /* Determine if successful. */
179 if (status)
180 {
181
182 /* No, return an error. */
183 return(NX_AUTO_IP_ERROR);
184 }
185
186 /* Create the AutoIP processing thread. */
187 status = tx_thread_create(&(auto_ip_ptr -> nx_auto_ip_thread), "NetX AutoIP", _nx_auto_ip_thread_entry, (ULONG) auto_ip_ptr,
188 stack_ptr, stack_size, priority, priority, 1, TX_DONT_START);
189
190 /* Determine if the thread creation was successful. */
191 if (status)
192 {
193
194 /* Delete the event flags. */
195 tx_event_flags_delete(&(auto_ip_ptr -> nx_auto_ip_conflict_event));
196
197 /* No, return an error. */
198 return(NX_AUTO_IP_ERROR);
199 }
200
201 /* Save the IP pointer and interface fields. */
202 auto_ip_ptr -> nx_auto_ip_ip_ptr = ip_ptr;
203
204 /* Default the auto IP interface to the primary interface. */
205 auto_ip_ptr -> nx_ip_interface_index = 0;
206
207 /* Save the AutoIP name. */
208 auto_ip_ptr -> nx_auto_ip_name = name;
209
210 /* Update the AutoIP structure ID. */
211 auto_ip_ptr -> nx_auto_ip_id = NX_AUTO_IP_ID;
212
213 /* Keep the AutoIP instance for callback notify. */
214 _nx_auto_ip_ptr = auto_ip_ptr;
215
216 /* Return a successful status. */
217 return(NX_SUCCESS);
218 }
219
220 /**************************************************************************/
221 /* */
222 /* FUNCTION RELEASE */
223 /* */
224 /* _nxe_auto_ip_set_interface PORTABLE C */
225 /* 6.1 */
226 /* AUTHOR */
227 /* */
228 /* Yuxin Zhou, Microsoft Corporation */
229 /* */
230 /* DESCRIPTION */
231 /* */
232 /* This function performs error checking services for the set interface*/
233 /* index service. */
234 /* */
235 /* INPUT */
236 /* */
237 /* auto_ip_ptr Pointer to AutoIP instance */
238 /* interface_index Index into IP interface table */
239 /* */
240 /* OUTPUT */
241 /* */
242 /* Completion Status */
243 /* */
244 /* CALLS */
245 /* */
246 /* None */
247 /* */
248 /* CALLED BY */
249 /* */
250 /* Application */
251 /* */
252 /* RELEASE HISTORY */
253 /* */
254 /* DATE NAME DESCRIPTION */
255 /* */
256 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
257 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
258 /* resulting in version 6.1 */
259 /* */
260 /**************************************************************************/
_nxe_auto_ip_set_interface(NX_AUTO_IP * auto_ip_ptr,UINT interface_index)261 UINT _nxe_auto_ip_set_interface(NX_AUTO_IP *auto_ip_ptr, UINT interface_index)
262 {
263
264 UINT status;
265
266
267 /* Check for invalid input pointers. */
268 if ((auto_ip_ptr == NX_NULL) || (auto_ip_ptr -> nx_auto_ip_id != NX_AUTO_IP_ID))
269 return(NX_PTR_ERROR);
270
271 /* Check for appropriate caller. */
272 NX_INIT_AND_THREADS_CALLER_CHECKING
273
274 status = _nx_auto_ip_set_interface(auto_ip_ptr, interface_index);
275
276 /* Return completion status. */
277 return(status);
278 }
279
280
281 /**************************************************************************/
282 /* */
283 /* FUNCTION RELEASE */
284 /* */
285 /* _nx_auto_ip_set_interface PORTABLE C */
286 /* 6.1 */
287 /* AUTHOR */
288 /* */
289 /* Yuxin Zhou, Microsoft Corporation */
290 /* */
291 /* DESCRIPTION */
292 /* */
293 /* This function sets the index for the interface on the local host */
294 /* needing auto IP to set the address. The default value is zero */
295 /* (primary interface). */
296 /* */
297 /* INPUT */
298 /* */
299 /* auto_ip_ptr Pointer to AutoIP instance */
300 /* interface_index Index into IP interface table */
301 /* */
302 /* OUTPUT */
303 /* */
304 /* Completion Status */
305 /* */
306 /* CALLS */
307 /* */
308 /* None */
309 /* */
310 /* CALLED BY */
311 /* */
312 /* Application */
313 /* */
314 /* RELEASE HISTORY */
315 /* */
316 /* DATE NAME DESCRIPTION */
317 /* */
318 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
319 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
320 /* resulting in version 6.1 */
321 /* */
322 /**************************************************************************/
_nx_auto_ip_set_interface(NX_AUTO_IP * auto_ip_ptr,UINT interface_index)323 UINT _nx_auto_ip_set_interface(NX_AUTO_IP *auto_ip_ptr, UINT interface_index)
324 {
325
326 /* Determine if a local IP address was successfully setup. */
327 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
328 {
329
330 /* Bad interface index. */
331 return(NX_AUTO_IP_BAD_INTERFACE_INDEX);
332 }
333
334
335 /* Set the index to the specified value. */
336 auto_ip_ptr -> nx_ip_interface_index = interface_index;
337
338 /* Return successful outcome. */
339 return(NX_SUCCESS);
340 }
341
342
343 /**************************************************************************/
344 /* */
345 /* FUNCTION RELEASE */
346 /* */
347 /* _nxe_auto_ip_get_address PORTABLE C */
348 /* 6.1 */
349 /* AUTHOR */
350 /* */
351 /* Yuxin Zhou, Microsoft Corporation */
352 /* */
353 /* DESCRIPTION */
354 /* */
355 /* This function checks for errors in the AutoIP get address function */
356 /* call. */
357 /* */
358 /* INPUT */
359 /* */
360 /* auto_ip_ptr Pointer to AutoIP instance */
361 /* local_ip_address Destination for local IP addr */
362 /* */
363 /* OUTPUT */
364 /* */
365 /* status Completion status */
366 /* */
367 /* CALLS */
368 /* */
369 /* _nx_auto_ip_get_address AutoIP get address function */
370 /* */
371 /* CALLED BY */
372 /* */
373 /* Application Code */
374 /* */
375 /* RELEASE HISTORY */
376 /* */
377 /* DATE NAME DESCRIPTION */
378 /* */
379 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
380 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
381 /* resulting in version 6.1 */
382 /* */
383 /**************************************************************************/
_nxe_auto_ip_get_address(NX_AUTO_IP * auto_ip_ptr,ULONG * local_ip_address)384 UINT _nxe_auto_ip_get_address(NX_AUTO_IP *auto_ip_ptr, ULONG *local_ip_address)
385 {
386
387 UINT status;
388
389 /* Check for invalid input pointers. */
390 if ((auto_ip_ptr == NX_NULL) || (auto_ip_ptr -> nx_auto_ip_id != NX_AUTO_IP_ID) || (local_ip_address == NX_NULL))
391 return(NX_PTR_ERROR);
392
393 /* Call actual AutoIP get address routine. */
394 status = _nx_auto_ip_get_address(auto_ip_ptr, local_ip_address);
395
396 /* Return status. */
397 return(status);
398 }
399
400
401 /**************************************************************************/
402 /* */
403 /* FUNCTION RELEASE */
404 /* */
405 /* _nx_auto_ip_get_address PORTABLE C */
406 /* 6.1 */
407 /* AUTHOR */
408 /* */
409 /* Yuxin Zhou, Microsoft Corporation */
410 /* */
411 /* DESCRIPTION */
412 /* */
413 /* This function retrieves the local IP address resolved by the AutoIP */
414 /* protocol. If there is no valid local IP address this routine */
415 /* returns an error and an IP address of all zeros. */
416 /* */
417 /* INPUT */
418 /* */
419 /* auto_ip_ptr Pointer to AutoIP instance */
420 /* local_ip_address Destination for local IP addr */
421 /* */
422 /* OUTPUT */
423 /* */
424 /* Completion Status */
425 /* */
426 /* CALLS */
427 /* */
428 /* None */
429 /* */
430 /* CALLED BY */
431 /* */
432 /* Application */
433 /* */
434 /* RELEASE HISTORY */
435 /* */
436 /* DATE NAME DESCRIPTION */
437 /* */
438 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
439 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
440 /* resulting in version 6.1 */
441 /* */
442 /**************************************************************************/
_nx_auto_ip_get_address(NX_AUTO_IP * auto_ip_ptr,ULONG * local_ip_address)443 UINT _nx_auto_ip_get_address(NX_AUTO_IP *auto_ip_ptr, ULONG *local_ip_address)
444 {
445
446 ULONG host_ip_address;
447 NX_IP *ip_ptr;
448
449
450 /* Set local variables for convenience. */
451 ip_ptr = auto_ip_ptr -> nx_auto_ip_ip_ptr;
452 host_ip_address = ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_ip_address;
453
454 /* Determine if a local IP address was successfully setup. */
455 if (auto_ip_ptr -> nx_auto_ip_current_local_address == host_ip_address)
456 {
457
458 /* Yes, a local IP address is setup. */
459 *local_ip_address = auto_ip_ptr -> nx_auto_ip_current_local_address;
460
461 /* Return success! */
462 return(NX_SUCCESS);
463 }
464 else
465 {
466
467 /* No, a local IP address has not been setup. Clear the return value. */
468 *local_ip_address = 0;
469
470 /* Return an error. */
471 return(NX_AUTO_IP_NO_LOCAL);
472 }
473 }
474
475
476 /**************************************************************************/
477 /* */
478 /* FUNCTION RELEASE */
479 /* */
480 /* _nxe_auto_ip_start PORTABLE C */
481 /* 6.1 */
482 /* AUTHOR */
483 /* */
484 /* Yuxin Zhou, Microsoft Corporation */
485 /* */
486 /* DESCRIPTION */
487 /* */
488 /* This function checks for errors in the AutoIP start function */
489 /* call. */
490 /* */
491 /* INPUT */
492 /* */
493 /* auto_ip_ptr Pointer to AutoIP instance */
494 /* */
495 /* OUTPUT */
496 /* */
497 /* status Completion status */
498 /* */
499 /* CALLS */
500 /* */
501 /* _nx_auto_ip_start AutoIP start function */
502 /* */
503 /* CALLED BY */
504 /* */
505 /* Application Code */
506 /* */
507 /* RELEASE HISTORY */
508 /* */
509 /* DATE NAME DESCRIPTION */
510 /* */
511 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
512 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
513 /* resulting in version 6.1 */
514 /* */
515 /**************************************************************************/
_nxe_auto_ip_start(NX_AUTO_IP * auto_ip_ptr,ULONG starting_local_address)516 UINT _nxe_auto_ip_start(NX_AUTO_IP *auto_ip_ptr, ULONG starting_local_address)
517 {
518
519 UINT status;
520
521
522 /* Check for invalid input pointers. */
523 if ((auto_ip_ptr == NX_NULL) || (auto_ip_ptr -> nx_auto_ip_id != NX_AUTO_IP_ID))
524 return(NX_PTR_ERROR);
525
526 /* Check for appropriate caller. */
527 NX_INIT_AND_THREADS_CALLER_CHECKING
528
529 /* Call actual AutoIP start routine. */
530 status = _nx_auto_ip_start(auto_ip_ptr, starting_local_address);
531
532 /* Return status. */
533 return(status);
534 }
535
536
537 /**************************************************************************/
538 /* */
539 /* FUNCTION RELEASE */
540 /* */
541 /* _nx_auto_ip_start PORTABLE C */
542 /* 6.1 */
543 /* AUTHOR */
544 /* */
545 /* Yuxin Zhou, Microsoft Corporation */
546 /* */
547 /* DESCRIPTION */
548 /* */
549 /* This function starts the AutoIP thread of a previously created */
550 /* AutoIP instance. */
551 /* */
552 /* INPUT */
553 /* */
554 /* auto_ip_ptr Pointer to AutoIP instance */
555 /* starting_local_address Starting local IP address, */
556 /* only IP addresses from */
557 /* 169.254.1.0 through */
558 /* 169.254.254.255 are valid,*/
559 /* where a value of 0 implies*/
560 /* a random generated value */
561 /* */
562 /* OUTPUT */
563 /* */
564 /* Completion Status */
565 /* */
566 /* CALLS */
567 /* */
568 /* tx_thread_resume Resume AutoIP thread */
569 /* */
570 /* CALLED BY */
571 /* */
572 /* Application */
573 /* */
574 /* RELEASE HISTORY */
575 /* */
576 /* DATE NAME DESCRIPTION */
577 /* */
578 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
579 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
580 /* resulting in version 6.1 */
581 /* */
582 /**************************************************************************/
_nx_auto_ip_start(NX_AUTO_IP * auto_ip_ptr,ULONG starting_local_address)583 UINT _nx_auto_ip_start(NX_AUTO_IP *auto_ip_ptr, ULONG starting_local_address)
584 {
585
586
587 /* First, start the local IP address to that supplied. */
588 auto_ip_ptr -> nx_auto_ip_current_local_address = starting_local_address;
589
590 /* Set the restart flag. */
591 auto_ip_ptr -> nx_auto_ip_restart_flag = NX_TRUE;
592
593 /* Set the event flags to ensure AutoIP thread wakes up. */
594 tx_event_flags_set(&(auto_ip_ptr -> nx_auto_ip_conflict_event), 0x1, TX_OR);
595
596 /* Resume the AutoIP thread. */
597 tx_thread_resume(&(auto_ip_ptr -> nx_auto_ip_thread));
598
599 /* Return status. */
600 return(NX_SUCCESS);
601 }
602
603
604 /**************************************************************************/
605 /* */
606 /* FUNCTION RELEASE */
607 /* */
608 /* _nxe_auto_ip_stop PORTABLE C */
609 /* 6.1 */
610 /* AUTHOR */
611 /* */
612 /* Yuxin Zhou, Microsoft Corporation */
613 /* */
614 /* DESCRIPTION */
615 /* */
616 /* This function checks for errors in the AutoIP stop function */
617 /* call. */
618 /* */
619 /* INPUT */
620 /* */
621 /* auto_ip_ptr Pointer to AutoIP instance */
622 /* */
623 /* OUTPUT */
624 /* */
625 /* status Completion status */
626 /* */
627 /* CALLS */
628 /* */
629 /* _nx_auto_ip_stop AutoIP stop function */
630 /* */
631 /* CALLED BY */
632 /* */
633 /* Application Code */
634 /* */
635 /* RELEASE HISTORY */
636 /* */
637 /* DATE NAME DESCRIPTION */
638 /* */
639 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
640 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
641 /* resulting in version 6.1 */
642 /* */
643 /**************************************************************************/
_nxe_auto_ip_stop(NX_AUTO_IP * auto_ip_ptr)644 UINT _nxe_auto_ip_stop(NX_AUTO_IP *auto_ip_ptr)
645 {
646
647 UINT status;
648
649
650 /* Check for invalid input pointers. */
651 if ((auto_ip_ptr == NX_NULL) || (auto_ip_ptr -> nx_auto_ip_id != NX_AUTO_IP_ID))
652 return(NX_PTR_ERROR);
653
654 /* Check for appropriate caller. */
655 NX_THREADS_ONLY_CALLER_CHECKING
656
657 /* Call actual AutoIP stop routine. */
658 status = _nx_auto_ip_stop(auto_ip_ptr);
659
660 /* Return status. */
661 return(status);
662 }
663
664
665 /**************************************************************************/
666 /* */
667 /* FUNCTION RELEASE */
668 /* */
669 /* _nx_auto_ip_stop PORTABLE C */
670 /* 6.1 */
671 /* AUTHOR */
672 /* */
673 /* Yuxin Zhou, Microsoft Corporation */
674 /* */
675 /* DESCRIPTION */
676 /* */
677 /* This function stops the AutoIP thread of a previously created and */
678 /* started AutoIP instance. */
679 /* */
680 /* INPUT */
681 /* */
682 /* auto_ip_ptr Pointer to AutoIP instance */
683 /* */
684 /* OUTPUT */
685 /* */
686 /* Completion Status */
687 /* */
688 /* CALLS */
689 /* */
690 /* tx_thread_suspend Suspend AutoIP thread */
691 /* */
692 /* CALLED BY */
693 /* */
694 /* Application */
695 /* */
696 /* RELEASE HISTORY */
697 /* */
698 /* DATE NAME DESCRIPTION */
699 /* */
700 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
701 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
702 /* resulting in version 6.1 */
703 /* */
704 /**************************************************************************/
_nx_auto_ip_stop(NX_AUTO_IP * auto_ip_ptr)705 UINT _nx_auto_ip_stop(NX_AUTO_IP *auto_ip_ptr)
706 {
707
708 UINT status;
709
710
711 /* Suspend the AutoIP thread. */
712 status = tx_thread_suspend(&(auto_ip_ptr -> nx_auto_ip_thread));
713
714 /* Return status. */
715 return(status);
716 }
717
718
719 /**************************************************************************/
720 /* */
721 /* FUNCTION RELEASE */
722 /* */
723 /* _nxe_auto_ip_delete PORTABLE C */
724 /* 6.1 */
725 /* AUTHOR */
726 /* */
727 /* Yuxin Zhou, Microsoft Corporation */
728 /* */
729 /* DESCRIPTION */
730 /* */
731 /* This function checks for errors in the AutoIP delete function */
732 /* call. */
733 /* */
734 /* INPUT */
735 /* */
736 /* auto_ip_ptr Pointer to AutoIP instance */
737 /* */
738 /* OUTPUT */
739 /* */
740 /* status Completion status */
741 /* */
742 /* CALLS */
743 /* */
744 /* _nx_auto_ip_delete AutoIP delete function */
745 /* */
746 /* CALLED BY */
747 /* */
748 /* Application Code */
749 /* */
750 /* RELEASE HISTORY */
751 /* */
752 /* DATE NAME DESCRIPTION */
753 /* */
754 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
755 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
756 /* resulting in version 6.1 */
757 /* */
758 /**************************************************************************/
_nxe_auto_ip_delete(NX_AUTO_IP * auto_ip_ptr)759 UINT _nxe_auto_ip_delete(NX_AUTO_IP *auto_ip_ptr)
760 {
761
762 UINT status;
763
764
765 /* Check for invalid input pointers. */
766 if ((auto_ip_ptr == NX_NULL) || (auto_ip_ptr -> nx_auto_ip_id != NX_AUTO_IP_ID))
767 return(NX_PTR_ERROR);
768
769 /* Check for appropriate caller. */
770 NX_THREADS_ONLY_CALLER_CHECKING
771
772 /* Call actual AutoIP delete routine. */
773 status = _nx_auto_ip_delete(auto_ip_ptr);
774
775 /* Return status. */
776 return(status);
777 }
778
779
780 /**************************************************************************/
781 /* */
782 /* FUNCTION RELEASE */
783 /* */
784 /* _nx_auto_ip_delete PORTABLE C */
785 /* 6.1 */
786 /* AUTHOR */
787 /* */
788 /* Yuxin Zhou, Microsoft Corporation */
789 /* */
790 /* DESCRIPTION */
791 /* */
792 /* This function deletes the previously created and stopped AutoIP */
793 /* AutoIP instance. */
794 /* */
795 /* INPUT */
796 /* */
797 /* auto_ip_ptr Pointer to AutoIP instance */
798 /* */
799 /* OUTPUT */
800 /* */
801 /* Completion Status */
802 /* */
803 /* CALLS */
804 /* */
805 /* tx_event_flags_delete Delete event flags */
806 /* tx_thread_delete Delete AutoIP thread */
807 /* tx_thread_terminate Terminate AutoIP thread */
808 /* */
809 /* CALLED BY */
810 /* */
811 /* Application */
812 /* */
813 /* RELEASE HISTORY */
814 /* */
815 /* DATE NAME DESCRIPTION */
816 /* */
817 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
818 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
819 /* resulting in version 6.1 */
820 /* */
821 /**************************************************************************/
_nx_auto_ip_delete(NX_AUTO_IP * auto_ip_ptr)822 UINT _nx_auto_ip_delete(NX_AUTO_IP *auto_ip_ptr)
823 {
824
825 NX_IP *ip_ptr;
826
827
828 /* First, set the ID to show it is invalid. */
829 auto_ip_ptr -> nx_auto_ip_id = 0;
830
831 /* Pickup the IP pointer. */
832 ip_ptr = auto_ip_ptr -> nx_auto_ip_ip_ptr;
833
834 /* Get IP mutex so IP conflict notification can be setup. */
835 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
836
837 /* Clear the handler to avoid conflict notification callbacks. */
838 ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_ip_conflict_notify_handler = NX_NULL;
839 ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_ip_probe_address = 0;
840
841 /* Release the IP internal mutex. */
842 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
843
844 /* Terminate the AutoIP thread. */
845 tx_thread_terminate(&(auto_ip_ptr -> nx_auto_ip_thread));
846
847 /* Delete the AutoIP thread. */
848 tx_thread_delete(&(auto_ip_ptr -> nx_auto_ip_thread));
849
850 /* Delete the AutoIP event flags. */
851 tx_event_flags_delete(&(auto_ip_ptr -> nx_auto_ip_conflict_event));
852
853 /* Return success. */
854 return(NX_SUCCESS);
855 }
856
857
858 /**************************************************************************/
859 /* */
860 /* FUNCTION RELEASE */
861 /* */
862 /* _nx_auto_ip_thread_entry PORTABLE C */
863 /* 6.1.11 */
864 /* AUTHOR */
865 /* */
866 /* Yuxin Zhou, Microsoft Corporation */
867 /* */
868 /* DESCRIPTION */
869 /* */
870 /* This function is the entry point of the AutoIP thread. All AutoIP */
871 /* actions are coordinated by this thread. */
872 /* */
873 /* INPUT */
874 /* */
875 /* auto_ip_ptr Pointer to AutoIP instance */
876 /* */
877 /* OUTPUT */
878 /* */
879 /* None */
880 /* */
881 /* CALLS */
882 /* */
883 /* _nx_auto_ip_arp_packet_send Send AutoIP probe and */
884 /* announce ARP messages */
885 /* nx_ip_interface_address_set Set interface address */
886 /* nx_ip_interface_status_check Get interface status */
887 /* tx_event_flags_get Get event flags */
888 /* tx_mutex_get Get IP protection */
889 /* tx_mutex_put Put IP protection */
890 /* tx_thread_sleep Thread sleep */
891 /* */
892 /* CALLED BY */
893 /* */
894 /* ThreadX */
895 /* */
896 /* RELEASE HISTORY */
897 /* */
898 /* DATE NAME DESCRIPTION */
899 /* */
900 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
901 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
902 /* resulting in version 6.1 */
903 /* 04-25-2022 Yuxin Zhou Modified comment(s), */
904 /* fixed compiler warnings, */
905 /* resulting in version 6.1.11 */
906 /* */
907 /**************************************************************************/
_nx_auto_ip_thread_entry(ULONG auto_ip_ptr_info)908 VOID _nx_auto_ip_thread_entry(ULONG auto_ip_ptr_info)
909 {
910
911 NX_AUTO_IP *auto_ip_ptr;
912 NX_IP *ip_ptr;
913 UINT i, status;
914 ULONG addresses;
915 ULONG conflict;
916 ULONG temp;
917 ULONG delay;
918 ULONG hw_address_lsw;
919 ULONG host_ip_address;
920
921
922 /* Pickup the AutoIP pointer. */
923 auto_ip_ptr = (NX_AUTO_IP *) auto_ip_ptr_info;
924
925 /* Pickup the associated IP pointer. */
926 ip_ptr = auto_ip_ptr -> nx_auto_ip_ip_ptr;
927
928 /* Wait for the IP instance to be initialized before proceeding. This will ensure the
929 MAC address is valid before a random local IP address is generated. */
930 nx_ip_interface_status_check(ip_ptr, auto_ip_ptr -> nx_ip_interface_index, NX_IP_LINK_ENABLED, &temp, NX_WAIT_FOREVER);
931
932 /* Set LSW of hardware address */
933 hw_address_lsw = ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_physical_address_lsw;
934
935 /* Setup the conflict flag to false. */
936 conflict = NX_FALSE;
937
938 /* Loop forever inside the AutoIP thread! */
939 while(1)
940 {
941
942 /* Probe for local IP address use! */
943
944 /* Update the local variable in case anything has changed. */
945 host_ip_address = ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_ip_address;
946
947 /* Wait until the IP address is non-zero. The only way this can be non-zero is
948 if the application has changed it or it was resolved by the DHCP protocol. */
949 while (host_ip_address)
950 {
951
952 /* Sleep for the maximum probe period. */
953 tx_thread_sleep(NX_IP_PERIODIC_RATE * NX_AUTO_IP_PROBE_MAX);
954
955 /* Get the IP address from the IP task and see if it has changed from non zero. */
956 host_ip_address = ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_ip_address;
957 }
958
959 /* Determine if the restart flag is set. */
960 if (auto_ip_ptr -> nx_auto_ip_restart_flag)
961 {
962
963 /* Clear the restart flag. */
964 auto_ip_ptr -> nx_auto_ip_restart_flag = NX_FALSE;
965
966 /* Reset the conflict count. */
967 auto_ip_ptr -> nx_auto_ip_conflict_count = 0;
968
969 /* Clear the conflict flag, since we might have an new starting local IP address. */
970 conflict = NX_FALSE;
971 }
972
973 /* Determine if a conflict condition is present. This flag is set at various places
974 below. */
975 if (conflict)
976 {
977
978 /* Yes, a conflict was detected. */
979
980 /* Increment the conflict count. */
981 auto_ip_ptr -> nx_auto_ip_conflict_count++;
982
983 /* Determine if we have reached the maximum number of conflicts. */
984 if (auto_ip_ptr -> nx_auto_ip_conflict_count > NX_AUTO_IP_MAX_CONFLICTS)
985 {
986
987 /* Yes, we have had excessive conflicts... we must now add extra delay. */
988 tx_thread_sleep(NX_IP_PERIODIC_RATE * NX_AUTO_IP_RATE_LIMIT_INTERVAL);
989 }
990
991 /* Clear the the local IP address in order to generate another random one. */
992 auto_ip_ptr -> nx_auto_ip_current_local_address = 0;
993
994 /* Clear the conflict flag. */
995 conflict = NX_FALSE;
996 }
997
998 /* Determine if a starting local IP address needs to be derived. */
999 if (auto_ip_ptr -> nx_auto_ip_current_local_address == 0)
1000 {
1001
1002 /* Yes, the starting local IP address must be derived. */
1003
1004 /* Get pseudo random value with LSW of MAC address. */
1005 temp = ((ULONG) NX_RAND()) + hw_address_lsw;
1006
1007 /* Determine the address range of local IP addresses. */
1008 addresses = NX_AUTO_IP_END_ADDRESS - NX_AUTO_IP_START_ADDRESS;
1009
1010 /* Make sure that the random number fits within this range. */
1011 temp = temp % addresses;
1012
1013 /* Now create a starting local IP address. */
1014 auto_ip_ptr -> nx_auto_ip_current_local_address = NX_AUTO_IP_START_ADDRESS + temp;
1015 }
1016
1017 /* Register with NetX for ARP conflict detection for this local IP address. */
1018
1019 /* Get IP mutex so ARP notification can be setup. */
1020 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
1021
1022 /* Finally, setup the handler to indicate the we want collision notification. */
1023 ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_ip_conflict_notify_handler = _nx_auto_ip_conflict;
1024
1025 /* Clear any outstanding events. */
1026 tx_event_flags_get(&(auto_ip_ptr -> nx_auto_ip_conflict_event), 0x1, TX_OR_CLEAR, &temp, TX_NO_WAIT);
1027
1028 /* Release the IP internal mutex. */
1029 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
1030
1031 /* Calculate the delay time. */
1032 delay = (ULONG)NX_RAND() % (NX_IP_PERIODIC_RATE * NX_AUTO_IP_PROBE_WAIT);
1033
1034 /* Sleep for a small period of time. */
1035 tx_thread_sleep(delay);
1036
1037 /* Loop to probe for the specified local IP address. */
1038 for (i = 0; i < NX_AUTO_IP_PROBE_NUM; i++)
1039 {
1040
1041 /* Increment the total probe count. */
1042 auto_ip_ptr -> nx_auto_ip_probe_count++;
1043
1044 /* Send the ARP probe. */
1045 _nx_arp_probe_send(ip_ptr, auto_ip_ptr -> nx_ip_interface_index, auto_ip_ptr -> nx_auto_ip_current_local_address);
1046
1047 /* Calculate the delay time. */
1048 delay = ((ULONG) NX_RAND()) % (NX_IP_PERIODIC_RATE * NX_AUTO_IP_PROBE_MAX);
1049
1050 /* Determine if this is less than the minimum. */
1051 if (delay < (NX_IP_PERIODIC_RATE * NX_AUTO_IP_PROBE_MIN))
1052 {
1053
1054 /* Set the delay to the minimum. */
1055 delay = (NX_IP_PERIODIC_RATE * NX_AUTO_IP_PROBE_MIN);
1056 }
1057
1058 /* Delay by waiting for conflict events before sending the next ARP probe. This event is
1059 set by the conflict callback function when an ARP entry is received that matches
1060 the registered address. */
1061 status = tx_event_flags_get(&(auto_ip_ptr -> nx_auto_ip_conflict_event), 0x1, TX_OR_CLEAR, &temp, delay);
1062
1063 /* Determine if conflict was detected. */
1064 if (status == NX_SUCCESS)
1065 {
1066
1067 /* Yes, a conflict is present. */
1068
1069 /* Set the conflict flag and get out of the loop. */
1070 conflict = NX_TRUE;
1071 break;
1072 }
1073
1074 /* Update the local variable in case anything has changed. */
1075 host_ip_address = ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_ip_address;
1076
1077 /* Check for a restart or an IP address change. */
1078 if (host_ip_address || (auto_ip_ptr -> nx_auto_ip_restart_flag))
1079 break;
1080 }
1081
1082 /* Determine if there was a conflict. If so, continue at the top of the loop. */
1083 if (conflict)
1084 {
1085
1086 #ifdef NX_AUTO_IP_DEBUG
1087 printf("AutoIP %s, CONFLICT for: %lu,%lu,%lu,%lu\n", auto_ip_ptr -> nx_auto_ip_name,
1088 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 24),
1089 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 16 & 0xFF),
1090 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 8 & 0xFF),
1091 (auto_ip_ptr -> nx_auto_ip_current_local_address & 0xFF));
1092 #endif
1093 continue;
1094 }
1095
1096 /* Check for a restart or an IP address change. */
1097 if (host_ip_address || (auto_ip_ptr -> nx_auto_ip_restart_flag))
1098 continue;
1099
1100 /* At this point, the local IP address has been successfully probed via ARP messages without
1101 any collisions. It is now time to go into an announce phase to indicate local IP address
1102 is ours! */
1103
1104 #ifdef NX_AUTO_IP_DEBUG
1105 printf("AutoIP %s, RESOLVED for: %lu,%lu,%lu,%lu\n", auto_ip_ptr -> nx_auto_ip_name,
1106 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 24),
1107 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 16 & 0xFF),
1108 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 8 & 0xFF),
1109 (auto_ip_ptr -> nx_auto_ip_current_local_address & 0xFF));
1110 #endif
1111
1112 /* Set the NetX IP address. */
1113 nx_ip_interface_address_set(ip_ptr, auto_ip_ptr -> nx_ip_interface_index, auto_ip_ptr -> nx_auto_ip_current_local_address, 0xFFFF0000);
1114
1115 /* Delay before announcing: NX_AUTO_IP_ANNOUNCE_WAIT. */
1116 tx_thread_sleep(NX_IP_PERIODIC_RATE * NX_AUTO_IP_ANNOUNCE_WAIT);
1117
1118 /* It is now time to go into an announce phase to indicate local IP address is ours! */
1119 for (i = 0; i < NX_AUTO_IP_ANNOUNCE_NUM; i++)
1120 {
1121
1122 /* Increment the total announcement count. */
1123 auto_ip_ptr -> nx_auto_ip_announce_count++;
1124
1125 /* Send the ARP announcement. */
1126 _nx_arp_announce_send(ip_ptr, auto_ip_ptr -> nx_ip_interface_index);
1127
1128 /* Calculate the delay time. */
1129 delay = (NX_IP_PERIODIC_RATE * NX_AUTO_IP_ANNOUNCE_INTERVAL);
1130
1131 /* Delay by waiting for conflict events before sending the next ARP announcement. This event is
1132 set by the conflict callback function when an ARP entry is received that matches
1133 the registered address. */
1134 status = tx_event_flags_get(&(auto_ip_ptr -> nx_auto_ip_conflict_event), 0x1, TX_OR_CLEAR, &temp, delay);
1135
1136 /* Determine if conflict was detected. */
1137 if (status == NX_SUCCESS)
1138 {
1139
1140 /* Yes, a conflict is present. */
1141
1142 /* Set the conflict flag and get out of the loop. */
1143 conflict = NX_TRUE;
1144 break;
1145 }
1146 }
1147
1148 /* Determine if there was a conflict. If so, continue at the top of the loop. */
1149 if (conflict)
1150 {
1151
1152 #ifdef NX_AUTO_IP_DEBUG
1153 printf("AutoIP %s, CONFLICT for: %lu,%lu,%lu,%lu\n", auto_ip_ptr -> nx_auto_ip_name,
1154 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 24),
1155 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 16 & 0xFF),
1156 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 8 & 0xFF),
1157 (auto_ip_ptr -> nx_auto_ip_current_local_address & 0xFF));
1158 #endif
1159
1160 /* Conflict, clear the IP address. */
1161 nx_ip_interface_address_set(ip_ptr, auto_ip_ptr -> nx_ip_interface_index, 0, 0);
1162
1163 continue;
1164 }
1165
1166 /* Now, wait infinitely for another conflict situation. */
1167 tx_event_flags_get(&(auto_ip_ptr -> nx_auto_ip_conflict_event), 0x1, TX_OR_CLEAR, &temp, TX_WAIT_FOREVER);
1168
1169 /* Update the local variable in case anything has changed. */
1170 host_ip_address = ip_ptr -> nx_ip_interface[auto_ip_ptr -> nx_ip_interface_index].nx_interface_ip_address;
1171
1172 /* Determine if a conflict is present. */
1173
1174 /* If we get here a late conflict is present. */
1175 if (auto_ip_ptr -> nx_auto_ip_current_local_address == host_ip_address)
1176 {
1177
1178 /* Increment the total defend count. */
1179 auto_ip_ptr -> nx_auto_ip_defend_count++;
1180
1181 #ifdef NX_AUTO_IP_DEBUG
1182 printf("AutoIP %s, DEFEND for: %lu,%lu,%lu,%lu\n", auto_ip_ptr -> nx_auto_ip_name,
1183 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 24),
1184 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 16 & 0xFF),
1185 (auto_ip_ptr -> nx_auto_ip_current_local_address >> 8 & 0xFF),
1186 (auto_ip_ptr -> nx_auto_ip_current_local_address & 0xFF));
1187 #endif
1188
1189 /* No defense currently, just clear the IP address once a late collision is detected
1190 and start over. */
1191 nx_ip_interface_address_set(ip_ptr, auto_ip_ptr -> nx_ip_interface_index, 0, 0);
1192
1193 /* Set the conflict flag. */
1194 conflict = NX_TRUE;
1195 }
1196 }
1197 }
1198
1199
1200 /**************************************************************************/
1201 /* */
1202 /* FUNCTION RELEASE */
1203 /* */
1204 /* _nx_auto_ip_conflict PORTABLE C */
1205 /* 6.1 */
1206 /* AUTHOR */
1207 /* */
1208 /* Yuxin Zhou, Microsoft Corporation */
1209 /* */
1210 /* DESCRIPTION */
1211 /* */
1212 /* This function notifies the AutoIP instance that a conflict was */
1213 /* detected by the NetX ARP receive packet handling routine. */
1214 /* */
1215 /* INPUT */
1216 /* */
1217 /* ip_ptr IP instance pointer */
1218 /* interface_index IP Interface Index */
1219 /* ip_address IP Address to bind to */
1220 /* physical_msw Physical address MSW */
1221 /* physical_lsw Physical address LSW */
1222 /* */
1223 /* OUTPUT */
1224 /* */
1225 /* None */
1226 /* */
1227 /* CALLS */
1228 /* */
1229 /* tx_event_flags_set Set event flags */
1230 /* */
1231 /* CALLED BY */
1232 /* */
1233 /* NetX */
1234 /* */
1235 /* RELEASE HISTORY */
1236 /* */
1237 /* DATE NAME DESCRIPTION */
1238 /* */
1239 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1240 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1241 /* resulting in version 6.1 */
1242 /* */
1243 /**************************************************************************/
_nx_auto_ip_conflict(NX_IP * ip_ptr,UINT interface_index,ULONG ip_address,ULONG physical_msw,ULONG physical_lsw)1244 VOID _nx_auto_ip_conflict(NX_IP *ip_ptr, UINT interface_index, ULONG ip_address, ULONG physical_msw, ULONG physical_lsw)
1245 {
1246
1247 NX_PARAMETER_NOT_USED(ip_ptr);
1248 NX_PARAMETER_NOT_USED(interface_index);
1249 NX_PARAMETER_NOT_USED(ip_address);
1250 NX_PARAMETER_NOT_USED(physical_msw);
1251 NX_PARAMETER_NOT_USED(physical_lsw);
1252
1253 /* Set the event flags to indicate that a collision was detected by NetX ARP processing. */
1254 tx_event_flags_set(&(_nx_auto_ip_ptr -> nx_auto_ip_conflict_event), 0x1, TX_OR);
1255 }
1256 #endif /* NX_DISABLE_IPV4 */
1257