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 /** Internet Control Message Protocol (ICMP) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "nx_api.h"
29 #include "tx_thread.h"
30 #include "nx_packet.h"
31 #include "nx_ip.h"
32 #include "nx_icmp.h"
33
34 #ifdef NX_IPSEC_ENABLE
35 #include "nx_ipsec.h"
36 #endif /* NX_IPSEC_ENABLE */
37
38 #ifndef NX_DISABLE_IPV4
39 /**************************************************************************/
40 /* */
41 /* FUNCTION RELEASE */
42 /* */
43 /* _nx_icmpv4_process_echo_reply PORTABLE C */
44 /* 6.1 */
45 /* AUTHOR */
46 /* */
47 /* Yuxin Zhou, Microsoft Corporation */
48 /* */
49 /* DESCRIPTION */
50 /* */
51 /* This function processes incoming echo reply message. It matches */
52 /* the thread that has pending echo request, and unblocks the thread. */
53 /* */
54 /* INPUT */
55 /* */
56 /* ip_ptr Pointer to IP control block */
57 /* packet_ptr ICMP packet pointer */
58 /* */
59 /* OUTPUT */
60 /* */
61 /* None */
62 /* */
63 /* CALLS */
64 /* */
65 /* _nx_packet_release Release packet back to pool */
66 /* _tx_thread_system_resume Resume the specified thread */
67 /* _tx_thread_system_preempt_check Check for preemption */
68 /* */
69 /* CALLED BY */
70 /* */
71 /* _nx_icmpv4_packet_process Main ICMP packet pocess */
72 /* */
73 /* RELEASE HISTORY */
74 /* */
75 /* DATE NAME DESCRIPTION */
76 /* */
77 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
78 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
79 /* resulting in version 6.1 */
80 /* */
81 /**************************************************************************/
_nx_icmpv4_process_echo_reply(NX_IP * ip_ptr,NX_PACKET * packet_ptr)82 VOID _nx_icmpv4_process_echo_reply(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
83 {
84
85 TX_INTERRUPT_SAVE_AREA
86
87 TX_THREAD *thread_ptr;
88 ULONG suspended;
89 USHORT sequence_num;
90 NX_ICMPV4_ECHO *echo_ptr;
91
92
93 /* Add debug information. */
94 NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
95
96
97 /* Point to the ICMP message header. */
98 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
99 echo_ptr = (NX_ICMPV4_ECHO *)packet_ptr -> nx_packet_prepend_ptr;
100
101 #ifndef NX_DISABLE_ICMP_INFO
102
103 /* Increment the ICMP responses received count. */
104 ip_ptr -> nx_ip_ping_responses_received++;
105 #endif
106
107 /* Pickup sequence number. */
108 sequence_num = echo_ptr -> nx_icmpv4_echo_sequence_num;
109
110 /* Convert to host byte order, if little endian taget. */
111 NX_CHANGE_USHORT_ENDIAN(sequence_num);
112
113 /* Disable interrupts. */
114 TX_DISABLE
115
116 /* Pickup the head pointer and the suspended count. */
117 thread_ptr = ip_ptr -> nx_ip_icmp_ping_suspension_list;
118 suspended = ip_ptr -> nx_ip_icmp_ping_suspended_count;
119
120 /* Temporarily disable preemption. */
121 _tx_thread_preempt_disable++;
122
123 /* Restore interrupts. */
124 TX_RESTORE
125
126 /* Search through the suspended threads waiting for a ECHO (ping) response
127 in an attempt to find a matching sequence number. */
128 while (suspended--)
129 {
130
131 /* Determine if the sequence number matches a suspended thread. */
132 if ((USHORT)(thread_ptr -> tx_thread_suspend_info) == sequence_num)
133 {
134
135 /* Disable interrupts. */
136 TX_DISABLE
137
138 /* See if this is the only suspended thread on the list. */
139 if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
140 {
141
142 /* Yes, the only suspended thread. */
143
144 /* Update the head pointer. */
145 ip_ptr -> nx_ip_icmp_ping_suspension_list = NX_NULL;
146 }
147 else
148 {
149
150 /* At least one more thread is on the same expiration list. */
151
152 /* Update the list head pointer. */
153 if (ip_ptr -> nx_ip_icmp_ping_suspension_list == thread_ptr)
154 {
155 ip_ptr -> nx_ip_icmp_ping_suspension_list = thread_ptr -> tx_thread_suspended_next;
156 }
157
158 /* Update the links of the adjacent threads. */
159 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous =
160 thread_ptr -> tx_thread_suspended_previous;
161 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next =
162 thread_ptr -> tx_thread_suspended_next;
163 }
164
165 /* Decrement the suspension count. */
166 ip_ptr -> nx_ip_icmp_ping_suspended_count--;
167
168 /* Prepare for resumption of the first thread. */
169
170 /* Clear cleanup routine to avoid timeout. */
171 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
172
173 /* Temporarily disable preemption. */
174 _tx_thread_preempt_disable++;
175
176 /* Restore interrupts. */
177 TX_RESTORE
178
179 /* Adjust this packet to remove the ICMP header that is still in front of
180 the response message. */
181 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - (ULONG)sizeof(NX_ICMPV4_ECHO);
182 packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_ICMPV4_ECHO);
183
184 /* Return this block pointer to the suspended thread waiting for
185 a block. */
186 *((NX_PACKET **)thread_ptr -> tx_thread_additional_suspend_info) = packet_ptr;
187
188 /* Clear packet pointer so we don't try to release it below. */
189 packet_ptr = NX_NULL;
190
191 /* Put return status into the thread control block. */
192 thread_ptr -> tx_thread_suspend_status = NX_SUCCESS;
193
194 /* Resume thread. */
195 _tx_thread_system_resume(thread_ptr);
196
197 /* Get out of the loop. */
198 break;
199 }
200 else
201 {
202 /* Just move to the next suspended thread. */
203 thread_ptr = thread_ptr -> tx_thread_suspended_next;
204 }
205 }
206
207 /* Determine if no match was made and we just have to release the packet. */
208 if (packet_ptr)
209 {
210
211 #ifndef NX_DISABLE_ICMP_INFO
212
213 /* Increment the ICMP invalid packet error. */
214 ip_ptr -> nx_ip_icmp_invalid_packets++;
215 #endif /* NX_DISABLE_ICMP_INFO */
216
217 /* Yes, just release the packet. */
218 _nx_packet_release(packet_ptr);
219 }
220
221 /* Disable interrupts. */
222 TX_DISABLE
223
224 /* Release preemption disable. */
225 _tx_thread_preempt_disable--;
226
227 /* Restore interrupts. */
228 TX_RESTORE
229
230 /* Check for preemption. */
231 _tx_thread_system_preempt_check();
232 }
233 #endif /* !NX_DISABLE_IPV4 */
234
235