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