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