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 /**   Internet Control Message Protocol (ICMP)                            */
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_ip.h"
29 #include "nx_icmp.h"
30 #include "nx_packet.h"
31 #include "tx_thread.h"
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _nx_icmp_packet_receive                             PORTABLE C      */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Yuxin Zhou, Microsoft Corporation                                   */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function receives an ICMP packet from the IP receive           */
46 /*    processing.  If this routine is called from an ISR, it simply       */
47 /*    places the new message on the ICMP message queue, and wakes up the  */
48 /*    IP processing thread.  If this routine is called from the IP helper */
49 /*    thread, then the ICMP message is processed directly.                */
50 /*                                                                        */
51 /*  INPUT                                                                 */
52 /*                                                                        */
53 /*    ip_ptr                                Pointer to IP control block   */
54 /*    packet_ptr                            Pointer to packet to send     */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    None                                                                */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    _nx_icmp_packet_process               Process ICMP packet           */
63 /*    tx_event_flags_set                    Set event flags for IP helper */
64 /*                                            thread                      */
65 /*                                                                        */
66 /*  CALLED BY                                                             */
67 /*                                                                        */
68 /*    _nx_ip_packet_receive                 Dispatch received IP packets  */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
75 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
76 /*                                            resulting in version 6.1    */
77 /*                                                                        */
78 /**************************************************************************/
_nx_icmp_packet_receive(NX_IP * ip_ptr,NX_PACKET * packet_ptr)79 VOID  _nx_icmp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
80 {
81 #ifndef NX_DISABLE_IPV4
82 
83 TX_INTERRUPT_SAVE_AREA
84 
85 #ifdef NX_ENABLE_ICMP_ADDRESS_CHECK
86 NX_IPV4_HEADER *ip_header_ptr;
87 NX_INTERFACE   *interface_ptr;
88 #endif /* NX_ENABLE_ICMP_ADDRESS_CHECK  */
89 
90 
91     /* Add debug information. */
92     NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
93 
94 #ifndef NX_DISABLE_ICMP_INFO
95 
96     /* Increment the ICMP total messages received counter.  */
97     ip_ptr -> nx_ip_icmp_total_messages_received++;
98 #endif
99 
100 #ifndef NX_DISABLE_RX_SIZE_CHECKING
101 
102     /* Check for valid packet length.  */
103     if (packet_ptr -> nx_packet_length < sizeof(NX_ICMP_HEADER))
104     {
105 
106 #ifndef NX_DISABLE_ICMP_INFO
107 
108         /* Increment the ICMP invalid packet error.  */
109         ip_ptr -> nx_ip_icmp_invalid_packets++;
110 #endif
111 
112         /* Invalid packet length, just release it.  */
113         _nx_packet_release(packet_ptr);
114 
115         /* The function is complete, just return!  */
116         return;
117     }
118 #endif
119 
120 #ifdef NX_ENABLE_ICMP_ADDRESS_CHECK
121 
122     /* An ICMP Echo Request destined to an IP broadcast or IP multicast address
123        MAY be silently discarded.
124        RFC 1122, Section 3.2.2.6, Page42.  */
125 
126     /* Pickup the IP header and interface.  */
127     ip_header_ptr = (NX_IPV4_HEADER *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV4_HEADER));
128     interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
129 
130     if (
131         /* Check for Multicast address */
132         ((ip_header_ptr -> nx_ip_header_destination_ip & NX_IP_CLASS_D_MASK) == NX_IP_CLASS_D_TYPE) ||
133         /* Check for subnet-directed broadcast */
134         (((ip_header_ptr -> nx_ip_header_destination_ip & interface_ptr -> nx_interface_ip_network_mask) == interface_ptr -> nx_interface_ip_network) &&
135          ((ip_header_ptr -> nx_ip_header_destination_ip & ~(interface_ptr -> nx_interface_ip_network_mask)) == ~(interface_ptr -> nx_interface_ip_network_mask))) ||
136         /* Check for local subnet address */
137         (ip_header_ptr -> nx_ip_header_destination_ip == interface_ptr -> nx_interface_ip_network)  ||
138         /* Check for limited broadcast */
139         (ip_header_ptr -> nx_ip_header_destination_ip == NX_IP_LIMITED_BROADCAST)
140        )
141     {
142 
143 #ifndef NX_DISABLE_ICMP_INFO
144 
145         /* Increment the ICMP invalid packet error.  */
146         ip_ptr -> nx_ip_icmp_invalid_packets++;
147 #endif
148 
149         /* Invalid packet length, just release it.  */
150         _nx_packet_release(packet_ptr);
151 
152         /* The function is complete, just return!  */
153         return;
154     }
155 #endif /* NX_ENABLE_ICMP_ADDRESS_CHECK  */
156 
157     /* Determine if this routine is being called from an ISR.  */
158     if ((TX_THREAD_GET_SYSTEM_STATE()) || (&(ip_ptr -> nx_ip_thread) != _tx_thread_current_ptr))
159     {
160 
161         /* If system state is non-zero, we are in an ISR. If the current thread is not the IP thread,
162            we need to prevent unnecessary recursion in loopback. Just place the message at the
163            end of the ICMP message queue and wakeup the IP helper thread.  */
164 
165         /* Disable interrupts.  */
166         TX_DISABLE
167 
168         /* Add the packet to the ICMP message queue.  */
169         if (ip_ptr -> nx_ip_icmp_queue_head)
170         {
171 
172             /* Link the current packet to the list head.  */
173             packet_ptr -> nx_packet_queue_next =  ip_ptr -> nx_ip_icmp_queue_head;
174         }
175         else
176         {
177 
178             /* Empty queue, add to the head of the ICMP message queue.  */
179             packet_ptr -> nx_packet_queue_next =  NX_NULL;
180         }
181 
182         /* Update the queue head pointer.  */
183         ip_ptr -> nx_ip_icmp_queue_head =  packet_ptr;
184 
185         /* Restore interrupts.  */
186         TX_RESTORE
187 
188         /* Wakeup IP thread for processing one or more messages in the ICMP queue.  */
189         tx_event_flags_set(&(ip_ptr -> nx_ip_events), NX_IP_ICMP_EVENT, TX_OR);
190     }
191     else
192     {
193 
194         /* The IP message was deferred, so this routine is called from the IP helper
195            thread and thus may call the ICMP processing directly.  */
196         _nx_icmp_packet_process(ip_ptr, packet_ptr);
197     }
198 #else
199     NX_PARAMETER_NOT_USED(ip_ptr);
200     NX_PARAMETER_NOT_USED(packet_ptr);
201 #endif /* NX_DISABLE_IPV4 */
202 }
203 
204