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