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