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_send PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Yuxin Zhou, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function builds an RARP packet and calls the associated driver */
45 /* to send it out on the network. */
46 /* */
47 /* INPUT */
48 /* */
49 /* ip_ptr Pointer to IP instance */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* None */
54 /* */
55 /* CALLS */
56 /* */
57 /* _nx_packet_allocate Allocate a packet for the */
58 /* RARP request */
59 /* (ip_link_driver) User supplied link driver */
60 /* */
61 /* CALLED BY */
62 /* */
63 /* NetX Source Code */
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
70 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
71 /* resulting in version 6.1 */
72 /* */
73 /**************************************************************************/
_nx_rarp_packet_send(NX_IP * ip_ptr)74 VOID _nx_rarp_packet_send(NX_IP *ip_ptr)
75 {
76
77 NX_PACKET *request_ptr;
78 ULONG *message_ptr;
79 NX_IP_DRIVER driver_request;
80 ULONG i;
81
82
83 /* Determine which interfaces to send RARP packets out from (e.g. do not have IP addresses). */
84 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
85 {
86
87 /* Skip this interface if it is not initialized yet. */
88 if (ip_ptr -> nx_ip_interface[i].nx_interface_valid == 0)
89 {
90 continue;
91 }
92
93 /* If the interface has a valid address, skip it. */
94 if (ip_ptr -> nx_ip_interface[i].nx_interface_ip_address != 0)
95 {
96 continue;
97 }
98
99
100 /* Skip this interface if mapping is not required, i.e. the driver is not Ethernet-like. */
101 /*lint -e{539} suppress positive indentation. */
102 if (ip_ptr -> nx_ip_interface[i].nx_interface_address_mapping_needed == 0)
103 {
104 continue;
105 }
106
107 /* Allocate a packet to build the RARP message in. */
108 #ifdef NX_ENABLE_DUAL_PACKET_POOL
109 /* Allocate from auxiliary packet pool first. */
110 if (_nx_packet_allocate(ip_ptr -> nx_ip_auxiliary_packet_pool, &request_ptr, (NX_PHYSICAL_HEADER + NX_RARP_MESSAGE_SIZE), NX_NO_WAIT))
111 {
112 if (ip_ptr -> nx_ip_auxiliary_packet_pool != ip_ptr -> nx_ip_default_packet_pool)
113 #endif /* NX_ENABLE_DUAL_PACKET_POOL */
114 {
115 if (_nx_packet_allocate(ip_ptr -> nx_ip_default_packet_pool, &request_ptr, (NX_PHYSICAL_HEADER + NX_RARP_MESSAGE_SIZE), NX_NO_WAIT))
116 {
117
118 /* Error getting packet, so just get out! */
119 return;
120 }
121 }
122 #ifdef NX_ENABLE_DUAL_PACKET_POOL
123 else
124 {
125
126 /* Error getting packet, so just get out! */
127 return;
128 }
129 }
130 #endif /* NX_ENABLE_DUAL_PACKET_POOL */
131
132 /* Add debug information. */
133 NX_PACKET_DEBUG(__FILE__, __LINE__, request_ptr);
134
135 #ifndef NX_DISABLE_RARP_INFO
136 /* Increment the RARP requests sent count. */
137 ip_ptr -> nx_ip_rarp_requests_sent++;
138 #endif
139 /*lint -e{644} suppress variable might not be initialized, since "request_ptr" was initialized in _nx_packet_allocate. */
140 request_ptr -> nx_packet_address.nx_packet_interface_ptr = &(ip_ptr -> nx_ip_interface[i]);
141 /* Build the RARP request packet. */
142
143 /* Setup the size of the RARP message. */
144 request_ptr -> nx_packet_length = NX_RARP_MESSAGE_SIZE;
145
146 /* Setup the prepend pointer. */
147 request_ptr -> nx_packet_prepend_ptr -= NX_RARP_MESSAGE_SIZE;
148
149 /* Setup the pointer to the message area. */
150 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
151 message_ptr = (ULONG *)request_ptr -> nx_packet_prepend_ptr;
152
153 /* Write the Hardware type into the message. */
154 *message_ptr = (ULONG)(NX_RARP_HARDWARE_TYPE << 16) | (NX_RARP_PROTOCOL_TYPE);
155 *(message_ptr + 1) = (ULONG)(NX_RARP_HARDWARE_SIZE << 24) | (NX_RARP_PROTOCOL_SIZE << 16) | NX_RARP_OPTION_REQUEST;
156 *(message_ptr + 2) = (ULONG)(request_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_physical_address_msw << 16) |
157 (request_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_physical_address_lsw >> 16);
158 *(message_ptr + 3) = (ULONG)(request_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_physical_address_lsw << 16);
159 *(message_ptr + 4) = (ULONG)(request_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_physical_address_msw & NX_LOWER_16_MASK);
160 *(message_ptr + 5) = (ULONG)(request_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_physical_address_lsw);
161 *(message_ptr + 6) = (ULONG)0;
162
163 /* If trace is enabled, insert this event into the trace buffer. */
164 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_RARP_SEND, ip_ptr, 0, request_ptr, *(message_ptr + 1), NX_TRACE_INTERNAL_EVENTS, 0, 0);
165
166 /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will
167 swap the endian of the RARP message. */
168 NX_CHANGE_ULONG_ENDIAN(*(message_ptr));
169 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 1));
170 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 2));
171 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 3));
172 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 4));
173 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 5));
174 NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 6));
175
176 /* Send the RARP request to the driver. */
177 driver_request.nx_ip_driver_ptr = ip_ptr;
178 driver_request.nx_ip_driver_command = NX_LINK_RARP_SEND;
179 driver_request.nx_ip_driver_packet = request_ptr;
180 driver_request.nx_ip_driver_physical_address_msw = 0xFFFFUL;
181 driver_request.nx_ip_driver_physical_address_lsw = 0xFFFFFFFFUL;
182 driver_request.nx_ip_driver_interface = request_ptr -> nx_packet_address.nx_packet_interface_ptr;
183
184 /* If trace is enabled, insert this event into the trace buffer. */
185 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_RARP_SEND, ip_ptr, request_ptr, request_ptr -> nx_packet_length, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
186
187 (request_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry)(&driver_request);
188 }
189
190 return;
191 }
192 #endif /* !NX_DISABLE_IPV4 */
193
194