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