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