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 /** Neighbor Discovery Cache */
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_nd_cache.h"
30
31 #ifdef FEATURE_NX_IPV6
32
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* nx_nd_cache_add PORTABLE C */
39 /* 6.1 */
40 /* AUTHOR */
41 /* */
42 /* Yuxin Zhou, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This internal function adds IPv6 and MAC mapping to the ND cache */
47 /* table. */
48 /* */
49 /* INPUT */
50 /* */
51 /* ip_ptr Pointer to the IP instance. */
52 /* dest_ip Pointer to the IP address. */
53 /* if_ptr Interface through which the neighbor can be*/
54 /* reached. */
55 /* mac Pointer to the MAC address to map to. */
56 /* IsStatic 1: the entry is manully configured, thus */
57 /* does not time out. */
58 /* 0: The entry is dynamically configured. */
59 /* status Initial status */
60 /* iface_address Interface associated with this entry. */
61 /* nd_cache_entry User specified storage space of pointer to */
62 /* the corresponding ND cache. */
63 /* */
64 /* OUTPUT */
65 /* */
66 /* status NX_SUCCESS: An ND cache entry has been */
67 /* added. nd_cache_entry contains valid */
68 /* value. */
69 /* NX_NOT_SUCCESSFUL: The ND cache entry */
70 /* cannot be added, or nd_cache_entry is */
71 /* NULL. */
72 /* */
73 /* CALLS */
74 /* */
75 /* tx_mutex_get Obtain protection mutex */
76 /* tx_mutex_put Release protection mutex */
77 /* _nx_nd_cache_add_entry Obtain an empty entry */
78 /* */
79 /* CALLED BY */
80 /* */
81 /* _nx_icmpv6_process_na Process NA message */
82 /* _nx_icmpv6_process_ns Process NS message */
83 /* _nx_icmpv6_process_ra Process RA message */
84 /* nx_icmpv6_process_redirect.c Process Redirect message */
85 /* nxd_nd_cache_entry_set.c User level service */
86 /* */
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 /**************************************************************************/
_nx_nd_cache_add(NX_IP * ip_ptr,ULONG * dest_ip,NX_INTERFACE * if_ptr,CHAR * mac,INT IsStatic,INT status,NXD_IPV6_ADDRESS * iface_address,ND_CACHE_ENTRY ** nd_cache_entry)97 UINT _nx_nd_cache_add(NX_IP *ip_ptr, ULONG *dest_ip, NX_INTERFACE *if_ptr, CHAR *mac, INT IsStatic,
98 INT status, NXD_IPV6_ADDRESS *iface_address,
99 ND_CACHE_ENTRY **nd_cache_entry)
100 {
101
102 USHORT *copy_from, *copy_to;
103 ND_CACHE_ENTRY *entry;
104
105
106 /* Initialize the return value. */
107 *nd_cache_entry = NX_NULL;
108
109 /* First find if there has a exit entry. */
110 if (_nx_nd_cache_find_entry(ip_ptr, dest_ip, &entry) != NX_SUCCESS)
111 {
112
113 /* Did not find a valid entry. Add one. */
114 if (_nx_nd_cache_add_entry(ip_ptr, dest_ip, iface_address, &entry) != NX_SUCCESS)
115 {
116
117 /* Can not add, return. */
118 return(NX_NOT_SUCCESSFUL);
119 }
120 }
121
122 /* At this point we know the entry is in the ND cache.
123 Finish up updating the rest of the information. */
124
125 /*lint -e{644} suppress variable might not be initialized, since "entry" was initialized in _nx_nd_cache_find_entry or _nx_nd_cache_add_entry. */
126 entry -> nx_nd_cache_is_static = IsStatic ? (UCHAR)1 : (UCHAR)0;
127
128 entry -> nx_nd_cache_interface_ptr = if_ptr;
129
130 /* If the entry is already in reachable state, and the link layer address
131 is the same, we should not update the status field. */
132 /*lint -e{929} -e{740} suppress cast of pointer to pointer, since it is necessary */
133 copy_from = (USHORT *)mac;
134
135 /*lint -e{927} suppress cast of pointer to pointer, since it is necessary */
136 copy_to = (USHORT *)(entry -> nx_nd_cache_mac_addr);
137
138 /* Set the return value. */
139 *nd_cache_entry = entry;
140
141 if (entry -> nx_nd_cache_nd_status == ND_CACHE_STATE_REACHABLE)
142 {
143 /* Check mac address.*/
144 if ((copy_from[0] == copy_to[0]) &&
145 (copy_from[1] == copy_to[1]) &&
146 (copy_from[2] == copy_to[2]))
147 {
148
149 /* The MAC address is the same. So we are done. */
150
151 return(NX_SUCCESS);
152 }
153 }
154
155 /* Is this a static entry? */
156 if (IsStatic)
157 {
158
159 /* Just set the status, no need to update the cache entry timeout. */
160 entry -> nx_nd_cache_nd_status = (UCHAR)status;
161 }
162 /* Is the status changed? */
163 else if (entry -> nx_nd_cache_nd_status != (UCHAR)status)
164 {
165
166 /* Update status in the cache entry. */
167 entry -> nx_nd_cache_nd_status = (UCHAR)status;
168
169 if (entry -> nx_nd_cache_nd_status == ND_CACHE_STATE_REACHABLE) /* New entry */
170 {
171
172 /* Set the timer tick. The tick value only applies to the REACHABLE state. */
173 entry -> nx_nd_cache_timer_tick = ip_ptr -> nx_ipv6_reachable_timer;
174 }
175 }
176
177 /* Copy the MAC address. */
178 *copy_to = *copy_from;
179 copy_to++; copy_from++;
180 *copy_to = *copy_from;
181 copy_to++; copy_from++;
182 *copy_to = *copy_from;
183
184 return(NX_SUCCESS);
185 }
186
187 #endif /* FEATURE_NX_IPV6 */
188
189