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 /**   Address Resolution Protocol (ARP)                                   */
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_arp.h"
29 
30 #ifndef NX_DISABLE_IPV4
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _nx_arp_entry_allocate                              PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Yuxin Zhou, Microsoft Corporation                                   */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function allocates an ARP entry for a specific new IP          */
44 /*    destination.                                                        */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    ip_ptr                                IP instance pointer           */
49 /*    arp_list_ptr                          List head of where to place   */
50 /*                                            the newly allocated ARP     */
51 /*                                            entry                       */
52 /*    is_static                             Entry attribute static/dynamic*/
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    status                                Completion status             */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    _nx_arp_dynamic_entry_delete          Delete the dynamic entry      */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    NetX Source Code                                                    */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
71 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
72 /*                                            resulting in version 6.1    */
73 /*                                                                        */
74 /**************************************************************************/
_nx_arp_entry_allocate(NX_IP * ip_ptr,NX_ARP ** arp_list_ptr,UINT is_static)75 UINT  _nx_arp_entry_allocate(NX_IP *ip_ptr, NX_ARP **arp_list_ptr, UINT is_static)
76 {
77 
78 TX_INTERRUPT_SAVE_AREA
79 NX_ARP *arp_entry;
80 UINT    status;
81 
82 
83     /* Determine if there is an ARP entry available in the dynamic list.  */
84     if (ip_ptr -> nx_ip_arp_dynamic_list)
85     {
86 
87         /* Yes there are one or more free entries.  */
88 
89         /* Pickup pointer to last used dynamic ARP entry.  */
90         arp_entry =  (ip_ptr -> nx_ip_arp_dynamic_list) -> nx_arp_pool_previous;
91 
92         /* Remove from the dynamic list. */
93         _nx_arp_dynamic_entry_delete(ip_ptr, arp_entry);
94 
95         /* Disable interrupts temporarily.  */
96         TX_DISABLE
97 
98         /* Link the ARP entry at the head of the IP list.  */
99 
100         /* Determine if the ARP entry is being added to an empty list.  */
101         if (*arp_list_ptr)
102         {
103 
104             /* Add the ARP entry to the beginning of the nonempty ARP
105                list.  */
106             arp_entry -> nx_arp_active_list_head =  arp_list_ptr;
107             arp_entry -> nx_arp_active_next =      *arp_list_ptr;
108             arp_entry -> nx_arp_active_previous =  (*arp_list_ptr) -> nx_arp_active_previous;
109             (arp_entry -> nx_arp_active_previous) -> nx_arp_active_next =  arp_entry;
110             (*arp_list_ptr) -> nx_arp_active_previous =  arp_entry;
111         }
112         else
113         {
114             /* Empty list, just put the ARP entry at the beginning.  */
115             arp_entry -> nx_arp_active_list_head =  arp_list_ptr;
116             arp_entry -> nx_arp_active_next =       arp_entry;
117             arp_entry -> nx_arp_active_previous =   arp_entry;
118 
119             /* Now setup the list head.  */
120             *arp_list_ptr =  arp_entry;
121         }
122 
123         /* Determine if this is a static entry. */
124         if (is_static == NX_TRUE)
125         {
126 
127             /* Remove this entry from the ARP dynamic list.  */
128 
129             /* Determine if this is the only ARP entry on the dynamic list.  */
130             if (arp_entry == arp_entry -> nx_arp_pool_next)
131             {
132 
133                 /* Remove the sole entry from the dynamic list head.  */
134                 ip_ptr -> nx_ip_arp_dynamic_list =  NX_NULL;
135             }
136             else
137             {
138 
139                 /* Remove the entry from a list of more than one entry.  */
140 
141                 /* Update the links of the adjacent ARP dynamic pool entries.  */
142                 (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous = arp_entry -> nx_arp_pool_previous;
143                 (arp_entry -> nx_arp_pool_previous) -> nx_arp_pool_next = arp_entry -> nx_arp_pool_next;
144             }
145 
146             /* Add the entry to the ARP static list.  */
147 
148             /* Determine if the ARP static list is empty.  */
149             if (ip_ptr -> nx_ip_arp_static_list == NX_NULL)
150             {
151 
152                 /* Just place this single ARP entry on the list.  */
153                 arp_entry -> nx_arp_pool_next =     arp_entry;
154                 arp_entry -> nx_arp_pool_previous = arp_entry;
155                 ip_ptr -> nx_ip_arp_static_list =   arp_entry;
156             }
157             else
158             {
159 
160                 /* Add to the end of the ARP static list.  */
161                 arp_entry -> nx_arp_pool_next = ip_ptr -> nx_ip_arp_static_list;
162                 arp_entry -> nx_arp_pool_previous = (ip_ptr -> nx_ip_arp_static_list) -> nx_arp_pool_previous;
163                 ((ip_ptr -> nx_ip_arp_static_list) -> nx_arp_pool_previous) -> nx_arp_pool_next = arp_entry;
164                 (ip_ptr -> nx_ip_arp_static_list) -> nx_arp_pool_previous = arp_entry;
165             }
166 
167 #ifndef NX_DISABLE_ARP_INFO
168             /* Increment the ARP static entry count.  */
169             ip_ptr -> nx_ip_arp_static_entries++;
170 #endif
171         }
172         else  /* Allocate entry from dynamic list. */
173         {
174 
175             /* Move this ARP entry to the front of the general ARP dynamic entry pool.  */
176             if (arp_entry != ip_ptr -> nx_ip_arp_dynamic_list)
177             {
178 
179                 /* The current ARP entry is not at the front of the list, so it
180                    must be moved.  */
181 
182                 /* Link up the neighbors first.  */
183                 (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous = arp_entry -> nx_arp_pool_previous;
184                 (arp_entry -> nx_arp_pool_previous) -> nx_arp_pool_next = arp_entry -> nx_arp_pool_next;
185 
186                 /* Now link this ARP entry to the head of the list.  */
187                 arp_entry -> nx_arp_pool_next =  ip_ptr -> nx_ip_arp_dynamic_list;
188                 arp_entry -> nx_arp_pool_previous =    (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous;
189                 (arp_entry -> nx_arp_pool_previous) -> nx_arp_pool_next =  arp_entry;
190                 (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous =  arp_entry;
191 
192                 /* Now set the list head to this ARP entry.  */
193                 ip_ptr -> nx_ip_arp_dynamic_list =  arp_entry;
194             }
195 
196             /* Increment the number of active dynamic entries.  */
197             ip_ptr -> nx_ip_arp_dynamic_active_count++;
198         }
199 
200         /* Set the entry type.  */
201         arp_entry -> nx_arp_route_static = is_static;
202 
203         /* Restore interrupts.  */
204         TX_RESTORE
205 
206         /* Setup a successful status return.  */
207         status =  NX_SUCCESS;
208     }
209     else
210     {
211 
212         /* No more ARP entries are available, all the ARP entries must be
213            allocated on the static list.  */
214         status =  NX_NO_MORE_ENTRIES;
215     }
216 
217     /* Return status to the caller.  */
218     return(status);
219 }
220 #endif /* !NX_DISABLE_IPV4  */
221 
222