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 IcmpErrorCode, Icmpv4ErrorCode, Icmpv6ErrorCode, IpExt, Marks, Mms, UnscaledWindowSize,
15 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}
75
76pub(crate) enum IcmpErrorResult {
78 ConnectionError(ConnectionError),
80 PmtuUpdate(Mms),
82}
83
84impl IcmpErrorResult {
85 pub(crate) fn try_from_icmp_error(err: IcmpErrorCode) -> Option<IcmpErrorResult> {
88 match err {
89 IcmpErrorCode::V4(Icmpv4ErrorCode::DestUnreachable(code, message)) => {
90 match code {
91 Icmpv4DestUnreachableCode::DestNetworkUnreachable => {
92 Some(IcmpErrorResult::ConnectionError(ConnectionError::NetworkUnreachable))
93 }
94 Icmpv4DestUnreachableCode::DestHostUnreachable => {
95 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
96 }
97 Icmpv4DestUnreachableCode::DestProtocolUnreachable => {
98 Some(IcmpErrorResult::ConnectionError(ConnectionError::ProtocolUnreachable))
99 }
100 Icmpv4DestUnreachableCode::DestPortUnreachable => {
101 Some(IcmpErrorResult::ConnectionError(ConnectionError::PortUnreachable))
102 }
103 Icmpv4DestUnreachableCode::SourceRouteFailed => {
104 Some(IcmpErrorResult::ConnectionError(ConnectionError::SourceRouteFailed))
105 }
106 Icmpv4DestUnreachableCode::DestNetworkUnknown => {
107 Some(IcmpErrorResult::ConnectionError(ConnectionError::NetworkUnreachable))
108 }
109 Icmpv4DestUnreachableCode::DestHostUnknown => {
110 Some(IcmpErrorResult::ConnectionError(ConnectionError::DestinationHostDown))
111 }
112 Icmpv4DestUnreachableCode::SourceHostIsolated => {
113 Some(IcmpErrorResult::ConnectionError(ConnectionError::SourceHostIsolated))
114 }
115 Icmpv4DestUnreachableCode::NetworkAdministrativelyProhibited => {
116 Some(IcmpErrorResult::ConnectionError(ConnectionError::NetworkUnreachable))
117 }
118 Icmpv4DestUnreachableCode::HostAdministrativelyProhibited => {
119 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
120 }
121 Icmpv4DestUnreachableCode::NetworkUnreachableForToS => {
122 Some(IcmpErrorResult::ConnectionError(ConnectionError::NetworkUnreachable))
123 }
124 Icmpv4DestUnreachableCode::HostUnreachableForToS => {
125 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
126 }
127 Icmpv4DestUnreachableCode::CommAdministrativelyProhibited => {
128 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
129 }
130 Icmpv4DestUnreachableCode::HostPrecedenceViolation => {
131 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
132 }
133 Icmpv4DestUnreachableCode::PrecedenceCutoffInEffect => {
134 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
135 }
136 Icmpv4DestUnreachableCode::FragmentationRequired => {
137 let mtu = message.next_hop_mtu().expect("stack should always fill in MTU");
138 let mtu = Mtu::new(mtu.get().into());
139 let mms = Mms::from_mtu::<Ipv4>(mtu, 0 )?;
140 Some(IcmpErrorResult::PmtuUpdate(mms))
141 }
142 }
143 }
144 IcmpErrorCode::V4(Icmpv4ErrorCode::ParameterProblem(_)) => {
145 Some(IcmpErrorResult::ConnectionError(ConnectionError::ProtocolError))
146 }
147 IcmpErrorCode::V4(Icmpv4ErrorCode::TimeExceeded(
148 Icmpv4TimeExceededCode::TtlExpired,
149 )) => Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable)),
150 IcmpErrorCode::V4(Icmpv4ErrorCode::TimeExceeded(
151 Icmpv4TimeExceededCode::FragmentReassemblyTimeExceeded,
152 )) => Some(IcmpErrorResult::ConnectionError(ConnectionError::TimedOut)),
153 IcmpErrorCode::V4(Icmpv4ErrorCode::Redirect(_)) => None,
154 IcmpErrorCode::V6(Icmpv6ErrorCode::DestUnreachable(code)) => {
155 Some(IcmpErrorResult::ConnectionError(match code {
156 Icmpv6DestUnreachableCode::NoRoute => ConnectionError::NetworkUnreachable,
157 Icmpv6DestUnreachableCode::CommAdministrativelyProhibited => {
158 ConnectionError::PermissionDenied
159 }
160 Icmpv6DestUnreachableCode::BeyondScope => ConnectionError::HostUnreachable,
161 Icmpv6DestUnreachableCode::AddrUnreachable => ConnectionError::HostUnreachable,
162 Icmpv6DestUnreachableCode::PortUnreachable => ConnectionError::PortUnreachable,
163 Icmpv6DestUnreachableCode::SrcAddrFailedPolicy => {
164 ConnectionError::PermissionDenied
165 }
166 Icmpv6DestUnreachableCode::RejectRoute => ConnectionError::PermissionDenied,
167 }))
168 }
169 IcmpErrorCode::V6(Icmpv6ErrorCode::ParameterProblem(_)) => {
170 Some(IcmpErrorResult::ConnectionError(ConnectionError::ProtocolError))
171 }
172 IcmpErrorCode::V6(Icmpv6ErrorCode::TimeExceeded(_)) => {
173 Some(IcmpErrorResult::ConnectionError(ConnectionError::HostUnreachable))
174 }
175 IcmpErrorCode::V6(Icmpv6ErrorCode::PacketTooBig(mtu)) => {
176 let mms = Mms::from_mtu::<Ipv6>(mtu, 0 )?;
177 Some(IcmpErrorResult::PmtuUpdate(mms))
178 }
179 }
180 }
181}
182
183#[derive(Derivative, GenericOverIp)]
185#[generic_over_ip(I, Ip)]
186#[derivative(Debug(bound = ""))]
187#[cfg_attr(any(test, feature = "testutils"), derivative(PartialEq(bound = "")))]
188pub struct TcpSocketTxMetadata<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
189 socket: WeakTcpSocketId<I, D, BT>,
191}
192
193impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
194 TcpSocketTxMetadata<I, D, BT>
195{
196 pub(crate) fn new(socket: WeakTcpSocketId<I, D, BT>) -> Self {
198 Self { socket }
199 }
200
201 pub fn socket(&self) -> &WeakTcpSocketId<I, D, BT> {
203 &self.socket
204 }
205}
206
207#[derive(GenericOverIp)]
209#[generic_over_ip(I, Ip)]
210pub struct TcpState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
211 pub isn_generator: IsnGenerator<BT::Instant>,
213 pub timestamp_offset_generator: TimestampOffsetGenerator<BT::Instant>,
215 pub sockets: Sockets<I, D, BT>,
217 pub counters_without_socket: TcpCountersWithoutSocket<I>,
219 pub counters_with_socket: TcpCountersWithSocket<I>,
221}
222
223impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpState<I, D, BT> {
224 pub fn new(now: BT::Instant, rng: &mut impl Rng) -> Self {
226 Self {
227 isn_generator: IsnGenerator::new(now, rng),
228 timestamp_offset_generator: TimestampOffsetGenerator::new(now, rng),
229 sockets: Sockets::new(),
230 counters_without_socket: Default::default(),
231 counters_with_socket: Default::default(),
232 }
233 }
234}
235
236#[derive(Copy, Clone, Debug)]
238#[cfg_attr(test, derive(Eq, PartialEq))]
239pub struct BufferSizes {
240 pub send: usize,
242 pub receive: usize,
244}
245#[cfg(any(test, feature = "testutils"))]
247impl Default for BufferSizes {
248 fn default() -> Self {
249 BufferSizes { send: WindowSize::DEFAULT.into(), receive: WindowSize::DEFAULT.into() }
250 }
251}
252
253impl BufferSizes {
254 pub(crate) fn rcv_limits(&self) -> BufferLimits {
255 let Self { send: _, receive } = self;
256 BufferLimits { capacity: *receive, len: 0 }
257 }
258
259 pub(crate) fn rwnd(&self) -> WindowSize {
260 let Self { send: _, receive } = *self;
261 WindowSize::new(receive).unwrap_or(WindowSize::MAX)
262 }
263
264 pub(crate) fn rwnd_unscaled(&self) -> UnscaledWindowSize {
265 let Self { send: _, receive } = *self;
266 UnscaledWindowSize::from(u16::try_from(receive).unwrap_or(u16::MAX))
267 }
268}
269
270pub(crate) enum BuffersRefMut<'a, R, S> {
272 NoBuffers,
274 Sizes(&'a mut BufferSizes),
276 Both { send: &'a mut S, recv: &'a mut R },
278 SendOnly(&'a mut S),
281 RecvOnly(&'a mut R),
284}
285
286impl<'a, R, S> BuffersRefMut<'a, R, S> {
287 pub(crate) fn into_send_buffer(self) -> Option<&'a mut S> {
288 match self {
289 Self::NoBuffers | Self::Sizes(_) | Self::RecvOnly(_) => None,
290 Self::Both { send, recv: _ } | Self::SendOnly(send) => Some(send),
291 }
292 }
293
294 pub(crate) fn into_receive_buffer(self) -> Option<&'a mut R> {
295 match self {
296 Self::NoBuffers | Self::Sizes(_) | Self::SendOnly(_) => None,
297 Self::Both { send: _, recv } | Self::RecvOnly(recv) => Some(recv),
298 }
299 }
300}
301
302#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
304pub struct TcpIpSockOptions {
305 pub marks: Marks,
307}
308
309impl<I: Ip> RouteResolutionOptions<I> for TcpIpSockOptions {
310 fn marks(&self) -> &Marks {
311 &self.marks
312 }
313
314 fn transparent(&self) -> bool {
315 false
316 }
317}
318
319impl<I: IpExt> SendOptions<I> for TcpIpSockOptions {
320 fn hop_limit(&self, _destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
321 None
322 }
323
324 fn multicast_loop(&self) -> bool {
325 false
326 }
327
328 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
329 None
330 }
331
332 fn dscp_and_ecn(&self) -> DscpAndEcn {
333 DscpAndEcn::default()
334 }
335
336 fn mtu(&self) -> Mtu {
337 Mtu::no_limit()
338 }
339}
340
341#[derive(Clone, Copy, Debug, PartialEq, Eq)]
345pub struct SocketOptions {
346 pub keep_alive: KeepAlive,
348 pub nagle_enabled: bool,
350 pub user_timeout: Option<NonZeroDuration>,
353 pub delayed_ack: bool,
355 pub fin_wait2_timeout: Option<Duration>,
358 pub max_syn_retries: NonZeroU8,
360 pub ip_options: TcpIpSockOptions,
362}
363
364impl Default for SocketOptions {
365 fn default() -> Self {
366 Self {
367 keep_alive: KeepAlive::default(),
368 nagle_enabled: true,
372 user_timeout: None,
373 delayed_ack: true,
374 fin_wait2_timeout: Some(DEFAULT_FIN_WAIT2_TIMEOUT),
375 max_syn_retries: DEFAULT_MAX_SYN_RETRIES,
376 ip_options: TcpIpSockOptions::default(),
377 }
378 }
379}
380
381#[derive(Clone, Copy, Debug, PartialEq, Eq)]
383pub struct KeepAlive {
384 pub idle: NonZeroDuration,
387 pub interval: NonZeroDuration,
389 pub count: NonZeroU8,
394 pub enabled: bool,
396}
397
398impl Default for KeepAlive {
399 fn default() -> Self {
400 const DEFAULT_IDLE_DURATION: NonZeroDuration =
403 NonZeroDuration::from_secs(2 * 60 * 60).unwrap();
404 const DEFAULT_INTERVAL: NonZeroDuration = NonZeroDuration::from_secs(75).unwrap();
405 const DEFAULT_COUNT: NonZeroU8 = NonZeroU8::new(9).unwrap();
406
407 Self {
408 idle: DEFAULT_IDLE_DURATION,
409 interval: DEFAULT_INTERVAL,
410 count: DEFAULT_COUNT,
411 enabled: false,
414 }
415 }
416}