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