1use core::num::NonZeroU8;
8use core::time::Duration;
9
10use derivative::Derivative;
11use net_types::SpecifiedAddr;
12use net_types::ip::{GenericOverIp, Ip, Ipv4, Ipv6, Mtu};
13use netstack3_base::{
14 ChecksumOffloadResult, IcmpErrorCode, Icmpv4ErrorCode, Icmpv6ErrorCode, IpExt, Marks, Mms,
15 UnscaledWindowSize, WeakDeviceIdentifier, WindowSize,
16};
17use netstack3_ip::socket::{RouteResolutionOptions, SendOptions};
18use packet_formats::icmp::{
19 Icmpv4DestUnreachableCode, Icmpv4TimeExceededCode, Icmpv6DestUnreachableCode,
20};
21use packet_formats::ip::DscpAndEcn;
22use packet_formats::utils::NonZeroDuration;
23use rand::Rng;
24use thiserror::Error;
25
26use crate::internal::buffer::BufferLimits;
27use crate::internal::counters::{TcpCountersWithSocket, TcpCountersWithoutSocket};
28use crate::internal::socket::generators::{IsnGenerator, TimestampOffsetGenerator};
29use crate::internal::socket::{DualStackIpExt, Sockets, TcpBindingsTypes, WeakTcpSocketId};
30use crate::internal::state::DEFAULT_MAX_SYN_RETRIES;
31
32pub const DEFAULT_FIN_WAIT2_TIMEOUT: Duration = Duration::from_secs(60);
34
35#[derive(Copy, Clone, Debug, PartialEq, Eq, Error)]
37pub enum ConnectionError {
38 #[error("connection refused (RST segment received while in SYN_SENT state")]
40 ConnectionRefused,
41 #[error("connection was reset because of a RST segment")]
43 ConnectionReset,
44 #[error("connection was closed because the network is unreachable")]
46 NetworkUnreachable,
47 #[error("connection was closed because the host is unreachable")]
49 HostUnreachable,
50 #[error("connection was closed because the protocol is unreachable")]
52 ProtocolUnreachable,
53 #[error("connection was closed because the port is unreachable")]
55 PortUnreachable,
56 #[error("connection was closed because the host is down")]
58 DestinationHostDown,
59 #[error("connection was closed because the source route failed")]
61 SourceRouteFailed,
62 #[error("connection was closed because the source host is isolated")]
64 SourceHostIsolated,
65 #[error("connection was closed because of a time out")]
67 TimedOut,
68 #[error("connection was closed because of a lack of required permissions")]
70 PermissionDenied,
71 #[error("connection was closed because there was a protocol error")]
73 ProtocolError,
74 #[error("connection was aborted by the system")]
76 Aborted,
77}
78
79pub(crate) enum IcmpErrorResult {
81 ConnectionError(ConnectionError),
83 PmtuUpdate(Mms),
85}
86
87impl IcmpErrorResult {
88 pub(crate) fn try_from_icmp_error(err: IcmpErrorCode) -> Option<IcmpErrorResult> {
91 match err {
92 IcmpErrorCode::V4(Icmpv4ErrorCode::DestUnreachable(code, message)) => {
93 match code {
94 Icmpv4DestUnreachableCode::DestNetworkUnreachable => {
95 Some(IcmpErrorResult::ConnectionError(ConnectionError::NetworkUnreachable))
96 }
97 Icmpv4DestUnreachableCode::DestHostUnreachable => {
98 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
99 }
100 Icmpv4DestUnreachableCode::DestProtocolUnreachable => {
101 Some(IcmpErrorResult::ConnectionError(ConnectionError::ProtocolUnreachable))
102 }
103 Icmpv4DestUnreachableCode::DestPortUnreachable => {
104 Some(IcmpErrorResult::ConnectionError(ConnectionError::PortUnreachable))
105 }
106 Icmpv4DestUnreachableCode::SourceRouteFailed => {
107 Some(IcmpErrorResult::ConnectionError(ConnectionError::SourceRouteFailed))
108 }
109 Icmpv4DestUnreachableCode::DestNetworkUnknown => {
110 Some(IcmpErrorResult::ConnectionError(ConnectionError::NetworkUnreachable))
111 }
112 Icmpv4DestUnreachableCode::DestHostUnknown => {
113 Some(IcmpErrorResult::ConnectionError(ConnectionError::DestinationHostDown))
114 }
115 Icmpv4DestUnreachableCode::SourceHostIsolated => {
116 Some(IcmpErrorResult::ConnectionError(ConnectionError::SourceHostIsolated))
117 }
118 Icmpv4DestUnreachableCode::NetworkAdministrativelyProhibited => {
119 Some(IcmpErrorResult::ConnectionError(ConnectionError::NetworkUnreachable))
120 }
121 Icmpv4DestUnreachableCode::HostAdministrativelyProhibited => {
122 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
123 }
124 Icmpv4DestUnreachableCode::NetworkUnreachableForToS => {
125 Some(IcmpErrorResult::ConnectionError(ConnectionError::NetworkUnreachable))
126 }
127 Icmpv4DestUnreachableCode::HostUnreachableForToS => {
128 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
129 }
130 Icmpv4DestUnreachableCode::CommAdministrativelyProhibited => {
131 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
132 }
133 Icmpv4DestUnreachableCode::HostPrecedenceViolation => {
134 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
135 }
136 Icmpv4DestUnreachableCode::PrecedenceCutoffInEffect => {
137 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
138 }
139 Icmpv4DestUnreachableCode::FragmentationRequired => {
140 let mtu = message.next_hop_mtu().expect("stack should always fill in MTU");
141 let mtu = Mtu::new(mtu.get().into());
142 let mms = Mms::from_mtu::<Ipv4>(mtu, 0 )?;
143 Some(IcmpErrorResult::PmtuUpdate(mms))
144 }
145 }
146 }
147 IcmpErrorCode::V4(Icmpv4ErrorCode::ParameterProblem(_)) => {
148 Some(IcmpErrorResult::ConnectionError(ConnectionError::ProtocolError))
149 }
150 IcmpErrorCode::V4(Icmpv4ErrorCode::TimeExceeded(
151 Icmpv4TimeExceededCode::TtlExpired,
152 )) => Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable)),
153 IcmpErrorCode::V4(Icmpv4ErrorCode::TimeExceeded(
154 Icmpv4TimeExceededCode::FragmentReassemblyTimeExceeded,
155 )) => Some(IcmpErrorResult::ConnectionError(ConnectionError::TimedOut)),
156 IcmpErrorCode::V4(Icmpv4ErrorCode::Redirect(_)) => None,
157 IcmpErrorCode::V6(Icmpv6ErrorCode::DestUnreachable(code)) => {
158 Some(IcmpErrorResult::ConnectionError(match code {
159 Icmpv6DestUnreachableCode::NoRoute => ConnectionError::NetworkUnreachable,
160 Icmpv6DestUnreachableCode::CommAdministrativelyProhibited => {
161 ConnectionError::PermissionDenied
162 }
163 Icmpv6DestUnreachableCode::BeyondScope => ConnectionError::HostUnreachable,
164 Icmpv6DestUnreachableCode::AddrUnreachable => ConnectionError::HostUnreachable,
165 Icmpv6DestUnreachableCode::PortUnreachable => ConnectionError::PortUnreachable,
166 Icmpv6DestUnreachableCode::SrcAddrFailedPolicy => {
167 ConnectionError::PermissionDenied
168 }
169 Icmpv6DestUnreachableCode::RejectRoute => ConnectionError::PermissionDenied,
170 }))
171 }
172 IcmpErrorCode::V6(Icmpv6ErrorCode::ParameterProblem(_)) => {
173 Some(IcmpErrorResult::ConnectionError(ConnectionError::ProtocolError))
174 }
175 IcmpErrorCode::V6(Icmpv6ErrorCode::TimeExceeded(_)) => {
176 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
177 }
178 IcmpErrorCode::V6(Icmpv6ErrorCode::PacketTooBig(mtu)) => {
179 let mms = Mms::from_mtu::<Ipv6>(mtu, 0 )?;
180 Some(IcmpErrorResult::PmtuUpdate(mms))
181 }
182 }
183 }
184}
185
186#[derive(Derivative, GenericOverIp)]
188#[generic_over_ip(I, Ip)]
189#[derivative(Debug(bound = ""))]
190#[cfg_attr(any(test, feature = "testutils"), derivative(PartialEq(bound = "")))]
191pub struct TcpSocketTxMetadata<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
192 socket: WeakTcpSocketId<I, D, BT>,
194 checksum_offload_result: Option<ChecksumOffloadResult>,
195}
196
197impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
198 TcpSocketTxMetadata<I, D, BT>
199{
200 pub(crate) fn new(socket: WeakTcpSocketId<I, D, BT>) -> Self {
202 Self { socket, checksum_offload_result: None }
203 }
204
205 pub fn socket(&self) -> &WeakTcpSocketId<I, D, BT> {
207 &self.socket
208 }
209
210 pub fn checksum_offload_result(&self) -> Option<ChecksumOffloadResult> {
212 self.checksum_offload_result.clone()
213 }
214
215 pub fn set_checksum_offload_result(&mut self, result: Option<ChecksumOffloadResult>) {
217 self.checksum_offload_result = result;
218 }
219}
220
221#[derive(GenericOverIp)]
223#[generic_over_ip(I, Ip)]
224pub struct TcpState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
225 pub isn_generator: IsnGenerator<BT::Instant>,
227 pub timestamp_offset_generator: TimestampOffsetGenerator<BT::Instant>,
229 pub sockets: Sockets<I, D, BT>,
231 pub counters_without_socket: TcpCountersWithoutSocket<I>,
233 pub counters_with_socket: TcpCountersWithSocket<I>,
235}
236
237impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpState<I, D, BT> {
238 pub fn new(now: BT::Instant, rng: &mut impl Rng) -> Self {
240 Self {
241 isn_generator: IsnGenerator::new(now, rng),
242 timestamp_offset_generator: TimestampOffsetGenerator::new(now, rng),
243 sockets: Sockets::new(),
244 counters_without_socket: Default::default(),
245 counters_with_socket: Default::default(),
246 }
247 }
248}
249
250#[derive(Copy, Clone, Debug)]
252#[cfg_attr(test, derive(Eq, PartialEq))]
253pub struct BufferSizes {
254 pub send: usize,
256 pub receive: usize,
258}
259#[cfg(any(test, feature = "testutils"))]
261impl Default for BufferSizes {
262 fn default() -> Self {
263 BufferSizes { send: WindowSize::DEFAULT.into(), receive: WindowSize::DEFAULT.into() }
264 }
265}
266
267impl BufferSizes {
268 pub(crate) fn rcv_limits(&self) -> BufferLimits {
269 let Self { send: _, receive } = self;
270 BufferLimits { capacity: *receive, len: 0 }
271 }
272
273 pub(crate) fn rwnd(&self) -> WindowSize {
274 let Self { send: _, receive } = *self;
275 WindowSize::new(receive).unwrap_or(WindowSize::MAX)
276 }
277
278 pub(crate) fn rwnd_unscaled(&self) -> UnscaledWindowSize {
279 let Self { send: _, receive } = *self;
280 UnscaledWindowSize::from(u16::try_from(receive).unwrap_or(u16::MAX))
281 }
282}
283
284pub(crate) enum BuffersRefMut<'a, R, S> {
286 NoBuffers,
288 Sizes(&'a mut BufferSizes),
290 Both { send: &'a mut S, recv: &'a mut R },
292 SendOnly(&'a mut S),
295 RecvOnly(&'a mut R),
298}
299
300impl<'a, R, S> BuffersRefMut<'a, R, S> {
301 pub(crate) fn into_send_buffer(self) -> Option<&'a mut S> {
302 match self {
303 Self::NoBuffers | Self::Sizes(_) | Self::RecvOnly(_) => None,
304 Self::Both { send, recv: _ } | Self::SendOnly(send) => Some(send),
305 }
306 }
307
308 pub(crate) fn into_receive_buffer(self) -> Option<&'a mut R> {
309 match self {
310 Self::NoBuffers | Self::Sizes(_) | Self::SendOnly(_) => None,
311 Self::Both { send: _, recv } | Self::RecvOnly(recv) => Some(recv),
312 }
313 }
314}
315
316#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
318pub struct TcpIpSockOptions {
319 pub marks: Marks,
321}
322
323impl<I: Ip> RouteResolutionOptions<I> for TcpIpSockOptions {
324 fn marks(&self) -> &Marks {
325 &self.marks
326 }
327
328 fn transparent(&self) -> bool {
329 false
330 }
331}
332
333impl<I: IpExt> SendOptions<I> for TcpIpSockOptions {
334 fn hop_limit(&self, _destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
335 None
336 }
337
338 fn multicast_loop(&self) -> bool {
339 false
340 }
341
342 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
343 None
344 }
345
346 fn dscp_and_ecn(&self) -> DscpAndEcn {
347 DscpAndEcn::default()
348 }
349
350 fn mtu(&self) -> Mtu {
351 Mtu::no_limit()
352 }
353}
354
355#[derive(Clone, Copy, Debug, PartialEq, Eq)]
359pub struct SocketOptions {
360 pub keep_alive: KeepAlive,
362 pub nagle_enabled: bool,
364 pub user_timeout: Option<NonZeroDuration>,
367 pub delayed_ack: bool,
369 pub fin_wait2_timeout: Option<Duration>,
372 pub max_syn_retries: NonZeroU8,
374 pub ip_options: TcpIpSockOptions,
376}
377
378impl Default for SocketOptions {
379 fn default() -> Self {
380 Self {
381 keep_alive: KeepAlive::default(),
382 nagle_enabled: true,
386 user_timeout: None,
387 delayed_ack: true,
388 fin_wait2_timeout: Some(DEFAULT_FIN_WAIT2_TIMEOUT),
389 max_syn_retries: DEFAULT_MAX_SYN_RETRIES,
390 ip_options: TcpIpSockOptions::default(),
391 }
392 }
393}
394
395#[derive(Clone, Copy, Debug, PartialEq, Eq)]
397pub struct KeepAlive {
398 pub idle: NonZeroDuration,
401 pub interval: NonZeroDuration,
403 pub count: NonZeroU8,
408 pub enabled: bool,
410}
411
412impl Default for KeepAlive {
413 fn default() -> Self {
414 const DEFAULT_IDLE_DURATION: NonZeroDuration =
417 NonZeroDuration::from_secs(2 * 60 * 60).unwrap();
418 const DEFAULT_INTERVAL: NonZeroDuration = NonZeroDuration::from_secs(75).unwrap();
419 const DEFAULT_COUNT: NonZeroU8 = NonZeroU8::new(9).unwrap();
420
421 Self {
422 idle: DEFAULT_IDLE_DURATION,
423 interval: DEFAULT_INTERVAL,
424 count: DEFAULT_COUNT,
425 enabled: false,
428 }
429 }
430}