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 #include "nx_packet.h"
30 
31 #ifndef NX_DISABLE_IPV4
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _nx_arp_packet_send                                 PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Yuxin Zhou, Microsoft Corporation                                   */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function builds an ARP packet and calls the associated driver  */
45 /*    to send it out on the specified network interface.                  */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    ip_ptr                                Pointer to IP instance        */
50 /*    destination_ip                        Destination IP address        */
51 /*    nx_interface                          Interface to transmit out     */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    None                                                                */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _nx_packet_allocate                   Allocate a packet for the     */
60 /*                                            ARP request                 */
61 /*    [ip_link_driver]                      User supplied link driver     */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    NetX Source Code                                                    */
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 /*                                                                        */
75 /**************************************************************************/
_nx_arp_packet_send(NX_IP * ip_ptr,ULONG destination_ip,NX_INTERFACE * nx_interface)76 VOID  _nx_arp_packet_send(NX_IP *ip_ptr, ULONG destination_ip, NX_INTERFACE *nx_interface)
77 {
78 
79 NX_PACKET   *request_ptr;
80 ULONG       *message_ptr;
81 NX_IP_DRIVER driver_request;
82 
83     /* nx_interface must not be NX_NULL. */
84     NX_ASSERT(nx_interface != NX_NULL);
85 
86     /* Allocate a packet to build the ARP message in.  */
87 #ifdef NX_ENABLE_DUAL_PACKET_POOL
88     /* Allocate from auxiliary packet pool first. */
89     if (_nx_packet_allocate(ip_ptr -> nx_ip_auxiliary_packet_pool, &request_ptr, (NX_PHYSICAL_HEADER + NX_ARP_MESSAGE_SIZE), NX_NO_WAIT))
90     {
91         if (ip_ptr -> nx_ip_auxiliary_packet_pool != ip_ptr -> nx_ip_default_packet_pool)
92 #endif /* NX_ENABLE_DUAL_PACKET_POOL */
93         {
94             if (_nx_packet_allocate(ip_ptr -> nx_ip_default_packet_pool, &request_ptr, (NX_PHYSICAL_HEADER + NX_ARP_MESSAGE_SIZE), NX_NO_WAIT))
95             {
96 
97                 /* Error getting packet, so just get out!  */
98                 return;
99             }
100         }
101 #ifdef NX_ENABLE_DUAL_PACKET_POOL
102         else
103         {
104 
105             /* Error getting packet, so just get out!  */
106             return;
107         }
108     }
109 #endif /* NX_ENABLE_DUAL_PACKET_POOL */
110 
111     /* Add debug information. */
112     NX_PACKET_DEBUG(__FILE__, __LINE__, request_ptr);
113 
114     /* Stamp the packet with the outgoing interface information. */
115     /*lint -e{644} suppress variable might not be initialized, since "request_ptr" was initialized in _nx_packet_allocate. */
116     request_ptr -> nx_packet_address.nx_packet_interface_ptr = nx_interface;
117 
118 #ifndef NX_DISABLE_ARP_INFO
119     /* Increment the ARP requests sent count.  */
120     ip_ptr -> nx_ip_arp_requests_sent++;
121 #endif
122 
123     /* If trace is enabled, insert this event into the trace buffer.  */
124     NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_ARP_REQUEST_SEND, ip_ptr, destination_ip, request_ptr, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
125 
126     /* Build the ARP request packet.  */
127 
128     /* Setup the size of the ARP message.  */
129     request_ptr -> nx_packet_length =  NX_ARP_MESSAGE_SIZE;
130 
131     /* Setup the prepend pointer.  */
132     request_ptr -> nx_packet_prepend_ptr -= NX_ARP_MESSAGE_SIZE;
133 
134     /* Setup the pointer to the message area.  */
135     /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
136     message_ptr =  (ULONG *)request_ptr -> nx_packet_prepend_ptr;
137 
138     /* Write the Hardware type into the message.  */
139     *message_ptr =      (ULONG)(NX_ARP_HARDWARE_TYPE << 16) | (NX_ARP_PROTOCOL_TYPE);
140     *(message_ptr + 1) =  (ULONG)(NX_ARP_HARDWARE_SIZE << 24) | (NX_ARP_PROTOCOL_SIZE << 16) |
141         NX_ARP_OPTION_REQUEST;
142 
143     /*lint -e{613} suppress possible use of null pointer, since nx_interface must not be NULL.  */
144     *(message_ptr + 2) =  (ULONG)(nx_interface -> nx_interface_physical_address_msw << 16) |
145         (nx_interface -> nx_interface_physical_address_lsw >> 16);
146     *(message_ptr + 3) =  (ULONG)(nx_interface -> nx_interface_physical_address_lsw << 16) |
147         (nx_interface -> nx_interface_ip_address >> 16);
148     *(message_ptr + 4) =  (ULONG)(nx_interface -> nx_interface_ip_address << 16);
149     *(message_ptr + 5) =  (ULONG)0;
150     *(message_ptr + 6) =  (ULONG)destination_ip;
151 
152     /* Endian swapping logic.  If NX_LITTLE_ENDIAN is specified, these macros will
153        swap the endian of the ARP message.  */
154     NX_CHANGE_ULONG_ENDIAN(*(message_ptr));
155     NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 1));
156     NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 2));
157     NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 3));
158     NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 4));
159     NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 5));
160     NX_CHANGE_ULONG_ENDIAN(*(message_ptr + 6));
161 
162     /* Set up the driver request. */
163     driver_request.nx_ip_driver_ptr =                   ip_ptr;
164     driver_request.nx_ip_driver_command =               NX_LINK_ARP_SEND;
165     driver_request.nx_ip_driver_packet =                request_ptr;
166     driver_request.nx_ip_driver_physical_address_msw =  0xFFFFUL;
167     driver_request.nx_ip_driver_physical_address_lsw =  0xFFFFFFFFUL;
168     driver_request.nx_ip_driver_interface            =  nx_interface;
169 
170     /* If trace is enabled, insert this event into the trace buffer.  */
171     NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_ARP_SEND, ip_ptr, request_ptr, request_ptr -> nx_packet_length, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
172 
173     /* Add debug information. */
174     NX_PACKET_DEBUG(__FILE__, __LINE__, request_ptr);
175 
176     /* Send the ARP request to the driver.  */
177     /*lint -e{613} suppress possible use of null pointer, since nx_interface must not be NULL.  */
178     (nx_interface -> nx_interface_link_driver_entry)(&driver_request);
179 }
180 #endif /* !NX_DISABLE_IPV4  */
181 
182