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