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