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 /** Reverse Address Resolution Protocol (RARP) */
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_rarp.h"
29 #include "nx_packet.h"
30
31 #ifndef NX_DISABLE_IPV4
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _nx_rarp_packet_receive PORTABLE C */
37 /* 6.1.11 */
38 /* AUTHOR */
39 /* */
40 /* Yuxin Zhou, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function processes the reception of both the RARP request and */
45 /* the RARP response. RARP responses received are used to setup the */
46 /* the IP address of this IP instance. Once the IP address is setup, */
47 /* RARP is automatically disabled. RARP requests are discarded */
48 /* at present time. */
49 /* */
50 /* INPUT */
51 /* */
52 /* ip_ptr Pointer to IP instance */
53 /* packet_ptr Received RARP packet */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* None */
58 /* */
59 /* CALLS */
60 /* */
61 /* _nx_packet_release Release the RARP request */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* _nx_rarp_queue_process RARP receive queue processing */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
72 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
73 /* resulting in version 6.1 */
74 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
75 /* added internal ip address */
76 /* change notification, */
77 /* resulting in version 6.1.11 */
78 /* */
79 /**************************************************************************/
_nx_rarp_packet_receive(NX_IP * ip_ptr,NX_PACKET * packet_ptr)80 VOID _nx_rarp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
81 {
82
83 TX_INTERRUPT_SAVE_AREA
84
85 ULONG *message_ptr;
86 UINT i;
87 VOID (*address_change_notify)(NX_IP *, VOID *) = NX_NULL;
88 VOID *additional_info = NX_NULL;
89 VOID (*address_change_notify_internal)(NX_IP *, VOID *) = NX_NULL;
90
91
92 #ifndef NX_DISABLE_RX_SIZE_CHECKING
93 /* Determine if the packet length is valid. */
94 if (packet_ptr -> nx_packet_length < NX_RARP_MESSAGE_SIZE)
95 {
96
97 #ifndef NX_DISABLE_RARP_INFO
98 /* Increment the RARP invalid messages count... At least until RARP server
99 logic is added. */
100 ip_ptr -> nx_ip_rarp_invalid_messages++;
101 #endif
102
103 /* Just release the packet. */
104 _nx_packet_release(packet_ptr);
105
106 /* Return to caller. */
107 return;
108 }
109 #endif /* NX_DISABLE_RX_SIZE_CHECKING */
110
111 /* Setup a pointer to the RARP message. */
112 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
113 message_ptr = (ULONG *)packet_ptr -> nx_packet_prepend_ptr;
114
115 /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will
116 swap the endian of the RARP message. */
117 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 1));
118 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 2));
119 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 3));
120 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 4));
121 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 5));
122 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 6));
123
124 /* If trace is enabled, insert this event into the trace buffer. */
125 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_RARP_RECEIVE, ip_ptr, *(message_ptr + 6), packet_ptr, *(message_ptr + 1), NX_TRACE_INTERNAL_EVENTS, 0, 0);
126
127 /* Determine what type of RARP message this is. Note that RARP requests must
128 also specify this IP instance's IP address. */
129 if ((*(message_ptr + 1) & 0xFFFF) == NX_RARP_OPTION_REQUEST)
130 {
131
132 #ifndef NX_DISABLE_RARP_INFO
133 /* Increment the RARP invalid messages count... At least until RARP server
134 logic is added. */
135 ip_ptr -> nx_ip_rarp_invalid_messages++;
136 #endif
137
138 /* Just release the packet. */
139 _nx_packet_release(packet_ptr);
140 }
141 else if ((*(message_ptr + 1) & 0xFFFF) == NX_RARP_OPTION_RESPONSE)
142 {
143
144 /* We have a response to a previous RARP request. */
145
146 #ifndef NX_DISABLE_ARP_INFO
147 /* Increment the RARP responses received count. */
148 ip_ptr -> nx_ip_rarp_responses_received++;
149 #endif
150
151 /* Disable Interrupts. */
152 TX_DISABLE
153
154 /* Determine if the target IP address is non-zero. */
155 if (*(message_ptr + 6) && (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address == 0))
156 {
157
158 /* Pickup the current notification callback and additional information pointers. */
159 address_change_notify = ip_ptr -> nx_ip_address_change_notify;
160 additional_info = ip_ptr -> nx_ip_address_change_notify_additional_info;
161
162 /* Pickup the internal notification callback. */
163 address_change_notify_internal = ip_ptr -> nx_ip_address_change_notify_internal;
164
165 /* Set the IP address of this IP instance to the target
166 IP address in the RARP response. */
167 packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address = *(message_ptr + 6);
168
169 /* Loop through all the interfaces and check whether or not to continue periodic RARP requests. */
170 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
171 {
172
173 /* Skip the invalid interface entry. */
174 if (ip_ptr -> nx_ip_interface[i].nx_interface_valid == 0)
175 {
176 continue;
177 }
178
179 /* Look for any interfaces still without a valid IP address. */
180 if ((ip_ptr -> nx_ip_interface[i].nx_interface_ip_address == 0) &&
181 (ip_ptr -> nx_ip_interface[i].nx_interface_address_mapping_needed == NX_TRUE))
182 {
183 /* At least one interface still has non-zero IP address. Continue RARP process. */
184 break;
185 }
186 }
187
188 /* Do we need to continue with periodic RARP requests? */
189 if (i >= NX_MAX_PHYSICAL_INTERFACES)
190 {
191
192 /* No, Disable the RARP activity now that we have a valid IP address. */
193 ip_ptr -> nx_ip_rarp_periodic_update = NX_NULL;
194 ip_ptr -> nx_ip_rarp_queue_process = NX_NULL;
195 }
196 }
197
198 /* Restore interrupts. */
199 TX_RESTORE
200
201 /* Release the RARP response packet. */
202 _nx_packet_release(packet_ptr);
203 }
204 else
205 {
206
207 #ifndef NX_DISABLE_RARP_INFO
208 /* Increment the RARP invalid messages count. */
209 ip_ptr -> nx_ip_rarp_invalid_messages++;
210 #endif
211
212 /* Invalid RARP message. Just release the packet. */
213 _nx_packet_release(packet_ptr);
214 }
215
216 /* Determine if the application should be notified of the IP address change. */
217 if (address_change_notify != NX_NULL)
218 {
219 /* Yes, call the application's IP address change notify function. */
220 (address_change_notify)(ip_ptr, additional_info);
221 }
222
223 /* Determine if the internal application should be notified of the IP address change. */
224 if (address_change_notify_internal != NX_NULL)
225 {
226 /* Yes, call the internal application's IP address change notify function. */
227 (address_change_notify_internal)(ip_ptr, NX_NULL);
228 }
229
230 return;
231 }
232 #endif /* !NX_DISABLE_IPV4 */
233
234