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 /**   Internet Control Message Protocol (ICMP)                            */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "nx_api.h"
28 #include "nx_ipv6.h"
29 #include "nx_icmpv6.h"
30 
31 #ifdef NX_IPSEC_ENABLE
32 #include "nx_ipsec.h"
33 #endif /* NX_IPSEC_ENABLE */
34 
35 
36 #ifdef FEATURE_NX_IPV6
37 
38 
39 /**************************************************************************/
40 /*                                                                        */
41 /*  FUNCTION                                               RELEASE        */
42 /*                                                                        */
43 /*    _nx_icmpv6_perform_DAD                              PORTABLE C      */
44 /*                                                           6.1.11       */
45 /*  AUTHOR                                                                */
46 /*                                                                        */
47 /*    Yuxin Zhou, Microsoft Corporation                                   */
48 /*                                                                        */
49 /*  DESCRIPTION                                                           */
50 /*                                                                        */
51 /*    This function is called from IP thread periodic process routine.    */
52 /*    It starts the Duplicate Address Detection process if the interface  */
53 /*    address is in tentative state (not validated yet).  It does nothing */
54 /*    to an address if the state of the address is not tentative.         */
55 /*                                                                        */
56 /*  INPUT                                                                 */
57 /*                                                                        */
58 /*    ip_ptr                                Pointer to IP instance        */
59 /*                                                                        */
60 /*  OUTPUT                                                                */
61 /*                                                                        */
62 /*    None                                                                */
63 /*                                                                        */
64 /*  CALLS                                                                 */
65 /*                                                                        */
66 /*    _nx_icmpv6_DAD_clear_NDCache_entry   Remove entry from cache table  */
67 /*    _nx_icmpv6_send_ns                   Send a Neighbor Solicitation   */
68 /*                                                message                 */
69 /*    [ipv6_address_change_notify]         User callback fucntion         */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    _nx_ip_thraed_entry                                                 */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
80 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
81 /*                                            resulting in version 6.1    */
82 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
83 /*                                            added internal ip address   */
84 /*                                            change notification,        */
85 /*                                            resulting in version 6.1.11 */
86 /*                                                                        */
87 /**************************************************************************/
88 
89 #ifndef NX_DISABLE_IPV6_DAD
90 
_nx_icmpv6_perform_DAD(NX_IP * ip_ptr)91 VOID _nx_icmpv6_perform_DAD(NX_IP *ip_ptr)
92 {
93 
94 UINT              i;
95 NXD_IPV6_ADDRESS *nx_ipv6_address_next;
96 
97 #ifdef NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY
98 UINT              ipv6_addr_index;
99 #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */
100 
101     /* Go through all addresses bound to the IP instance. */
102     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
103     {
104 
105         /* Check if this interface valid. */
106         if (!ip_ptr -> nx_ip_interface[i].nxd_interface_ipv6_address_list_head)
107         {
108             continue;
109         }
110 
111         /* Only interested in addresses in the tentative state. */
112         for (nx_ipv6_address_next = ip_ptr -> nx_ip_interface[i].nxd_interface_ipv6_address_list_head;
113              nx_ipv6_address_next;
114              nx_ipv6_address_next = nx_ipv6_address_next -> nxd_ipv6_address_next)
115         {
116 
117             /* Check the address state. */
118             if (nx_ipv6_address_next -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_TENTATIVE)
119             {
120 
121                 /* Check if the number of NS messages is used up. */
122                 if (nx_ipv6_address_next -> nxd_ipv6_address_DupAddrDetectTransmit)
123                 {
124 
125                     /* No. This interface is still under DAD.  Transmit a NS */
126                     _nx_icmpv6_send_ns(ip_ptr,
127                                        nx_ipv6_address_next -> nxd_ipv6_address,
128                                        0, nx_ipv6_address_next, 0, NX_NULL);
129 
130                     nx_ipv6_address_next -> nxd_ipv6_address_DupAddrDetectTransmit--;
131                 }
132                 else
133                 {
134 
135                     /* So far we didn't get any conflict addresses back.
136                        So promote the address to VALID */
137 
138                     nx_ipv6_address_next -> nxd_ipv6_address_state = NX_IPV6_ADDR_STATE_VALID;
139                     _nx_icmpv6_DAD_clear_NDCache_entry(ip_ptr,
140                                                        nx_ipv6_address_next -> nxd_ipv6_address);
141 
142 #ifdef NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY
143                     /* If the callback function is set, invoke the callback function . */
144                     if (ip_ptr -> nx_ipv6_address_change_notify)
145                     {
146                         ipv6_addr_index = (ULONG)nx_ipv6_address_next -> nxd_ipv6_address_index;
147                         ip_ptr -> nx_ipv6_address_change_notify(ip_ptr, NX_IPV6_ADDRESS_DAD_SUCCESSFUL,
148                                                                 i, ipv6_addr_index, &nx_ipv6_address_next -> nxd_ipv6_address[0]);
149                     }
150 
151                     /* If the internal callback function is set, invoke the callback function . */
152                     if (ip_ptr -> nx_ipv6_address_change_notify_internal)
153                     {
154                         ipv6_addr_index = (ULONG)nx_ipv6_address_next -> nxd_ipv6_address_index;
155                         ip_ptr -> nx_ipv6_address_change_notify_internal(ip_ptr, NX_IPV6_ADDRESS_DAD_SUCCESSFUL,
156                                                                          i, ipv6_addr_index, &nx_ipv6_address_next -> nxd_ipv6_address[0]);
157                     }
158 #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */
159                 }
160             }
161         }
162     }
163 }
164 
165 #endif /* NX_DISABLE_IPV6_DAD */
166 
167 
168 #endif /* FEATURE_NX_IPV6 */
169 
170