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_packet.h"
29 #include "nx_ip.h"
30 #include "nx_icmp.h"
31
32 #ifdef NX_IPSEC_ENABLE
33 #include "nx_ipsec.h"
34 #endif /* NX_IPSEC_ENABLE */
35
36 #ifndef NX_DISABLE_IPV4
37 /**************************************************************************/
38 /* */
39 /* FUNCTION RELEASE */
40 /* */
41 /* _nx_icmpv4_packet_process PORTABLE C */
42 /* 6.1 */
43 /* AUTHOR */
44 /* */
45 /* Yuxin Zhou, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function processes the ICMPv4 received packet and lifts any */
50 /* associated threads suspended on it. */
51 /* */
52 /* INPUT */
53 /* */
54 /* ip_ptr Pointer to IP control block */
55 /* packet_ptr ICMP packet pointer */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* None */
60 /* */
61 /* CALLS */
62 /* */
63 /* _nx_ip_checksum_compute Compute checksum */
64 /* _nx_ip_packet_send Send ICMP packet out */
65 /* _nx_packet_release Release packet to packet pool */
66 /* _tx_thread_system_resume Resume suspended thread */
67 /* _tx_thread_system_preempt_check Check for preemption */
68 /* */
69 /* CALLED BY */
70 /* */
71 /* _nx_icmp_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_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr)82 VOID _nx_icmpv4_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
83 {
84
85 NX_ICMPV4_HEADER *header_ptr;
86 USHORT checksum;
87 #if defined(NX_DISABLE_ICMPV4_RX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE)
88 UINT compute_checksum = 1;
89 #endif /* defined(NX_DISABLE_ICMPV4_RX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) */
90 #ifdef TX_ENABLE_EVENT_TRACE
91 NX_IPV4_HEADER *ip_header_ptr;
92 #endif /* TX_ENABLE_EVENT_TRACE */
93
94
95 /* Add debug information. */
96 NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
97
98 /* Point to the ICMP message header. */
99 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
100 header_ptr = (NX_ICMPV4_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
101
102 #ifdef NX_DISABLE_ICMPV4_RX_CHECKSUM
103 compute_checksum = 0;
104 #endif /* NX_DISABLE_ICMPV4_RX_CHECKSUM */
105
106 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
107 if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_ICMPV4_RX_CHECKSUM)
108 {
109 compute_checksum = 0;
110 }
111 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
112 #ifdef NX_IPSEC_ENABLE
113 if ((packet_ptr -> nx_packet_ipsec_sa_ptr != NX_NULL) && (((NX_IPSEC_SA *)(packet_ptr -> nx_packet_ipsec_sa_ptr)) -> nx_ipsec_sa_encryption_method != NX_CRYPTO_NONE))
114 {
115 compute_checksum = 1;
116 }
117 #endif
118 #if defined(NX_DISABLE_ICMPV4_RX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE)
119 if (compute_checksum)
120 #endif /* defined(NX_DISABLE_ICMPV4_RX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) */
121 {
122
123 /* Calculate the ICMP message checksum. */
124 checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_ICMP,
125 (UINT)packet_ptr -> nx_packet_length,
126 /* ICMPv4 checksum does not include
127 src/dest addresses */
128 NX_NULL, NX_NULL);
129
130 checksum = ((USHORT) ~checksum) & NX_LOWER_16_MASK;
131
132 /* Determine if the checksum is valid. */
133 if (checksum)
134 {
135
136 #ifndef NX_DISABLE_ICMP_INFO
137
138 /* Increment the ICMP invalid packet error. */
139 ip_ptr -> nx_ip_icmp_invalid_packets++;
140
141 /* Increment the ICMP checksum error count. */
142 ip_ptr -> nx_ip_icmp_checksum_errors++;
143 #endif
144
145 /* Nope, the checksum is invalid. Toss this ICMP packet out. */
146 _nx_packet_release(packet_ptr);
147 return;
148 }
149 }
150
151 /* Determine the message type and call the appropriate handler. */
152 if (header_ptr -> nx_icmpv4_header_type == NX_ICMP_ECHO_REPLY_TYPE)
153 {
154 _nx_icmpv4_process_echo_reply(ip_ptr, packet_ptr);
155 }
156 else if (header_ptr -> nx_icmpv4_header_type == NX_ICMP_ECHO_REQUEST_TYPE)
157 {
158 _nx_icmpv4_process_echo_request(ip_ptr, packet_ptr);
159 }
160 else
161 {
162
163 #ifndef NX_DISABLE_ICMP_INFO
164
165 /* Increment the ICMP unhandled message count. */
166 ip_ptr -> nx_ip_icmp_unhandled_messages++;
167 #endif
168
169 #ifdef TX_ENABLE_EVENT_TRACE
170
171 /* Set the IP header. */
172 ip_header_ptr = (NX_IPV4_HEADER *)packet_ptr -> nx_packet_ip_header;
173
174 /* If trace is enabled, insert this event into the trace buffer. */
175 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_ICMP_RECEIVE, ip_ptr, ip_header_ptr -> nx_ip_header_source_ip, packet_ptr, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
176 #endif /* TX_ENABLE_EVENT_TRACE */
177
178 /* Unhandled ICMP message, just release it. */
179 _nx_packet_release(packet_ptr);
180 }
181 }
182 #endif /* !NX_DISABLE_IPV4 */
183
184