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(Clone(bound = ""), 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 pub fn split_for_multiple_frames(self) -> (Self, Self) {
224 (self.clone(), self)
225 }
226}
227
228#[derive(GenericOverIp)]
230#[generic_over_ip(I, Ip)]
231pub struct TcpState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
232 pub isn_generator: IsnGenerator<BT::Instant>,
234 pub timestamp_offset_generator: TimestampOffsetGenerator<BT::Instant>,
236 pub sockets: Sockets<I, D, BT>,
238 pub counters_without_socket: TcpCountersWithoutSocket<I>,
240 pub counters_with_socket: TcpCountersWithSocket<I>,
242}
243
244impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpState<I, D, BT> {
245 pub fn new(now: BT::Instant, rng: &mut impl Rng) -> Self {
247 Self {
248 isn_generator: IsnGenerator::new(now, rng),
249 timestamp_offset_generator: TimestampOffsetGenerator::new(now, rng),
250 sockets: Sockets::new(),
251 counters_without_socket: Default::default(),
252 counters_with_socket: Default::default(),
253 }
254 }
255}
256
257#[derive(Copy, Clone, Debug)]
259#[cfg_attr(test, derive(Eq, PartialEq))]
260pub struct BufferSizes {
261 pub send: usize,
263 pub receive: usize,
265}
266#[cfg(any(test, feature = "testutils"))]
268impl Default for BufferSizes {
269 fn default() -> Self {
270 BufferSizes { send: WindowSize::DEFAULT.into(), receive: WindowSize::DEFAULT.into() }
271 }
272}
273
274impl BufferSizes {
275 pub(crate) fn rcv_limits(&self) -> BufferLimits {
276 let Self { send: _, receive } = self;
277 BufferLimits { capacity: *receive, len: 0 }
278 }
279
280 pub(crate) fn rwnd(&self) -> WindowSize {
281 let Self { send: _, receive } = *self;
282 WindowSize::new(receive).unwrap_or(WindowSize::MAX)
283 }
284
285 pub(crate) fn rwnd_unscaled(&self) -> UnscaledWindowSize {
286 let Self { send: _, receive } = *self;
287 UnscaledWindowSize::from(u16::try_from(receive).unwrap_or(u16::MAX))
288 }
289}
290
291pub(crate) enum BuffersRefMut<'a, R, S> {
293 NoBuffers,
295 Sizes(&'a mut BufferSizes),
297 Both { send: &'a mut S, recv: &'a mut R },
299 SendOnly(&'a mut S),
302 RecvOnly(&'a mut R),
305}
306
307impl<'a, R, S> BuffersRefMut<'a, R, S> {
308 pub(crate) fn into_send_buffer(self) -> Option<&'a mut S> {
309 match self {
310 Self::NoBuffers | Self::Sizes(_) | Self::RecvOnly(_) => None,
311 Self::Both { send, recv: _ } | Self::SendOnly(send) => Some(send),
312 }
313 }
314
315 pub(crate) fn into_receive_buffer(self) -> Option<&'a mut R> {
316 match self {
317 Self::NoBuffers | Self::Sizes(_) | Self::SendOnly(_) => None,
318 Self::Both { send: _, recv } | Self::RecvOnly(recv) => Some(recv),
319 }
320 }
321}
322
323#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
325pub struct TcpIpSockOptions {
326 pub marks: Marks,
328}
329
330impl<I: Ip> RouteResolutionOptions<I> for TcpIpSockOptions {
331 fn marks(&self) -> &Marks {
332 &self.marks
333 }
334
335 fn transparent(&self) -> bool {
336 false
337 }
338}
339
340impl<I: IpExt> SendOptions<I> for TcpIpSockOptions {
341 fn hop_limit(&self, _destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
342 None
343 }
344
345 fn multicast_loop(&self) -> bool {
346 false
347 }
348
349 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
350 None
351 }
352
353 fn dscp_and_ecn(&self) -> DscpAndEcn {
354 DscpAndEcn::default()
355 }
356
357 fn mtu(&self) -> Mtu {
358 Mtu::no_limit()
359 }
360}
361
362#[derive(Clone, Copy, Debug, PartialEq, Eq)]
366pub struct SocketOptions {
367 pub keep_alive: KeepAlive,
369 pub nagle_enabled: bool,
371 pub user_timeout: Option<NonZeroDuration>,
374 pub delayed_ack: bool,
376 pub fin_wait2_timeout: Option<Duration>,
379 pub max_syn_retries: NonZeroU8,
381 pub ip_options: TcpIpSockOptions,
383}
384
385impl Default for SocketOptions {
386 fn default() -> Self {
387 Self {
388 keep_alive: KeepAlive::default(),
389 nagle_enabled: true,
393 user_timeout: None,
394 delayed_ack: true,
395 fin_wait2_timeout: Some(DEFAULT_FIN_WAIT2_TIMEOUT),
396 max_syn_retries: DEFAULT_MAX_SYN_RETRIES,
397 ip_options: TcpIpSockOptions::default(),
398 }
399 }
400}
401
402#[derive(Clone, Copy, Debug, PartialEq, Eq)]
404pub struct KeepAlive {
405 pub idle: NonZeroDuration,
408 pub interval: NonZeroDuration,
410 pub count: NonZeroU8,
415 pub enabled: bool,
417}
418
419impl Default for KeepAlive {
420 fn default() -> Self {
421 const DEFAULT_IDLE_DURATION: NonZeroDuration =
424 NonZeroDuration::from_secs(2 * 60 * 60).unwrap();
425 const DEFAULT_INTERVAL: NonZeroDuration = NonZeroDuration::from_secs(75).unwrap();
426 const DEFAULT_COUNT: NonZeroU8 = NonZeroU8::new(9).unwrap();
427
428 Self {
429 idle: DEFAULT_IDLE_DURATION,
430 interval: DEFAULT_INTERVAL,
431 count: DEFAULT_COUNT,
432 enabled: false,
435 }
436 }
437}