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 /**   Transmission Control Protocol (TCP)                                 */
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_tcp.h"
30 #include "nx_packet.h"
31 #include "nx_ip.h"
32 
33 #ifdef NX_IPSEC_ENABLE
34 #include "nx_ipsec.h"
35 #endif /*NX_IPSEC_ENABLE*/
36 
37 #ifdef FEATURE_NX_IPV6
38 #include "nx_ipv6.h"
39 #endif /* FEATURE_NX_IPV6 */
40 
41 /**************************************************************************/
42 /*                                                                        */
43 /*  FUNCTION                                               RELEASE        */
44 /*                                                                        */
45 /*    _nx_tcp_no_connection_reset                         PORTABLE C      */
46 /*                                                           6.1          */
47 /*  AUTHOR                                                                */
48 /*                                                                        */
49 /*    Yuxin Zhou, Microsoft Corporation                                   */
50 /*                                                                        */
51 /*  DESCRIPTION                                                           */
52 /*                                                                        */
53 /*    This function sends a reset when there is no connection present,    */
54 /*    which avoids the timeout processing on the other side of the        */
55 /*    connection.                                                         */
56 /*                                                                        */
57 /*  INPUT                                                                 */
58 /*                                                                        */
59 /*    ip_ptr                                Pointer to IP control block   */
60 /*    packet_ptr                            Pointer to packet to send     */
61 /*    tcp_header_ptr                        TCP header                    */
62 /*                                                                        */
63 /*  OUTPUT                                                                */
64 /*                                                                        */
65 /*    None                                                                */
66 /*                                                                        */
67 /*  CALLS                                                                 */
68 /*                                                                        */
69 /*    _nxd_tcp_no_connect_reset             Invokes tcp no conn reset     */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    _nx_tcp_packet_process                TCP packet processing         */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
80 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
81 /*                                            resulting in version 6.1    */
82 /*                                                                        */
83 /**************************************************************************/
_nx_tcp_no_connection_reset(NX_IP * ip_ptr,NX_PACKET * packet_ptr,NX_TCP_HEADER * tcp_header_ptr)84 VOID  _nx_tcp_no_connection_reset(NX_IP *ip_ptr, NX_PACKET *packet_ptr, NX_TCP_HEADER *tcp_header_ptr)
85 {
86 
87 NX_TCP_SOCKET fake_socket;
88 ULONG         header_length;
89 #ifdef NX_IPSEC_ENABLE
90 VOID         *sa;
91 NXD_ADDRESS   source_ip;
92 NXD_ADDRESS   destination_ip;
93 UINT          ret;
94 ULONG         data_offset = 0;
95 #endif /* NX_IPSEC_ENABLE */
96 
97 
98     /* Clear the fake socket first.  */
99     memset((void *)&fake_socket, 0, sizeof(NX_TCP_SOCKET));
100 
101     /* Build a fake socket so we can send a reset TCP requests that are not valid.  */
102     fake_socket.nx_tcp_socket_ip_ptr = ip_ptr;
103 
104     /* Set the connection IP address.  */
105 #ifndef NX_DISABLE_IPV4
106     if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
107     {
108     NX_IPV4_HEADER *ip_header_ptr;
109 
110         /* Set the IP header.  */
111         /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
112         ip_header_ptr =  (NX_IPV4_HEADER *)packet_ptr -> nx_packet_ip_header;
113 
114         /* Set the connection ip.  */
115         fake_socket.nx_tcp_socket_connect_ip.nxd_ip_version = NX_IP_VERSION_V4;
116         fake_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4 = ip_header_ptr -> nx_ip_header_source_ip;
117 
118         /* Assume the interface that receives the incoming packet is the best interface
119            for sending responses. */
120         fake_socket.nx_tcp_socket_connect_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
121         fake_socket.nx_tcp_socket_next_hop_address = NX_NULL;
122 
123         /* Find the next hop info. */
124         _nx_ip_route_find(ip_ptr, fake_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4, &fake_socket.nx_tcp_socket_connect_interface,
125                           &fake_socket.nx_tcp_socket_next_hop_address);
126 
127 #ifdef NX_IPSEC_ENABLE
128         /* Get the source ip address.  */
129         source_ip.nxd_ip_version = NX_IP_VERSION_V4;
130         source_ip.nxd_ip_address.v4 = fake_socket.nx_tcp_socket_connect_interface -> nx_interface_ip_address;
131 
132         /* Get the destination ip address.  */
133         destination_ip.nxd_ip_version = NX_IP_VERSION_V4;
134         destination_ip.nxd_ip_address.v4 = ip_header_ptr -> nx_ip_header_source_ip;
135 #endif /*NX_IPSEC_ENABLE*/
136     }
137 #endif /* !NX_DISABLE_IPV4  */
138 
139 #ifdef FEATURE_NX_IPV6
140     if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
141     {
142     NX_IPV6_HEADER *ipv6_header_ptr;
143 
144         /* Set the IP header.  */
145         /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
146         ipv6_header_ptr = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
147 
148         /* Set the connection ip.  */
149         fake_socket.nx_tcp_socket_connect_ip.nxd_ip_version = NX_IP_VERSION_V6;
150         COPY_IPV6_ADDRESS(&ipv6_header_ptr -> nx_ip_header_source_ip[0], fake_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v6);
151 
152         /* Set the outgoing address.  */
153         fake_socket.nx_tcp_socket_ipv6_addr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr;
154 
155         /* Set the connect ip interface.  */
156         fake_socket.nx_tcp_socket_connect_interface = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
157 
158 #ifdef NX_IPSEC_ENABLE
159         /* Get the source ip address.  */
160         source_ip.nxd_ip_version = NX_IP_VERSION_V6;
161         COPY_IPV6_ADDRESS(fake_socket.nx_tcp_socket_ipv6_addr -> nxd_ipv6_address, source_ip.nxd_ip_address.v6);
162 
163         /* Get the destination ip address.  */
164         destination_ip.nxd_ip_version = NX_IP_VERSION_V6;
165         COPY_IPV6_ADDRESS(&ipv6_header_ptr -> nx_ip_header_source_ip[0], destination_ip.nxd_ip_address.v6);
166 #endif /*NX_IPSEC_ENABLE*/
167     }
168 #endif /* FEATURE_NX_IPV6 */
169 
170     /* Set the source port and destination port.  */
171     fake_socket.nx_tcp_socket_port  = (UINT)(tcp_header_ptr -> nx_tcp_header_word_0 & NX_LOWER_16_MASK);
172     fake_socket.nx_tcp_socket_connect_port = (UINT)(tcp_header_ptr -> nx_tcp_header_word_0 >> NX_SHIFT_BY_16);
173 
174     /* Set the sequence number only if the incoming segment does not have the ACK flag, according to
175        Section 3.4, "Reset Generation" on page 37, RFC793. */
176     if (!(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_ACK_BIT))
177     {
178         /* Get the header length.  */
179         header_length = (tcp_header_ptr -> nx_tcp_header_word_3 >> NX_TCP_HEADER_SHIFT) * (ULONG)sizeof(ULONG);
180 
181         /* Update sequence number to set the reset acknowledge number.  */
182         tcp_header_ptr -> nx_tcp_sequence_number += (packet_ptr -> nx_packet_length - header_length);
183 
184         /* Check the SYN and FIN bits.  */
185         if (tcp_header_ptr -> nx_tcp_header_word_3 & (NX_TCP_SYN_BIT | NX_TCP_FIN_BIT))
186         {
187 
188             /* Update sequence number to set the reset acknowledge number.  */
189             tcp_header_ptr -> nx_tcp_sequence_number++;
190         }
191     }
192 
193 #ifdef NX_IPSEC_ENABLE
194     /* Check for possible SA match. */
195     if (ip_ptr -> nx_ip_packet_egress_sa_lookup != NX_NULL)                   /* IPsec is enabled. */
196     {
197 
198         /* If the SA has not been set. */
199         ret = ip_ptr -> nx_ip_packet_egress_sa_lookup(ip_ptr,                                   /* IP ptr */
200                                                       &source_ip,                               /* src_addr */
201                                                       &destination_ip,                          /* dest_addr */
202                                                       NX_PROTOCOL_TCP,                          /* protocol */
203                                                       fake_socket.nx_tcp_socket_port,           /* src_port */
204                                                       fake_socket.nx_tcp_socket_connect_port,   /* dest_port */
205                                                       &data_offset, &sa, 0);
206         if (ret == NX_IPSEC_TRAFFIC_PROTECT)
207         {
208 
209             /* Save the SA to the socket. */
210             fake_socket.nx_tcp_socket_egress_sa = sa;
211             fake_socket.nx_tcp_socket_egress_sa_data_offset = data_offset;
212         }
213         else if (ret == NX_IPSEC_TRAFFIC_DROP || ret == NX_IPSEC_TRAFFIC_PENDING_IKEV2)
214         {
215 
216             return;
217         }
218         else
219         {
220 
221             /* Zero out SA information. */
222             fake_socket.nx_tcp_socket_egress_sa = NX_NULL;
223             fake_socket.nx_tcp_socket_egress_sa_data_offset = 0;
224         }
225     }
226 #endif
227 
228     fake_socket.nx_tcp_socket_time_to_live = (UINT)NX_IP_TIME_TO_LIVE;
229 
230     /* Send a RST to indicate the connection was not available.  */
231     _nx_tcp_packet_send_rst(&fake_socket, tcp_header_ptr);
232 }
233 
234