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_ipv6.h"
31 #include "nx_icmpv6.h"
32
33 #ifdef NX_IPSEC_ENABLE
34 #include "nx_ipsec.h"
35 #endif /* NX_IPSEC_ENABLE */
36
37
38 #ifdef FEATURE_NX_IPV6
39
40
41
42
43 /**************************************************************************/
44 /* */
45 /* FUNCTION RELEASE */
46 /* */
47 /* _nx_icmpv6_packet_process PORTABLE C */
48 /* 6.3.0 */
49 /* AUTHOR */
50 /* */
51 /* Yuxin Zhou, Microsoft Corporation */
52 /* */
53 /* DESCRIPTION */
54 /* */
55 /* This function processes the ICMPv6 received packet, computes the */
56 /* ICMP header checksum, and determines ICMPv6 message type and which */
57 /* handler to process it. It also lifts any associated threads */
58 /* suspended on it. */
59 /* */
60 /* INPUT */
61 /* */
62 /* ip_ptr Pointer to IP control block */
63 /* packet_ptr Received ICMP packet pointer */
64 /* */
65 /* OUTPUT */
66 /* */
67 /* None */
68 /* */
69 /* CALLS */
70 /* */
71 /* _nx_ip_checksum_compute Computer ICMP checksum */
72 /* _nx_packet_release Packet release function */
73 /* _tx_thread_system_preempt_check Check for preemption */
74 /* _nx_icmpv6_process_echo_reply Function that processes the */
75 /* echo reply message. */
76 /* _nx_icmpv6_process_echo_request Function that processes the */
77 /* echo request message. */
78 /* _nx_icmpv6_process_ra Function that processes the */
79 /* router advertisement */
80 /* message. */
81 /* _nx_icmpv6_process_na Function that processes the */
82 /* neighbor advertisement. */
83 /* _nx_icmpv6_process_ns Function that processes the */
84 /* neighbor solicitation */
85 /* message. */
86 /* */
87 /* CALLED BY */
88 /* */
89 /* _nx_icmp_packet_process Main ICMP packet processer */
90 /* */
91 /* RELEASE HISTORY */
92 /* */
93 /* DATE NAME DESCRIPTION */
94 /* */
95 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
96 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
97 /* resulting in version 6.1 */
98 /* 10-31-2023 Bo Chen Modified comment(s), improved */
99 /* packet length verification, */
100 /* resulting in version 6.3.0 */
101 /* */
102 /**************************************************************************/
_nx_icmpv6_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr)103 VOID _nx_icmpv6_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
104 {
105
106 NX_ICMPV6_HEADER *header_ptr;
107 USHORT checksum;
108 #if defined(NX_DISABLE_ICMPV6_RX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE)
109 UINT compute_checksum = 1;
110 #endif /* defined(NX_DISABLE_ICMPV6_RX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) */
111 NX_IPV6_HEADER *ipv6_header;
112
113
114 /* Add debug information. */
115 NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
116
117 /* Check packet length is at least sizeof(NX_ICMPV6_HEADER). */
118 if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) < sizeof(NX_ICMPV6_HEADER))
119 {
120 #ifndef NX_DISABLE_ICMP_INFO
121
122 /* Increment the ICMP invalid packet error. */
123 ip_ptr -> nx_ip_icmp_invalid_packets++;
124 #endif
125
126 _nx_packet_release(packet_ptr);
127 return;
128 }
129
130 /* Points to the ICMP message header. */
131 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
132 header_ptr = (NX_ICMPV6_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
133
134 #ifdef NX_DISABLE_ICMPV6_RX_CHECKSUM
135 compute_checksum = 0;
136 #endif /* NX_DISABLE_ICMPV6_RX_CHECKSUM */
137
138 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
139 if (packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_ICMPV6_RX_CHECKSUM)
140 {
141 compute_checksum = 0;
142 }
143 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
144 #ifdef NX_IPSEC_ENABLE
145 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))
146 {
147 compute_checksum = 1;
148 }
149 #endif
150 #if defined(NX_DISABLE_ICMPV6_RX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE)
151 if (compute_checksum)
152 #endif /* defined(NX_DISABLE_ICMPV6_RX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) */
153 {
154 /* Points to the IPv6 header. */
155 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
156 ipv6_header = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
157
158 /* Calculate the ICMP message checksum. */
159 checksum = _nx_ip_checksum_compute(packet_ptr, NX_PROTOCOL_ICMPV6,
160 (UINT)packet_ptr -> nx_packet_length,
161 (ipv6_header -> nx_ip_header_source_ip),
162 (ipv6_header -> nx_ip_header_destination_ip));
163
164 checksum = (USHORT)(~checksum) & NX_LOWER_16_MASK;
165
166 /* Determine if the checksum is valid. */
167 if (checksum)
168 {
169
170 #ifndef NX_DISABLE_ICMP_INFO
171
172 /* Increment the ICMP invalid packet error. */
173 ip_ptr -> nx_ip_icmp_invalid_packets++;
174
175 /* Increment the ICMP checksum error count. */
176 ip_ptr -> nx_ip_icmp_checksum_errors++;
177 #endif
178
179 /* Nope, the checksum is invalid. Toss this ICMP packet out. */
180 _nx_packet_release(packet_ptr);
181 return;
182 }
183 }
184
185 /* Determine the message type and call the appropriate handler. */
186 if (header_ptr -> nx_icmpv6_header_type == NX_ICMPV6_ECHO_REPLY_TYPE)
187 {
188 _nx_icmpv6_process_echo_reply(ip_ptr, packet_ptr);
189 }
190 else if (header_ptr -> nx_icmpv6_header_type == NX_ICMPV6_ECHO_REQUEST_TYPE)
191 {
192 _nx_icmpv6_process_echo_request(ip_ptr, packet_ptr);
193 }
194 else if (header_ptr -> nx_icmpv6_header_type == NX_ICMPV6_NEIGHBOR_SOLICITATION_TYPE)
195 {
196
197 _nx_icmpv6_process_ns(ip_ptr, packet_ptr);
198 }
199
200 #ifndef NX_DISABLE_ICMPV6_ROUTER_ADVERTISEMENT_PROCESS
201 else if (header_ptr -> nx_icmpv6_header_type == NX_ICMPV6_ROUTER_ADVERTISEMENT_TYPE)
202 {
203
204 _nx_icmpv6_process_ra(ip_ptr, packet_ptr);
205 }
206 #endif
207 else if (header_ptr -> nx_icmpv6_header_type == NX_ICMPV6_NEIGHBOR_ADVERTISEMENT_TYPE)
208 {
209
210 _nx_icmpv6_process_na(ip_ptr, packet_ptr);
211 }
212 #ifndef NX_DISABLE_ICMPV6_REDIRECT_PROCESS
213 else if (header_ptr -> nx_icmpv6_header_type == NX_ICMPV6_REDIRECT_MESSAGE_TYPE)
214 {
215
216 _nx_icmpv6_process_redirect(ip_ptr, packet_ptr);
217 }
218 #endif
219
220 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
221 else if (header_ptr -> nx_icmpv6_header_type == NX_ICMPV6_PACKET_TOO_BIG_TYPE)
222 {
223 _nx_icmpv6_process_packet_too_big(ip_ptr, packet_ptr);
224 }
225 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
226
227 else
228 {
229
230 #ifndef NX_DISABLE_ICMP_INFO
231
232 /* Increment the ICMP unhandled message count. */
233 ip_ptr -> nx_ip_icmp_unhandled_messages++;
234 #endif
235
236 /* Unhandled ICMP message, just release it. */
237 _nx_packet_release(packet_ptr);
238 }
239 }
240
241
242 #endif /* FEATURE_NX_IPV6 */
243
244