1pub(crate) mod accept_queue;
21pub(crate) mod demux;
22pub(crate) mod diagnostics;
23pub(crate) mod generators;
24
25use alloc::vec::Vec;
26use core::fmt::{self, Debug};
27use core::marker::PhantomData;
28use core::num::{NonZeroU16, NonZeroUsize};
29use core::ops::{Deref, DerefMut, RangeInclusive};
30
31use assert_matches::assert_matches;
32use derivative::Derivative;
33use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
34use log::{debug, error};
35use net_types::ip::{
36 GenericOverIp, Ip, IpAddr, IpAddress, IpVersion, IpVersionMarker, Ipv4, Ipv4Addr, Ipv6,
37 Ipv6Addr,
38};
39use net_types::{
40 AddrAndPortFormatter, AddrAndZone, MulticastAddress as _, SpecifiedAddr, ZonedAddr,
41};
42use netstack3_base::socket::{
43 self, AddrIsMappedError, AddrVec, Bound, ConnAddr, ConnIpAddr, DualStackListenerIpAddr,
44 DualStackLocalIp, DualStackRemoteIp, DualStackTuple, EitherIpProto, EitherStack,
45 IncompatibleError, InsertError, Inserter, ListenerAddr, ListenerAddrInfo, ListenerIpAddr,
46 MaybeDualStack, NotDualStackCapableError, RemoveResult, SetDualStackEnabledError, ShutdownType,
47 SocketCookie, SocketDeviceUpdate, SocketDeviceUpdateNotAllowedError, SocketIpAddr, SocketIpExt,
48 SocketMapAddrSpec, SocketMapAddrStateSpec, SocketMapAddrStateUpdateSharingSpec,
49 SocketMapConflictPolicy, SocketMapStateSpec, SocketMapUpdateSharingPolicy,
50 SocketZonedAddrExt as _, UpdateSharingError,
51};
52use netstack3_base::socketmap::{IterShadows as _, SocketMap, Tagged as _};
53use netstack3_base::sync::RwLock;
54use netstack3_base::{
55 AnyDevice, BidirectionalConverter as _, ContextPair, Control, CoreTimerContext,
56 CoreTxMetadataContext, CtxPair, DeferredResourceRemovalContext, DeviceIdContext,
57 EitherDeviceId, ExistsError, HandleableTimer, IcmpErrorCode, Inspector, InspectorDeviceExt,
58 InspectorExt, InstantBindingsTypes, InstantContext, IpDeviceAddr, IpExt,
59 IpSocketPropertiesMatcher, LocalAddressError, Mark, MarkDomain, Marks, MatcherBindingsTypes,
60 Mss, OwnedOrRefsBidirectionalConverter, PortAllocImpl, ReferenceNotifiers,
61 ReferenceNotifiersExt as _, RemoveResourceResultWithContext, ResourceCounterContext as _,
62 RngContext, Segment, SeqNum, SettingsContext, SocketDiagnosticsSeed, StrongDeviceIdentifier,
63 TimerBindingsTypes, TimerContext, TxMetadataBindingsTypes, WeakDeviceIdentifier,
64 ZonedAddressError,
65};
66use netstack3_filter::{FilterIpExt, SocketOpsFilterBindingContext, Tuple};
67use netstack3_hashmap::{HashMap, hash_map};
68use netstack3_ip::socket::{
69 DeviceIpSocketHandler, IpSock, IpSockCreateAndSendError, IpSockCreationError, IpSocketArgs,
70 IpSocketHandler,
71};
72use netstack3_ip::{
73 self as ip, BaseTransportIpContext, IpLayerIpExt, MarksBindingsContext, SocketMetadata,
74 TransportIpContext,
75};
76use netstack3_trace::{TraceResourceId, trace_duration};
77use packet_formats::ip::{IpProto, Ipv4Proto, Ipv6Proto};
78use smallvec::{SmallVec, smallvec};
79use thiserror::Error;
80
81use crate::internal::base::{
82 BufferSizes, BuffersRefMut, ConnectionError, SocketOptions, TcpIpSockOptions,
83 TcpSocketTxMetadata,
84};
85use crate::internal::buffer::{Buffer, IntoBuffers, ReceiveBuffer, SendBuffer};
86use crate::internal::counters::{
87 self, CombinedTcpCounters, TcpCounterContext, TcpCountersRefs, TcpCountersWithSocket,
88};
89use crate::internal::settings::TcpSettings;
90use crate::internal::socket::accept_queue::{AcceptQueue, ListenerNotifier};
91use crate::internal::socket::demux::tcp_serialize_segment;
92use crate::internal::socket::diagnostics::{
93 TcpSocketDiagnostics, TcpSocketDiagnosticsSeed, TcpSocketStateForMatching,
94};
95
96use crate::internal::socket::generators::{IsnGenerator, TimestampOffsetGenerator};
97use crate::internal::state::info::TcpSocketInfo;
98use crate::internal::state::{
99 CloseError, CloseReason, Closed, Initial, NewlyClosed, ShouldRetransmit, State,
100 StateMachineDebugId, Takeable, TakeableRef,
101};
102
103pub trait DualStackIpExt:
108 DualStackBaseIpExt + netstack3_base::socket::DualStackIpExt<OtherVersion: DualStackBaseIpExt>
109{
110}
111
112impl<I> DualStackIpExt for I where
113 I: DualStackBaseIpExt
114 + netstack3_base::socket::DualStackIpExt<OtherVersion: DualStackBaseIpExt>
115{
116}
117
118pub trait DualStackBaseIpExt:
120 netstack3_base::socket::DualStackIpExt + SocketIpExt + IpLayerIpExt
121{
122 type DemuxSocketId<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>: SpecSocketId;
125
126 type ConnectionAndAddr<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>: Send + Sync + Debug;
130
131 type ListenerIpAddr: Send + Sync + Debug + Clone;
135
136 type OriginalDstAddr;
140
141 type DualStackIpOptions: Send + Sync + Debug + Default + Clone + Copy;
143
144 fn as_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
147 id: &Self::DemuxSocketId<D, BT>,
148 ) -> EitherStack<&TcpSocketId<Self, D, BT>, &TcpSocketId<Self::OtherVersion, D, BT>>
149 where
150 Self::OtherVersion: DualStackBaseIpExt;
151
152 fn into_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
155 id: Self::DemuxSocketId<D, BT>,
156 ) -> EitherStack<TcpSocketId<Self, D, BT>, TcpSocketId<Self::OtherVersion, D, BT>>
157 where
158 Self::OtherVersion: DualStackBaseIpExt;
159
160 fn into_demux_socket_id<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
162 id: TcpSocketId<Self, D, BT>,
163 ) -> Self::DemuxSocketId<D, BT>
164 where
165 Self::OtherVersion: DualStackBaseIpExt;
166
167 fn get_conn_info<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
168 conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
169 ) -> ConnectionInfo<Self::Addr, D>;
170 fn get_accept_queue_mut<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
171 conn_and_addr: &mut Self::ConnectionAndAddr<D, BT>,
172 ) -> &mut Option<
173 AcceptQueue<
174 TcpSocketId<Self, D, BT>,
175 BT::ReturnedBuffers,
176 BT::ListenerNotifierOrProvidedBuffers,
177 >,
178 >
179 where
180 Self::OtherVersion: DualStackBaseIpExt;
181 fn get_defunct<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
182 conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
183 ) -> bool;
184 fn get_state<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
185 conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
186 ) -> &State<BT::Instant, BT::ReceiveBuffer, BT::SendBuffer, BT::ListenerNotifierOrProvidedBuffers>;
187 fn get_bound_info<D: WeakDeviceIdentifier>(
188 listener_addr: &ListenerAddr<Self::ListenerIpAddr, D>,
189 ) -> BoundInfo<Self::Addr, D>;
190
191 fn destroy_socket_with_demux_id<
192 CC: TcpContext<Self, BC> + TcpContext<Self::OtherVersion, BC>,
193 BC: TcpBindingsContext<CC::DeviceId>,
194 >(
195 core_ctx: &mut CC,
196 bindings_ctx: &mut BC,
197 demux_id: Self::DemuxSocketId<CC::WeakDeviceId, BC>,
198 ) where
199 Self::OtherVersion: DualStackBaseIpExt;
200
201 fn get_original_dst(addr: Self::OriginalDstAddr) -> Self::Addr;
206}
207
208impl DualStackBaseIpExt for Ipv4 {
209 type DemuxSocketId<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> =
210 EitherStack<TcpSocketId<Ipv4, D, BT>, TcpSocketId<Ipv6, D, BT>>;
211 type ConnectionAndAddr<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> =
212 (Connection<Ipv4, Ipv4, D, BT>, ConnAddr<ConnIpAddr<Ipv4Addr, NonZeroU16, NonZeroU16>, D>);
213 type ListenerIpAddr = ListenerIpAddr<Ipv4Addr, NonZeroU16>;
214 type OriginalDstAddr = Ipv4Addr;
215 type DualStackIpOptions = ();
216
217 fn as_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
218 id: &Self::DemuxSocketId<D, BT>,
219 ) -> EitherStack<&TcpSocketId<Self, D, BT>, &TcpSocketId<Self::OtherVersion, D, BT>> {
220 match id {
221 EitherStack::ThisStack(id) => EitherStack::ThisStack(id),
222 EitherStack::OtherStack(id) => EitherStack::OtherStack(id),
223 }
224 }
225 fn into_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
226 id: Self::DemuxSocketId<D, BT>,
227 ) -> EitherStack<TcpSocketId<Self, D, BT>, TcpSocketId<Self::OtherVersion, D, BT>> {
228 id
229 }
230 fn into_demux_socket_id<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
231 id: TcpSocketId<Self, D, BT>,
232 ) -> Self::DemuxSocketId<D, BT> {
233 EitherStack::ThisStack(id)
234 }
235 fn get_conn_info<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
236 (_conn, addr): &Self::ConnectionAndAddr<D, BT>,
237 ) -> ConnectionInfo<Self::Addr, D> {
238 addr.clone().into()
239 }
240 fn get_accept_queue_mut<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
241 (conn, _addr): &mut Self::ConnectionAndAddr<D, BT>,
242 ) -> &mut Option<
243 AcceptQueue<
244 TcpSocketId<Self, D, BT>,
245 BT::ReturnedBuffers,
246 BT::ListenerNotifierOrProvidedBuffers,
247 >,
248 > {
249 &mut conn.accept_queue
250 }
251 fn get_defunct<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
252 (conn, _addr): &Self::ConnectionAndAddr<D, BT>,
253 ) -> bool {
254 conn.defunct
255 }
256 fn get_state<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
257 (conn, _addr): &Self::ConnectionAndAddr<D, BT>,
258 ) -> &State<BT::Instant, BT::ReceiveBuffer, BT::SendBuffer, BT::ListenerNotifierOrProvidedBuffers>
259 {
260 &conn.state
261 }
262 fn get_bound_info<D: WeakDeviceIdentifier>(
263 listener_addr: &ListenerAddr<Self::ListenerIpAddr, D>,
264 ) -> BoundInfo<Self::Addr, D> {
265 listener_addr.clone().into()
266 }
267
268 fn destroy_socket_with_demux_id<
269 CC: TcpContext<Self, BC> + TcpContext<Self::OtherVersion, BC>,
270 BC: TcpBindingsContext<CC::DeviceId>,
271 >(
272 core_ctx: &mut CC,
273 bindings_ctx: &mut BC,
274 demux_id: Self::DemuxSocketId<CC::WeakDeviceId, BC>,
275 ) {
276 match demux_id {
277 EitherStack::ThisStack(id) => destroy_socket(core_ctx, bindings_ctx, id),
278 EitherStack::OtherStack(id) => destroy_socket(core_ctx, bindings_ctx, id),
279 }
280 }
281
282 fn get_original_dst(addr: Self::OriginalDstAddr) -> Self::Addr {
283 addr
284 }
285}
286
287#[derive(Derivative, Debug, Clone, Copy, PartialEq, Eq)]
289#[derivative(Default)]
290pub struct Ipv6Options {
291 #[derivative(Default(value = "true"))]
293 pub dual_stack_enabled: bool,
294}
295
296impl DualStackBaseIpExt for Ipv6 {
297 type DemuxSocketId<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> = TcpSocketId<Ipv6, D, BT>;
298 type ConnectionAndAddr<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> = EitherStack<
299 (Connection<Ipv6, Ipv6, D, BT>, ConnAddr<ConnIpAddr<Ipv6Addr, NonZeroU16, NonZeroU16>, D>),
300 (Connection<Ipv6, Ipv4, D, BT>, ConnAddr<ConnIpAddr<Ipv4Addr, NonZeroU16, NonZeroU16>, D>),
301 >;
302 type DualStackIpOptions = Ipv6Options;
303 type ListenerIpAddr = DualStackListenerIpAddr<Ipv6Addr, NonZeroU16>;
304 type OriginalDstAddr = EitherStack<Ipv6Addr, Ipv4Addr>;
305
306 fn as_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
307 id: &Self::DemuxSocketId<D, BT>,
308 ) -> EitherStack<&TcpSocketId<Self, D, BT>, &TcpSocketId<Self::OtherVersion, D, BT>> {
309 EitherStack::ThisStack(id)
310 }
311 fn into_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
312 id: Self::DemuxSocketId<D, BT>,
313 ) -> EitherStack<TcpSocketId<Self, D, BT>, TcpSocketId<Self::OtherVersion, D, BT>> {
314 EitherStack::ThisStack(id)
315 }
316
317 fn into_demux_socket_id<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
318 id: TcpSocketId<Self, D, BT>,
319 ) -> Self::DemuxSocketId<D, BT> {
320 id
321 }
322 fn get_conn_info<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
323 conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
324 ) -> ConnectionInfo<Self::Addr, D> {
325 match conn_and_addr {
326 EitherStack::ThisStack((_conn, addr)) => addr.clone().into(),
327 EitherStack::OtherStack((
328 _conn,
329 ConnAddr {
330 ip:
331 ConnIpAddr { local: (local_ip, local_port), remote: (remote_ip, remote_port) },
332 device,
333 },
334 )) => ConnectionInfo {
335 local_addr: SocketAddr {
336 ip: maybe_zoned(local_ip.addr().to_ipv6_mapped(), device),
337 port: *local_port,
338 },
339 remote_addr: SocketAddr {
340 ip: maybe_zoned(remote_ip.addr().to_ipv6_mapped(), device),
341 port: *remote_port,
342 },
343 device: device.clone(),
344 },
345 }
346 }
347 fn get_accept_queue_mut<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
348 conn_and_addr: &mut Self::ConnectionAndAddr<D, BT>,
349 ) -> &mut Option<
350 AcceptQueue<
351 TcpSocketId<Self, D, BT>,
352 BT::ReturnedBuffers,
353 BT::ListenerNotifierOrProvidedBuffers,
354 >,
355 > {
356 match conn_and_addr {
357 EitherStack::ThisStack((conn, _addr)) => &mut conn.accept_queue,
358 EitherStack::OtherStack((conn, _addr)) => &mut conn.accept_queue,
359 }
360 }
361 fn get_defunct<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
362 conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
363 ) -> bool {
364 match conn_and_addr {
365 EitherStack::ThisStack((conn, _addr)) => conn.defunct,
366 EitherStack::OtherStack((conn, _addr)) => conn.defunct,
367 }
368 }
369 fn get_state<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
370 conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
371 ) -> &State<BT::Instant, BT::ReceiveBuffer, BT::SendBuffer, BT::ListenerNotifierOrProvidedBuffers>
372 {
373 match conn_and_addr {
374 EitherStack::ThisStack((conn, _addr)) => &conn.state,
375 EitherStack::OtherStack((conn, _addr)) => &conn.state,
376 }
377 }
378 fn get_bound_info<D: WeakDeviceIdentifier>(
379 ListenerAddr { ip, device }: &ListenerAddr<Self::ListenerIpAddr, D>,
380 ) -> BoundInfo<Self::Addr, D> {
381 match ip {
382 DualStackListenerIpAddr::ThisStack(ip) => {
383 ListenerAddr { ip: ip.clone(), device: device.clone() }.into()
384 }
385 DualStackListenerIpAddr::OtherStack(ListenerIpAddr {
386 addr,
387 identifier: local_port,
388 }) => BoundInfo {
389 addr: Some(maybe_zoned(
390 addr.map(|a| a.addr()).unwrap_or(Ipv4::UNSPECIFIED_ADDRESS).to_ipv6_mapped(),
391 &device,
392 )),
393 port: *local_port,
394 device: device.clone(),
395 },
396 DualStackListenerIpAddr::BothStacks(local_port) => {
397 BoundInfo { addr: None, port: *local_port, device: device.clone() }
398 }
399 }
400 }
401
402 fn destroy_socket_with_demux_id<
403 CC: TcpContext<Self, BC> + TcpContext<Self::OtherVersion, BC>,
404 BC: TcpBindingsContext<CC::DeviceId>,
405 >(
406 core_ctx: &mut CC,
407 bindings_ctx: &mut BC,
408 demux_id: Self::DemuxSocketId<CC::WeakDeviceId, BC>,
409 ) {
410 destroy_socket(core_ctx, bindings_ctx, demux_id)
411 }
412
413 fn get_original_dst(addr: Self::OriginalDstAddr) -> Self::Addr {
414 match addr {
415 EitherStack::ThisStack(addr) => addr,
416 EitherStack::OtherStack(addr) => *addr.to_ipv6_mapped(),
417 }
418 }
419}
420
421#[derive(Derivative, GenericOverIp)]
423#[generic_over_ip()]
424#[derivative(
425 Clone(bound = ""),
426 Eq(bound = ""),
427 PartialEq(bound = ""),
428 Hash(bound = ""),
429 Debug(bound = "")
430)]
431#[allow(missing_docs)]
432pub enum TcpTimerId<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
433 V4(WeakTcpSocketId<Ipv4, D, BT>),
434 V6(WeakTcpSocketId<Ipv6, D, BT>),
435}
436
437impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
438 From<WeakTcpSocketId<I, D, BT>> for TcpTimerId<D, BT>
439{
440 fn from(f: WeakTcpSocketId<I, D, BT>) -> Self {
441 I::map_ip(f, TcpTimerId::V4, TcpTimerId::V6)
442 }
443}
444
445pub trait TcpBindingsTypes:
474 InstantBindingsTypes + TimerBindingsTypes + TxMetadataBindingsTypes + MatcherBindingsTypes + 'static
475{
476 type ReceiveBuffer: ReceiveBuffer + Send + Sync;
478 type SendBuffer: SendBuffer + Send + Sync;
480 type ReturnedBuffers: Debug + Send + Sync;
484 type ListenerNotifierOrProvidedBuffers: Debug
489 + IntoBuffers<Self::ReceiveBuffer, Self::SendBuffer>
490 + ListenerNotifier
491 + Send
492 + Sync;
493
494 fn new_passive_open_buffers(
497 buffer_sizes: BufferSizes,
498 ) -> (Self::ReceiveBuffer, Self::SendBuffer, Self::ReturnedBuffers);
499}
500
501pub trait TcpSocketDestructionContext: ReferenceNotifiers + InstantContext {
504 fn defer_tcp_socket_destruction<I, S>(&self, result: RemoveResourceResultWithContext<S, Self>)
508 where
509 I: Ip,
510 S: SocketDiagnosticsSeed<Output = TcpSocketDiagnostics<I, Self::Instant>> + Send;
511}
512
513pub trait TcpBindingsContext<D>:
517 Sized
518 + DeferredResourceRemovalContext
519 + TimerContext
520 + RngContext
521 + TcpBindingsTypes
522 + SocketOpsFilterBindingContext<D>
523 + SettingsContext<TcpSettings>
524 + TcpSocketDestructionContext
525 + MarksBindingsContext
526{
527}
528
529impl<D, BC> TcpBindingsContext<D> for BC where
530 BC: Sized
531 + DeferredResourceRemovalContext
532 + TimerContext
533 + RngContext
534 + TcpBindingsTypes
535 + SocketOpsFilterBindingContext<D>
536 + SettingsContext<TcpSettings>
537 + TcpSocketDestructionContext
538 + MarksBindingsContext
539{
540}
541
542pub trait TcpDemuxContext<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>:
544 TcpCoreTimerContext<I, D, BT>
545{
546 type IpTransportCtx<'a>: TransportIpContext<I, BT, DeviceId = D::Strong, WeakDeviceId = D>
548 + DeviceIpSocketHandler<I, BT>
549 + TcpCoreTimerContext<I, D, BT>;
550
551 fn with_demux<O, F: FnOnce(&DemuxState<I, D, BT>) -> O>(&mut self, cb: F) -> O;
553
554 fn with_demux_mut<O, F: FnOnce(&mut DemuxState<I, D, BT>) -> O>(&mut self, cb: F) -> O;
556}
557
558pub trait AsThisStack<T> {
566 fn as_this_stack(&mut self) -> &mut T;
568}
569
570impl<T> AsThisStack<T> for T {
571 fn as_this_stack(&mut self) -> &mut T {
572 self
573 }
574}
575
576pub trait TcpSocketContext<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>:
578 TcpCounterContext<I, D, BT> + CoreTxMetadataContext<TcpSocketTxMetadata<I, D, BT>, BT>
579{
580}
581
582impl<CC, I, D, BC> TcpSocketContext<I, D, BC> for CC
583where
584 I: DualStackIpExt,
585 D: WeakDeviceIdentifier,
586 BC: TcpBindingsTypes,
587 CC: TcpCounterContext<I, D, BC> + CoreTxMetadataContext<TcpSocketTxMetadata<I, D, BC>, BC>,
588{
589}
590
591pub trait TcpCoreTimerContext<I: DualStackIpExt, D: WeakDeviceIdentifier, BC: TcpBindingsTypes>:
593 CoreTimerContext<WeakTcpSocketId<I, D, BC>, BC>
594{
595}
596
597impl<CC, I, D, BC> TcpCoreTimerContext<I, D, BC> for CC
598where
599 I: DualStackIpExt,
600 D: WeakDeviceIdentifier,
601 BC: TcpBindingsTypes,
602 CC: CoreTimerContext<WeakTcpSocketId<I, D, BC>, BC>,
603{
604}
605
606pub trait DualStackConverter<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>:
608 OwnedOrRefsBidirectionalConverter<
609 I::ConnectionAndAddr<D, BT>,
610 EitherStack<
611 (
612 Connection<I, I, D, BT>,
613 ConnAddr<ConnIpAddr<<I as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
614 ),
615 (
616 Connection<I, I::OtherVersion, D, BT>,
617 ConnAddr<ConnIpAddr<<I::OtherVersion as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
618 ),
619 >,
620 > + OwnedOrRefsBidirectionalConverter<
621 I::ListenerIpAddr,
622 DualStackListenerIpAddr<I::Addr, NonZeroU16>,
623 > + OwnedOrRefsBidirectionalConverter<
624 ListenerAddr<I::ListenerIpAddr, D>,
625 ListenerAddr<DualStackListenerIpAddr<I::Addr, NonZeroU16>, D>,
626 > + OwnedOrRefsBidirectionalConverter<
627 I::OriginalDstAddr,
628 EitherStack<I::Addr, <I::OtherVersion as Ip>::Addr>,
629 >
630{
631}
632
633impl<I, D, BT, O> DualStackConverter<I, D, BT> for O
634where
635 I: DualStackIpExt,
636 D: WeakDeviceIdentifier,
637 BT: TcpBindingsTypes,
638 O: OwnedOrRefsBidirectionalConverter<
639 I::ConnectionAndAddr<D, BT>,
640 EitherStack<
641 (
642 Connection<I, I, D, BT>,
643 ConnAddr<ConnIpAddr<<I as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
644 ),
645 (
646 Connection<I, I::OtherVersion, D, BT>,
647 ConnAddr<ConnIpAddr<<I::OtherVersion as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
648 ),
649 >,
650 > + OwnedOrRefsBidirectionalConverter<
651 I::ListenerIpAddr,
652 DualStackListenerIpAddr<I::Addr, NonZeroU16>,
653 > + OwnedOrRefsBidirectionalConverter<
654 ListenerAddr<I::ListenerIpAddr, D>,
655 ListenerAddr<DualStackListenerIpAddr<I::Addr, NonZeroU16>, D>,
656 > + OwnedOrRefsBidirectionalConverter<
657 I::OriginalDstAddr,
658 EitherStack<I::Addr, <I::OtherVersion as Ip>::Addr>,
659 >,
660{
661}
662
663pub trait SingleStackConverter<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>:
665 OwnedOrRefsBidirectionalConverter<
666 I::ConnectionAndAddr<D, BT>,
667 (Connection<I, I, D, BT>, ConnAddr<ConnIpAddr<<I as Ip>::Addr, NonZeroU16, NonZeroU16>, D>),
668 > + OwnedOrRefsBidirectionalConverter<I::ListenerIpAddr, ListenerIpAddr<I::Addr, NonZeroU16>>
669 + OwnedOrRefsBidirectionalConverter<
670 ListenerAddr<I::ListenerIpAddr, D>,
671 ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
672 > + OwnedOrRefsBidirectionalConverter<I::OriginalDstAddr, I::Addr>
673{
674}
675
676impl<I, D, BT, O> SingleStackConverter<I, D, BT> for O
677where
678 I: DualStackIpExt,
679 D: WeakDeviceIdentifier,
680 BT: TcpBindingsTypes,
681 O: OwnedOrRefsBidirectionalConverter<
682 I::ConnectionAndAddr<D, BT>,
683 (
684 Connection<I, I, D, BT>,
685 ConnAddr<ConnIpAddr<<I as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
686 ),
687 > + OwnedOrRefsBidirectionalConverter<I::ListenerIpAddr, ListenerIpAddr<I::Addr, NonZeroU16>>
688 + OwnedOrRefsBidirectionalConverter<
689 ListenerAddr<I::ListenerIpAddr, D>,
690 ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
691 > + OwnedOrRefsBidirectionalConverter<I::OriginalDstAddr, I::Addr>,
692{
693}
694
695pub trait TcpContext<I: DualStackIpExt, BC: TcpBindingsTypes>:
697 TcpDemuxContext<I, Self::WeakDeviceId, BC>
698 + IpSocketHandler<I, BC>
699 + TcpSocketContext<I, Self::WeakDeviceId, BC>
700{
701 type ThisStackIpTransportAndDemuxCtx<'a>: TransportIpContext<I, BC, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>
704 + DeviceIpSocketHandler<I, BC>
705 + TcpDemuxContext<I, Self::WeakDeviceId, BC>
706 + TcpSocketContext<I, Self::WeakDeviceId, BC>;
707
708 type SingleStackIpTransportAndDemuxCtx<'a>: TransportIpContext<I, BC, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>
710 + DeviceIpSocketHandler<I, BC>
711 + TcpDemuxContext<I, Self::WeakDeviceId, BC>
712 + AsThisStack<Self::ThisStackIpTransportAndDemuxCtx<'a>>
713 + TcpSocketContext<I, Self::WeakDeviceId, BC>;
714
715 type SingleStackConverter: SingleStackConverter<I, Self::WeakDeviceId, BC>;
719
720 type DualStackIpTransportAndDemuxCtx<'a>: TransportIpContext<I, BC, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>
722 + DeviceIpSocketHandler<I, BC>
723 + TcpDemuxContext<I, Self::WeakDeviceId, BC>
724 + TransportIpContext<
725 I::OtherVersion,
726 BC,
727 DeviceId = Self::DeviceId,
728 WeakDeviceId = Self::WeakDeviceId,
729 > + DeviceIpSocketHandler<I::OtherVersion, BC>
730 + TcpDemuxContext<I::OtherVersion, Self::WeakDeviceId, BC>
731 + TcpDualStackContext<I, Self::WeakDeviceId, BC>
732 + AsThisStack<Self::ThisStackIpTransportAndDemuxCtx<'a>>
733 + TcpSocketContext<I, Self::WeakDeviceId, BC>
734 + TcpCounterContext<I::OtherVersion, Self::WeakDeviceId, BC>;
735
736 type DualStackConverter: DualStackConverter<I, Self::WeakDeviceId, BC>;
740
741 fn with_all_sockets_mut<O, F: FnOnce(&mut TcpSocketSet<I, Self::WeakDeviceId, BC>) -> O>(
743 &mut self,
744 cb: F,
745 ) -> O;
746
747 fn for_each_socket<
749 F: FnMut(&TcpSocketId<I, Self::WeakDeviceId, BC>, &TcpSocketState<I, Self::WeakDeviceId, BC>),
750 >(
751 &mut self,
752 cb: F,
753 );
754
755 fn with_socket_mut_generators_transport_demux<
758 O,
759 F: for<'a> FnOnce(
760 MaybeDualStack<
761 (&'a mut Self::DualStackIpTransportAndDemuxCtx<'a>, Self::DualStackConverter),
762 (&'a mut Self::SingleStackIpTransportAndDemuxCtx<'a>, Self::SingleStackConverter),
763 >,
764 &mut TcpSocketState<I, Self::WeakDeviceId, BC>,
765 &IsnGenerator<BC::Instant>,
766 &TimestampOffsetGenerator<BC::Instant>,
767 ) -> O,
768 >(
769 &mut self,
770 id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
771 cb: F,
772 ) -> O;
773
774 fn with_socket<O, F: FnOnce(&TcpSocketState<I, Self::WeakDeviceId, BC>) -> O>(
776 &mut self,
777 id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
778 cb: F,
779 ) -> O {
780 self.with_socket_and_converter(id, |socket_state, _converter| cb(socket_state))
781 }
782
783 fn with_socket_and_converter<
786 O,
787 F: FnOnce(
788 &TcpSocketState<I, Self::WeakDeviceId, BC>,
789 MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>,
790 ) -> O,
791 >(
792 &mut self,
793 id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
794 cb: F,
795 ) -> O;
796
797 fn with_socket_mut_transport_demux<
800 O,
801 F: for<'a> FnOnce(
802 MaybeDualStack<
803 (&'a mut Self::DualStackIpTransportAndDemuxCtx<'a>, Self::DualStackConverter),
804 (&'a mut Self::SingleStackIpTransportAndDemuxCtx<'a>, Self::SingleStackConverter),
805 >,
806 &mut TcpSocketState<I, Self::WeakDeviceId, BC>,
807 ) -> O,
808 >(
809 &mut self,
810 id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
811 cb: F,
812 ) -> O {
813 self.with_socket_mut_generators_transport_demux(
814 id,
815 |ctx, socket_state, _isn, _timestamp_offset| cb(ctx, socket_state),
816 )
817 }
818
819 fn with_socket_mut<O, F: FnOnce(&mut TcpSocketState<I, Self::WeakDeviceId, BC>) -> O>(
821 &mut self,
822 id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
823 cb: F,
824 ) -> O {
825 self.with_socket_mut_generators_transport_demux(
826 id,
827 |_ctx, socket_state, _isn, _timestamp_offset| cb(socket_state),
828 )
829 }
830
831 fn with_socket_mut_and_converter<
834 O,
835 F: FnOnce(
836 &mut TcpSocketState<I, Self::WeakDeviceId, BC>,
837 MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>,
838 ) -> O,
839 >(
840 &mut self,
841 id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
842 cb: F,
843 ) -> O {
844 self.with_socket_mut_generators_transport_demux(
845 id,
846 |ctx, socket_state, _isn, _timestamp_offset| {
847 let converter = match ctx {
848 MaybeDualStack::NotDualStack((_core_ctx, converter)) => {
849 MaybeDualStack::NotDualStack(converter)
850 }
851 MaybeDualStack::DualStack((_core_ctx, converter)) => {
852 MaybeDualStack::DualStack(converter)
853 }
854 };
855 cb(socket_state, converter)
856 },
857 )
858 }
859}
860
861#[derive(Clone, Copy)]
863pub struct Ipv6SocketIdToIpv4DemuxIdConverter;
864
865pub trait DualStackDemuxIdConverter<I: DualStackIpExt>: 'static + Clone + Copy {
869 fn convert<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
871 &self,
872 id: TcpSocketId<I, D, BT>,
873 ) -> <I::OtherVersion as DualStackBaseIpExt>::DemuxSocketId<D, BT>;
874}
875
876impl DualStackDemuxIdConverter<Ipv6> for Ipv6SocketIdToIpv4DemuxIdConverter {
877 fn convert<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
878 &self,
879 id: TcpSocketId<Ipv6, D, BT>,
880 ) -> <Ipv4 as DualStackBaseIpExt>::DemuxSocketId<D, BT> {
881 EitherStack::OtherStack(id)
882 }
883}
884
885pub trait TcpDualStackContext<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
887 type DualStackIpTransportCtx<'a>: TransportIpContext<I, BT, DeviceId = D::Strong, WeakDeviceId = D>
889 + DeviceIpSocketHandler<I, BT>
890 + TcpCoreTimerContext<I, D, BT>
891 + TransportIpContext<I::OtherVersion, BT, DeviceId = D::Strong, WeakDeviceId = D>
892 + DeviceIpSocketHandler<I::OtherVersion, BT>
893 + TcpCoreTimerContext<I::OtherVersion, D, BT>;
894
895 fn other_demux_id_converter(&self) -> impl DualStackDemuxIdConverter<I>;
897
898 fn into_other_demux_socket_id(
900 &self,
901 id: TcpSocketId<I, D, BT>,
902 ) -> <I::OtherVersion as DualStackBaseIpExt>::DemuxSocketId<D, BT> {
903 self.other_demux_id_converter().convert(id)
904 }
905
906 fn dual_stack_demux_id(
908 &self,
909 id: TcpSocketId<I, D, BT>,
910 ) -> DualStackTuple<I, DemuxSocketId<I, D, BT>> {
911 let this_id = DemuxSocketId::<I, _, _>(I::into_demux_socket_id(id.clone()));
912 let other_id = DemuxSocketId::<I::OtherVersion, _, _>(self.into_other_demux_socket_id(id));
913 DualStackTuple::new(this_id, other_id)
914 }
915
916 fn dual_stack_enabled(&self, ip_options: &I::DualStackIpOptions) -> bool;
918 fn set_dual_stack_enabled(&self, ip_options: &mut I::DualStackIpOptions, value: bool);
920
921 fn with_both_demux_mut<
923 O,
924 F: FnOnce(&mut DemuxState<I, D, BT>, &mut DemuxState<I::OtherVersion, D, BT>) -> O,
925 >(
926 &mut self,
927 cb: F,
928 ) -> O;
929}
930
931#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, GenericOverIp)]
933#[generic_over_ip(A, IpAddress)]
934pub struct SocketAddr<A: IpAddress, D> {
935 pub ip: ZonedAddr<SpecifiedAddr<A>, D>,
937 pub port: NonZeroU16,
939}
940
941impl<A: IpAddress, D> From<SocketAddr<A, D>>
942 for IpAddr<SocketAddr<Ipv4Addr, D>, SocketAddr<Ipv6Addr, D>>
943{
944 fn from(addr: SocketAddr<A, D>) -> IpAddr<SocketAddr<Ipv4Addr, D>, SocketAddr<Ipv6Addr, D>> {
945 <A::Version as Ip>::map_ip_in(addr, |i| IpAddr::V4(i), |i| IpAddr::V6(i))
946 }
947}
948
949impl<A: IpAddress, D> SocketAddr<A, D> {
950 pub fn map_zone<Y>(self, f: impl FnOnce(D) -> Y) -> SocketAddr<A, Y> {
952 let Self { ip, port } = self;
953 SocketAddr { ip: ip.map_zone(f), port }
954 }
955}
956
957impl<A: IpAddress, D: fmt::Display> fmt::Display for SocketAddr<A, D> {
958 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
959 let Self { ip, port } = self;
960 let formatter = AddrAndPortFormatter::<_, _, A::Version>::new(
961 ip.as_ref().map_addr(core::convert::AsRef::<A>::as_ref),
962 port,
963 );
964 formatter.fmt(f)
965 }
966}
967
968pub(crate) enum TcpPortSpec {}
970
971impl SocketMapAddrSpec for TcpPortSpec {
972 type RemoteIdentifier = NonZeroU16;
973 type LocalIdentifier = NonZeroU16;
974}
975
976pub enum TcpIpTransportContext {}
978
979pub trait SpecSocketId: Clone + Eq + PartialEq + Debug + 'static {}
985impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> SpecSocketId
986 for TcpSocketId<I, D, BT>
987{
988}
989
990impl<A: SpecSocketId, B: SpecSocketId> SpecSocketId for EitherStack<A, B> {}
991
992struct TcpSocketSpec<I, D, BT>(PhantomData<(I, D, BT)>, !);
994
995impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> SocketMapStateSpec
996 for TcpSocketSpec<I, D, BT>
997{
998 type ListenerId = I::DemuxSocketId<D, BT>;
999 type ConnId = I::DemuxSocketId<D, BT>;
1000
1001 type ListenerSharingState = ListenerSharingState;
1002 type ConnSharingState = SharingState;
1003 type AddrVecTag = AddrVecTag;
1004
1005 type ListenerAddrState = ListenerAddrState<Self::ListenerId>;
1006 type ConnAddrState = ConnAddrState<Self::ConnId>;
1007
1008 fn listener_tag(
1009 ListenerAddrInfo { has_device, specified_addr }: ListenerAddrInfo,
1010 state: &Self::ListenerAddrState,
1011 ) -> Self::AddrVecTag {
1012 let (sharing, state) = match state {
1013 ListenerAddrState::ExclusiveBound(_) => {
1014 (SharingState::Exclusive, SocketTagState::Bound)
1015 }
1016 ListenerAddrState::ExclusiveListener(_) => {
1017 (SharingState::Exclusive, SocketTagState::Listener)
1018 }
1019 ListenerAddrState::Shared { listener, bound: _ } => (
1020 SharingState::ReuseAddress,
1021 match listener {
1022 Some(_) => SocketTagState::Listener,
1023 None => SocketTagState::Bound,
1024 },
1025 ),
1026 };
1027 AddrVecTag { sharing, state, has_device, specified_addr }
1028 }
1029
1030 fn connected_tag(has_device: bool, state: &Self::ConnAddrState) -> Self::AddrVecTag {
1031 let ConnAddrState { sharing, id: _ } = state;
1032 AddrVecTag {
1033 sharing: *sharing,
1034 has_device,
1035 state: SocketTagState::Conn,
1036 specified_addr: true,
1037 }
1038 }
1039}
1040
1041#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1042struct AddrVecTag {
1043 sharing: SharingState,
1044 state: SocketTagState,
1045 has_device: bool,
1046 specified_addr: bool,
1047}
1048
1049#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1050enum SocketTagState {
1051 Conn,
1052 Listener,
1053 Bound,
1054}
1055
1056#[derive(Debug)]
1057enum ListenerAddrState<S> {
1058 ExclusiveBound(S),
1059 ExclusiveListener(S),
1060 Shared { listener: Option<S>, bound: SmallVec<[S; 1]> },
1061}
1062
1063#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1064pub struct ListenerSharingState {
1065 pub(crate) sharing: SharingState,
1066 pub(crate) listening: bool,
1067}
1068
1069enum ListenerAddrInserter<'a, S> {
1070 Listener(&'a mut Option<S>),
1071 Bound(&'a mut SmallVec<[S; 1]>),
1072}
1073
1074impl<'a, S> Inserter<S> for ListenerAddrInserter<'a, S> {
1075 fn insert(self, id: S) {
1076 match self {
1077 Self::Listener(o) => *o = Some(id),
1078 Self::Bound(b) => b.push(id),
1079 }
1080 }
1081}
1082
1083impl<S: SpecSocketId> SocketMapAddrStateSpec for ListenerAddrState<S> {
1084 type SharingState = ListenerSharingState;
1085 type Id = S;
1086 type Inserter<'a> = ListenerAddrInserter<'a, S>;
1087
1088 fn new(new_sharing_state: &Self::SharingState, id: Self::Id) -> Self {
1089 let ListenerSharingState { sharing, listening } = new_sharing_state;
1090 match sharing {
1091 SharingState::Exclusive => match listening {
1092 true => Self::ExclusiveListener(id),
1093 false => Self::ExclusiveBound(id),
1094 },
1095 SharingState::ReuseAddress => {
1096 let (listener, bound) =
1097 if *listening { (Some(id), Default::default()) } else { (None, smallvec![id]) };
1098 Self::Shared { listener, bound }
1099 }
1100 }
1101 }
1102
1103 fn contains_id(&self, id: &Self::Id) -> bool {
1104 match self {
1105 Self::ExclusiveBound(x) | Self::ExclusiveListener(x) => id == x,
1106 Self::Shared { listener, bound } => {
1107 listener.as_ref().is_some_and(|x| id == x) || bound.contains(id)
1108 }
1109 }
1110 }
1111
1112 fn could_insert(
1113 &self,
1114 new_sharing_state: &Self::SharingState,
1115 ) -> Result<(), IncompatibleError> {
1116 match self {
1117 Self::ExclusiveBound(_) | Self::ExclusiveListener(_) => Err(IncompatibleError),
1118 Self::Shared { listener, bound: _ } => {
1119 let ListenerSharingState { listening: _, sharing } = new_sharing_state;
1120 match sharing {
1121 SharingState::Exclusive => Err(IncompatibleError),
1122 SharingState::ReuseAddress => match listener {
1123 Some(_) => Err(IncompatibleError),
1124 None => Ok(()),
1125 },
1126 }
1127 }
1128 }
1129 }
1130
1131 fn remove_by_id(&mut self, id: Self::Id) -> RemoveResult {
1132 match self {
1133 Self::ExclusiveBound(b) => {
1134 assert_eq!(*b, id);
1135 RemoveResult::IsLast
1136 }
1137 Self::ExclusiveListener(l) => {
1138 assert_eq!(*l, id);
1139 RemoveResult::IsLast
1140 }
1141 Self::Shared { listener, bound } => {
1142 match listener {
1143 Some(l) if *l == id => {
1144 *listener = None;
1145 }
1146 Some(_) | None => {
1147 let index = bound.iter().position(|b| *b == id).expect("invalid socket ID");
1148 let _: S = bound.swap_remove(index);
1149 }
1150 };
1151 match (listener, bound.is_empty()) {
1152 (Some(_), _) => RemoveResult::Success,
1153 (None, false) => RemoveResult::Success,
1154 (None, true) => RemoveResult::IsLast,
1155 }
1156 }
1157 }
1158 }
1159
1160 fn try_get_inserter<'a, 'b>(
1161 &'b mut self,
1162 new_sharing_state: &'a Self::SharingState,
1163 ) -> Result<Self::Inserter<'b>, IncompatibleError> {
1164 match self {
1165 Self::ExclusiveBound(_) | Self::ExclusiveListener(_) => Err(IncompatibleError),
1166 Self::Shared { listener, bound } => {
1167 let ListenerSharingState { listening, sharing } = new_sharing_state;
1168 match sharing {
1169 SharingState::Exclusive => Err(IncompatibleError),
1170 SharingState::ReuseAddress => {
1171 match listener {
1172 Some(_) => {
1173 Err(IncompatibleError)
1176 }
1177 None => Ok(match listening {
1178 true => ListenerAddrInserter::Listener(listener),
1179 false => ListenerAddrInserter::Bound(bound),
1180 }),
1181 }
1182 }
1183 }
1184 }
1185 }
1186 }
1187
1188 fn sharing_state(&self) -> Self::SharingState {
1189 let (sharing, listening) = match self {
1190 Self::ExclusiveBound(_) => (SharingState::Exclusive, false),
1191 Self::ExclusiveListener(_) => (SharingState::Exclusive, true),
1192 Self::Shared { listener, bound: _ } => (SharingState::ReuseAddress, listener.is_some()),
1193 };
1194 ListenerSharingState { sharing, listening }
1195 }
1196}
1197
1198fn check_conflicts<I, D, BT>(
1202 socketmap: &SocketMap<AddrVec<I, D, TcpPortSpec>, Bound<TcpSocketSpec<I, D, BT>>>,
1203 addr: &ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1204 filter: impl Fn(&AddrVecTag) -> bool,
1205) -> Result<(), InsertError>
1206where
1207 I: DualStackIpExt,
1208 D: WeakDeviceIdentifier,
1209 BT: TcpBindingsTypes,
1210{
1211 let addr_vec = AddrVec::Listen(addr.clone());
1213 for shadow_addr in addr_vec.iter_shadows() {
1214 if let Some(bound) = socketmap.get(&shadow_addr) {
1215 let tag = bound.tag(&shadow_addr);
1216 if filter(&tag) {
1217 return Err(InsertError::ShadowAddrExists);
1218 }
1219 }
1220 }
1221
1222 if socketmap.descendant_counts(&addr.clone().into()).any(|(tag, _)| filter(tag)) {
1224 return Err(InsertError::WouldShadowExisting);
1225 }
1226
1227 if addr.device.is_some()
1230 && socketmap
1231 .descendant_counts(&addr.without_device().into())
1232 .any(|(tag, _)| !tag.has_device && filter(tag))
1233 {
1234 return Err(InsertError::IndirectConflict);
1235 }
1236
1237 if addr.ip.addr.is_some()
1239 && socketmap
1240 .descendant_counts(&addr.without_addr().into())
1241 .any(|(tag, _)| !tag.specified_addr && filter(tag))
1242 {
1243 return Err(InsertError::IndirectConflict);
1244 }
1245
1246 Ok(())
1247}
1248
1249impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1250 SocketMapUpdateSharingPolicy<
1251 ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1252 ListenerSharingState,
1253 I,
1254 D,
1255 TcpPortSpec,
1256 > for TcpSocketSpec<I, D, BT>
1257{
1258 fn allows_sharing_update(
1259 socketmap: &SocketMap<AddrVec<I, D, TcpPortSpec>, Bound<Self>>,
1260 addr: &ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1261 old_state: &ListenerSharingState,
1262 new_state: &ListenerSharingState,
1263 ) -> Result<(), UpdateSharingError> {
1264 match (old_state.listening, new_state.listening) {
1265 (true, false) => (), (true, true) | (false, false) => (), (false, true) => {
1268 check_conflicts(socketmap, addr, |tag| tag.state == SocketTagState::Listener)
1269 .map_err(|_conflict| UpdateSharingError)?;
1270 }
1271 }
1272
1273 match (old_state.sharing, new_state.sharing) {
1274 (SharingState::Exclusive, SharingState::Exclusive)
1275 | (SharingState::ReuseAddress, SharingState::ReuseAddress)
1276 | (SharingState::Exclusive, SharingState::ReuseAddress) => (),
1277 (SharingState::ReuseAddress, SharingState::Exclusive) => {
1278 check_conflicts(socketmap, addr, |tag| tag.state != SocketTagState::Conn)
1284 .map_err(|_conflict| UpdateSharingError)?;
1285 }
1286 }
1287
1288 Ok(())
1289 }
1290}
1291
1292impl<S: SpecSocketId> SocketMapAddrStateUpdateSharingSpec for ListenerAddrState<S> {
1293 fn try_update_sharing(
1294 &mut self,
1295 id: Self::Id,
1296 ListenerSharingState{listening: new_listening, sharing: new_sharing}: &Self::SharingState,
1297 ) -> Result<(), IncompatibleError> {
1298 match self {
1299 Self::ExclusiveBound(i) | Self::ExclusiveListener(i) => {
1300 assert_eq!(i, &id);
1301 *self = match new_sharing {
1302 SharingState::Exclusive => match new_listening {
1303 true => Self::ExclusiveListener(id),
1304 false => Self::ExclusiveBound(id),
1305 },
1306 SharingState::ReuseAddress => {
1307 let (listener, bound) = match new_listening {
1308 true => (Some(id), Default::default()),
1309 false => (None, smallvec![id]),
1310 };
1311 Self::Shared { listener, bound }
1312 }
1313 };
1314 Ok(())
1315 }
1316 Self::Shared { listener, bound } => {
1317 if listener.as_ref() == Some(&id) {
1318 match new_sharing {
1319 SharingState::Exclusive => {
1320 if bound.is_empty() {
1321 *self = match new_listening {
1322 true => Self::ExclusiveListener(id),
1323 false => Self::ExclusiveBound(id),
1324 };
1325 Ok(())
1326 } else {
1327 Err(IncompatibleError)
1328 }
1329 }
1330 SharingState::ReuseAddress => match new_listening {
1331 true => Ok(()), false => {
1333 bound.push(id);
1334 *listener = None;
1335 Ok(())
1336 }
1337 },
1338 }
1339 } else {
1340 let index = bound
1341 .iter()
1342 .position(|b| b == &id)
1343 .expect("ID is neither listener nor bound");
1344 if *new_listening && listener.is_some() {
1345 return Err(IncompatibleError);
1346 }
1347 match new_sharing {
1348 SharingState::Exclusive => {
1349 if bound.len() > 1 {
1350 return Err(IncompatibleError);
1351 } else {
1352 *self = match new_listening {
1353 true => Self::ExclusiveListener(id),
1354 false => Self::ExclusiveBound(id),
1355 };
1356 Ok(())
1357 }
1358 }
1359 SharingState::ReuseAddress => {
1360 match new_listening {
1361 false => Ok(()), true => {
1363 let _: S = bound.swap_remove(index);
1364 *listener = Some(id);
1365 Ok(())
1366 }
1367 }
1368 }
1369 }
1370 }
1371 }
1372 }
1373 }
1374}
1375
1376#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1377pub enum SharingState {
1378 Exclusive,
1379 ReuseAddress,
1380}
1381
1382impl Default for SharingState {
1383 fn default() -> Self {
1384 Self::Exclusive
1385 }
1386}
1387
1388impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1389 SocketMapConflictPolicy<
1390 ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1391 ListenerSharingState,
1392 I,
1393 D,
1394 TcpPortSpec,
1395 > for TcpSocketSpec<I, D, BT>
1396{
1397 fn check_insert_conflicts(
1398 state: &ListenerSharingState,
1399 addr: &ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1400 socketmap: &SocketMap<AddrVec<I, D, TcpPortSpec>, Bound<Self>>,
1401 ) -> Result<(), InsertError> {
1402 fn can_share(s1: SharingState, s2: SharingState) -> bool {
1403 (s1, s2) == (SharingState::ReuseAddress, SharingState::ReuseAddress)
1404 }
1405
1406 check_conflicts(socketmap, addr, |tag| {
1407 tag.state == SocketTagState::Listener || !can_share(tag.sharing, state.sharing)
1408 })
1409 }
1410}
1411
1412impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1413 SocketMapConflictPolicy<
1414 ConnAddr<ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>, D>,
1415 SharingState,
1416 I,
1417 D,
1418 TcpPortSpec,
1419 > for TcpSocketSpec<I, D, BT>
1420{
1421 fn check_insert_conflicts(
1422 _sharing: &SharingState,
1423 addr: &ConnAddr<ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>, D>,
1424 socketmap: &SocketMap<AddrVec<I, D, TcpPortSpec>, Bound<Self>>,
1425 ) -> Result<(), InsertError> {
1426 let addr_vec = AddrVec::Conn(addr.clone());
1429 if socketmap.get(&addr_vec).is_some() {
1430 return Err(InsertError::Exists);
1431 }
1432
1433 match &addr.device {
1434 None => {
1439 if socketmap.descendant_counts(&addr_vec).len() > 0 {
1440 return Err(InsertError::WouldShadowExisting);
1441 }
1442 }
1443 Some(_device) => {
1447 if socketmap.get(&AddrVec::Conn(ConnAddr { device: None, ip: addr.ip })).is_some() {
1448 return Err(InsertError::ShadowAddrExists);
1449 }
1450 }
1451 }
1452 Ok(())
1454 }
1455}
1456
1457#[derive(Debug)]
1458struct ConnAddrState<S> {
1459 sharing: SharingState,
1460 id: S,
1461}
1462
1463impl<S: SpecSocketId> ConnAddrState<S> {
1464 #[cfg_attr(feature = "instrumented", track_caller)]
1465 pub(crate) fn id(&self) -> S {
1466 self.id.clone()
1467 }
1468}
1469
1470impl<S: SpecSocketId> SocketMapAddrStateSpec for ConnAddrState<S> {
1471 type Id = S;
1472 type Inserter<'a> = !;
1473 type SharingState = SharingState;
1474
1475 fn new(new_sharing_state: &Self::SharingState, id: Self::Id) -> Self {
1476 Self { sharing: *new_sharing_state, id }
1477 }
1478
1479 fn contains_id(&self, id: &Self::Id) -> bool {
1480 &self.id == id
1481 }
1482
1483 fn could_insert(
1484 &self,
1485 _new_sharing_state: &Self::SharingState,
1486 ) -> Result<(), IncompatibleError> {
1487 Err(IncompatibleError)
1488 }
1489
1490 fn remove_by_id(&mut self, id: Self::Id) -> RemoveResult {
1491 let Self { sharing: _, id: existing_id } = self;
1492 assert_eq!(*existing_id, id);
1493 return RemoveResult::IsLast;
1494 }
1495
1496 fn try_get_inserter<'a, 'b>(
1497 &'b mut self,
1498 _new_sharing_state: &'a Self::SharingState,
1499 ) -> Result<Self::Inserter<'b>, IncompatibleError> {
1500 Err(IncompatibleError)
1501 }
1502
1503 fn sharing_state(&self) -> Self::SharingState {
1504 self.sharing
1505 }
1506}
1507
1508#[derive(Debug, Clone)]
1509#[cfg_attr(test, derive(PartialEq))]
1510pub struct Unbound<D, Extra> {
1511 bound_device: Option<D>,
1512 buffer_sizes: BufferSizes,
1513 socket_extra: Takeable<Extra>,
1514}
1515
1516type PrimaryRc<I, D, BT> = netstack3_base::sync::PrimaryRc<ReferenceState<I, D, BT>>;
1517type StrongRc<I, D, BT> = netstack3_base::sync::StrongRc<ReferenceState<I, D, BT>>;
1518type WeakRc<I, D, BT> = netstack3_base::sync::WeakRc<ReferenceState<I, D, BT>>;
1519
1520#[derive(Derivative)]
1521#[derivative(Debug(bound = "D: Debug"))]
1522pub enum TcpSocketSetEntry<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1523 Primary(PrimaryRc<I, D, BT>),
1525 DeadOnArrival,
1535}
1536
1537#[derive(Debug, Derivative)]
1540#[derivative(Default(bound = ""))]
1541pub struct TcpSocketSet<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1542 HashMap<TcpSocketId<I, D, BT>, TcpSocketSetEntry<I, D, BT>>,
1543);
1544
1545impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Deref
1546 for TcpSocketSet<I, D, BT>
1547{
1548 type Target = HashMap<TcpSocketId<I, D, BT>, TcpSocketSetEntry<I, D, BT>>;
1549 fn deref(&self) -> &Self::Target {
1550 &self.0
1551 }
1552}
1553
1554impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> DerefMut
1555 for TcpSocketSet<I, D, BT>
1556{
1557 fn deref_mut(&mut self) -> &mut Self::Target {
1558 &mut self.0
1559 }
1560}
1561
1562impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Drop
1568 for TcpSocketSet<I, D, BT>
1569{
1570 fn drop(&mut self) {
1571 let Self(map) = self;
1580 for TcpSocketId(rc) in map.keys() {
1581 let guard = rc.locked_state.read();
1582 let accept_queue = match &(*guard).socket_state {
1583 TcpSocketStateInner::Listener(Listener { accept_queue, .. }) => accept_queue,
1584 _ => continue,
1585 };
1586 if !accept_queue.is_closed() {
1587 let (_pending_sockets_iterator, _): (_, BT::ListenerNotifierOrProvidedBuffers) =
1588 accept_queue.close();
1589 }
1590 }
1591 }
1592}
1593
1594type BoundSocketMap<I, D, BT> = socket::BoundSocketMap<I, D, TcpPortSpec, TcpSocketSpec<I, D, BT>>;
1595
1596#[derive(GenericOverIp)]
1598#[generic_over_ip(I, Ip)]
1599pub struct DemuxState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1600 socketmap: BoundSocketMap<I, D, BT>,
1601}
1602
1603pub struct Sockets<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1605 demux: RwLock<DemuxState<I, D, BT>>,
1606 all_sockets: RwLock<TcpSocketSet<I, D, BT>>,
1609}
1610
1611impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1612 OrderedLockAccess<DemuxState<I, D, BT>> for Sockets<I, D, BT>
1613{
1614 type Lock = RwLock<DemuxState<I, D, BT>>;
1615 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
1616 OrderedLockRef::new(&self.demux)
1617 }
1618}
1619
1620impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1621 OrderedLockAccess<TcpSocketSet<I, D, BT>> for Sockets<I, D, BT>
1622{
1623 type Lock = RwLock<TcpSocketSet<I, D, BT>>;
1624 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
1625 OrderedLockRef::new(&self.all_sockets)
1626 }
1627}
1628
1629#[derive(Derivative)]
1631#[derivative(Debug(bound = "D: Debug"))]
1632pub struct ReferenceState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1633 locked_state: RwLock<TcpSocketState<I, D, BT>>,
1634 counters: TcpCountersWithSocket<I>,
1635}
1636
1637#[derive(Derivative)]
1639#[derivative(Debug(bound = "D: Debug"))]
1640pub struct TcpSocketState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1641 socket_state: TcpSocketStateInner<I, D, BT>,
1642 sharing: SharingState,
1643 ip_options: I::DualStackIpOptions,
1645 socket_options: SocketOptions,
1647}
1648
1649#[derive(Derivative)]
1650#[derivative(Debug(bound = "D: Debug"))]
1651pub enum TcpSocketStateInner<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1652 Unbound(Unbound<D, BT::ListenerNotifierOrProvidedBuffers>),
1653 Bound(BoundState<I, D, BT>),
1654 Listener(Listener<I, D, BT>),
1655 Connected { conn: I::ConnectionAndAddr<D, BT>, timer: BT::Timer },
1656}
1657
1658struct TcpPortAlloc<'a, I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1659 &'a BoundSocketMap<I, D, BT>,
1660);
1661
1662impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> PortAllocImpl
1663 for TcpPortAlloc<'_, I, D, BT>
1664{
1665 const EPHEMERAL_RANGE: RangeInclusive<u16> = 49152..=65535;
1666 type Id = Option<SocketIpAddr<I::Addr>>;
1667 type PortAvailableArg = Option<NonZeroU16>;
1673
1674 fn is_port_available(&self, addr: &Self::Id, port: u16, arg: &Option<NonZeroU16>) -> bool {
1675 let Self(socketmap) = self;
1676 let port = NonZeroU16::new(port).unwrap();
1679
1680 if arg.is_some_and(|a| a == port) {
1682 return false;
1683 }
1684
1685 let root_addr = AddrVec::from(ListenerAddr {
1686 ip: ListenerIpAddr { addr: *addr, identifier: port },
1687 device: None,
1688 });
1689
1690 root_addr.iter_shadows().chain(core::iter::once(root_addr.clone())).all(|a| match &a {
1694 AddrVec::Listen(l) => socketmap.listeners().get_by_addr(&l).is_none(),
1695 AddrVec::Conn(_c) => {
1696 unreachable!("no connection shall be included in an iteration from a listener")
1697 }
1698 }) && socketmap.get_shadower_counts(&root_addr) == 0
1699 }
1700}
1701
1702struct TcpDualStackPortAlloc<'a, I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1703 &'a BoundSocketMap<I, D, BT>,
1704 &'a BoundSocketMap<I::OtherVersion, D, BT>,
1705);
1706
1707impl<'a, I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> PortAllocImpl
1710 for TcpDualStackPortAlloc<'a, I, D, BT>
1711{
1712 const EPHEMERAL_RANGE: RangeInclusive<u16> =
1713 <TcpPortAlloc<'a, I, D, BT> as PortAllocImpl>::EPHEMERAL_RANGE;
1714 type Id = ();
1715 type PortAvailableArg = ();
1716
1717 fn is_port_available(&self, (): &Self::Id, port: u16, (): &Self::PortAvailableArg) -> bool {
1718 let Self(this, other) = self;
1719 TcpPortAlloc(this).is_port_available(&None, port, &None)
1720 && TcpPortAlloc(other).is_port_available(&None, port, &None)
1721 }
1722}
1723
1724impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Sockets<I, D, BT> {
1725 pub(crate) fn new() -> Self {
1726 Self {
1727 demux: RwLock::new(DemuxState { socketmap: Default::default() }),
1728 all_sockets: Default::default(),
1729 }
1730 }
1731}
1732
1733#[derive(Derivative)]
1739#[derivative(Debug(bound = "D: Debug"))]
1740pub struct Connection<
1741 SockI: DualStackIpExt,
1742 WireI: DualStackIpExt,
1743 D: WeakDeviceIdentifier,
1744 BT: TcpBindingsTypes,
1745> {
1746 accept_queue: Option<
1747 AcceptQueue<
1748 TcpSocketId<SockI, D, BT>,
1749 BT::ReturnedBuffers,
1750 BT::ListenerNotifierOrProvidedBuffers,
1751 >,
1752 >,
1753 state: State<
1754 BT::Instant,
1755 BT::ReceiveBuffer,
1756 BT::SendBuffer,
1757 BT::ListenerNotifierOrProvidedBuffers,
1758 >,
1759 ip_sock: IpSock<WireI, D>,
1760 defunct: bool,
1764 soft_error: Option<ConnectionError>,
1768 handshake_status: HandshakeStatus,
1770}
1771
1772impl<SockI: DualStackIpExt, WireI: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1773 Connection<SockI, WireI, D, BT>
1774{
1775 fn on_icmp_error<CC: TcpCounterContext<SockI, D, BT>>(
1779 &mut self,
1780 core_ctx: &mut CC,
1781 id: &TcpSocketId<SockI, D, BT>,
1782 seq: SeqNum,
1783 error: IcmpErrorCode,
1784 ) -> (NewlyClosed, ShouldRetransmit) {
1785 let Connection { soft_error, state, .. } = self;
1786 let (new_soft_error, newly_closed, should_send) =
1787 state.on_icmp_error(&TcpCountersRefs::from_ctx(core_ctx, id), error, seq);
1788 *soft_error = soft_error.or(new_soft_error);
1789 (newly_closed, should_send)
1790 }
1791}
1792
1793#[derive(Derivative)]
1798#[derivative(Debug(bound = "D: Debug"))]
1799#[cfg_attr(
1800 test,
1801 derivative(
1802 PartialEq(
1803 bound = "BT::ReturnedBuffers: PartialEq, BT::ListenerNotifierOrProvidedBuffers: PartialEq, I::ListenerIpAddr: PartialEq"
1804 ),
1805 Eq(
1806 bound = "BT::ReturnedBuffers: Eq, BT::ListenerNotifierOrProvidedBuffers: Eq, I::ListenerIpAddr: Eq"
1807 ),
1808 )
1809)]
1810pub struct Listener<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1811 addr: ListenerAddr<I::ListenerIpAddr, D>,
1812 backlog: NonZeroUsize,
1813 accept_queue: AcceptQueue<
1814 TcpSocketId<I, D, BT>,
1815 BT::ReturnedBuffers,
1816 BT::ListenerNotifierOrProvidedBuffers,
1817 >,
1818 buffer_sizes: BufferSizes,
1819 }
1822
1823impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Listener<I, D, BT> {
1824 fn new(
1825 addr: ListenerAddr<I::ListenerIpAddr, D>,
1826 backlog: NonZeroUsize,
1827 buffer_sizes: BufferSizes,
1828 notifier: BT::ListenerNotifierOrProvidedBuffers,
1829 ) -> Self {
1830 Self { addr, backlog, accept_queue: AcceptQueue::new(notifier), buffer_sizes }
1831 }
1832}
1833
1834#[derive(Clone, Derivative)]
1835#[derivative(Debug(bound = "D: Debug"))]
1836#[cfg_attr(test, derive(Eq, PartialEq))]
1837pub struct BoundState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1838 addr: ListenerAddr<I::ListenerIpAddr, D>,
1839 buffer_sizes: BufferSizes,
1840 socket_extra: Takeable<BT::ListenerNotifierOrProvidedBuffers>,
1841}
1842
1843#[derive(Derivative, GenericOverIp)]
1845#[generic_over_ip(I, Ip)]
1846#[derivative(Eq(bound = ""), PartialEq(bound = ""), Hash(bound = ""))]
1847pub struct TcpSocketId<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1848 StrongRc<I, D, BT>,
1849);
1850
1851impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Clone
1852 for TcpSocketId<I, D, BT>
1853{
1854 #[cfg_attr(feature = "instrumented", track_caller)]
1855 fn clone(&self) -> Self {
1856 let Self(rc) = self;
1857 Self(StrongRc::clone(rc))
1858 }
1859}
1860
1861impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpSocketId<I, D, BT> {
1862 pub(crate) fn new(
1863 socket_state: TcpSocketStateInner<I, D, BT>,
1864 socket_options: SocketOptions,
1865 ) -> (Self, PrimaryRc<I, D, BT>) {
1866 let primary = PrimaryRc::new(ReferenceState {
1867 locked_state: RwLock::new(TcpSocketState {
1868 socket_state,
1869 sharing: Default::default(),
1870 ip_options: Default::default(),
1871 socket_options,
1872 }),
1873 counters: Default::default(),
1874 });
1875 let socket = Self(PrimaryRc::clone_strong(&primary));
1876 (socket, primary)
1877 }
1878
1879 pub(crate) fn new_cyclic<
1880 F: FnOnce(WeakTcpSocketId<I, D, BT>) -> TcpSocketStateInner<I, D, BT>,
1881 >(
1882 init: F,
1883 sharing: SharingState,
1884 socket_options: SocketOptions,
1885 ) -> (Self, PrimaryRc<I, D, BT>) {
1886 let primary = PrimaryRc::new_cyclic(move |weak| {
1887 let socket_state = init(WeakTcpSocketId(weak));
1888 ReferenceState {
1889 locked_state: RwLock::new(TcpSocketState {
1890 socket_state,
1891 sharing,
1892 ip_options: Default::default(),
1893 socket_options,
1894 }),
1895 counters: Default::default(),
1896 }
1897 });
1898 let socket = Self(PrimaryRc::clone_strong(&primary));
1899 (socket, primary)
1900 }
1901
1902 pub fn counters(&self) -> &TcpCountersWithSocket<I> {
1904 let Self(rc) = self;
1905 &rc.counters
1906 }
1907
1908 pub(crate) fn trace_id(&self) -> TraceResourceId<'_> {
1909 let Self(inner) = self;
1910 TraceResourceId::new(inner.resource_token())
1911 }
1912
1913 pub fn socket_cookie(&self) -> SocketCookie {
1915 let Self(inner) = self;
1916 SocketCookie::new(inner.resource_token())
1917 }
1918
1919 pub fn socket_info(&self) -> netstack3_base::socket::SocketInfo {
1921 let Self(inner) = self;
1922 netstack3_base::socket::SocketInfo {
1923 proto: I::map_ip(
1924 (),
1925 |()| EitherIpProto::V4(Ipv4Proto::Proto(IpProto::Tcp)),
1926 |()| EitherIpProto::V6(Ipv6Proto::Proto(IpProto::Tcp)),
1927 ),
1928 cookie: SocketCookie::new(inner.resource_token()),
1929 }
1930 }
1931
1932 pub(crate) fn either(&self) -> EitherTcpSocketId<'_, D, BT> {
1933 I::map_ip_in(self, EitherTcpSocketId::V4, EitherTcpSocketId::V6)
1934 }
1935
1936 pub(crate) fn get_bound_device<CC>(&self, core_ctx: &mut CC) -> Option<D>
1937 where
1938 CC: TcpContext<I, BT, WeakDeviceId = D>,
1939 {
1940 core_ctx.with_socket(self, |state| match &state.socket_state {
1941 TcpSocketStateInner::Unbound(state) => state.bound_device.clone(),
1942 TcpSocketStateInner::Listener(Listener { addr, .. })
1943 | TcpSocketStateInner::Bound(BoundState { addr, .. }) => addr.device.clone(),
1944 TcpSocketStateInner::Connected { conn, .. } => I::get_conn_info(&conn).device,
1945 })
1946 }
1947}
1948
1949impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Debug
1950 for TcpSocketId<I, D, BT>
1951{
1952 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1953 let Self(rc) = self;
1954 f.debug_tuple("TcpSocketId").field(&StrongRc::debug_id(rc)).finish()
1955 }
1956}
1957
1958impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpSocketId<I, D, BT> {
1959 pub(crate) fn downgrade(&self) -> WeakTcpSocketId<I, D, BT> {
1960 let Self(this) = self;
1961 WeakTcpSocketId(StrongRc::downgrade(this))
1962 }
1963}
1964
1965impl<CC, I, BT> SocketMetadata<CC> for TcpSocketId<I, CC::WeakDeviceId, BT>
1966where
1967 CC: ?Sized + TcpContext<I, BT>,
1968 I: DualStackIpExt,
1969 BT: TcpBindingsTypes,
1970{
1971 fn socket_info(&self, _core_ctx: &mut CC) -> netstack3_base::socket::SocketInfo {
1972 self.socket_info()
1973 }
1974
1975 fn marks(&self, core_ctx: &mut CC) -> Marks {
1976 core_ctx.with_socket(self, |state| state.socket_options.ip_options.marks.clone())
1977 }
1978}
1979
1980#[derive(Derivative, GenericOverIp)]
1982#[generic_over_ip(I, Ip)]
1983#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Hash(bound = ""))]
1984pub struct WeakTcpSocketId<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1985 WeakRc<I, D, BT>,
1986);
1987
1988impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Debug
1989 for WeakTcpSocketId<I, D, BT>
1990{
1991 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1992 let Self(rc) = self;
1993 f.debug_tuple("WeakTcpSocketId").field(&rc.debug_id()).finish()
1994 }
1995}
1996
1997impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1998 PartialEq<TcpSocketId<I, D, BT>> for WeakTcpSocketId<I, D, BT>
1999{
2000 fn eq(&self, other: &TcpSocketId<I, D, BT>) -> bool {
2001 let Self(this) = self;
2002 let TcpSocketId(other) = other;
2003 StrongRc::weak_ptr_eq(other, this)
2004 }
2005}
2006
2007impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> WeakTcpSocketId<I, D, BT> {
2008 #[cfg_attr(feature = "instrumented", track_caller)]
2010 pub fn upgrade(&self) -> Option<TcpSocketId<I, D, BT>> {
2011 let Self(this) = self;
2012 this.upgrade().map(TcpSocketId)
2013 }
2014}
2015
2016impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
2017 OrderedLockAccess<TcpSocketState<I, D, BT>> for TcpSocketId<I, D, BT>
2018{
2019 type Lock = RwLock<TcpSocketState<I, D, BT>>;
2020 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
2021 let Self(rc) = self;
2022 OrderedLockRef::new(&rc.locked_state)
2023 }
2024}
2025
2026#[derive(Derivative)]
2032#[derivative(Debug(bound = ""))]
2033pub(crate) enum EitherTcpSocketId<'a, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
2034 #[derivative(Debug = "transparent")]
2035 V4(&'a TcpSocketId<Ipv4, D, BT>),
2036 #[derivative(Debug = "transparent")]
2037 V6(&'a TcpSocketId<Ipv6, D, BT>),
2038}
2039
2040impl<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> StateMachineDebugId
2041 for EitherTcpSocketId<'_, D, BT>
2042{
2043 fn trace_id(&self) -> TraceResourceId<'_> {
2044 match self {
2045 Self::V4(v4) => v4.trace_id(),
2046 Self::V6(v6) => v6.trace_id(),
2047 }
2048 }
2049}
2050
2051#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2053pub enum HandshakeStatus {
2054 Pending,
2056 Aborted,
2058 Completed {
2060 reported: bool,
2062 },
2063}
2064
2065impl HandshakeStatus {
2066 fn update_if_pending(&mut self, new_status: Self) -> bool {
2067 if *self == HandshakeStatus::Pending {
2068 *self = new_status;
2069 true
2070 } else {
2071 false
2072 }
2073 }
2074}
2075
2076fn bind_get_local_addr_and_device<I, BT, CC>(
2078 core_ctx: &mut CC,
2079 addr: Option<ZonedAddr<SocketIpAddr<I::Addr>, CC::DeviceId>>,
2080 bound_device: &Option<CC::WeakDeviceId>,
2081) -> Result<(Option<SocketIpAddr<I::Addr>>, Option<CC::WeakDeviceId>), LocalAddressError>
2082where
2083 I: DualStackIpExt,
2084 BT: TcpBindingsTypes,
2085 CC: TransportIpContext<I, BT>,
2086{
2087 let (local_ip, device) = match addr {
2088 Some(addr) => {
2089 let (addr, required_device) = addr
2093 .resolve_addr_with_device(bound_device.clone())
2094 .map_err(LocalAddressError::Zone)?;
2095
2096 if addr.addr().is_multicast()
2099 || I::map_ip_in(addr.addr(), |ip| ip.is_limited_broadcast(), |_| false)
2100 {
2101 return Err(LocalAddressError::CannotBindToAddress);
2102 }
2103
2104 core_ctx.with_devices_with_assigned_addr(addr.clone().into(), |mut assigned_to| {
2105 if !assigned_to.any(|d| {
2106 required_device
2107 .as_ref()
2108 .map_or(true, |device| device == &EitherDeviceId::Strong(d))
2109 }) {
2110 Err(LocalAddressError::AddressMismatch)
2111 } else {
2112 Ok(())
2113 }
2114 })?;
2115 (Some(addr), required_device)
2116 }
2117 None => (None, bound_device.clone().map(EitherDeviceId::Weak)),
2118 };
2119 let weak_device = device.map(|d| d.as_weak().into_owned());
2120 Ok((local_ip, weak_device))
2121}
2122
2123fn bind_install_in_demux<I, D, BC>(
2124 bindings_ctx: &mut BC,
2125 demux_socket_id: I::DemuxSocketId<D, BC>,
2126 local_ip: Option<SocketIpAddr<I::Addr>>,
2127 weak_device: Option<D>,
2128 port: Option<NonZeroU16>,
2129 sharing: SharingState,
2130 DemuxState { socketmap }: &mut DemuxState<I, D, BC>,
2131) -> Result<ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>, LocalAddressError>
2132where
2133 I: DualStackIpExt,
2134 BC: TcpBindingsTypes + RngContext,
2135 D: WeakDeviceIdentifier,
2136{
2137 let port = match port {
2138 None => {
2139 match netstack3_base::simple_randomized_port_alloc(
2140 &mut bindings_ctx.rng(),
2141 &local_ip,
2142 &TcpPortAlloc(socketmap),
2143 &None,
2144 ) {
2145 Some(port) => NonZeroU16::new(port).expect("ephemeral ports must be non-zero"),
2146 None => {
2147 return Err(LocalAddressError::FailedToAllocateLocalPort);
2148 }
2149 }
2150 }
2151 Some(port) => port,
2152 };
2153
2154 let addr = ListenerAddr {
2155 ip: ListenerIpAddr { addr: local_ip, identifier: port },
2156 device: weak_device,
2157 };
2158 let sharing = ListenerSharingState { sharing, listening: false };
2159
2160 let _inserted = socketmap
2161 .listeners_mut()
2162 .try_insert(addr.clone(), sharing, demux_socket_id)
2163 .map_err(Into::<LocalAddressError>::into)?;
2164
2165 Ok(addr)
2166}
2167
2168fn try_update_listener_sharing<I, CC, BT>(
2169 core_ctx: MaybeDualStack<
2170 (&mut CC::DualStackIpTransportAndDemuxCtx<'_>, CC::DualStackConverter),
2171 (&mut CC::SingleStackIpTransportAndDemuxCtx<'_>, CC::SingleStackConverter),
2172 >,
2173 id: &TcpSocketId<I, CC::WeakDeviceId, BT>,
2174 addr: ListenerAddr<I::ListenerIpAddr, CC::WeakDeviceId>,
2175 sharing: &ListenerSharingState,
2176 new_sharing: ListenerSharingState,
2177) -> Result<(), UpdateSharingError>
2178where
2179 I: DualStackIpExt,
2180 CC: TcpContext<I, BT>,
2181 BT: TcpBindingsTypes,
2182{
2183 match core_ctx {
2184 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
2185 core_ctx.with_demux_mut(|DemuxState { socketmap }| {
2186 let mut entry = socketmap
2187 .listeners_mut()
2188 .entry(&I::into_demux_socket_id(id.clone()), &converter.convert(addr))
2189 .expect("invalid listener id");
2190 entry.try_update_sharing(sharing, new_sharing)
2191 })
2192 }
2193 MaybeDualStack::DualStack((core_ctx, converter)) => match converter.convert(addr) {
2194 ListenerAddr { ip: DualStackListenerIpAddr::ThisStack(ip), device } => {
2195 TcpDemuxContext::<I, _, _>::with_demux_mut(core_ctx, |DemuxState { socketmap }| {
2196 let mut entry = socketmap
2197 .listeners_mut()
2198 .entry(&I::into_demux_socket_id(id.clone()), &ListenerAddr { ip, device })
2199 .expect("invalid listener id");
2200 entry.try_update_sharing(sharing, new_sharing)
2201 })
2202 }
2203 ListenerAddr { ip: DualStackListenerIpAddr::OtherStack(ip), device } => {
2204 let demux_id = core_ctx.into_other_demux_socket_id(id.clone());
2205 TcpDemuxContext::<I::OtherVersion, _, _>::with_demux_mut(
2206 core_ctx,
2207 |DemuxState { socketmap }| {
2208 let mut entry = socketmap
2209 .listeners_mut()
2210 .entry(&demux_id, &ListenerAddr { ip, device })
2211 .expect("invalid listener id");
2212 entry.try_update_sharing(sharing, new_sharing)
2213 },
2214 )
2215 }
2216 ListenerAddr { ip: DualStackListenerIpAddr::BothStacks(port), device } => {
2217 let other_demux_id = core_ctx.into_other_demux_socket_id(id.clone());
2218 let demux_id = I::into_demux_socket_id(id.clone());
2219 core_ctx.with_both_demux_mut(
2220 |DemuxState { socketmap: this_socketmap, .. },
2221 DemuxState { socketmap: other_socketmap, .. }| {
2222 let this_stack_listener_addr = ListenerAddr {
2223 ip: ListenerIpAddr { addr: None, identifier: port },
2224 device: device.clone(),
2225 };
2226 let mut this_stack_entry = this_socketmap
2227 .listeners_mut()
2228 .entry(&demux_id, &this_stack_listener_addr)
2229 .expect("invalid listener id");
2230 this_stack_entry.try_update_sharing(sharing, new_sharing)?;
2231 let mut other_stack_entry = other_socketmap
2232 .listeners_mut()
2233 .entry(
2234 &other_demux_id,
2235 &ListenerAddr {
2236 ip: ListenerIpAddr { addr: None, identifier: port },
2237 device,
2238 },
2239 )
2240 .expect("invalid listener id");
2241 match other_stack_entry.try_update_sharing(sharing, new_sharing) {
2242 Ok(()) => Ok(()),
2243 Err(err) => {
2244 this_stack_entry
2245 .try_update_sharing(&new_sharing, *sharing)
2246 .expect("failed to revert the sharing setting");
2247 Err(err)
2248 }
2249 }
2250 },
2251 )
2252 }
2253 },
2254 }
2255}
2256
2257struct ErrorReporter<'a, I, R, S, ActiveOpen> {
2258 state: &'a mut State<I, R, S, ActiveOpen>,
2259 soft_error: &'a mut Option<ConnectionError>,
2260}
2261
2262impl<'a, I, R, S, ActiveOpen> ErrorReporter<'a, I, R, S, ActiveOpen> {
2263 fn report_error(self) -> Option<ConnectionError> {
2264 let Self { state, soft_error } = self;
2265 if let State::Closed(Closed { reason }) = state {
2266 if let Some(hard_error) = reason.take() {
2267 return Some(hard_error);
2268 }
2269 }
2270 soft_error.take()
2271 }
2272
2273 fn new(
2274 state: &'a mut State<I, R, S, ActiveOpen>,
2275 soft_error: &'a mut Option<ConnectionError>,
2276 ) -> Self {
2277 Self { state, soft_error }
2278 }
2279}
2280
2281pub struct TcpApi<I: Ip, C>(C, IpVersionMarker<I>);
2283
2284impl<I: Ip, C> TcpApi<I, C> {
2285 pub fn new(ctx: C) -> Self {
2287 Self(ctx, IpVersionMarker::new())
2288 }
2289}
2290
2291type TcpApiSocketId<I, C> = TcpSocketId<
2296 I,
2297 <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
2298 <C as ContextPair>::BindingsContext,
2299>;
2300
2301impl<I, C> TcpApi<I, C>
2302where
2303 I: DualStackIpExt,
2304 C: ContextPair,
2305 C::CoreContext: TcpContext<I, C::BindingsContext>,
2306 C::BindingsContext: TcpBindingsContext<
2307 <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
2308 >,
2309{
2310 pub(crate) fn core_ctx(&mut self) -> &mut C::CoreContext {
2311 let Self(pair, IpVersionMarker { .. }) = self;
2312 pair.core_ctx()
2313 }
2314
2315 pub(crate) fn contexts(&mut self) -> (&mut C::CoreContext, &mut C::BindingsContext) {
2316 let Self(pair, IpVersionMarker { .. }) = self;
2317 pair.contexts()
2318 }
2319
2320 pub fn create(
2322 &mut self,
2323 socket_extra: <C::BindingsContext as TcpBindingsTypes>::ListenerNotifierOrProvidedBuffers,
2324 ) -> TcpApiSocketId<I, C> {
2325 let (core_ctx, bindings_ctx) = self.contexts();
2326 let settings = bindings_ctx.settings();
2327 let buffer_sizes = BufferSizes {
2328 send: settings.send_buffer.default().get(),
2329 receive: settings.receive_buffer.default().get(),
2330 };
2331 core_ctx.with_all_sockets_mut(|all_sockets| {
2332 let (sock, primary) = TcpSocketId::new(
2333 TcpSocketStateInner::Unbound(Unbound {
2334 bound_device: Default::default(),
2335 buffer_sizes,
2336 socket_extra: Takeable::new(socket_extra),
2337 }),
2338 SocketOptions::default(),
2339 );
2340 assert_matches::assert_matches!(
2341 all_sockets.insert(sock.clone(), TcpSocketSetEntry::Primary(primary)),
2342 None
2343 );
2344 sock
2345 })
2346 }
2347
2348 pub fn bind(
2355 &mut self,
2356 id: &TcpApiSocketId<I, C>,
2357 addr: Option<
2358 ZonedAddr<
2359 SpecifiedAddr<I::Addr>,
2360 <C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
2361 >,
2362 >,
2363 port: Option<NonZeroU16>,
2364 ) -> Result<(), BindError> {
2365 #[derive(GenericOverIp)]
2366 #[generic_over_ip(I, Ip)]
2367 enum BindAddr<I: DualStackIpExt, D> {
2368 BindInBothStacks,
2369 BindInOneStack(
2370 EitherStack<
2371 Option<ZonedAddr<SocketIpAddr<I::Addr>, D>>,
2372 Option<ZonedAddr<SocketIpAddr<<I::OtherVersion as Ip>::Addr>, D>>,
2373 >,
2374 ),
2375 }
2376 debug!("bind {id:?} to {addr:?}:{port:?}");
2377 let bind_addr = match addr {
2378 None => I::map_ip(
2379 (),
2380 |()| BindAddr::BindInOneStack(EitherStack::ThisStack(None)),
2381 |()| BindAddr::BindInBothStacks,
2382 ),
2383 Some(addr) => match DualStackLocalIp::<I, _>::new(addr) {
2384 DualStackLocalIp::ThisStack(addr) => {
2385 BindAddr::BindInOneStack(EitherStack::ThisStack(Some(addr)))
2386 }
2387 DualStackLocalIp::OtherStack(addr) => {
2388 BindAddr::BindInOneStack(EitherStack::OtherStack(addr))
2389 }
2390 },
2391 };
2392
2393 let (core_ctx, bindings_ctx) = self.contexts();
2394 let result = core_ctx.with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
2395 let TcpSocketState { socket_state, sharing, ip_options, socket_options: _ } = socket_state;
2396 let Unbound { bound_device, buffer_sizes, socket_extra } =
2397 match socket_state {
2398 TcpSocketStateInner::Unbound(u) => u,
2399 TcpSocketStateInner::Bound(_)
2400 |TcpSocketStateInner::Listener(_)
2401 | TcpSocketStateInner::Connected{..}
2402 => return Err(BindError::AlreadyBound),
2403 };
2404
2405 let listener_addr = match core_ctx {
2406 MaybeDualStack::NotDualStack((core_ctx, converter)) => match bind_addr {
2407 BindAddr::BindInOneStack(EitherStack::ThisStack(local_addr)) => {
2408 let (local_addr, device) = bind_get_local_addr_and_device(core_ctx, local_addr, bound_device)?;
2409 let addr =
2410 core_ctx.with_demux_mut(|demux| {
2411 bind_install_in_demux(
2412 bindings_ctx,
2413 I::into_demux_socket_id(id.clone()),
2414 local_addr,
2415 device,
2416 port,
2417 *sharing,
2418 demux,
2419 )
2420 })?;
2421 converter.convert_back(addr)
2422 }
2423 BindAddr::BindInOneStack(EitherStack::OtherStack(_)) | BindAddr::BindInBothStacks => {
2424 return Err(LocalAddressError::CannotBindToAddress.into());
2425 }
2426 },
2427 MaybeDualStack::DualStack((core_ctx, converter)) => {
2428 let bind_addr = match (
2429 core_ctx.dual_stack_enabled(&ip_options),
2430 bind_addr
2431 ) {
2432 (true, BindAddr::BindInBothStacks)
2435 => BindAddr::<I, _>::BindInBothStacks,
2436 (false, BindAddr::BindInBothStacks)
2438 => BindAddr::BindInOneStack(EitherStack::ThisStack(None)),
2439 (true | false, BindAddr::BindInOneStack(EitherStack::ThisStack(ip)))
2441 => BindAddr::BindInOneStack(EitherStack::ThisStack(ip)),
2442 (true, BindAddr::BindInOneStack(EitherStack::OtherStack(ip)))
2445 => BindAddr::BindInOneStack(EitherStack::OtherStack(ip)),
2446 (false, BindAddr::BindInOneStack(EitherStack::OtherStack(_)))
2447 => return Err(LocalAddressError::CannotBindToAddress.into()),
2448 };
2449 match bind_addr {
2450 BindAddr::BindInOneStack(EitherStack::ThisStack(addr)) => {
2451 let (addr, device) = bind_get_local_addr_and_device::<I, _, _>(core_ctx, addr, bound_device)?;
2452 let ListenerAddr { ip, device } =
2453 core_ctx.with_demux_mut(|demux: &mut DemuxState<I, _, _>| {
2454 bind_install_in_demux(
2455 bindings_ctx,
2456 I::into_demux_socket_id(id.clone()),
2457 addr,
2458 device,
2459 port,
2460 *sharing,
2461 demux,
2462 )
2463 })?;
2464 converter.convert_back(ListenerAddr {
2465 ip: DualStackListenerIpAddr::ThisStack(ip),
2466 device,
2467 })
2468 }
2469 BindAddr::BindInOneStack(EitherStack::OtherStack(addr)) => {
2470 let other_demux_id = core_ctx.into_other_demux_socket_id(id.clone());
2471 let (addr, device) = bind_get_local_addr_and_device::<I::OtherVersion, _, _>(core_ctx, addr, bound_device)?;
2472 let ListenerAddr { ip, device } =
2473 core_ctx.with_demux_mut(|demux: &mut DemuxState<I::OtherVersion, _, _>| {
2474 bind_install_in_demux(
2475 bindings_ctx,
2476 other_demux_id,
2477 addr,
2478 device,
2479 port,
2480 *sharing,
2481 demux,
2482 )
2483 })?;
2484 converter.convert_back(ListenerAddr {
2485 ip: DualStackListenerIpAddr::OtherStack(ip),
2486 device,
2487 })
2488 }
2489 BindAddr::BindInBothStacks => {
2490 let other_demux_id = core_ctx.into_other_demux_socket_id(id.clone());
2491 let (port, device) =
2492 core_ctx.with_both_demux_mut(|demux, other_demux| {
2493 let port_alloc = TcpDualStackPortAlloc(
2498 &demux.socketmap,
2499 &other_demux.socketmap
2500 );
2501 let port = match port {
2502 Some(port) => port,
2503 None => match netstack3_base::simple_randomized_port_alloc(
2504 &mut bindings_ctx.rng(),
2505 &(),
2506 &port_alloc,
2507 &(),
2508 ){
2509 Some(port) => NonZeroU16::new(port)
2510 .expect("ephemeral ports must be non-zero"),
2511 None => {
2512 return Err(LocalAddressError::FailedToAllocateLocalPort);
2513 }
2514 }
2515 };
2516 let this_stack_addr = bind_install_in_demux(
2517 bindings_ctx,
2518 I::into_demux_socket_id(id.clone()),
2519 None,
2520 bound_device.clone(),
2521 Some(port),
2522 *sharing,
2523 demux,
2524 )?;
2525 match bind_install_in_demux(
2526 bindings_ctx,
2527 other_demux_id,
2528 None,
2529 bound_device.clone(),
2530 Some(port),
2531 *sharing,
2532 other_demux,
2533 ) {
2534 Ok(ListenerAddr { ip, device }) => {
2535 assert_eq!(this_stack_addr.ip.identifier, ip.identifier);
2536 Ok((port, device))
2537 }
2538 Err(err) => {
2539 demux.socketmap.listeners_mut().remove(&I::into_demux_socket_id(id.clone()), &this_stack_addr).expect("failed to unbind");
2540 Err(err)
2541 }
2542 }
2543 })?;
2544 converter.convert_back(ListenerAddr {
2545 ip: DualStackListenerIpAddr::BothStacks(port),
2546 device,
2547 })
2548 }
2549 }
2550 },
2551 };
2552
2553 *socket_state = TcpSocketStateInner::Bound(BoundState {
2554 addr: listener_addr,
2555 buffer_sizes: buffer_sizes.clone(),
2556 socket_extra: Takeable::from_ref(socket_extra.to_ref()),
2557 });
2558
2559 Ok(())
2560 });
2561 match &result {
2562 Err(BindError::LocalAddressError(LocalAddressError::FailedToAllocateLocalPort)) => {
2563 core_ctx.increment_both(id, |c| &c.failed_port_reservations);
2564 }
2565 Err(_) | Ok(_) => {}
2566 }
2567 result
2568 }
2569
2570 pub fn listen(
2572 &mut self,
2573 id: &TcpApiSocketId<I, C>,
2574 backlog: NonZeroUsize,
2575 ) -> Result<(), ListenError> {
2576 debug!("listen on {id:?} with backlog {backlog}");
2577 self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
2578 let TcpSocketState { socket_state, sharing, ip_options: _, socket_options: _ } =
2579 socket_state;
2580 let BoundState { addr, buffer_sizes, socket_extra } = match socket_state {
2581 TcpSocketStateInner::Bound(bound_state) => bound_state,
2582 TcpSocketStateInner::Connected { .. }
2583 | TcpSocketStateInner::Unbound(_)
2584 | TcpSocketStateInner::Listener(_) => {
2585 return Err(ListenError::NotSupported);
2586 }
2587 };
2588 try_update_listener_sharing::<_, C::CoreContext, _>(
2589 core_ctx,
2590 id,
2591 addr.clone(),
2592 &ListenerSharingState { sharing: *sharing, listening: false },
2593 ListenerSharingState { sharing: *sharing, listening: true },
2594 )
2595 .map_err(|UpdateSharingError| ListenError::ListenerExists)?;
2596
2597 *socket_state = TcpSocketStateInner::Listener(Listener::new(
2598 addr.clone(),
2599 backlog,
2600 buffer_sizes.clone(),
2601 socket_extra.to_ref().take(),
2602 ));
2603 Ok(())
2604 })
2605 }
2606
2607 pub fn accept(
2612 &mut self,
2613 id: &TcpApiSocketId<I, C>,
2614 ) -> Result<
2615 (
2616 TcpApiSocketId<I, C>,
2617 SocketAddr<I::Addr, <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId>,
2618 <C::BindingsContext as TcpBindingsTypes>::ReturnedBuffers,
2619 ),
2620 AcceptError,
2621 > {
2622 let (conn_id, client_buffers) = self.core_ctx().with_socket_mut(id, |socket_state| {
2623 debug!("accept on {id:?}");
2624 let accept_queue = match &mut socket_state.socket_state {
2625 TcpSocketStateInner::Listener(Listener { accept_queue, .. }) => accept_queue,
2626 TcpSocketStateInner::Unbound(_)
2627 | TcpSocketStateInner::Bound(_)
2628 | TcpSocketStateInner::Connected { .. } => {
2629 return Err(AcceptError::NotSupported);
2630 }
2631 };
2632 let (conn_id, client_buffers) =
2633 accept_queue.pop_ready().ok_or(AcceptError::WouldBlock)?;
2634
2635 Ok::<_, AcceptError>((conn_id, client_buffers))
2636 })?;
2637
2638 let remote_addr =
2639 self.core_ctx().with_socket_mut_and_converter(&conn_id, |socket_state, _converter| {
2640 let conn_and_addr = assert_matches!(
2641 &mut socket_state.socket_state,
2642 TcpSocketStateInner::Connected{ conn, .. } => conn,
2643 "invalid socket ID"
2644 );
2645 *I::get_accept_queue_mut(conn_and_addr) = None;
2646 let ConnectionInfo { local_addr: _, remote_addr, device: _ } =
2647 I::get_conn_info(conn_and_addr);
2648 remote_addr
2649 });
2650
2651 debug!("accepted connection {conn_id:?} from {remote_addr:?} on {id:?}");
2652 Ok((conn_id, remote_addr, client_buffers))
2653 }
2654
2655 pub fn connect(
2662 &mut self,
2663 id: &TcpApiSocketId<I, C>,
2664 remote_ip: Option<
2665 ZonedAddr<
2666 SpecifiedAddr<I::Addr>,
2667 <C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
2668 >,
2669 >,
2670 remote_port: NonZeroU16,
2671 ) -> Result<(), ConnectError> {
2672 let (core_ctx, bindings_ctx) = self.contexts();
2673 let result = core_ctx.with_socket_mut_generators_transport_demux(
2674 id,
2675 |core_ctx, socket_state, isn, timestamp_offset| {
2676 let TcpSocketState { socket_state, sharing, ip_options, socket_options } =
2677 socket_state;
2678 debug!("connect on {id:?} to {remote_ip:?}:{remote_port}");
2679 let remote_ip = DualStackRemoteIp::<I, _>::new(remote_ip);
2680 let (bound_device, local_addr, buffer_sizes, socket_extra) = match socket_state {
2681 TcpSocketStateInner::Connected { conn, timer: _ } => {
2682 let (handshake_status, error_reporter) = match core_ctx {
2683 MaybeDualStack::NotDualStack((_core_ctx, converter)) => {
2684 let (conn, _addr) = converter.convert(conn);
2685 (
2686 &mut conn.handshake_status,
2687 ErrorReporter::new(&mut conn.state, &mut conn.soft_error),
2688 )
2689 }
2690 MaybeDualStack::DualStack((_core_ctx, converter)) => {
2691 match converter.convert(conn) {
2692 EitherStack::ThisStack((conn, _addr)) => (
2693 &mut conn.handshake_status,
2694 ErrorReporter::new(&mut conn.state, &mut conn.soft_error),
2695 ),
2696 EitherStack::OtherStack((conn, _addr)) => (
2697 &mut conn.handshake_status,
2698 ErrorReporter::new(&mut conn.state, &mut conn.soft_error),
2699 ),
2700 }
2701 }
2702 };
2703 match handshake_status {
2704 HandshakeStatus::Pending => return Err(ConnectError::Pending),
2705 HandshakeStatus::Aborted => {
2706 return Err(error_reporter
2707 .report_error()
2708 .map(ConnectError::ConnectionError)
2709 .unwrap_or(ConnectError::Aborted));
2710 }
2711 HandshakeStatus::Completed { reported } => {
2712 if *reported {
2713 return Err(ConnectError::Completed);
2714 } else {
2715 *reported = true;
2716 return Ok(());
2717 }
2718 }
2719 }
2720 }
2721 TcpSocketStateInner::Unbound(Unbound {
2722 bound_device,
2723 socket_extra,
2724 buffer_sizes,
2725 }) => (
2726 bound_device.clone(),
2727 DualStackTuple::<I, _>::new(None, None),
2728 *buffer_sizes,
2729 socket_extra.to_ref(),
2730 ),
2731 TcpSocketStateInner::Listener(_) => {
2732 return Err(ConnectError::Listener);
2733 }
2734 TcpSocketStateInner::Bound(BoundState { addr, buffer_sizes, socket_extra }) => {
2735 let local_addr = match &core_ctx {
2736 MaybeDualStack::DualStack((_core_ctx, converter)) => {
2737 match converter.convert(addr.clone()) {
2738 ListenerAddr {
2739 ip: DualStackListenerIpAddr::ThisStack(ip),
2740 device,
2741 } => {
2742 DualStackTuple::new(Some(ListenerAddr { ip, device }), None)
2743 }
2744 ListenerAddr {
2745 ip: DualStackListenerIpAddr::OtherStack(ip),
2746 device,
2747 } => {
2748 DualStackTuple::new(None, Some(ListenerAddr { ip, device }))
2749 }
2750 ListenerAddr {
2751 ip: DualStackListenerIpAddr::BothStacks(port),
2752 device,
2753 } => DualStackTuple::new(
2754 Some(ListenerAddr {
2755 ip: ListenerIpAddr { addr: None, identifier: port },
2756 device: device.clone(),
2757 }),
2758 Some(ListenerAddr {
2759 ip: ListenerIpAddr { addr: None, identifier: port },
2760 device,
2761 }),
2762 ),
2763 }
2764 }
2765 MaybeDualStack::NotDualStack((_core_ctx, converter)) => {
2766 DualStackTuple::new(Some(converter.convert(addr.clone())), None)
2767 }
2768 };
2769 (None, local_addr, *buffer_sizes, socket_extra.to_ref())
2770 }
2771 };
2772 let local_addr = local_addr.into_inner();
2775 match (core_ctx, local_addr, remote_ip) {
2776 (
2780 MaybeDualStack::NotDualStack((core_ctx, converter)),
2781 (local_addr_this_stack, None),
2782 DualStackRemoteIp::ThisStack(remote_ip),
2783 ) => {
2784 *socket_state = connect_inner(
2785 core_ctx,
2786 bindings_ctx,
2787 id,
2788 isn,
2789 timestamp_offset,
2790 LocalAddrForConnect::from_local_addr(
2791 local_addr_this_stack.clone(),
2792 bound_device,
2793 ),
2794 remote_ip,
2795 remote_port,
2796 socket_extra,
2797 buffer_sizes,
2798 socket_options,
2799 *sharing,
2800 SingleStackDemuxStateAccessor(
2801 &I::into_demux_socket_id(id.clone()),
2802 local_addr_this_stack,
2803 ),
2804 |conn, addr| converter.convert_back((conn, addr)),
2805 <C::CoreContext as CoreTimerContext<_, _>>::convert_timer,
2806 )?;
2807 Ok(())
2808 }
2809 (
2813 MaybeDualStack::DualStack((core_ctx, converter)),
2814 (local_addr_this_stack, local_addr_other_stack @ None)
2815 | (local_addr_this_stack @ Some(_), local_addr_other_stack @ Some(_)),
2816 DualStackRemoteIp::ThisStack(remote_ip),
2817 ) => {
2818 *socket_state = connect_inner(
2819 core_ctx,
2820 bindings_ctx,
2821 id,
2822 isn,
2823 timestamp_offset,
2824 LocalAddrForConnect::from_local_addr(
2825 local_addr_this_stack.clone(),
2826 bound_device,
2827 ),
2828 remote_ip,
2829 remote_port,
2830 socket_extra,
2831 buffer_sizes,
2832 socket_options,
2833 *sharing,
2834 DualStackDemuxStateAccessor(
2835 id,
2836 DualStackTuple::new(local_addr_this_stack, local_addr_other_stack),
2837 ),
2838 |conn, addr| {
2839 converter.convert_back(EitherStack::ThisStack((conn, addr)))
2840 },
2841 <C::CoreContext as CoreTimerContext<_, _>>::convert_timer,
2842 )?;
2843 Ok(())
2844 }
2845 (
2849 MaybeDualStack::DualStack((core_ctx, converter)),
2850 (local_addr_this_stack @ None, local_addr_other_stack)
2851 | (local_addr_this_stack @ Some(_), local_addr_other_stack @ Some(_)),
2852 DualStackRemoteIp::OtherStack(remote_ip),
2853 ) => {
2854 if !core_ctx.dual_stack_enabled(ip_options) {
2855 return Err(ConnectError::NoRoute);
2856 }
2857 *socket_state = connect_inner(
2858 core_ctx,
2859 bindings_ctx,
2860 id,
2861 isn,
2862 timestamp_offset,
2863 LocalAddrForConnect::from_local_addr(
2864 local_addr_other_stack.clone(),
2865 bound_device,
2866 ),
2867 remote_ip,
2868 remote_port,
2869 socket_extra,
2870 buffer_sizes,
2871 socket_options,
2872 *sharing,
2873 DualStackDemuxStateAccessor(
2874 id,
2875 DualStackTuple::new(local_addr_this_stack, local_addr_other_stack),
2876 ),
2877 |conn, addr| {
2878 converter.convert_back(EitherStack::OtherStack((conn, addr)))
2879 },
2880 <C::CoreContext as CoreTimerContext<_, _>>::convert_timer,
2881 )?;
2882 Ok(())
2883 }
2884 (
2887 MaybeDualStack::NotDualStack(_),
2888 (_, Some(_other_stack_local_addr)),
2889 DualStackRemoteIp::ThisStack(_) | DualStackRemoteIp::OtherStack(_),
2890 ) => unreachable!("The socket cannot be bound in the other stack"),
2891 (
2893 MaybeDualStack::DualStack(_),
2894 (None, Some(_other_stack_local_addr)),
2895 DualStackRemoteIp::ThisStack(_),
2896 ) => Err(ConnectError::NoRoute),
2897 (
2899 MaybeDualStack::DualStack(_) | MaybeDualStack::NotDualStack(_),
2900 (Some(_this_stack_local_addr), _),
2901 DualStackRemoteIp::OtherStack(_),
2902 ) => Err(ConnectError::NoRoute),
2903 (
2905 MaybeDualStack::NotDualStack(_),
2906 (None, None),
2907 DualStackRemoteIp::OtherStack(_),
2908 ) => Err(ConnectError::NoRoute),
2909 }
2910 },
2911 );
2912 match &result {
2913 Ok(()) => {}
2914 Err(err) => {
2915 core_ctx.increment_both(id, |counters| &counters.failed_connection_attempts);
2916 match err {
2917 ConnectError::NoRoute => {
2918 core_ctx
2919 .increment_both(id, |counters| &counters.active_open_no_route_errors);
2920 }
2921 ConnectError::NoPort => {
2922 core_ctx.increment_both(id, |counters| &counters.failed_port_reservations);
2923 }
2924 _ => {}
2925 }
2926 }
2927 }
2928 result
2929 }
2930
2931 pub fn close(&mut self, id: TcpApiSocketId<I, C>) {
2933 debug!("close on {id:?}");
2934 let (core_ctx, bindings_ctx) = self.contexts();
2935 let (destroy, pending) =
2936 core_ctx.with_socket_mut_transport_demux(&id, |core_ctx, socket_state| {
2937 let TcpSocketState { socket_state, sharing: _, ip_options: _, socket_options } =
2938 socket_state;
2939 match socket_state {
2940 TcpSocketStateInner::Unbound(_) => (true, None),
2941 TcpSocketStateInner::Bound(BoundState { addr, .. })
2942 | TcpSocketStateInner::Listener(Listener { addr, .. }) => {
2943 match core_ctx {
2944 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
2945 TcpDemuxContext::<I, _, _>::with_demux_mut(
2946 core_ctx,
2947 |DemuxState { socketmap }| {
2948 socketmap
2949 .listeners_mut()
2950 .remove(
2951 &I::into_demux_socket_id(id.clone()),
2952 &converter.convert(addr),
2953 )
2954 .expect("failed to remove from socketmap");
2955 },
2956 );
2957 }
2958 MaybeDualStack::DualStack((core_ctx, converter)) => {
2959 match converter.convert(addr.clone()) {
2960 ListenerAddr {
2961 ip: DualStackListenerIpAddr::ThisStack(ip),
2962 device,
2963 } => TcpDemuxContext::<I, _, _>::with_demux_mut(
2964 core_ctx,
2965 |DemuxState { socketmap }| {
2966 socketmap
2967 .listeners_mut()
2968 .remove(
2969 &I::into_demux_socket_id(id.clone()),
2970 &ListenerAddr { ip, device },
2971 )
2972 .expect("failed to remove from socketmap");
2973 },
2974 ),
2975 ListenerAddr {
2976 ip: DualStackListenerIpAddr::OtherStack(ip),
2977 device,
2978 } => {
2979 let other_demux_id =
2980 core_ctx.into_other_demux_socket_id(id.clone());
2981 TcpDemuxContext::<I::OtherVersion, _, _>::with_demux_mut(
2982 core_ctx,
2983 |DemuxState { socketmap }| {
2984 socketmap
2985 .listeners_mut()
2986 .remove(
2987 &other_demux_id,
2988 &ListenerAddr { ip, device },
2989 )
2990 .expect("failed to remove from socketmap");
2991 },
2992 );
2993 }
2994 ListenerAddr {
2995 ip: DualStackListenerIpAddr::BothStacks(port),
2996 device,
2997 } => {
2998 let other_demux_id =
2999 core_ctx.into_other_demux_socket_id(id.clone());
3000 core_ctx.with_both_demux_mut(|demux, other_demux| {
3001 demux
3002 .socketmap
3003 .listeners_mut()
3004 .remove(
3005 &I::into_demux_socket_id(id.clone()),
3006 &ListenerAddr {
3007 ip: ListenerIpAddr {
3008 addr: None,
3009 identifier: port,
3010 },
3011 device: device.clone(),
3012 },
3013 )
3014 .expect("failed to remove from socketmap");
3015 other_demux
3016 .socketmap
3017 .listeners_mut()
3018 .remove(
3019 &other_demux_id,
3020 &ListenerAddr {
3021 ip: ListenerIpAddr {
3022 addr: None,
3023 identifier: port,
3024 },
3025 device,
3026 },
3027 )
3028 .expect("failed to remove from socketmap");
3029 });
3030 }
3031 }
3032 }
3033 };
3034 if let TcpSocketStateInner::Listener(Listener {
3038 addr,
3039 backlog: _,
3040 accept_queue,
3041 buffer_sizes,
3042 }) = socket_state
3043 {
3044 let (pending, socket_extra) = accept_queue.close();
3045 let addr = addr.clone();
3046 let buffer_sizes = buffer_sizes.clone();
3047 *socket_state = TcpSocketStateInner::Bound(BoundState {
3048 addr,
3049 buffer_sizes,
3050 socket_extra: Takeable::new(socket_extra),
3051 });
3052 (true, Some(pending))
3053 } else {
3054 (true, None)
3055 }
3056 }
3057 TcpSocketStateInner::Connected { conn, timer } => {
3058 fn do_close<SockI, WireI, CC, BC>(
3059 core_ctx: &mut CC,
3060 bindings_ctx: &mut BC,
3061 id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
3062 demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, BC>,
3063 socket_options: &SocketOptions,
3064 conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
3065 addr: &ConnAddr<
3066 ConnIpAddr<<WireI as Ip>::Addr, NonZeroU16, NonZeroU16>,
3067 CC::WeakDeviceId,
3068 >,
3069 timer: &mut BC::Timer,
3070 ) -> bool
3071 where
3072 SockI: DualStackIpExt,
3073 WireI: DualStackIpExt,
3074 BC: TcpBindingsContext<CC::DeviceId>,
3075 CC: TransportIpContext<WireI, BC>
3076 + TcpDemuxContext<WireI, CC::WeakDeviceId, BC>
3077 + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
3078 {
3079 let _: Result<(), CloseError> = conn.state.shutdown_recv();
3081
3082 conn.defunct = true;
3083 let newly_closed = match conn.state.close(
3084 &TcpCountersRefs::from_ctx(core_ctx, id),
3085 CloseReason::Close { now: bindings_ctx.now() },
3086 socket_options,
3087 ) {
3088 Err(CloseError::NoConnection) => NewlyClosed::No,
3089 Err(CloseError::Closing) | Ok(NewlyClosed::No) => do_send_inner(
3090 &id,
3091 socket_options,
3092 conn,
3093 DoSendLimit::MultipleSegments,
3094 &addr,
3095 timer,
3096 core_ctx,
3097 bindings_ctx,
3098 ),
3099 Ok(NewlyClosed::Yes) => NewlyClosed::Yes,
3100 };
3101 handle_newly_closed(
3105 core_ctx,
3106 bindings_ctx,
3107 newly_closed,
3108 demux_id,
3109 addr,
3110 timer,
3111 );
3112 let now_closed = matches!(conn.state, State::Closed(_));
3113 if now_closed {
3114 debug_assert!(
3115 core_ctx.with_demux_mut(|DemuxState { socketmap }| {
3116 socketmap.conns_mut().entry(demux_id, addr).is_none()
3117 }),
3118 "lingering state in socketmap: demux_id: {:?}, addr: {:?}",
3119 demux_id,
3120 addr,
3121 );
3122 debug_assert_eq!(
3123 bindings_ctx.scheduled_instant(timer),
3124 None,
3125 "lingering timer for {:?}",
3126 id,
3127 )
3128 };
3129 now_closed
3130 }
3131 let closed = match core_ctx {
3132 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3133 let (conn, addr) = converter.convert(conn);
3134 do_close(
3135 core_ctx,
3136 bindings_ctx,
3137 &id,
3138 &I::into_demux_socket_id(id.clone()),
3139 socket_options,
3140 conn,
3141 addr,
3142 timer,
3143 )
3144 }
3145 MaybeDualStack::DualStack((core_ctx, converter)) => {
3146 match converter.convert(conn) {
3147 EitherStack::ThisStack((conn, addr)) => do_close(
3148 core_ctx,
3149 bindings_ctx,
3150 &id,
3151 &I::into_demux_socket_id(id.clone()),
3152 socket_options,
3153 conn,
3154 addr,
3155 timer,
3156 ),
3157 EitherStack::OtherStack((conn, addr)) => do_close(
3158 core_ctx,
3159 bindings_ctx,
3160 &id,
3161 &core_ctx.into_other_demux_socket_id(id.clone()),
3162 socket_options,
3163 conn,
3164 addr,
3165 timer,
3166 ),
3167 }
3168 }
3169 };
3170 (closed, None)
3171 }
3172 }
3173 });
3174
3175 close_pending_sockets(core_ctx, bindings_ctx, pending.into_iter().flatten());
3176
3177 if destroy {
3178 destroy_socket(core_ctx, bindings_ctx, id);
3179 }
3180 }
3181
3182 pub fn shutdown(
3197 &mut self,
3198 id: &TcpApiSocketId<I, C>,
3199 shutdown_type: ShutdownType,
3200 ) -> Result<bool, NoConnection> {
3201 debug!("shutdown [{shutdown_type:?}] for {id:?}");
3202 let (core_ctx, bindings_ctx) = self.contexts();
3203 let (result, pending) =
3204 core_ctx.with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
3205 let TcpSocketState { socket_state, sharing, ip_options: _, socket_options } =
3206 socket_state;
3207 match socket_state {
3208 TcpSocketStateInner::Unbound(_) => Err(NoConnection),
3209 TcpSocketStateInner::Connected { conn, timer } => {
3210 fn do_shutdown<SockI, WireI, CC, BC>(
3211 core_ctx: &mut CC,
3212 bindings_ctx: &mut BC,
3213 id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
3214 demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, BC>,
3215 socket_options: &SocketOptions,
3216 conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
3217 addr: &ConnAddr<
3218 ConnIpAddr<<WireI as Ip>::Addr, NonZeroU16, NonZeroU16>,
3219 CC::WeakDeviceId,
3220 >,
3221 timer: &mut BC::Timer,
3222 shutdown_type: ShutdownType,
3223 ) -> Result<(), NoConnection>
3224 where
3225 SockI: DualStackIpExt,
3226 WireI: DualStackIpExt,
3227 BC: TcpBindingsContext<CC::DeviceId>,
3228 CC: TransportIpContext<WireI, BC>
3229 + TcpDemuxContext<WireI, CC::WeakDeviceId, BC>
3230 + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
3231 {
3232 let (shutdown_send, shutdown_receive) = shutdown_type.to_send_receive();
3233 if shutdown_receive {
3234 match conn.state.shutdown_recv() {
3235 Ok(()) => (),
3236 Err(CloseError::NoConnection) => return Err(NoConnection),
3237 Err(CloseError::Closing) => (),
3238 }
3239 }
3240
3241 if !shutdown_send {
3242 return Ok(());
3243 }
3244
3245 match conn.state.close(
3246 &TcpCountersRefs::from_ctx(core_ctx, id),
3247 CloseReason::Shutdown,
3248 socket_options,
3249 ) {
3250 Ok(newly_closed) => {
3251 let newly_closed = match newly_closed {
3252 NewlyClosed::Yes => NewlyClosed::Yes,
3253 NewlyClosed::No => do_send_inner(
3254 id,
3255 socket_options,
3256 conn,
3257 DoSendLimit::MultipleSegments,
3258 addr,
3259 timer,
3260 core_ctx,
3261 bindings_ctx,
3262 ),
3263 };
3264 handle_newly_closed(
3265 core_ctx,
3266 bindings_ctx,
3267 newly_closed,
3268 demux_id,
3269 addr,
3270 timer,
3271 );
3272 Ok(())
3273 }
3274 Err(CloseError::NoConnection) => Err(NoConnection),
3275 Err(CloseError::Closing) => Ok(()),
3276 }
3277 }
3278 match core_ctx {
3279 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3280 let (conn, addr) = converter.convert(conn);
3281 do_shutdown(
3282 core_ctx,
3283 bindings_ctx,
3284 id,
3285 &I::into_demux_socket_id(id.clone()),
3286 socket_options,
3287 conn,
3288 addr,
3289 timer,
3290 shutdown_type,
3291 )?
3292 }
3293 MaybeDualStack::DualStack((core_ctx, converter)) => {
3294 match converter.convert(conn) {
3295 EitherStack::ThisStack((conn, addr)) => do_shutdown(
3296 core_ctx,
3297 bindings_ctx,
3298 id,
3299 &I::into_demux_socket_id(id.clone()),
3300 socket_options,
3301 conn,
3302 addr,
3303 timer,
3304 shutdown_type,
3305 )?,
3306 EitherStack::OtherStack((conn, addr)) => do_shutdown(
3307 core_ctx,
3308 bindings_ctx,
3309 id,
3310 &core_ctx.into_other_demux_socket_id(id.clone()),
3311 socket_options,
3312 conn,
3313 addr,
3314 timer,
3315 shutdown_type,
3316 )?,
3317 }
3318 }
3319 };
3320 Ok((true, None))
3321 }
3322 TcpSocketStateInner::Bound(_) => Err(NoConnection),
3323 TcpSocketStateInner::Listener(listener) => {
3324 let (_shutdown_send, shutdown_receive) = shutdown_type.to_send_receive();
3325
3326 if !shutdown_receive {
3327 return Ok((false, None));
3328 }
3329
3330 let (pending, new_state) =
3331 shut_down_listener_socket::<I, C::CoreContext, C::BindingsContext>(
3332 core_ctx, id, listener, *sharing,
3333 );
3334 *socket_state = TcpSocketStateInner::Bound(new_state);
3335 Ok((false, Some(pending)))
3336 }
3337 }
3338 })?;
3339
3340 close_pending_sockets(core_ctx, bindings_ctx, pending.into_iter().flatten());
3341
3342 Ok(result)
3343 }
3344
3345 pub fn on_receive_buffer_read(&mut self, id: &TcpApiSocketId<I, C>) {
3352 let (core_ctx, bindings_ctx) = self.contexts();
3353 core_ctx.with_socket_mut_transport_demux(
3354 id,
3355 |core_ctx, TcpSocketState { socket_state, sharing: _, ip_options: _, socket_options }| {
3356 let conn = match socket_state {
3357 TcpSocketStateInner::Unbound(_)| TcpSocketStateInner::Bound(_)|
3358 TcpSocketStateInner::Listener(_) => return,
3359 TcpSocketStateInner::Connected { conn, .. } => conn,
3360 };
3361
3362 let now = bindings_ctx.now();
3363 match core_ctx {
3364 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3365 let (conn, addr) = converter.convert(conn);
3366 if let Some(ack) = conn.state.poll_receive_data_dequeued(now) {
3367 send_tcp_segment(
3368 core_ctx,
3369 bindings_ctx,
3370 Some(id),
3371 Some(&conn.ip_sock),
3372 addr.ip,
3373 ack.into_empty(),
3374 &socket_options.ip_options,
3375 )
3376 }
3377 }
3378 MaybeDualStack::DualStack((core_ctx, converter)) => {
3379 match converter.convert(conn) {
3380 EitherStack::ThisStack((conn, addr)) => {
3381 if let Some(ack) = conn.state.poll_receive_data_dequeued(now) {
3382 send_tcp_segment(
3383 core_ctx,
3384 bindings_ctx,
3385 Some(id),
3386 Some(&conn.ip_sock),
3387 addr.ip,
3388 ack.into_empty(),
3389 &socket_options.ip_options,
3390 )
3391 }
3392 }
3393 EitherStack::OtherStack((conn, addr)) => {
3394 if let Some(ack) = conn.state.poll_receive_data_dequeued(now) {
3395 send_tcp_segment(
3396 core_ctx,
3397 bindings_ctx,
3398 Some(id),
3399 Some(&conn.ip_sock),
3400 addr.ip,
3401 ack.into_empty(),
3402 &socket_options.ip_options,
3403 )
3404 }
3405 }
3406 }
3407 }
3408 }
3409 },
3410 )
3411 }
3412
3413 fn set_device_conn<SockI, WireI, CC>(
3414 core_ctx: &mut CC,
3415 bindings_ctx: &mut C::BindingsContext,
3416 addr: &mut ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
3417 demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, C::BindingsContext>,
3418 ip_options: &TcpIpSockOptions,
3419 conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, C::BindingsContext>,
3420 new_device: Option<CC::DeviceId>,
3421 ) -> Result<(), SetDeviceError>
3422 where
3423 SockI: DualStackIpExt,
3424 WireI: DualStackIpExt,
3425 CC: TransportIpContext<WireI, C::BindingsContext>
3426 + TcpDemuxContext<WireI, CC::WeakDeviceId, C::BindingsContext>,
3427 {
3428 let ConnAddr {
3429 device: old_device,
3430 ip: ConnIpAddr { local: (local_ip, _), remote: (remote_ip, _) },
3431 } = addr;
3432
3433 let update = SocketDeviceUpdate {
3434 local_ip: Some(local_ip.as_ref()),
3435 remote_ip: Some(remote_ip.as_ref()),
3436 old_device: old_device.as_ref(),
3437 };
3438 match update.check_update(new_device.as_ref()) {
3439 Ok(()) => (),
3440 Err(SocketDeviceUpdateNotAllowedError) => return Err(SetDeviceError::ZoneChange),
3441 }
3442 let new_socket = core_ctx
3443 .new_ip_socket(
3444 bindings_ctx,
3445 IpSocketArgs {
3446 device: new_device.as_ref().map(EitherDeviceId::Strong),
3447 local_ip: IpDeviceAddr::new_from_socket_ip_addr(*local_ip),
3448 remote_ip: *remote_ip,
3449 proto: IpProto::Tcp.into(),
3450 options: ip_options,
3451 },
3452 )
3453 .map_err(|_: IpSockCreationError| SetDeviceError::Unroutable)?;
3454 let new_address = ConnAddr { device: new_socket.device().cloned(), ..addr.clone() };
3455 core_ctx.with_demux_mut(|DemuxState { socketmap }| {
3456 let entry = match socketmap.conns_mut().entry(demux_id, addr) {
3457 Some(entry) => entry,
3458 None => {
3459 debug!("no demux entry for {addr:?} with {demux_id:?}");
3460 assert_matches!(&conn.state, State::Closed(_) | State::TimeWait(_));
3464 *addr = new_address;
3468 return Ok(());
3469 }
3470 };
3471
3472 match entry.try_update_addr(new_address) {
3473 Ok(entry) => {
3474 *addr = entry.get_addr().clone();
3475 conn.ip_sock = new_socket;
3476 Ok(())
3477 }
3478 Err((ExistsError, _entry)) => Err(SetDeviceError::Conflict),
3479 }
3480 })
3481 }
3482
3483 fn set_device_listener<WireI, D>(
3487 demux_id: &WireI::DemuxSocketId<D, C::BindingsContext>,
3488 ip_addr: ListenerIpAddr<WireI::Addr, NonZeroU16>,
3489 old_device: Option<D>,
3490 new_device: Option<&D>,
3491 DemuxState { socketmap }: &mut DemuxState<WireI, D, C::BindingsContext>,
3492 ) -> Result<(), SetDeviceError>
3493 where
3494 WireI: DualStackIpExt,
3495 D: WeakDeviceIdentifier,
3496 {
3497 let entry = socketmap
3498 .listeners_mut()
3499 .entry(demux_id, &ListenerAddr { ip: ip_addr, device: old_device.clone() })
3500 .expect("invalid ID");
3501
3502 let update = SocketDeviceUpdate {
3503 local_ip: ip_addr.addr.as_ref().map(|a| a.as_ref()),
3504 remote_ip: None,
3505 old_device: old_device.as_ref(),
3506 };
3507 match update.check_update(new_device) {
3508 Ok(()) => (),
3509 Err(SocketDeviceUpdateNotAllowedError) => return Err(SetDeviceError::ZoneChange),
3510 }
3511 match entry.try_update_addr(ListenerAddr { device: new_device.cloned(), ip: ip_addr }) {
3512 Ok(_entry) => Ok(()),
3513 Err((ExistsError, _entry)) => Err(SetDeviceError::Conflict),
3514 }
3515 }
3516
3517 pub fn set_device(
3521 &mut self,
3522 id: &TcpApiSocketId<I, C>,
3523 new_device: Option<<C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId>,
3524 ) -> Result<(), SetDeviceError> {
3525 let (core_ctx, bindings_ctx) = self.contexts();
3526 let weak_device = new_device.as_ref().map(|d| d.downgrade());
3527 core_ctx.with_socket_mut_transport_demux(id, move |core_ctx, socket_state| {
3528 debug!("set device on {id:?} to {new_device:?}");
3529 let TcpSocketState { socket_state, sharing: _, ip_options: _, socket_options } =
3530 socket_state;
3531 match socket_state {
3532 TcpSocketStateInner::Unbound(unbound) => {
3533 unbound.bound_device = weak_device;
3534 Ok(())
3535 }
3536 TcpSocketStateInner::Connected { conn, timer: _ } => {
3537 let this_or_other_stack = match core_ctx {
3538 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3539 let (conn, addr) = converter.convert(conn);
3540 EitherStack::ThisStack((
3541 core_ctx.as_this_stack(),
3542 conn,
3543 addr,
3544 I::into_demux_socket_id(id.clone()),
3545 ))
3546 }
3547 MaybeDualStack::DualStack((core_ctx, converter)) => {
3548 match converter.convert(conn) {
3549 EitherStack::ThisStack((conn, addr)) => EitherStack::ThisStack((
3550 core_ctx.as_this_stack(),
3551 conn,
3552 addr,
3553 I::into_demux_socket_id(id.clone()),
3554 )),
3555 EitherStack::OtherStack((conn, addr)) => {
3556 let demux_id = core_ctx.into_other_demux_socket_id(id.clone());
3557 EitherStack::OtherStack((core_ctx, conn, addr, demux_id))
3558 }
3559 }
3560 }
3561 };
3562 match this_or_other_stack {
3563 EitherStack::ThisStack((core_ctx, conn, addr, demux_id)) => {
3564 Self::set_device_conn::<_, I, _>(
3565 core_ctx,
3566 bindings_ctx,
3567 addr,
3568 &demux_id,
3569 &socket_options.ip_options,
3570 conn,
3571 new_device,
3572 )
3573 }
3574 EitherStack::OtherStack((core_ctx, conn, addr, demux_id)) => {
3575 Self::set_device_conn::<_, I::OtherVersion, _>(
3576 core_ctx,
3577 bindings_ctx,
3578 addr,
3579 &demux_id,
3580 &socket_options.ip_options,
3581 conn,
3582 new_device,
3583 )
3584 }
3585 }
3586 }
3587 TcpSocketStateInner::Bound(BoundState { addr, .. })
3588 | TcpSocketStateInner::Listener(Listener { addr, .. }) => match core_ctx {
3589 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3590 let ListenerAddr { ip, device } = converter.convert(addr);
3591 core_ctx.with_demux_mut(|demux| {
3592 Self::set_device_listener(
3593 &I::into_demux_socket_id(id.clone()),
3594 ip.clone(),
3595 device.clone(),
3596 weak_device.as_ref(),
3597 demux,
3598 )?;
3599 *device = weak_device;
3600 Ok(())
3601 })
3602 }
3603 MaybeDualStack::DualStack((core_ctx, converter)) => {
3604 match converter.convert(addr) {
3605 ListenerAddr { ip: DualStackListenerIpAddr::ThisStack(ip), device } => {
3606 TcpDemuxContext::<I, _, _>::with_demux_mut(core_ctx, |demux| {
3607 Self::set_device_listener(
3608 &I::into_demux_socket_id(id.clone()),
3609 ip.clone(),
3610 device.clone(),
3611 weak_device.as_ref(),
3612 demux,
3613 )?;
3614 *device = weak_device;
3615 Ok(())
3616 })
3617 }
3618 ListenerAddr {
3619 ip: DualStackListenerIpAddr::OtherStack(ip),
3620 device,
3621 } => {
3622 let other_demux_id =
3623 core_ctx.into_other_demux_socket_id(id.clone());
3624 TcpDemuxContext::<I::OtherVersion, _, _>::with_demux_mut(
3625 core_ctx,
3626 |demux| {
3627 Self::set_device_listener(
3628 &other_demux_id,
3629 ip.clone(),
3630 device.clone(),
3631 weak_device.as_ref(),
3632 demux,
3633 )?;
3634 *device = weak_device;
3635 Ok(())
3636 },
3637 )
3638 }
3639 ListenerAddr {
3640 ip: DualStackListenerIpAddr::BothStacks(port),
3641 device,
3642 } => {
3643 let other_demux_id =
3644 core_ctx.into_other_demux_socket_id(id.clone());
3645 core_ctx.with_both_demux_mut(|demux, other_demux| {
3646 let old_device = device.clone();
3647 Self::set_device_listener(
3648 &I::into_demux_socket_id(id.clone()),
3649 ListenerIpAddr { addr: None, identifier: *port },
3650 old_device.clone(),
3651 weak_device.as_ref(),
3652 demux,
3653 )?;
3654 match Self::set_device_listener(
3655 &other_demux_id,
3656 ListenerIpAddr { addr: None, identifier: *port },
3657 old_device.clone(),
3658 weak_device.as_ref(),
3659 other_demux,
3660 ) {
3661 Ok(()) => {
3662 *device = weak_device;
3663 Ok(())
3664 }
3665 Err(e) => {
3666 Self::set_device_listener(
3667 &I::into_demux_socket_id(id.clone()),
3668 ListenerIpAddr { addr: None, identifier: *port },
3669 weak_device.clone(),
3670 old_device.as_ref(),
3671 demux,
3672 )
3673 .expect("failed to revert back the device setting");
3674 Err(e)
3675 }
3676 }
3677 })
3678 }
3679 }
3680 }
3681 },
3682 }
3683 })
3684 }
3685
3686 pub fn get_info(
3688 &mut self,
3689 id: &TcpApiSocketId<I, C>,
3690 ) -> SocketInfo<I::Addr, <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId> {
3691 self.core_ctx().with_socket_and_converter(
3692 id,
3693 |TcpSocketState { socket_state, sharing: _, ip_options: _, socket_options: _ },
3694 _converter| {
3695 match socket_state {
3696 TcpSocketStateInner::Unbound(unbound) => SocketInfo::Unbound(unbound.into()),
3697 TcpSocketStateInner::Connected { conn, timer: _ } => {
3698 SocketInfo::Connection(I::get_conn_info(conn))
3699 }
3700 TcpSocketStateInner::Bound(BoundState { addr, .. })
3701 | TcpSocketStateInner::Listener(Listener { addr, .. }) => {
3702 SocketInfo::Bound(I::get_bound_info(addr))
3703 }
3704 }
3705 },
3706 )
3707 }
3708
3709 pub fn do_send(&mut self, conn_id: &TcpApiSocketId<I, C>) {
3716 let (core_ctx, bindings_ctx) = self.contexts();
3717 core_ctx.with_socket_mut_transport_demux(conn_id, |core_ctx, socket_state| {
3718 let TcpSocketState { socket_state, sharing: _, ip_options: _, socket_options } =
3719 socket_state;
3720 let (conn, timer) = assert_matches!(
3721 socket_state,
3722 TcpSocketStateInner::Connected { conn, timer } => (conn, timer)
3723 );
3724 match core_ctx {
3725 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3726 let (conn, addr) = converter.convert(conn);
3727 do_send_inner_and_then_handle_newly_closed(
3728 conn_id,
3729 &I::into_demux_socket_id(conn_id.clone()),
3730 socket_options,
3731 conn,
3732 DoSendLimit::MultipleSegments,
3733 addr,
3734 timer,
3735 core_ctx,
3736 bindings_ctx,
3737 );
3738 }
3739 MaybeDualStack::DualStack((core_ctx, converter)) => match converter.convert(conn) {
3740 EitherStack::ThisStack((conn, addr)) => {
3741 do_send_inner_and_then_handle_newly_closed(
3742 conn_id,
3743 &I::into_demux_socket_id(conn_id.clone()),
3744 socket_options,
3745 conn,
3746 DoSendLimit::MultipleSegments,
3747 addr,
3748 timer,
3749 core_ctx,
3750 bindings_ctx,
3751 )
3752 }
3753 EitherStack::OtherStack((conn, addr)) => {
3754 let other_demux_id = core_ctx.into_other_demux_socket_id(conn_id.clone());
3755 do_send_inner_and_then_handle_newly_closed(
3756 conn_id,
3757 &other_demux_id,
3758 socket_options,
3759 conn,
3760 DoSendLimit::MultipleSegments,
3761 addr,
3762 timer,
3763 core_ctx,
3764 bindings_ctx,
3765 );
3766 }
3767 },
3768 };
3769 })
3770 }
3771
3772 fn handle_timer(
3773 &mut self,
3774 weak_id: WeakTcpSocketId<
3775 I,
3776 <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
3777 C::BindingsContext,
3778 >,
3779 ) {
3780 let id = match weak_id.upgrade() {
3781 Some(c) => c,
3782 None => return,
3783 };
3784 let (core_ctx, bindings_ctx) = self.contexts();
3785 debug!("handle_timer on {id:?}");
3786 let id_alias = &id;
3788 let bindings_ctx_alias = &mut *bindings_ctx;
3789 let closed_and_defunct =
3790 core_ctx.with_socket_mut_transport_demux(&id, move |core_ctx, socket_state| {
3791 let TcpSocketState { socket_state, sharing: _, ip_options: _, socket_options } =
3792 socket_state;
3793 let id = id_alias;
3794 trace_duration!("tcp::handle_timer", "id" => id.trace_id());
3795 let bindings_ctx = bindings_ctx_alias;
3796 let (conn, timer) = assert_matches!(
3797 socket_state,
3798 TcpSocketStateInner::Connected{ conn, timer} => (conn, timer)
3799 );
3800 fn do_handle_timer<SockI, WireI, CC, BC>(
3801 core_ctx: &mut CC,
3802 bindings_ctx: &mut BC,
3803 id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
3804 demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, BC>,
3805 socket_options: &SocketOptions,
3806 conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
3807 addr: &ConnAddr<
3808 ConnIpAddr<<WireI as Ip>::Addr, NonZeroU16, NonZeroU16>,
3809 CC::WeakDeviceId,
3810 >,
3811 timer: &mut BC::Timer,
3812 ) -> bool
3813 where
3814 SockI: DualStackIpExt,
3815 WireI: DualStackIpExt,
3816 BC: TcpBindingsContext<CC::DeviceId>,
3817 CC: TransportIpContext<WireI, BC>
3818 + TcpDemuxContext<WireI, CC::WeakDeviceId, BC>
3819 + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
3820 {
3821 let time_wait = matches!(conn.state, State::TimeWait(_));
3822 let newly_closed = do_send_inner(
3823 id,
3824 socket_options,
3825 conn,
3826 DoSendLimit::MultipleSegments,
3827 addr,
3828 timer,
3829 core_ctx,
3830 bindings_ctx,
3831 );
3832 match (newly_closed, time_wait) {
3833 (NewlyClosed::Yes, time_wait) => {
3836 let result = core_ctx.with_demux_mut(|DemuxState { socketmap }| {
3837 socketmap.conns_mut().remove(demux_id, addr)
3838 });
3839 result.unwrap_or_else(|e| {
3848 if time_wait {
3849 debug!(
3850 "raced with timewait removal for {id:?} {addr:?}: {e:?}"
3851 );
3852 } else {
3853 panic!("failed to remove from socketmap: {e:?}");
3854 }
3855 });
3856 let _: Option<_> = bindings_ctx.cancel_timer(timer);
3857
3858 let Closed { reason } = assert_matches!(
3859 &conn.state, State::Closed(c) => c
3860 );
3861 let _: bool = conn.handshake_status.update_if_pending(match reason {
3862 None => HandshakeStatus::Completed {
3863 reported: conn.accept_queue.is_some(),
3864 },
3865 Some(_err) => HandshakeStatus::Aborted,
3866 });
3867 }
3868 (NewlyClosed::No, _) => {}
3869 }
3870 conn.defunct && matches!(conn.state, State::Closed(_))
3871 }
3872 match core_ctx {
3873 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3874 let (conn, addr) = converter.convert(conn);
3875 do_handle_timer(
3876 core_ctx,
3877 bindings_ctx,
3878 id,
3879 &I::into_demux_socket_id(id.clone()),
3880 socket_options,
3881 conn,
3882 addr,
3883 timer,
3884 )
3885 }
3886 MaybeDualStack::DualStack((core_ctx, converter)) => {
3887 match converter.convert(conn) {
3888 EitherStack::ThisStack((conn, addr)) => do_handle_timer(
3889 core_ctx,
3890 bindings_ctx,
3891 id,
3892 &I::into_demux_socket_id(id.clone()),
3893 socket_options,
3894 conn,
3895 addr,
3896 timer,
3897 ),
3898 EitherStack::OtherStack((conn, addr)) => do_handle_timer(
3899 core_ctx,
3900 bindings_ctx,
3901 id,
3902 &core_ctx.into_other_demux_socket_id(id.clone()),
3903 socket_options,
3904 conn,
3905 addr,
3906 timer,
3907 ),
3908 }
3909 }
3910 }
3911 });
3912 if closed_and_defunct {
3913 destroy_socket(core_ctx, bindings_ctx, id);
3915 }
3916 }
3917
3918 pub fn with_socket_options_mut<R, F: FnOnce(&mut SocketOptions) -> R>(
3920 &mut self,
3921 id: &TcpApiSocketId<I, C>,
3922 f: F,
3923 ) -> R {
3924 let (core_ctx, _) = self.contexts();
3925 core_ctx.with_socket_mut(id, |socket| f(&mut socket.socket_options))
3926 }
3927
3928 pub fn with_socket_options<R, F: FnOnce(&SocketOptions) -> R>(
3930 &mut self,
3931 id: &TcpApiSocketId<I, C>,
3932 f: F,
3933 ) -> R {
3934 self.core_ctx().with_socket(id, |socket| f(&socket.socket_options))
3935 }
3936
3937 pub fn set_send_buffer_size(&mut self, id: &TcpApiSocketId<I, C>, size: usize) {
3940 let (core_ctx, bindings_ctx) = self.contexts();
3941 set_buffer_size::<SendBufferSize, I, _, _>(core_ctx, bindings_ctx, id, size)
3942 }
3943
3944 pub fn send_buffer_size(&mut self, id: &TcpApiSocketId<I, C>) -> Option<usize> {
3947 get_buffer_size::<SendBufferSize, I, _, _>(self.core_ctx(), id)
3948 }
3949
3950 pub fn set_receive_buffer_size(&mut self, id: &TcpApiSocketId<I, C>, size: usize) {
3953 let (core_ctx, bindings_ctx) = self.contexts();
3954 set_buffer_size::<ReceiveBufferSize, I, _, _>(core_ctx, bindings_ctx, id, size)
3955 }
3956
3957 pub fn receive_buffer_size(&mut self, id: &TcpApiSocketId<I, C>) -> Option<usize> {
3960 get_buffer_size::<ReceiveBufferSize, I, _, _>(self.core_ctx(), id)
3961 }
3962
3963 pub fn set_reuseaddr(
3965 &mut self,
3966 id: &TcpApiSocketId<I, C>,
3967 reuse: bool,
3968 ) -> Result<(), SetReuseAddrError> {
3969 let new_sharing = match reuse {
3970 true => SharingState::ReuseAddress,
3971 false => SharingState::Exclusive,
3972 };
3973 self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
3974 let old_sharing = socket_state.sharing;
3975 if old_sharing == new_sharing {
3976 return Ok(());
3977 }
3978
3979 match &socket_state.socket_state {
3980 TcpSocketStateInner::Unbound(_) => (),
3981 TcpSocketStateInner::Bound(BoundState { addr, .. })
3982 | TcpSocketStateInner::Listener(Listener { addr, .. }) => {
3983 let listening =
3984 matches!(&socket_state.socket_state, TcpSocketStateInner::Listener(_));
3985 try_update_listener_sharing::<_, C::CoreContext, _>(
3986 core_ctx,
3987 id,
3988 addr.clone(),
3989 &ListenerSharingState { sharing: old_sharing, listening },
3990 ListenerSharingState { sharing: new_sharing, listening },
3991 )
3992 .map_err(|UpdateSharingError| SetReuseAddrError::AddrInUse)?;
3993 }
3994 TcpSocketStateInner::Connected { .. } => {
3995 return Err(SetReuseAddrError::NotSupported);
3998 }
3999 };
4000
4001 socket_state.sharing = new_sharing;
4002 Ok(())
4003 })
4004 }
4005
4006 pub fn reuseaddr(&mut self, id: &TcpApiSocketId<I, C>) -> bool {
4008 self.core_ctx().with_socket(id, |state| state.sharing == SharingState::ReuseAddress)
4009 }
4010
4011 pub fn dual_stack_enabled(
4013 &mut self,
4014 id: &TcpSocketId<
4015 I,
4016 <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
4017 C::BindingsContext,
4018 >,
4019 ) -> Result<bool, NotDualStackCapableError> {
4020 self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, socket_state| match core_ctx
4021 {
4022 MaybeDualStack::NotDualStack(_) => Err(NotDualStackCapableError),
4023 MaybeDualStack::DualStack((core_ctx, _converter)) => {
4024 Ok(core_ctx.dual_stack_enabled(&socket_state.ip_options))
4025 }
4026 })
4027 }
4028
4029 pub fn set_mark(&mut self, id: &TcpApiSocketId<I, C>, domain: MarkDomain, mark: Mark) {
4031 self.with_socket_options_mut(id, |options| *options.ip_options.marks.get_mut(domain) = mark)
4032 }
4033
4034 pub fn get_mark(&mut self, id: &TcpApiSocketId<I, C>, domain: MarkDomain) -> Mark {
4036 self.with_socket_options(id, |options| *options.ip_options.marks.get(domain))
4037 }
4038
4039 pub fn set_dual_stack_enabled(
4041 &mut self,
4042 id: &TcpSocketId<
4043 I,
4044 <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
4045 C::BindingsContext,
4046 >,
4047 value: bool,
4048 ) -> Result<(), SetDualStackEnabledError> {
4049 self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, socket_state| match core_ctx
4050 {
4051 MaybeDualStack::NotDualStack(_) => Err(NotDualStackCapableError.into()),
4052 MaybeDualStack::DualStack((core_ctx, _converter)) => match socket_state.socket_state {
4053 TcpSocketStateInner::Unbound(_) => {
4054 Ok(core_ctx.set_dual_stack_enabled(&mut socket_state.ip_options, value))
4055 }
4056 TcpSocketStateInner::Connected { .. }
4057 | TcpSocketStateInner::Bound(_)
4058 | TcpSocketStateInner::Listener(_) => Err(SetDualStackEnabledError::SocketIsBound),
4059 },
4060 })
4061 }
4062
4063 fn on_icmp_error_conn(
4064 core_ctx: &mut C::CoreContext,
4065 bindings_ctx: &mut C::BindingsContext,
4066 id: TcpSocketId<
4067 I,
4068 <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
4069 C::BindingsContext,
4070 >,
4071 seq: SeqNum,
4072 error: IcmpErrorCode,
4073 ) {
4074 let destroy = core_ctx.with_socket_mut_transport_demux(&id, |core_ctx, socket_state| {
4075 let (conn_and_addr, timer) = assert_matches!(
4076 &mut socket_state.socket_state,
4077 TcpSocketStateInner::Connected { conn, timer } => (conn, timer),
4078 "invalid socket ID");
4079 let (
4080 newly_closed,
4081 accept_queue,
4082 state,
4083 soft_error,
4084 handshake_status,
4085 this_or_other_stack,
4086 ) = match core_ctx {
4087 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
4088 let (conn, addr) = converter.convert(conn_and_addr);
4089 let (newly_closed, should_send) = conn.on_icmp_error(core_ctx, &id, seq, error);
4090 let core_ctx = core_ctx.as_this_stack();
4091 let demux_id = I::into_demux_socket_id(id.clone());
4092
4093 match should_send {
4094 ShouldRetransmit::No => {}
4095 ShouldRetransmit::Yes => do_send_inner_and_then_handle_newly_closed(
4096 &id,
4097 &demux_id,
4098 &socket_state.socket_options,
4099 conn,
4100 DoSendLimit::OneSegment,
4101 addr,
4102 timer,
4103 core_ctx,
4104 bindings_ctx,
4105 ),
4106 }
4107
4108 (
4109 newly_closed,
4110 &mut conn.accept_queue,
4111 &mut conn.state,
4112 &mut conn.soft_error,
4113 &mut conn.handshake_status,
4114 EitherStack::ThisStack((core_ctx, demux_id, addr)),
4115 )
4116 }
4117 MaybeDualStack::DualStack((core_ctx, converter)) => {
4118 match converter.convert(conn_and_addr) {
4119 EitherStack::ThisStack((conn, addr)) => {
4120 let (newly_closed, should_send) =
4121 conn.on_icmp_error(core_ctx, &id, seq, error);
4122 let core_ctx = core_ctx.as_this_stack();
4123 let demux_id = I::into_demux_socket_id(id.clone());
4124
4125 match should_send {
4126 ShouldRetransmit::No => {}
4127 ShouldRetransmit::Yes => {
4128 do_send_inner_and_then_handle_newly_closed(
4129 &id,
4130 &demux_id,
4131 &socket_state.socket_options,
4132 conn,
4133 DoSendLimit::OneSegment,
4134 addr,
4135 timer,
4136 core_ctx,
4137 bindings_ctx,
4138 )
4139 }
4140 }
4141
4142 (
4143 newly_closed,
4144 &mut conn.accept_queue,
4145 &mut conn.state,
4146 &mut conn.soft_error,
4147 &mut conn.handshake_status,
4148 EitherStack::ThisStack((core_ctx, demux_id, addr)),
4149 )
4150 }
4151 EitherStack::OtherStack((conn, addr)) => {
4152 let (newly_closed, should_send) =
4153 conn.on_icmp_error(core_ctx, &id, seq, error);
4154 let demux_id = core_ctx.into_other_demux_socket_id(id.clone());
4155
4156 match should_send {
4157 ShouldRetransmit::No => {}
4158 ShouldRetransmit::Yes => {
4159 do_send_inner_and_then_handle_newly_closed(
4160 &id,
4161 &demux_id,
4162 &socket_state.socket_options,
4163 conn,
4164 DoSendLimit::OneSegment,
4165 addr,
4166 timer,
4167 core_ctx,
4168 bindings_ctx,
4169 )
4170 }
4171 }
4172
4173 (
4174 newly_closed,
4175 &mut conn.accept_queue,
4176 &mut conn.state,
4177 &mut conn.soft_error,
4178 &mut conn.handshake_status,
4179 EitherStack::OtherStack((core_ctx, demux_id, addr)),
4180 )
4181 }
4182 }
4183 }
4184 };
4185
4186 if let State::Closed(Closed { reason }) = state {
4187 debug!("handshake_status: {handshake_status:?}");
4188 let _: bool = handshake_status.update_if_pending(HandshakeStatus::Aborted);
4189 match this_or_other_stack {
4191 EitherStack::ThisStack((core_ctx, demux_id, addr)) => {
4192 handle_newly_closed::<I, _, _, _>(
4193 core_ctx,
4194 bindings_ctx,
4195 newly_closed,
4196 &demux_id,
4197 addr,
4198 timer,
4199 );
4200 }
4201 EitherStack::OtherStack((core_ctx, demux_id, addr)) => {
4202 handle_newly_closed::<I::OtherVersion, _, _, _>(
4203 core_ctx,
4204 bindings_ctx,
4205 newly_closed,
4206 &demux_id,
4207 addr,
4208 timer,
4209 );
4210 }
4211 };
4212 match accept_queue {
4213 Some(accept_queue) => {
4214 accept_queue.remove(&id);
4215 return true;
4217 }
4218 None => {
4219 if let Some(err) = reason {
4220 if *err == ConnectionError::TimedOut {
4221 *err = soft_error.unwrap_or(ConnectionError::TimedOut);
4222 }
4223 }
4224 }
4225 }
4226 }
4227 false
4228 });
4229 if destroy {
4230 destroy_socket(core_ctx, bindings_ctx, id);
4231 }
4232 }
4233
4234 fn on_icmp_error(
4235 &mut self,
4236 orig_src_ip: SpecifiedAddr<I::Addr>,
4237 orig_dst_ip: SpecifiedAddr<I::Addr>,
4238 orig_src_port: NonZeroU16,
4239 orig_dst_port: NonZeroU16,
4240 seq: SeqNum,
4241 error: IcmpErrorCode,
4242 ) where
4243 C::CoreContext: TcpContext<I::OtherVersion, C::BindingsContext>,
4244 C::BindingsContext: TcpBindingsContext<
4245 <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
4246 >,
4247 {
4248 let (core_ctx, bindings_ctx) = self.contexts();
4249
4250 let orig_src_ip = match SocketIpAddr::try_from(orig_src_ip) {
4251 Ok(ip) => ip,
4252 Err(AddrIsMappedError {}) => {
4253 debug!("ignoring ICMP error from IPv4-mapped-IPv6 source: {}", orig_src_ip);
4254 return;
4255 }
4256 };
4257 let orig_dst_ip = match SocketIpAddr::try_from(orig_dst_ip) {
4258 Ok(ip) => ip,
4259 Err(AddrIsMappedError {}) => {
4260 debug!("ignoring ICMP error to IPv4-mapped-IPv6 destination: {}", orig_dst_ip);
4261 return;
4262 }
4263 };
4264
4265 let id = TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
4266 socketmap
4267 .conns()
4268 .get_by_addr(&ConnAddr {
4269 ip: ConnIpAddr {
4270 local: (orig_src_ip, orig_src_port),
4271 remote: (orig_dst_ip, orig_dst_port),
4272 },
4273 device: None,
4274 })
4275 .map(|ConnAddrState { sharing: _, id }| id.clone())
4276 });
4277
4278 let id = match id {
4279 Some(id) => id,
4280 None => return,
4281 };
4282
4283 match I::into_dual_stack_ip_socket(id) {
4284 EitherStack::ThisStack(id) => {
4285 Self::on_icmp_error_conn(core_ctx, bindings_ctx, id, seq, error)
4286 }
4287 EitherStack::OtherStack(id) => TcpApi::<I::OtherVersion, C>::on_icmp_error_conn(
4288 core_ctx,
4289 bindings_ctx,
4290 id,
4291 seq,
4292 error,
4293 ),
4294 };
4295 }
4296
4297 pub fn get_socket_error(&mut self, id: &TcpApiSocketId<I, C>) -> Option<ConnectionError> {
4299 self.core_ctx().with_socket_mut_and_converter(id, |socket_state, converter| {
4300 match &mut socket_state.socket_state {
4301 TcpSocketStateInner::Unbound(_)
4302 | TcpSocketStateInner::Bound(_)
4303 | TcpSocketStateInner::Listener(_) => None,
4304 TcpSocketStateInner::Connected { conn, timer: _ } => {
4305 let reporter = match converter {
4306 MaybeDualStack::NotDualStack(converter) => {
4307 let (conn, _addr) = converter.convert(conn);
4308 ErrorReporter::new(&mut conn.state, &mut conn.soft_error)
4309 }
4310 MaybeDualStack::DualStack(converter) => match converter.convert(conn) {
4311 EitherStack::ThisStack((conn, _addr)) => {
4312 ErrorReporter::new(&mut conn.state, &mut conn.soft_error)
4313 }
4314 EitherStack::OtherStack((conn, _addr)) => {
4315 ErrorReporter::new(&mut conn.state, &mut conn.soft_error)
4316 }
4317 },
4318 };
4319 reporter.report_error()
4320 }
4321 }
4322 })
4323 }
4324
4325 pub fn get_original_destination(
4333 &mut self,
4334 id: &TcpApiSocketId<I, C>,
4335 ) -> Result<(SpecifiedAddr<I::Addr>, NonZeroU16), OriginalDestinationError> {
4336 self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, state| {
4337 let TcpSocketState { socket_state, .. } = state;
4338 let conn = match socket_state {
4339 TcpSocketStateInner::Connected { conn, .. } => conn,
4340 TcpSocketStateInner::Bound(_)
4341 | TcpSocketStateInner::Listener(_)
4342 | TcpSocketStateInner::Unbound(_) => {
4343 return Err(OriginalDestinationError::NotConnected);
4344 }
4345 };
4346
4347 fn tuple<I: IpExt>(
4348 ConnIpAddr { local, remote }: ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>,
4349 ) -> Tuple<I> {
4350 let (local_addr, local_port) = local;
4351 let (remote_addr, remote_port) = remote;
4352 Tuple {
4353 protocol: IpProto::Tcp.into(),
4354 src_addr: local_addr.addr(),
4355 dst_addr: remote_addr.addr(),
4356 src_port_or_id: local_port.get(),
4357 dst_port_or_id: remote_port.get(),
4358 }
4359 }
4360
4361 let (addr, port) = match core_ctx {
4362 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
4363 let (_conn, addr) = converter.convert(conn);
4364 let tuple: Tuple<I> = tuple(addr.ip);
4365 core_ctx
4366 .get_original_destination(&tuple)
4367 .ok_or(OriginalDestinationError::NotFound)
4368 }
4369 MaybeDualStack::DualStack((core_ctx, converter)) => match converter.convert(conn) {
4370 EitherStack::ThisStack((_conn, addr)) => {
4371 let tuple: Tuple<I> = tuple(addr.ip);
4372 let (addr, port) = core_ctx
4373 .get_original_destination(&tuple)
4374 .ok_or(OriginalDestinationError::NotFound)?;
4375 let addr = I::get_original_dst(
4376 converter.convert_back(EitherStack::ThisStack(addr)),
4377 );
4378 Ok((addr, port))
4379 }
4380 EitherStack::OtherStack((_conn, addr)) => {
4381 let tuple: Tuple<I::OtherVersion> = tuple(addr.ip);
4382 let (addr, port) = core_ctx
4383 .get_original_destination(&tuple)
4384 .ok_or(OriginalDestinationError::NotFound)?;
4385 let addr = I::get_original_dst(
4386 converter.convert_back(EitherStack::OtherStack(addr)),
4387 );
4388 Ok((addr, port))
4389 }
4390 },
4391 }?;
4392
4393 let addr = SpecifiedAddr::new(addr).ok_or_else(|| {
4398 error!("original destination for socket {id:?} had unspecified addr (port {port})");
4399 OriginalDestinationError::UnspecifiedDestinationAddr
4400 })?;
4401 let port = NonZeroU16::new(port).ok_or_else(|| {
4402 error!("original destination for socket {id:?} had unspecified port (addr {addr})");
4403 OriginalDestinationError::UnspecifiedDestinationPort
4404 })?;
4405 Ok((addr, port))
4406 })
4407 }
4408
4409 pub fn bound_sockets_diagnostics<M, E>(
4411 &mut self,
4412 matcher: &M,
4413 results: &mut E,
4414 extended_info: bool,
4415 ) where
4416 M: IpSocketPropertiesMatcher<<C::BindingsContext as MatcherBindingsTypes>::DeviceClass>
4417 + ?Sized,
4418 E: Extend<TcpSocketDiagnostics<I, <C::BindingsContext as InstantBindingsTypes>::Instant>>,
4419 <C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId:
4420 netstack3_base::InterfaceProperties<
4421 <C::BindingsContext as MatcherBindingsTypes>::DeviceClass,
4422 >,
4423 {
4424 self.core_ctx().for_each_socket(|id, state| {
4425 if !matcher.matches_ip_socket(&TcpSocketStateForMatching { state, id }) {
4426 return;
4427 }
4428
4429 let counters = id.counters();
4432 results.extend(state.get_diagnostics(counters, extended_info).map(
4433 |(tuple, state_machine, marks, tcp_info)| TcpSocketDiagnostics {
4434 tuple,
4435 state_machine,
4436 cookie: id.socket_cookie(),
4437 marks,
4438 tcp_info,
4439 },
4440 ));
4441 });
4442 }
4443
4444 pub fn disconnect_bound<M>(&mut self, matcher: &M) -> usize
4452 where
4453 M: IpSocketPropertiesMatcher<<C::BindingsContext as MatcherBindingsTypes>::DeviceClass>
4454 + ?Sized,
4455 <C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId:
4456 netstack3_base::InterfaceProperties<
4457 <C::BindingsContext as MatcherBindingsTypes>::DeviceClass,
4458 >,
4459 {
4460 let (core_ctx, bindings_ctx) = self.contexts();
4461
4462 let mut ids = Vec::new();
4468 core_ctx.for_each_socket(|id, state| {
4469 if matcher.matches_ip_socket(&TcpSocketStateForMatching { state, id }) {
4470 ids.push(id.clone());
4471 }
4472 });
4473
4474 ids.into_iter()
4478 .filter(|id| match disconnect_socket(core_ctx, bindings_ctx, &id) {
4479 Ok(()) => true,
4480 Err(NoConnection) => false,
4483 })
4484 .count()
4485 }
4486
4487 pub fn inspect<N>(&mut self, inspector: &mut N)
4489 where
4490 N: Inspector
4491 + InspectorDeviceExt<<C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId>,
4492 {
4493 self.core_ctx().for_each_socket(|socket_id, socket_state| {
4494 inspector.record_debug_child(socket_id, |node| {
4495 node.record_str("TransportProtocol", "TCP");
4496 node.record_str(
4497 "NetworkProtocol",
4498 match I::VERSION {
4499 IpVersion::V4 => "IPv4",
4500 IpVersion::V6 => "IPv6",
4501 },
4502 );
4503 let info = socket_state.tcp_info(socket_id.counters());
4504 let TcpSocketState { socket_state, sharing: _, ip_options: _, socket_options } =
4505 socket_state;
4506 node.delegate_inspectable(&socket_options.ip_options.marks);
4507 match socket_state {
4508 TcpSocketStateInner::Unbound(_) => {
4509 node.record_local_socket_addr::<N, I::Addr, _, NonZeroU16>(None);
4510 node.record_remote_socket_addr::<N, I::Addr, _, NonZeroU16>(None);
4511 }
4512 TcpSocketStateInner::Bound(BoundState { addr, .. }) => {
4513 let BoundInfo { addr, port, device } = I::get_bound_info(addr);
4514 let local = addr.map_or_else(
4515 || ZonedAddr::Unzoned(I::UNSPECIFIED_ADDRESS),
4516 |addr| maybe_zoned(addr.addr(), &device).into(),
4517 );
4518 node.record_local_socket_addr::<N, _, _, _>(Some((local, port)));
4519 node.record_remote_socket_addr::<N, I::Addr, _, NonZeroU16>(None);
4520 }
4521 TcpSocketStateInner::Listener(Listener {
4522 addr, accept_queue, backlog, ..
4523 }) => {
4524 let BoundInfo { addr, port, device } = I::get_bound_info(addr);
4525 let local = addr.map_or_else(
4526 || ZonedAddr::Unzoned(I::UNSPECIFIED_ADDRESS),
4527 |addr| maybe_zoned(addr.addr(), &device).into(),
4528 );
4529 node.record_local_socket_addr::<N, _, _, _>(Some((local, port)));
4530 node.record_remote_socket_addr::<N, I::Addr, _, NonZeroU16>(None);
4531 node.record_child("AcceptQueue", |node| {
4532 node.record_usize("BacklogSize", *backlog);
4533 accept_queue.inspect(node);
4534 });
4535 }
4536 TcpSocketStateInner::Connected { conn, .. } => {
4537 if I::get_defunct(conn) {
4538 return;
4539 }
4540 let state = I::get_state(conn);
4541 let ConnectionInfo {
4542 local_addr: SocketAddr { ip: local_ip, port: local_port },
4543 remote_addr: SocketAddr { ip: remote_ip, port: remote_port },
4544 device: _,
4545 } = I::get_conn_info(conn);
4546 node.record_local_socket_addr::<N, I::Addr, _, _>(Some((
4547 local_ip.into(),
4548 local_port,
4549 )));
4550 node.record_remote_socket_addr::<N, I::Addr, _, _>(Some((
4551 remote_ip.into(),
4552 remote_port,
4553 )));
4554 node.record_display("State", state);
4555 }
4556 }
4557 node.record_child("TcpInfo", |node| {
4558 node.delegate_inspectable(&info);
4559 });
4560 node.record_child("Counters", |node| {
4561 node.delegate_inspectable(&CombinedTcpCounters {
4562 with_socket: socket_id.counters(),
4563 without_socket: None,
4564 })
4565 })
4566 });
4567 })
4568 }
4569
4570 pub fn with_send_buffer<
4575 R,
4576 F: FnOnce(&mut <C::BindingsContext as TcpBindingsTypes>::SendBuffer) -> R,
4577 >(
4578 &mut self,
4579 id: &TcpApiSocketId<I, C>,
4580 f: F,
4581 ) -> Option<R> {
4582 self.core_ctx().with_socket_mut_and_converter(id, |state, converter| {
4583 get_buffers_mut::<_, C::CoreContext, _>(state, converter).into_send_buffer().map(f)
4584 })
4585 }
4586
4587 pub fn with_receive_buffer<
4592 R,
4593 F: FnOnce(&mut <C::BindingsContext as TcpBindingsTypes>::ReceiveBuffer) -> R,
4594 >(
4595 &mut self,
4596 id: &TcpApiSocketId<I, C>,
4597 f: F,
4598 ) -> Option<R> {
4599 self.core_ctx().with_socket_mut_and_converter(id, |state, converter| {
4600 get_buffers_mut::<_, C::CoreContext, _>(state, converter).into_receive_buffer().map(f)
4601 })
4602 }
4603}
4604
4605fn destroy_socket<I, CC, BC>(
4607 core_ctx: &mut CC,
4608 bindings_ctx: &mut BC,
4609 id: TcpSocketId<I, CC::WeakDeviceId, BC>,
4610) where
4611 I: DualStackIpExt,
4612 CC: TcpContext<I, BC>,
4613 BC: TcpBindingsContext<CC::DeviceId>,
4614{
4615 core_ctx.with_all_sockets_mut(move |all_sockets| {
4616 let cookie = id.socket_cookie();
4617 let TcpSocketId(rc) = &id;
4618 let debug_refs = StrongRc::debug_references(rc);
4619 let entry = all_sockets.entry(id);
4620 let primary = match entry {
4621 hash_map::Entry::Occupied(o) => match o.get() {
4622 TcpSocketSetEntry::DeadOnArrival => {
4623 let id = o.key();
4624 debug!("{id:?} destruction skipped, socket is DOA. References={debug_refs:?}",);
4625 None
4626 }
4627 TcpSocketSetEntry::Primary(_) => {
4628 assert_matches!(o.remove_entry(), (_, TcpSocketSetEntry::Primary(p)) => Some(p))
4629 }
4630 },
4631 hash_map::Entry::Vacant(v) => {
4632 let id = v.key();
4633 let TcpSocketId(rc) = id;
4634 if !StrongRc::marked_for_destruction(rc) {
4635 debug!(
4639 "{id:?} raced with insertion, marking socket as DOA. \
4640 References={debug_refs:?}",
4641 );
4642 let _: &mut _ = v.insert(TcpSocketSetEntry::DeadOnArrival);
4643 } else {
4644 debug!("{id:?} destruction is already deferred. References={debug_refs:?}");
4645 }
4646 None
4647 }
4648 };
4649
4650 let Some(primary) = primary else {
4651 cfg_if::cfg_if! {
4655 if #[cfg(test)] {
4656 panic!("deferred destruction not allowed in tests. \
4657 References={debug_refs:?}");
4658 } else {
4659 return;
4660 }
4661 }
4662 };
4663
4664 let remove_result =
4668 BC::unwrap_or_notify_with_new_reference_notifier(primary, move |state| {
4669 TcpSocketDiagnosticsSeed {
4670 state: state.locked_state.into_inner(),
4671 counters: state.counters,
4672 cookie,
4673 }
4674 });
4675
4676 bindings_ctx.defer_tcp_socket_destruction(remove_result);
4677 });
4678}
4679
4680fn shut_down_listener_socket<I, CC, BC>(
4684 core_ctx: MaybeDualStack<
4685 (&mut CC::DualStackIpTransportAndDemuxCtx<'_>, CC::DualStackConverter),
4686 (&mut CC::SingleStackIpTransportAndDemuxCtx<'_>, CC::SingleStackConverter),
4687 >,
4688 id: &TcpSocketId<I, CC::WeakDeviceId, BC>,
4689 listener: &Listener<I, CC::WeakDeviceId, BC>,
4690 sharing: SharingState,
4691) -> (
4692 impl Iterator<Item = TcpSocketId<I, CC::WeakDeviceId, BC>> + use<I, CC, BC>,
4693 BoundState<I, CC::WeakDeviceId, BC>,
4694)
4695where
4696 I: DualStackIpExt,
4697 BC: TcpBindingsContext<CC::DeviceId>,
4698 CC: TcpContext<I, BC>,
4699{
4700 let Listener { addr, backlog: _, accept_queue, buffer_sizes } = listener;
4701 let (pending, socket_extra) = accept_queue.close();
4702
4703 try_update_listener_sharing::<_, CC, _>(
4704 core_ctx,
4705 id,
4706 addr.clone(),
4707 &ListenerSharingState { listening: true, sharing },
4708 ListenerSharingState { listening: false, sharing },
4709 )
4710 .unwrap_or_else(|e| {
4711 unreachable!("downgrading a TCP listener to bound should not fail, got {e:?}")
4712 });
4713
4714 let bound = BoundState {
4715 addr: addr.clone(),
4716 buffer_sizes: buffer_sizes.clone(),
4717 socket_extra: Takeable::new(socket_extra),
4718 };
4719
4720 (pending, bound)
4721}
4722
4723fn disconnect_socket<I, CC, BC>(
4724 core_ctx: &mut CC,
4725 bindings_ctx: &mut BC,
4726 id: &TcpSocketId<I, CC::WeakDeviceId, BC>,
4727) -> Result<(), NoConnection>
4728where
4729 I: DualStackIpExt,
4730 BC: TcpBindingsContext<CC::DeviceId>,
4731 CC: TcpContext<I, BC>,
4732{
4733 debug!("disconnect for {id:?}");
4734 let pending = core_ctx.with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
4735 let TcpSocketState { socket_state, sharing, ip_options: _, socket_options } = socket_state;
4736 match socket_state {
4737 TcpSocketStateInner::Unbound(_) => Err(NoConnection),
4738 TcpSocketStateInner::Connected { conn, timer } => {
4739 match core_ctx {
4740 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
4741 let (conn, addr) = converter.convert(conn);
4742 abort_socket(
4743 core_ctx,
4744 bindings_ctx,
4745 id,
4746 &I::into_demux_socket_id(id.clone()),
4747 socket_options,
4748 timer,
4749 conn,
4750 addr,
4751 ConnectionError::Aborted,
4752 )
4753 }
4754 MaybeDualStack::DualStack((core_ctx, converter)) => {
4755 match converter.convert(conn) {
4756 EitherStack::ThisStack((conn, addr)) => abort_socket(
4757 core_ctx,
4758 bindings_ctx,
4759 id,
4760 &I::into_demux_socket_id(id.clone()),
4761 socket_options,
4762 timer,
4763 conn,
4764 addr,
4765 ConnectionError::Aborted,
4766 ),
4767 EitherStack::OtherStack((conn, addr)) => abort_socket(
4768 core_ctx,
4769 bindings_ctx,
4770 id,
4771 &core_ctx.into_other_demux_socket_id(id.clone()),
4772 socket_options,
4773 timer,
4774 conn,
4775 addr,
4776 ConnectionError::Aborted,
4777 ),
4778 }
4779 }
4780 };
4781 Ok(None)
4782 }
4783 TcpSocketStateInner::Bound(_) => Ok(None),
4784 TcpSocketStateInner::Listener(listener) => {
4785 let (pending, bound) =
4786 shut_down_listener_socket::<I, CC, BC>(core_ctx, id, listener, *sharing);
4787 *socket_state = TcpSocketStateInner::Bound(bound);
4788 Ok(Some(pending))
4789 }
4790 }
4791 })?;
4792
4793 close_pending_sockets(core_ctx, bindings_ctx, pending.into_iter().flatten());
4794
4795 Ok(())
4796}
4797
4798fn close_pending_sockets<I, CC, BC>(
4803 core_ctx: &mut CC,
4804 bindings_ctx: &mut BC,
4805 pending: impl Iterator<Item = TcpSocketId<I, CC::WeakDeviceId, BC>>,
4806) where
4807 I: DualStackIpExt,
4808 BC: TcpBindingsContext<CC::DeviceId>,
4809 CC: TcpContext<I, BC>,
4810{
4811 for conn_id in pending {
4812 core_ctx.with_socket_mut_transport_demux(&conn_id, |core_ctx, socket_state| {
4813 let TcpSocketState { socket_state, sharing: _, ip_options: _, socket_options } =
4814 socket_state;
4815 let (conn_and_addr, timer) = assert_matches!(
4816 socket_state,
4817 TcpSocketStateInner::Connected{ conn, timer } => (conn, timer),
4818 "invalid socket ID"
4819 );
4820 let _: Option<BC::Instant> = bindings_ctx.cancel_timer(timer);
4821 let this_or_other_stack = match core_ctx {
4822 MaybeDualStack::NotDualStack((core_ctx, converter)) => {
4823 let (conn, addr) = converter.convert(conn_and_addr);
4824 EitherStack::ThisStack((
4825 core_ctx.as_this_stack(),
4826 I::into_demux_socket_id(conn_id.clone()),
4827 conn,
4828 addr.clone(),
4829 ))
4830 }
4831 MaybeDualStack::DualStack((core_ctx, converter)) => match converter
4832 .convert(conn_and_addr)
4833 {
4834 EitherStack::ThisStack((conn, addr)) => EitherStack::ThisStack((
4835 core_ctx.as_this_stack(),
4836 I::into_demux_socket_id(conn_id.clone()),
4837 conn,
4838 addr.clone(),
4839 )),
4840 EitherStack::OtherStack((conn, addr)) => {
4841 let other_demux_id = core_ctx.into_other_demux_socket_id(conn_id.clone());
4842 EitherStack::OtherStack((core_ctx, other_demux_id, conn, addr.clone()))
4843 }
4844 },
4845 };
4846
4847 match this_or_other_stack {
4848 EitherStack::ThisStack((core_ctx, demux_id, conn, conn_addr)) => abort_socket(
4849 core_ctx,
4850 bindings_ctx,
4851 &conn_id,
4852 &demux_id,
4853 socket_options,
4854 timer,
4855 conn,
4856 &conn_addr,
4857 ConnectionError::ConnectionReset,
4858 ),
4859 EitherStack::OtherStack((core_ctx, demux_id, conn, conn_addr)) => abort_socket(
4860 core_ctx,
4861 bindings_ctx,
4862 &conn_id,
4863 &demux_id,
4864 socket_options,
4865 timer,
4866 conn,
4867 &conn_addr,
4868 ConnectionError::ConnectionReset,
4869 ),
4870 }
4871 });
4872 destroy_socket(core_ctx, bindings_ctx, conn_id);
4873 }
4874}
4875
4876fn abort_socket<WireI, SockI, DC, BC>(
4877 core_ctx: &mut DC,
4878 bindings_ctx: &mut BC,
4879 sock_id: &TcpSocketId<SockI, DC::WeakDeviceId, BC>,
4880 demux_id: &WireI::DemuxSocketId<DC::WeakDeviceId, BC>,
4881 socket_options: &SocketOptions,
4882 timer: &mut BC::Timer,
4883 conn: &mut Connection<SockI, WireI, DC::WeakDeviceId, BC>,
4884 conn_addr: &ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, DC::WeakDeviceId>,
4885 reason: ConnectionError,
4886) where
4887 WireI: DualStackIpExt,
4888 SockI: DualStackIpExt,
4889 DC: TransportIpContext<WireI, BC>
4890 + DeviceIpSocketHandler<WireI, BC>
4891 + TcpDemuxContext<WireI, DC::WeakDeviceId, BC>
4892 + TcpSocketContext<SockI, DC::WeakDeviceId, BC>,
4893 BC: TcpBindingsContext<DC::DeviceId>,
4894{
4895 debug!("aborting socket {sock_id:?} with reason {reason}");
4896 let (maybe_reset, newly_closed) =
4897 conn.state.abort(&TcpCountersRefs::from_ctx(core_ctx, sock_id), bindings_ctx.now(), reason);
4898 handle_newly_closed(core_ctx, bindings_ctx, newly_closed, demux_id, conn_addr, timer);
4899 if let Some(reset) = maybe_reset {
4900 let ConnAddr { ip, device: _ } = conn_addr;
4901 send_tcp_segment(
4902 core_ctx,
4903 bindings_ctx,
4904 Some(sock_id),
4905 Some(&conn.ip_sock),
4906 *ip,
4907 reset.into_empty(),
4908 &socket_options.ip_options,
4909 );
4910 }
4911}
4912
4913pub(crate) enum DoSendLimit {
4915 OneSegment,
4916 MultipleSegments,
4917}
4918
4919fn do_send_inner_and_then_handle_newly_closed<SockI, WireI, CC, BC>(
4921 conn_id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
4922 demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, BC>,
4923 socket_options: &SocketOptions,
4924 conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
4925 limit: DoSendLimit,
4926 addr: &ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
4927 timer: &mut BC::Timer,
4928 core_ctx: &mut CC,
4929 bindings_ctx: &mut BC,
4930) where
4931 SockI: DualStackIpExt,
4932 WireI: DualStackIpExt,
4933 BC: TcpBindingsContext<CC::DeviceId>,
4934 CC: TransportIpContext<WireI, BC>
4935 + TcpSocketContext<SockI, CC::WeakDeviceId, BC>
4936 + TcpDemuxContext<WireI, CC::WeakDeviceId, BC>,
4937{
4938 let newly_closed =
4939 do_send_inner(conn_id, socket_options, conn, limit, addr, timer, core_ctx, bindings_ctx);
4940 handle_newly_closed(core_ctx, bindings_ctx, newly_closed, demux_id, addr, timer);
4941}
4942
4943#[inline]
4944fn handle_newly_closed<I, D, CC, BC>(
4945 core_ctx: &mut CC,
4946 bindings_ctx: &mut BC,
4947 newly_closed: NewlyClosed,
4948 demux_id: &I::DemuxSocketId<D, BC>,
4949 addr: &ConnAddr<ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>, D>,
4950 timer: &mut BC::Timer,
4951) where
4952 I: DualStackIpExt,
4953 D: WeakDeviceIdentifier,
4954 CC: TcpDemuxContext<I, D, BC>,
4955 BC: TcpBindingsContext<D::Strong>,
4956{
4957 if newly_closed == NewlyClosed::Yes {
4958 core_ctx.with_demux_mut(|DemuxState { socketmap }| {
4959 socketmap.conns_mut().remove(demux_id, addr).expect("failed to remove from demux");
4960 let _: Option<_> = bindings_ctx.cancel_timer(timer);
4961 });
4962 }
4963}
4964
4965fn do_send_inner<SockI, WireI, CC, BC>(
4966 conn_id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
4967 socket_options: &SocketOptions,
4968 conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
4969 limit: DoSendLimit,
4970 addr: &ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
4971 timer: &mut BC::Timer,
4972 core_ctx: &mut CC,
4973 bindings_ctx: &mut BC,
4974) -> NewlyClosed
4975where
4976 SockI: DualStackIpExt,
4977 WireI: DualStackIpExt,
4978 BC: TcpBindingsContext<CC::DeviceId>,
4979 CC: TransportIpContext<WireI, BC> + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
4980{
4981 let newly_closed = loop {
4982 match conn.state.poll_send(
4983 &conn_id.either(),
4984 &TcpCountersRefs::from_ctx(core_ctx, conn_id),
4985 bindings_ctx.now(),
4986 socket_options,
4987 ) {
4988 Ok(seg) => {
4989 send_tcp_segment(
4990 core_ctx,
4991 bindings_ctx,
4992 Some(conn_id),
4993 Some(&conn.ip_sock),
4994 addr.ip.clone(),
4995 seg,
4996 &socket_options.ip_options,
4997 );
4998 match limit {
4999 DoSendLimit::OneSegment => break NewlyClosed::No,
5000 DoSendLimit::MultipleSegments => {}
5001 }
5002 }
5003 Err(newly_closed) => break newly_closed,
5004 }
5005 };
5006
5007 if let Some(instant) = conn.state.poll_send_at() {
5008 let _: Option<_> = bindings_ctx.schedule_timer_instant(instant, timer);
5009 }
5010
5011 newly_closed
5012}
5013
5014enum SendBufferSize {}
5015enum ReceiveBufferSize {}
5016
5017trait AccessBufferSize<R, S> {
5018 fn set_buffer_size(buffers: BuffersRefMut<'_, R, S>, new_size: usize);
5019 fn get_buffer_size(buffers: BuffersRefMut<'_, R, S>) -> Option<usize>;
5020 fn allowed_range(settings: &TcpSettings) -> (usize, usize);
5021}
5022
5023impl<R: Buffer, S: Buffer> AccessBufferSize<R, S> for SendBufferSize {
5024 fn set_buffer_size(buffers: BuffersRefMut<'_, R, S>, new_size: usize) {
5025 match buffers {
5026 BuffersRefMut::NoBuffers | BuffersRefMut::RecvOnly { .. } => {}
5027 BuffersRefMut::Both { send, recv: _ } | BuffersRefMut::SendOnly(send) => {
5028 send.request_capacity(new_size)
5029 }
5030 BuffersRefMut::Sizes(BufferSizes { send, receive: _ }) => *send = new_size,
5031 }
5032 }
5033
5034 fn allowed_range(settings: &TcpSettings) -> (usize, usize) {
5035 (settings.send_buffer.min().get(), settings.send_buffer.max().get())
5036 }
5037
5038 fn get_buffer_size(buffers: BuffersRefMut<'_, R, S>) -> Option<usize> {
5039 match buffers {
5040 BuffersRefMut::NoBuffers | BuffersRefMut::RecvOnly { .. } => None,
5041 BuffersRefMut::Both { send, recv: _ } | BuffersRefMut::SendOnly(send) => {
5042 Some(send.target_capacity())
5043 }
5044 BuffersRefMut::Sizes(BufferSizes { send, receive: _ }) => Some(*send),
5045 }
5046 }
5047}
5048
5049impl<R: Buffer, S: Buffer> AccessBufferSize<R, S> for ReceiveBufferSize {
5050 fn set_buffer_size(buffers: BuffersRefMut<'_, R, S>, new_size: usize) {
5051 match buffers {
5052 BuffersRefMut::NoBuffers | BuffersRefMut::SendOnly(_) => {}
5053 BuffersRefMut::Both { recv, send: _ } | BuffersRefMut::RecvOnly(recv) => {
5054 recv.request_capacity(new_size)
5055 }
5056 BuffersRefMut::Sizes(BufferSizes { receive, send: _ }) => *receive = new_size,
5057 }
5058 }
5059
5060 fn allowed_range(settings: &TcpSettings) -> (usize, usize) {
5061 (settings.receive_buffer.min().get(), settings.receive_buffer.max().get())
5062 }
5063
5064 fn get_buffer_size(buffers: BuffersRefMut<'_, R, S>) -> Option<usize> {
5065 match buffers {
5066 BuffersRefMut::NoBuffers | BuffersRefMut::SendOnly(_) => None,
5067 BuffersRefMut::Both { recv, send: _ } | BuffersRefMut::RecvOnly(recv) => {
5068 Some(recv.target_capacity())
5069 }
5070 BuffersRefMut::Sizes(BufferSizes { receive, send: _ }) => Some(*receive),
5071 }
5072 }
5073}
5074
5075fn get_buffers_mut<I, CC, BC>(
5076 state: &mut TcpSocketState<I, CC::WeakDeviceId, BC>,
5077 converter: MaybeDualStack<CC::DualStackConverter, CC::SingleStackConverter>,
5078) -> BuffersRefMut<'_, BC::ReceiveBuffer, BC::SendBuffer>
5079where
5080 I: DualStackIpExt,
5081 CC: TcpContext<I, BC>,
5082 BC: TcpBindingsContext<CC::DeviceId>,
5083{
5084 match &mut state.socket_state {
5085 TcpSocketStateInner::Unbound(Unbound { buffer_sizes, .. })
5086 | TcpSocketStateInner::Bound(BoundState { buffer_sizes, .. })
5087 | TcpSocketStateInner::Listener(Listener { buffer_sizes, .. }) => {
5088 BuffersRefMut::Sizes(buffer_sizes)
5089 }
5090 TcpSocketStateInner::Connected { conn, .. } => {
5091 let state = match converter {
5092 MaybeDualStack::NotDualStack(converter) => {
5093 let (conn, _addr) = converter.convert(conn);
5094 &mut conn.state
5095 }
5096 MaybeDualStack::DualStack(converter) => match converter.convert(conn) {
5097 EitherStack::ThisStack((conn, _addr)) => &mut conn.state,
5098 EitherStack::OtherStack((conn, _addr)) => &mut conn.state,
5099 },
5100 };
5101 state.buffers_mut()
5102 }
5103 }
5104}
5105
5106fn set_buffer_size<
5107 Which: AccessBufferSize<BC::ReceiveBuffer, BC::SendBuffer>,
5108 I: DualStackIpExt,
5109 BC: TcpBindingsContext<CC::DeviceId>,
5110 CC: TcpContext<I, BC>,
5111>(
5112 core_ctx: &mut CC,
5113 bindings_ctx: &mut BC,
5114 id: &TcpSocketId<I, CC::WeakDeviceId, BC>,
5115 size: usize,
5116) {
5117 let (min, max) = Which::allowed_range(&*bindings_ctx.settings());
5118 let size = size.clamp(min, max);
5119 core_ctx.with_socket_mut_and_converter(id, |state, converter| {
5120 Which::set_buffer_size(get_buffers_mut::<I, CC, BC>(state, converter), size)
5121 })
5122}
5123
5124fn get_buffer_size<
5125 Which: AccessBufferSize<BC::ReceiveBuffer, BC::SendBuffer>,
5126 I: DualStackIpExt,
5127 BC: TcpBindingsContext<CC::DeviceId>,
5128 CC: TcpContext<I, BC>,
5129>(
5130 core_ctx: &mut CC,
5131 id: &TcpSocketId<I, CC::WeakDeviceId, BC>,
5132) -> Option<usize> {
5133 core_ctx.with_socket_mut_and_converter(id, |state, converter| {
5134 Which::get_buffer_size(get_buffers_mut::<I, CC, BC>(state, converter))
5135 })
5136}
5137
5138#[derive(Debug, GenericOverIp, Error)]
5140#[generic_over_ip()]
5141pub enum SetDeviceError {
5142 #[error("cannot set bound device due to conflict with another socket")]
5144 Conflict,
5145 #[error("cannot set bound device as socket would become unroutable")]
5147 Unroutable,
5148 #[error("cannot set bound device as socket's address has a different zone")]
5150 ZoneChange,
5151}
5152
5153#[derive(Debug, GenericOverIp, Error)]
5155#[generic_over_ip()]
5156pub enum AcceptError {
5157 #[error("would block: no currently-established socket")]
5159 WouldBlock,
5160 #[error("this socket does not support accept")]
5162 NotSupported,
5163}
5164
5165#[derive(Debug, GenericOverIp, PartialEq, Error)]
5167#[generic_over_ip()]
5168pub enum ListenError {
5169 #[error("conflict with another listening socket")]
5171 ListenerExists,
5172 #[error("listening not supported")]
5174 NotSupported,
5175}
5176
5177#[derive(Debug, GenericOverIp, Eq, PartialEq, Error)]
5179#[generic_over_ip()]
5180#[error("no connection")]
5181pub struct NoConnection;
5182
5183#[derive(Debug, GenericOverIp, Error)]
5185#[generic_over_ip()]
5186pub enum SetReuseAddrError {
5187 #[error("cannot share in-use address")]
5189 AddrInUse,
5190 #[error("cannot set ReuseAddr on a connected socket")]
5192 NotSupported,
5193}
5194
5195#[derive(Debug, Error, GenericOverIp)]
5197#[generic_over_ip()]
5198#[cfg_attr(test, derive(PartialEq, Eq))]
5199pub enum ConnectError {
5200 #[error("unable to allocate a port")]
5202 NoPort,
5203 #[error("no route to remote host")]
5205 NoRoute,
5206 #[error(transparent)]
5208 Zone(#[from] ZonedAddressError),
5209 #[error("there is already a connection at the address requested")]
5211 ConnectionExists,
5212 #[error("called connect on a listener")]
5214 Listener,
5215 #[error("the handshake has already started")]
5217 Pending,
5218 #[error("the handshake is completed")]
5220 Completed,
5221 #[error("the handshake is aborted")]
5223 Aborted,
5224 #[error("connection error: {0}")]
5226 ConnectionError(#[from] ConnectionError),
5227}
5228
5229#[derive(Debug, Error, GenericOverIp, PartialEq)]
5231#[generic_over_ip()]
5232pub enum BindError {
5233 #[error("the socket was already bound")]
5235 AlreadyBound,
5236 #[error(transparent)]
5238 LocalAddressError(#[from] LocalAddressError),
5239}
5240
5241#[derive(GenericOverIp, Debug, Error)]
5243#[generic_over_ip()]
5244pub enum OriginalDestinationError {
5245 #[error("cannot retrieve original destination for unconnected socket")]
5247 NotConnected,
5248 #[error("socket's original destination could not be found in connection tracking table")]
5251 NotFound,
5252 #[error("socket's original destination address should be specified for TCP")]
5255 UnspecifiedDestinationAddr,
5256 #[error("socket's original destination port should be specified for TCP")]
5259 UnspecifiedDestinationPort,
5260}
5261
5262#[derive(GenericOverIp)]
5264#[generic_over_ip(I, Ip)]
5265pub struct DemuxSocketId<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
5266 I::DemuxSocketId<D, BT>,
5267);
5268
5269trait DemuxStateAccessor<I: DualStackIpExt, CC: DeviceIdContext<AnyDevice>, BT: TcpBindingsTypes> {
5273 fn update_demux_state_for_connect<
5278 O,
5279 E,
5280 F: FnOnce(
5281 &I::DemuxSocketId<CC::WeakDeviceId, BT>,
5282 &mut DemuxState<I, CC::WeakDeviceId, BT>,
5283 ) -> Result<O, E>,
5284 >(
5285 self,
5286 core_ctx: &mut CC,
5287 cb: F,
5288 ) -> Result<O, E>;
5289}
5290
5291struct SingleStackDemuxStateAccessor<
5292 'a,
5293 I: DualStackIpExt,
5294 CC: DeviceIdContext<AnyDevice>,
5295 BT: TcpBindingsTypes,
5296>(
5297 &'a I::DemuxSocketId<CC::WeakDeviceId, BT>,
5298 Option<ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, CC::WeakDeviceId>>,
5299);
5300
5301impl<'a, I, CC, BT> DemuxStateAccessor<I, CC, BT> for SingleStackDemuxStateAccessor<'a, I, CC, BT>
5302where
5303 I: DualStackIpExt,
5304 BT: TcpBindingsTypes,
5305 CC: DeviceIdContext<AnyDevice> + TcpDemuxContext<I, CC::WeakDeviceId, BT>,
5306{
5307 fn update_demux_state_for_connect<
5308 O,
5309 E,
5310 F: FnOnce(
5311 &I::DemuxSocketId<CC::WeakDeviceId, BT>,
5312 &mut DemuxState<I, CC::WeakDeviceId, BT>,
5313 ) -> Result<O, E>,
5314 >(
5315 self,
5316 core_ctx: &mut CC,
5317 cb: F,
5318 ) -> Result<O, E> {
5319 core_ctx.with_demux_mut(|demux| {
5320 let Self(demux_id, listener_addr) = self;
5321 let output = cb(demux_id, demux)?;
5322
5323 if let Some(listener_addr) = listener_addr {
5327 demux
5328 .socketmap
5329 .listeners_mut()
5330 .remove(demux_id, &listener_addr)
5331 .expect("failed to remove a bound socket");
5332 }
5333 Ok(output)
5334 })
5335 }
5336}
5337
5338struct DualStackDemuxStateAccessor<
5339 'a,
5340 I: DualStackIpExt,
5341 CC: DeviceIdContext<AnyDevice>,
5342 BT: TcpBindingsTypes,
5343>(
5344 &'a TcpSocketId<I, CC::WeakDeviceId, BT>,
5345 DualStackTuple<I, Option<ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, CC::WeakDeviceId>>>,
5346);
5347
5348impl<'a, SockI, WireI, CC, BT> DemuxStateAccessor<WireI, CC, BT>
5349 for DualStackDemuxStateAccessor<'a, SockI, CC, BT>
5350where
5351 SockI: DualStackIpExt,
5352 WireI: DualStackIpExt,
5353 BT: TcpBindingsTypes,
5354 CC: DeviceIdContext<AnyDevice>
5355 + TcpDualStackContext<SockI, CC::WeakDeviceId, BT>
5356 + TcpDemuxContext<WireI, CC::WeakDeviceId, BT>
5357 + TcpDemuxContext<WireI::OtherVersion, CC::WeakDeviceId, BT>,
5358{
5359 fn update_demux_state_for_connect<
5360 O,
5361 E,
5362 F: FnOnce(
5363 &WireI::DemuxSocketId<CC::WeakDeviceId, BT>,
5364 &mut DemuxState<WireI, CC::WeakDeviceId, BT>,
5365 ) -> Result<O, E>,
5366 >(
5367 self,
5368 core_ctx: &mut CC,
5369 cb: F,
5370 ) -> Result<O, E> {
5371 let Self(id, local_addr) = self;
5372 let (DemuxSocketId(wire_id), DemuxSocketId(other_id)) =
5373 core_ctx.dual_stack_demux_id(id.clone()).cast::<WireI>().into_inner();
5374 let (wire_local_addr, other_local_addr) = local_addr.cast::<WireI>().into_inner();
5375 let output = core_ctx.with_demux_mut(|wire_demux: &mut DemuxState<WireI, _, _>| {
5376 let output = cb(&wire_id, wire_demux)?;
5377
5378 if let Some(wire_local_addr) = wire_local_addr {
5380 wire_demux
5381 .socketmap
5382 .listeners_mut()
5383 .remove(&wire_id, &wire_local_addr)
5384 .expect("failed to remove a bound socket");
5385 }
5386 Ok(output)
5387 })?;
5388
5389 if let Some(other_local_addr) = other_local_addr {
5392 core_ctx.with_demux_mut(|other_demux: &mut DemuxState<WireI::OtherVersion, _, _>| {
5393 other_demux
5394 .socketmap
5395 .listeners_mut()
5396 .remove(&other_id, &other_local_addr)
5397 .expect("failed to remove a bound socket");
5398 });
5399 }
5400
5401 Ok(output)
5402 }
5403}
5404
5405#[derive(Debug)]
5406enum LocalAddrForConnect<D, A: IpAddress> {
5407 Unbound { device: Option<D> },
5408 Listener { addr: ListenerAddr<ListenerIpAddr<A, NonZeroU16>, D> },
5409}
5410
5411impl<D, A: IpAddress> LocalAddrForConnect<D, A> {
5412 fn from_local_addr(
5413 listener_addr: Option<ListenerAddr<ListenerIpAddr<A, NonZeroU16>, D>>,
5414 device: Option<D>,
5415 ) -> Self {
5416 match listener_addr {
5417 Some(addr) => Self::Listener { addr },
5418 None => Self::Unbound { device },
5419 }
5420 }
5421}
5422
5423fn connect_inner<CC, BC, SockI, WireI, Demux>(
5424 core_ctx: &mut CC,
5425 bindings_ctx: &mut BC,
5426 sock_id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
5427 isn: &IsnGenerator<BC::Instant>,
5428 timestamp_offset: &TimestampOffsetGenerator<BC::Instant>,
5429 local_addr: LocalAddrForConnect<CC::WeakDeviceId, WireI::Addr>,
5430 remote_ip: ZonedAddr<SocketIpAddr<WireI::Addr>, CC::DeviceId>,
5431 remote_port: NonZeroU16,
5432 active_open: TakeableRef<'_, BC::ListenerNotifierOrProvidedBuffers>,
5433 buffer_sizes: BufferSizes,
5434 socket_options: &SocketOptions,
5435 sharing: SharingState,
5436 demux: Demux,
5437 convert_back_op: impl FnOnce(
5438 Connection<SockI, WireI, CC::WeakDeviceId, BC>,
5439 ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
5440 ) -> SockI::ConnectionAndAddr<CC::WeakDeviceId, BC>,
5441 convert_timer: impl FnOnce(WeakTcpSocketId<SockI, CC::WeakDeviceId, BC>) -> BC::DispatchId,
5442) -> Result<TcpSocketStateInner<SockI, CC::WeakDeviceId, BC>, ConnectError>
5443where
5444 SockI: DualStackIpExt,
5445 WireI: DualStackIpExt,
5446 BC: TcpBindingsContext<CC::DeviceId>,
5447 CC: TransportIpContext<WireI, BC>
5448 + DeviceIpSocketHandler<WireI, BC>
5449 + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
5450 Demux: DemuxStateAccessor<WireI, CC, BC>,
5451{
5452 let (local_ip, bound_device, local_port) = match local_addr {
5453 LocalAddrForConnect::Listener {
5454 addr: ListenerAddr { ip: ListenerIpAddr { addr, identifier }, device },
5455 } => (addr.and_then(IpDeviceAddr::new_from_socket_ip_addr), device, Some(identifier)),
5456 LocalAddrForConnect::Unbound { device } => (None, device, None),
5457 };
5458 let (remote_ip, device) = remote_ip.resolve_addr_with_device(bound_device)?;
5459
5460 if remote_ip.addr().is_multicast()
5465 || WireI::map_ip_in(remote_ip.addr(), |ip| ip.is_limited_broadcast(), |_| false)
5466 {
5467 return Err(ConnectError::NoRoute);
5468 }
5469
5470 let ip_sock = core_ctx
5471 .new_ip_socket(
5472 bindings_ctx,
5473 IpSocketArgs {
5474 device: device.as_ref().map(|d| d.as_ref()),
5475 local_ip,
5476 remote_ip,
5477 proto: IpProto::Tcp.into(),
5478 options: &socket_options.ip_options,
5479 },
5480 )
5481 .map_err(|err| match err {
5482 IpSockCreationError::Route(_) => ConnectError::NoRoute,
5483 })?;
5484
5485 let device_mms = core_ctx.get_mms(bindings_ctx, &ip_sock, &socket_options.ip_options).map_err(
5486 |_err: ip::socket::MmsError| {
5487 ConnectError::NoRoute
5490 },
5491 )?;
5492
5493 let conn_addr =
5494 demux.update_demux_state_for_connect(core_ctx, |demux_id, DemuxState { socketmap }| {
5495 let local_port = local_port.map_or_else(
5496 || match netstack3_base::simple_randomized_port_alloc(
5502 &mut bindings_ctx.rng(),
5503 &Some(SocketIpAddr::from(*ip_sock.local_ip())),
5504 &TcpPortAlloc(socketmap),
5505 &Some(remote_port),
5506 ) {
5507 Some(port) => {
5508 Ok(NonZeroU16::new(port).expect("ephemeral ports must be non-zero"))
5509 }
5510 None => Err(ConnectError::NoPort),
5511 },
5512 Ok,
5513 )?;
5514
5515 let conn_addr = ConnAddr {
5516 ip: ConnIpAddr {
5517 local: (SocketIpAddr::from(*ip_sock.local_ip()), local_port),
5518 remote: (*ip_sock.remote_ip(), remote_port),
5519 },
5520 device: ip_sock.device().cloned(),
5521 };
5522
5523 let _entry = socketmap
5524 .conns_mut()
5525 .try_insert(conn_addr.clone(), sharing, demux_id.clone())
5526 .map_err(|err| match err {
5527 InsertError::Exists | InsertError::WouldShadowExisting => {
5529 ConnectError::ConnectionExists
5530 }
5531 InsertError::ShadowAddrExists | InsertError::IndirectConflict => {
5534 panic!("failed to insert connection: {:?}", err)
5535 }
5536 })?;
5537 Ok::<_, ConnectError>(conn_addr)
5538 })?;
5539
5540 let isn = isn.generate::<SocketIpAddr<WireI::Addr>, NonZeroU16>(
5541 bindings_ctx.now(),
5542 conn_addr.ip.local,
5543 conn_addr.ip.remote,
5544 );
5545 let timestamp_offset = timestamp_offset.generate::<SocketIpAddr<WireI::Addr>, NonZeroU16>(
5546 bindings_ctx.now(),
5547 conn_addr.ip.local,
5548 conn_addr.ip.remote,
5549 );
5550
5551 let now = bindings_ctx.now();
5552 let mss = Mss::from_mms(device_mms).ok_or(ConnectError::NoRoute)?;
5553
5554 let active_open = active_open.take();
5557 Ok((move || {
5558 let (syn_sent, syn) = Closed::<Initial>::connect(
5559 isn,
5560 timestamp_offset,
5561 now,
5562 active_open,
5563 buffer_sizes,
5564 mss,
5565 Mss::default::<WireI>(),
5566 socket_options,
5567 );
5568 let state = State::<_, BC::ReceiveBuffer, BC::SendBuffer, _>::SynSent(syn_sent);
5569 let poll_send_at = state.poll_send_at().expect("no retrans timer");
5570
5571 send_tcp_segment(
5573 core_ctx,
5574 bindings_ctx,
5575 Some(&sock_id),
5576 Some(&ip_sock),
5577 conn_addr.ip,
5578 syn.into_empty(),
5579 &socket_options.ip_options,
5580 );
5581
5582 let mut timer = bindings_ctx.new_timer(convert_timer(sock_id.downgrade()));
5583 assert_eq!(bindings_ctx.schedule_timer_instant(poll_send_at, &mut timer), None);
5584
5585 let conn = convert_back_op(
5586 Connection {
5587 accept_queue: None,
5588 state,
5589 ip_sock,
5590 defunct: false,
5591 soft_error: None,
5592 handshake_status: HandshakeStatus::Pending,
5593 },
5594 conn_addr,
5595 );
5596 core_ctx.increment_both(sock_id, |counters| &counters.active_connection_openings);
5597 TcpSocketStateInner::Connected { conn, timer }
5598 })())
5599}
5600
5601#[derive(Clone, Debug, Eq, PartialEq, GenericOverIp)]
5603#[generic_over_ip(A, IpAddress)]
5604pub enum SocketInfo<A: IpAddress, D> {
5605 Unbound(UnboundInfo<D>),
5607 Bound(BoundInfo<A, D>),
5609 Connection(ConnectionInfo<A, D>),
5611}
5612
5613#[derive(Clone, Debug, Eq, PartialEq, GenericOverIp)]
5615#[generic_over_ip()]
5616pub struct UnboundInfo<D> {
5617 pub device: Option<D>,
5619}
5620
5621#[derive(Clone, Debug, Eq, PartialEq, GenericOverIp)]
5623#[generic_over_ip(A, IpAddress)]
5624pub struct BoundInfo<A: IpAddress, D> {
5625 pub addr: Option<ZonedAddr<SpecifiedAddr<A>, D>>,
5627 pub port: NonZeroU16,
5629 pub device: Option<D>,
5631}
5632
5633#[derive(Clone, Debug, Eq, PartialEq, GenericOverIp)]
5635#[generic_over_ip(A, IpAddress)]
5636pub struct ConnectionInfo<A: IpAddress, D> {
5637 pub local_addr: SocketAddr<A, D>,
5639 pub remote_addr: SocketAddr<A, D>,
5641 pub device: Option<D>,
5643}
5644
5645impl<D: Clone, Extra> From<&'_ Unbound<D, Extra>> for UnboundInfo<D> {
5646 fn from(unbound: &Unbound<D, Extra>) -> Self {
5647 Self { device: unbound.bound_device.clone() }
5648 }
5649}
5650
5651fn maybe_zoned<A: IpAddress, D: Clone>(
5652 ip: SpecifiedAddr<A>,
5653 device: &Option<D>,
5654) -> ZonedAddr<SpecifiedAddr<A>, D> {
5655 device
5656 .as_ref()
5657 .and_then(|device| {
5658 AddrAndZone::new(ip, device).map(|az| ZonedAddr::Zoned(az.map_zone(Clone::clone)))
5659 })
5660 .unwrap_or(ZonedAddr::Unzoned(ip))
5661}
5662
5663impl<A: IpAddress, D: Clone> From<ListenerAddr<ListenerIpAddr<A, NonZeroU16>, D>>
5664 for BoundInfo<A, D>
5665{
5666 fn from(addr: ListenerAddr<ListenerIpAddr<A, NonZeroU16>, D>) -> Self {
5667 let ListenerAddr { ip: ListenerIpAddr { addr, identifier }, device } = addr;
5668 let addr = addr.map(|ip| maybe_zoned(ip.into(), &device));
5669 BoundInfo { addr, port: identifier, device }
5670 }
5671}
5672
5673impl<A: IpAddress, D: Clone> From<ConnAddr<ConnIpAddr<A, NonZeroU16, NonZeroU16>, D>>
5674 for ConnectionInfo<A, D>
5675{
5676 fn from(addr: ConnAddr<ConnIpAddr<A, NonZeroU16, NonZeroU16>, D>) -> Self {
5677 let ConnAddr { ip: ConnIpAddr { local, remote }, device } = addr;
5678 let convert = |(ip, port): (SocketIpAddr<A>, NonZeroU16)| SocketAddr {
5679 ip: maybe_zoned(ip.into(), &device),
5680 port,
5681 };
5682 Self { local_addr: convert(local), remote_addr: convert(remote), device }
5683 }
5684}
5685
5686impl<CC, BC> HandleableTimer<CC, BC> for TcpTimerId<CC::WeakDeviceId, BC>
5687where
5688 BC: TcpBindingsContext<CC::DeviceId>,
5689 CC: TcpContext<Ipv4, BC> + TcpContext<Ipv6, BC>,
5690{
5691 fn handle(self, core_ctx: &mut CC, bindings_ctx: &mut BC, _: BC::UniqueTimerId) {
5692 let ctx_pair = CtxPair { core_ctx, bindings_ctx };
5693 match self {
5694 TcpTimerId::V4(conn_id) => TcpApi::new(ctx_pair).handle_timer(conn_id),
5695 TcpTimerId::V6(conn_id) => TcpApi::new(ctx_pair).handle_timer(conn_id),
5696 }
5697 }
5698}
5699
5700fn send_tcp_segment<'a, WireI, SockI, CC, BC, D>(
5708 core_ctx: &mut CC,
5709 bindings_ctx: &mut BC,
5710 socket_id: Option<&TcpSocketId<SockI, D, BC>>,
5711 ip_sock: Option<&IpSock<WireI, D>>,
5712 conn_addr: ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>,
5713 segment: Segment<<BC::SendBuffer as SendBuffer>::Payload<'a>>,
5714 ip_sock_options: &TcpIpSockOptions,
5715) where
5716 WireI: IpExt + FilterIpExt,
5717 SockI: IpExt + DualStackIpExt,
5718 CC: TcpSocketContext<SockI, D, BC>
5719 + IpSocketHandler<WireI, BC, DeviceId = D::Strong, WeakDeviceId = D>,
5720 BC: TcpBindingsTypes,
5721 D: WeakDeviceIdentifier,
5722{
5723 let tx_metadata: BC::TxMetadata = match socket_id {
5728 Some(socket_id) => {
5729 core_ctx.convert_tx_meta(TcpSocketTxMetadata::new(socket_id.downgrade()))
5730 }
5731 None => Default::default(),
5732 };
5733
5734 let (header, data) = segment.into_parts();
5735 let control = header.control;
5736 let result = match ip_sock {
5737 Some(ip_sock) => {
5738 let body = tcp_serialize_segment(&header, data, conn_addr);
5739 core_ctx
5740 .send_ip_packet(bindings_ctx, ip_sock, body, ip_sock_options, tx_metadata)
5741 .map_err(|err| IpSockCreateAndSendError::Send(err))
5742 }
5743 None => {
5744 let ConnIpAddr { local: (local_ip, _), remote: (remote_ip, _) } = conn_addr;
5745 core_ctx.send_oneshot_ip_packet(
5746 bindings_ctx,
5747 IpSocketArgs {
5748 device: None,
5749 local_ip: IpDeviceAddr::new_from_socket_ip_addr(local_ip),
5750 remote_ip,
5751 proto: IpProto::Tcp.into(),
5752 options: ip_sock_options,
5753 },
5754 tx_metadata,
5755 |_addr| tcp_serialize_segment(&header, data, conn_addr),
5756 )
5757 }
5758 };
5759 match result {
5760 Ok(()) => {
5761 counters::increment_counter_with_optional_socket_id(core_ctx, socket_id, |counters| {
5762 &counters.segments_sent
5763 });
5764 if let Some(control) = control {
5765 counters::increment_counter_with_optional_socket_id(
5766 core_ctx,
5767 socket_id,
5768 |counters| match control {
5769 Control::RST => &counters.resets_sent,
5770 Control::SYN => &counters.syns_sent,
5771 Control::FIN => &counters.fins_sent,
5772 },
5773 )
5774 }
5775 }
5776 Err(err) => {
5777 counters::increment_counter_with_optional_socket_id(core_ctx, socket_id, |counters| {
5778 &counters.segment_send_errors
5779 });
5780 match socket_id {
5781 Some(socket_id) => debug!("{:?}: failed to send segment: {:?}", socket_id, err),
5782 None => debug!("TCP: failed to send segment: {:?}", err),
5783 }
5784 }
5785 }
5786}
5787
5788impl<I, C> TcpApi<I, C>
5789where
5790 I: DualStackIpExt,
5791 C: ContextPair,
5792 C::CoreContext: TcpContext<I, C::BindingsContext>,
5793 C::BindingsContext: TcpBindingsContext<
5794 <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
5795 >,
5796{
5797 pub fn get_tcp_info(
5799 &mut self,
5800 id: &TcpApiSocketId<I, C>,
5801 ) -> TcpSocketInfo<<C::BindingsContext as InstantBindingsTypes>::Instant> {
5802 self.core_ctx().with_socket(id, |socket_state| socket_state.tcp_info(id.counters()))
5803 }
5804}
5805
5806#[cfg(test)]
5807mod tests {
5808 use alloc::rc::Rc;
5809 use alloc::string::String;
5810 use alloc::sync::Arc;
5811 use alloc::vec::Vec;
5812 use alloc::{format, vec};
5813 use core::cell::RefCell;
5814 use core::num::NonZeroU16;
5815 use core::time::Duration;
5816
5817 use ip_test_macro::ip_test;
5818 use net_declare::{net_ip_v4, net_ip_v6};
5819 use net_types::ip::{Ip, IpAddr, IpVersion, Ipv4, Ipv4SourceAddr, Ipv6, Ipv6SourceAddr, Mtu};
5820 use net_types::{LinkLocalAddr, Witness};
5821 use netstack3_base::sync::{DynDebugReferences, Mutex};
5822 use netstack3_base::testutil::{
5823 AlwaysDefaultsSettingsContext, FakeAtomicInstant, FakeCoreCtx, FakeCryptoRng, FakeDeviceId,
5824 FakeInstant, FakeNetwork, FakeNetworkSpec, FakeStrongDeviceId, FakeTimerCtx, FakeTimerId,
5825 FakeTxMetadata, FakeWeakDeviceId, InstantAndData, MultipleDevicesId, PendingFrameData,
5826 StepResult, TestIpExt, WithFakeFrameContext, WithFakeTimerContext, new_rng,
5827 run_with_many_seeds, set_logger_for_test,
5828 };
5829 use netstack3_base::{
5830 ContextProvider, CounterCollection, CounterContext, IcmpIpExt, Icmpv4ErrorCode,
5831 Icmpv6ErrorCode, Instant as _, InstantContext, LinkDevice, Mark, MarkDomain,
5832 MatcherBindingsTypes, Mms, NetworkSerializationContext, ReferenceNotifiers,
5833 ResourceCounterContext, StrongDeviceIdentifier, Uninstantiable, UninstantiableWrapper,
5834 };
5835 use netstack3_filter::testutil::NoOpSocketOpsFilter;
5836 use netstack3_filter::{SocketOpsFilter, TransportPacketSerializer, Tuple};
5837 use netstack3_ip::device::IpDeviceStateIpExt;
5838 use netstack3_ip::nud::LinkResolutionContext;
5839 use netstack3_ip::nud::testutil::FakeLinkResolutionNotifier;
5840 use netstack3_ip::socket::testutil::{FakeDeviceConfig, FakeDualStackIpSocketCtx};
5841 use netstack3_ip::socket::{IpSockSendError, MmsError, RouteResolutionOptions, SendOptions};
5842 use netstack3_ip::testutil::DualStackSendIpPacketMeta;
5843 use netstack3_ip::{
5844 BaseTransportIpContext, HopLimits, IpTransportContext, LocalDeliveryPacketInfo,
5845 };
5846 use packet::{Buf, BufferMut, NestablePacketBuilder as _, ParseBuffer as _, Serializer as _};
5847 use packet_formats::icmp::{
5848 IcmpDestUnreachable, Icmpv4DestUnreachableCode, Icmpv4ParameterProblemCode,
5849 Icmpv4TimeExceededCode, Icmpv6DestUnreachableCode, Icmpv6ParameterProblemCode,
5850 Icmpv6TimeExceededCode,
5851 };
5852 use packet_formats::tcp::{TcpParseArgs, TcpSegment, TcpSegmentBuilder};
5853 use rand::RngExt as _;
5854 use test_case::test_case;
5855
5856 use super::*;
5857 use crate::internal::base::{ConnectionError, DEFAULT_FIN_WAIT2_TIMEOUT};
5858 use crate::internal::buffer::BufferLimits;
5859 use crate::internal::buffer::testutil::{
5860 ClientBuffers, ProvidedBuffers, RingBuffer, TestSendBuffer, WriteBackClientBuffers,
5861 };
5862 use crate::internal::congestion::CongestionWindow;
5863 use crate::internal::counters::TcpCountersWithoutSocket;
5864 use crate::internal::counters::testutil::{
5865 CounterExpectations, CounterExpectationsWithoutSocket,
5866 };
5867 use crate::internal::state::{Established, MSL, TimeWait};
5868
5869 pub(crate) trait TcpTestIpExt:
5870 DualStackIpExt + TestIpExt + IpDeviceStateIpExt + DualStackIpExt
5871 {
5872 type SingleStackConverter: SingleStackConverter<Self, FakeWeakDeviceId<FakeDeviceId>, TcpBindingsCtx<FakeDeviceId>>;
5873 type DualStackConverter: DualStackConverter<Self, FakeWeakDeviceId<FakeDeviceId>, TcpBindingsCtx<FakeDeviceId>>;
5874 fn recv_src_addr(addr: Self::Addr) -> Self::RecvSrcAddr;
5875
5876 fn converter() -> MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>;
5877 }
5878
5879 trait TcpTestBindingsTypes<D: StrongDeviceIdentifier>:
5886 TcpBindingsTypes<DispatchId = TcpTimerId<D::Weak, Self>> + Sized
5887 {
5888 }
5889
5890 impl<D, BT> TcpTestBindingsTypes<D> for BT
5891 where
5892 BT: TcpBindingsTypes<DispatchId = TcpTimerId<D::Weak, Self>> + Sized,
5893 D: StrongDeviceIdentifier,
5894 {
5895 }
5896
5897 struct FakeTcpState<I: TcpTestIpExt, D: FakeStrongDeviceId, BT: TcpBindingsTypes> {
5898 isn_generator: Rc<IsnGenerator<BT::Instant>>,
5899 timestamp_offset_generator: Rc<TimestampOffsetGenerator<BT::Instant>>,
5900 demux: Rc<RefCell<DemuxState<I, D::Weak, BT>>>,
5901 all_sockets: TcpSocketSet<I, D::Weak, BT>,
5904 counters_with_socket: TcpCountersWithSocket<I>,
5905 counters_without_socket: TcpCountersWithoutSocket<I>,
5906 }
5907
5908 impl<I, D, BT> Default for FakeTcpState<I, D, BT>
5909 where
5910 I: TcpTestIpExt,
5911 D: FakeStrongDeviceId,
5912 BT: TcpBindingsTypes,
5913 BT::Instant: Default,
5914 {
5915 fn default() -> Self {
5916 Self {
5917 isn_generator: Default::default(),
5918 timestamp_offset_generator: Default::default(),
5919 all_sockets: Default::default(),
5920 demux: Rc::new(RefCell::new(DemuxState { socketmap: Default::default() })),
5921 counters_with_socket: Default::default(),
5922 counters_without_socket: Default::default(),
5923 }
5924 }
5925 }
5926
5927 struct FakeDualStackTcpState<D: FakeStrongDeviceId, BT: TcpBindingsTypes> {
5928 v4: FakeTcpState<Ipv4, D, BT>,
5929 v6: FakeTcpState<Ipv6, D, BT>,
5930 }
5931
5932 impl<D, BT> Default for FakeDualStackTcpState<D, BT>
5933 where
5934 D: FakeStrongDeviceId,
5935 BT: TcpBindingsTypes,
5936 BT::Instant: Default,
5937 {
5938 fn default() -> Self {
5939 Self { v4: Default::default(), v6: Default::default() }
5940 }
5941 }
5942
5943 type InnerCoreCtx<D> =
5944 FakeCoreCtx<FakeDualStackIpSocketCtx<D>, DualStackSendIpPacketMeta<D>, D>;
5945
5946 pub(crate) struct TcpCoreCtx<D: FakeStrongDeviceId, BT: TcpBindingsTypes> {
5947 tcp: FakeDualStackTcpState<D, BT>,
5948 ip_socket_ctx: InnerCoreCtx<D>,
5949 recv_packet_marks: netstack3_base::Marks,
5951 }
5952
5953 impl<D: FakeStrongDeviceId, BT: TcpBindingsTypes> ContextProvider for TcpCoreCtx<D, BT> {
5954 type Context = Self;
5955
5956 fn context(&mut self) -> &mut Self::Context {
5957 self
5958 }
5959 }
5960
5961 impl<D, BT> DeviceIdContext<AnyDevice> for TcpCoreCtx<D, BT>
5962 where
5963 D: FakeStrongDeviceId,
5964 BT: TcpBindingsTypes,
5965 {
5966 type DeviceId = D;
5967 type WeakDeviceId = FakeWeakDeviceId<D>;
5968 }
5969
5970 pub(crate) type TcpCtx<D> = CtxPair<TcpCoreCtx<D, TcpBindingsCtx<D>>, TcpBindingsCtx<D>>;
5971
5972 pub(crate) struct FakeTcpNetworkSpec<D: FakeStrongDeviceId>(PhantomData<D>, !);
5973 impl<D: FakeStrongDeviceId> FakeNetworkSpec for FakeTcpNetworkSpec<D> {
5974 type Context = TcpCtx<D>;
5975 type TimerId = TcpTimerId<D::Weak, TcpBindingsCtx<D>>;
5976 type SendMeta = DualStackSendIpPacketMeta<D>;
5977 type RecvMeta = DualStackSendIpPacketMeta<D>;
5978 fn handle_frame(ctx: &mut Self::Context, meta: Self::RecvMeta, buffer: Buf<Vec<u8>>) {
5979 let TcpCtx { core_ctx, bindings_ctx } = ctx;
5980 match meta {
5981 DualStackSendIpPacketMeta::V4(meta) => {
5982 let early_demux_socket =
5983 <TcpIpTransportContext as IpTransportContext<Ipv4, _, _>>::early_demux(
5984 core_ctx,
5985 &meta.device,
5986 *meta.src_ip,
5987 *meta.dst_ip,
5988 buffer.as_ref(),
5989 );
5990 <TcpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_ip_packet(
5991 core_ctx,
5992 bindings_ctx,
5993 &meta.device,
5994 Ipv4::recv_src_addr(*meta.src_ip),
5995 meta.dst_ip,
5996 buffer,
5997 &mut LocalDeliveryPacketInfo {
5998 marks: core_ctx.recv_packet_marks,
5999 ..Default::default()
6000 },
6001 early_demux_socket,
6002 )
6003 .expect("failed to deliver bytes");
6004 }
6005 DualStackSendIpPacketMeta::V6(meta) => {
6006 let early_demux_socket =
6007 <TcpIpTransportContext as IpTransportContext<Ipv6, _, _>>::early_demux(
6008 core_ctx,
6009 &meta.device,
6010 *meta.src_ip,
6011 *meta.dst_ip,
6012 buffer.as_ref(),
6013 );
6014 <TcpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
6015 core_ctx,
6016 bindings_ctx,
6017 &meta.device,
6018 Ipv6::recv_src_addr(*meta.src_ip),
6019 meta.dst_ip,
6020 buffer,
6021 &mut LocalDeliveryPacketInfo {
6022 marks: core_ctx.recv_packet_marks,
6023 ..Default::default()
6024 },
6025 early_demux_socket,
6026 )
6027 .expect("failed to deliver bytes");
6028 }
6029 }
6030 }
6031 fn handle_timer(ctx: &mut Self::Context, dispatch: Self::TimerId, _: FakeTimerId) {
6032 match dispatch {
6033 TcpTimerId::V4(id) => ctx.tcp_api().handle_timer(id),
6034 TcpTimerId::V6(id) => ctx.tcp_api().handle_timer(id),
6035 }
6036 }
6037 fn process_queues(_ctx: &mut Self::Context) -> bool {
6038 false
6039 }
6040 fn fake_frames(ctx: &mut Self::Context) -> &mut impl WithFakeFrameContext<Self::SendMeta> {
6041 &mut ctx.core_ctx.ip_socket_ctx.frames
6042 }
6043 }
6044
6045 impl<D: FakeStrongDeviceId> WithFakeTimerContext<TcpTimerId<D::Weak, TcpBindingsCtx<D>>>
6046 for TcpCtx<D>
6047 {
6048 fn with_fake_timer_ctx<
6049 O,
6050 F: FnOnce(&FakeTimerCtx<TcpTimerId<D::Weak, TcpBindingsCtx<D>>>) -> O,
6051 >(
6052 &self,
6053 f: F,
6054 ) -> O {
6055 let Self { core_ctx: _, bindings_ctx } = self;
6056 f(&bindings_ctx.timers)
6057 }
6058
6059 fn with_fake_timer_ctx_mut<
6060 O,
6061 F: FnOnce(&mut FakeTimerCtx<TcpTimerId<D::Weak, TcpBindingsCtx<D>>>) -> O,
6062 >(
6063 &mut self,
6064 f: F,
6065 ) -> O {
6066 let Self { core_ctx: _, bindings_ctx } = self;
6067 f(&mut bindings_ctx.timers)
6068 }
6069 }
6070
6071 #[derive(Derivative)]
6072 #[derivative(Default(bound = ""))]
6073 pub(crate) struct TcpBindingsCtx<D: FakeStrongDeviceId> {
6074 rng: FakeCryptoRng,
6075 timers: FakeTimerCtx<TcpTimerId<D::Weak, Self>>,
6076 }
6077
6078 impl<D: FakeStrongDeviceId> ContextProvider for TcpBindingsCtx<D> {
6079 type Context = Self;
6080 fn context(&mut self) -> &mut Self::Context {
6081 self
6082 }
6083 }
6084
6085 impl<D: LinkDevice + FakeStrongDeviceId> LinkResolutionContext<D> for TcpBindingsCtx<D> {
6086 type Notifier = FakeLinkResolutionNotifier<D>;
6087 }
6088
6089 impl<D: FakeStrongDeviceId> TimerBindingsTypes for TcpBindingsCtx<D> {
6091 type Timer = <FakeTimerCtx<TcpTimerId<D::Weak, Self>> as TimerBindingsTypes>::Timer;
6092 type DispatchId =
6093 <FakeTimerCtx<TcpTimerId<D::Weak, Self>> as TimerBindingsTypes>::DispatchId;
6094 type UniqueTimerId =
6095 <FakeTimerCtx<TcpTimerId<D::Weak, Self>> as TimerBindingsTypes>::UniqueTimerId;
6096 }
6097
6098 impl<D: FakeStrongDeviceId> InstantBindingsTypes for TcpBindingsCtx<D> {
6100 type Instant = FakeInstant;
6101 type AtomicInstant = FakeAtomicInstant;
6102 }
6103
6104 impl<D: FakeStrongDeviceId> SocketOpsFilterBindingContext<D> for TcpBindingsCtx<D> {
6105 fn socket_ops_filter(&self) -> impl SocketOpsFilter<D> {
6106 NoOpSocketOpsFilter
6107 }
6108 }
6109
6110 impl<D: FakeStrongDeviceId> InstantContext for TcpBindingsCtx<D> {
6112 fn now(&self) -> FakeInstant {
6113 self.timers.now()
6114 }
6115 }
6116
6117 impl<D: FakeStrongDeviceId> TimerContext for TcpBindingsCtx<D> {
6119 fn new_timer(&mut self, id: Self::DispatchId) -> Self::Timer {
6120 self.timers.new_timer(id)
6121 }
6122
6123 fn schedule_timer_instant(
6124 &mut self,
6125 time: Self::Instant,
6126 timer: &mut Self::Timer,
6127 ) -> Option<Self::Instant> {
6128 self.timers.schedule_timer_instant(time, timer)
6129 }
6130
6131 fn cancel_timer(&mut self, timer: &mut Self::Timer) -> Option<Self::Instant> {
6132 self.timers.cancel_timer(timer)
6133 }
6134
6135 fn scheduled_instant(&self, timer: &mut Self::Timer) -> Option<Self::Instant> {
6136 self.timers.scheduled_instant(timer)
6137 }
6138
6139 fn unique_timer_id(&self, timer: &Self::Timer) -> Self::UniqueTimerId {
6140 self.timers.unique_timer_id(timer)
6141 }
6142 }
6143
6144 impl<D: FakeStrongDeviceId> ReferenceNotifiers for TcpBindingsCtx<D> {
6145 type ReferenceReceiver<T: 'static> = !;
6146
6147 type ReferenceNotifier<T: Send + 'static> = !;
6148
6149 fn new_reference_notifier<T: Send + 'static>(
6150 debug_references: DynDebugReferences,
6151 ) -> (Self::ReferenceNotifier<T>, Self::ReferenceReceiver<T>) {
6152 panic!(
6154 "can't create deferred reference notifiers for type {}: \
6155 debug_references={debug_references:?}",
6156 core::any::type_name::<T>()
6157 );
6158 }
6159 }
6160
6161 impl<D: FakeStrongDeviceId> DeferredResourceRemovalContext for TcpBindingsCtx<D> {
6162 fn defer_removal<T: Send + 'static>(&mut self, receiver: Self::ReferenceReceiver<T>) {
6163 match receiver {}
6164 }
6165 }
6166
6167 impl<D: FakeStrongDeviceId> RngContext for TcpBindingsCtx<D> {
6168 type Rng<'a> = &'a mut FakeCryptoRng;
6169 fn rng(&mut self) -> Self::Rng<'_> {
6170 &mut self.rng
6171 }
6172 }
6173
6174 impl<D: FakeStrongDeviceId> TxMetadataBindingsTypes for TcpBindingsCtx<D> {
6175 type TxMetadata = FakeTxMetadata;
6176 }
6177
6178 impl<D: FakeStrongDeviceId> MatcherBindingsTypes for TcpBindingsCtx<D> {
6179 type DeviceClass = ();
6180 type BindingsPacketMatcher = !;
6181 }
6182
6183 impl<D: FakeStrongDeviceId> MarksBindingsContext for TcpBindingsCtx<D> {
6184 fn marks_to_keep_on_egress() -> &'static [netstack3_base::MarkDomain] {
6185 const MARKS: [netstack3_base::MarkDomain; 1] = [netstack3_base::MarkDomain::Mark1];
6186 &MARKS
6187 }
6188
6189 fn marks_to_set_on_ingress() -> &'static [netstack3_base::MarkDomain] {
6190 const MARKS: [netstack3_base::MarkDomain; 1] = [netstack3_base::MarkDomain::Mark2];
6191 &MARKS
6192 }
6193 }
6194
6195 impl<D: FakeStrongDeviceId> TcpBindingsTypes for TcpBindingsCtx<D> {
6196 type ReceiveBuffer = Arc<Mutex<RingBuffer>>;
6197 type SendBuffer = TestSendBuffer;
6198 type ReturnedBuffers = ClientBuffers;
6199 type ListenerNotifierOrProvidedBuffers = ProvidedBuffers;
6200
6201 fn new_passive_open_buffers(
6202 buffer_sizes: BufferSizes,
6203 ) -> (Self::ReceiveBuffer, Self::SendBuffer, Self::ReturnedBuffers) {
6204 let client = ClientBuffers::new(buffer_sizes);
6205 (
6206 Arc::clone(&client.receive),
6207 TestSendBuffer::new(Arc::clone(&client.send), RingBuffer::default()),
6208 client,
6209 )
6210 }
6211 }
6212
6213 impl<D: FakeStrongDeviceId> AlwaysDefaultsSettingsContext for TcpBindingsCtx<D> {}
6214
6215 impl<D: FakeStrongDeviceId> TcpSocketDestructionContext for TcpBindingsCtx<D> {
6216 fn defer_tcp_socket_destruction<I, S>(
6217 &self,
6218 _result: RemoveResourceResultWithContext<S, Self>,
6219 ) where
6220 I: Ip,
6221 S: SocketDiagnosticsSeed<Output = TcpSocketDiagnostics<I, Self::Instant>>
6222 + Send
6223 + 'static,
6224 {
6225 }
6227 }
6228
6229 const LINK_MTU: Mtu = Mtu::new(1500);
6230
6231 impl<I, D, BC> DeviceIpSocketHandler<I, BC> for TcpCoreCtx<D, BC>
6232 where
6233 I: TcpTestIpExt,
6234 D: FakeStrongDeviceId,
6235 BC: TcpTestBindingsTypes<D>,
6236 {
6237 fn get_mms<O>(
6238 &mut self,
6239 _bindings_ctx: &mut BC,
6240 _ip_sock: &IpSock<I, Self::WeakDeviceId>,
6241 _options: &O,
6242 ) -> Result<Mms, MmsError>
6243 where
6244 O: RouteResolutionOptions<I>,
6245 {
6246 Ok(Mms::from_mtu::<I>(LINK_MTU, 0).unwrap())
6247 }
6248 }
6249
6250 impl<I, D, BC> BaseTransportIpContext<I, BC> for TcpCoreCtx<D, BC>
6252 where
6253 I: TcpTestIpExt,
6254 D: FakeStrongDeviceId,
6255 BC: TcpTestBindingsTypes<D>,
6256 {
6257 type DevicesWithAddrIter<'a>
6258 = <InnerCoreCtx<D> as BaseTransportIpContext<I, BC>>::DevicesWithAddrIter<'a>
6259 where
6260 Self: 'a;
6261
6262 fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
6263 &mut self,
6264 addr: SpecifiedAddr<I::Addr>,
6265 cb: F,
6266 ) -> O {
6267 BaseTransportIpContext::<I, BC>::with_devices_with_assigned_addr(
6268 &mut self.ip_socket_ctx,
6269 addr,
6270 cb,
6271 )
6272 }
6273
6274 fn get_default_hop_limits(&mut self, device: Option<&Self::DeviceId>) -> HopLimits {
6275 BaseTransportIpContext::<I, BC>::get_default_hop_limits(&mut self.ip_socket_ctx, device)
6276 }
6277
6278 fn get_original_destination(&mut self, tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
6279 BaseTransportIpContext::<I, BC>::get_original_destination(
6280 &mut self.ip_socket_ctx,
6281 tuple,
6282 )
6283 }
6284 }
6285
6286 impl<I: TcpTestIpExt, D: FakeStrongDeviceId, BC: TcpTestBindingsTypes<D>> IpSocketHandler<I, BC>
6288 for TcpCoreCtx<D, BC>
6289 {
6290 fn new_ip_socket<O>(
6291 &mut self,
6292 bindings_ctx: &mut BC,
6293 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
6294 ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
6295 where
6296 O: RouteResolutionOptions<I>,
6297 {
6298 IpSocketHandler::<I, BC>::new_ip_socket(&mut self.ip_socket_ctx, bindings_ctx, args)
6299 }
6300
6301 fn send_ip_packet<S, O>(
6302 &mut self,
6303 bindings_ctx: &mut BC,
6304 socket: &IpSock<I, Self::WeakDeviceId>,
6305 body: S,
6306 options: &O,
6307 tx_meta: BC::TxMetadata,
6308 ) -> Result<(), IpSockSendError>
6309 where
6310 S: TransportPacketSerializer<I>,
6311 S::Buffer: BufferMut,
6312 O: SendOptions<I> + RouteResolutionOptions<I>,
6313 {
6314 self.ip_socket_ctx.send_ip_packet(bindings_ctx, socket, body, options, tx_meta)
6315 }
6316
6317 fn confirm_reachable<O>(
6318 &mut self,
6319 bindings_ctx: &mut BC,
6320 socket: &IpSock<I, Self::WeakDeviceId>,
6321 options: &O,
6322 ) where
6323 O: RouteResolutionOptions<I>,
6324 {
6325 self.ip_socket_ctx.confirm_reachable(bindings_ctx, socket, options)
6326 }
6327 }
6328
6329 impl<D, BC> TcpDemuxContext<Ipv4, D::Weak, BC> for TcpCoreCtx<D, BC>
6330 where
6331 D: FakeStrongDeviceId,
6332 BC: TcpTestBindingsTypes<D>,
6333 {
6334 type IpTransportCtx<'a> = Self;
6335 fn with_demux<O, F: FnOnce(&DemuxState<Ipv4, D::Weak, BC>) -> O>(&mut self, cb: F) -> O {
6336 cb(&self.tcp.v4.demux.borrow())
6337 }
6338
6339 fn with_demux_mut<O, F: FnOnce(&mut DemuxState<Ipv4, D::Weak, BC>) -> O>(
6340 &mut self,
6341 cb: F,
6342 ) -> O {
6343 cb(&mut self.tcp.v4.demux.borrow_mut())
6344 }
6345 }
6346
6347 impl<D, BC> TcpDemuxContext<Ipv6, D::Weak, BC> for TcpCoreCtx<D, BC>
6348 where
6349 D: FakeStrongDeviceId,
6350 BC: TcpTestBindingsTypes<D>,
6351 {
6352 type IpTransportCtx<'a> = Self;
6353 fn with_demux<O, F: FnOnce(&DemuxState<Ipv6, D::Weak, BC>) -> O>(&mut self, cb: F) -> O {
6354 cb(&self.tcp.v6.demux.borrow())
6355 }
6356
6357 fn with_demux_mut<O, F: FnOnce(&mut DemuxState<Ipv6, D::Weak, BC>) -> O>(
6358 &mut self,
6359 cb: F,
6360 ) -> O {
6361 cb(&mut self.tcp.v6.demux.borrow_mut())
6362 }
6363 }
6364
6365 impl<I, D, BT> CoreTimerContext<WeakTcpSocketId<I, D::Weak, BT>, BT> for TcpCoreCtx<D, BT>
6366 where
6367 I: DualStackIpExt,
6368 D: FakeStrongDeviceId,
6369 BT: TcpTestBindingsTypes<D>,
6370 {
6371 fn convert_timer(dispatch_id: WeakTcpSocketId<I, D::Weak, BT>) -> BT::DispatchId {
6372 dispatch_id.into()
6373 }
6374 }
6375
6376 impl<I, D, BC> CoreTxMetadataContext<TcpSocketTxMetadata<I, D::Weak, BC>, BC> for TcpCoreCtx<D, BC>
6377 where
6378 I: TcpTestIpExt,
6379 D: FakeStrongDeviceId,
6380 BC: TcpTestBindingsTypes<D>,
6381 {
6382 fn convert_tx_meta(&self, _tx_meta: TcpSocketTxMetadata<I, D::Weak, BC>) -> BC::TxMetadata {
6383 Default::default()
6384 }
6385 }
6386
6387 impl<D: FakeStrongDeviceId, BC: TcpTestBindingsTypes<D>> TcpContext<Ipv6, BC>
6388 for TcpCoreCtx<D, BC>
6389 {
6390 type ThisStackIpTransportAndDemuxCtx<'a> = Self;
6391 type SingleStackIpTransportAndDemuxCtx<'a> = UninstantiableWrapper<Self>;
6392 type SingleStackConverter = Uninstantiable;
6393 type DualStackIpTransportAndDemuxCtx<'a> = Self;
6394 type DualStackConverter = ();
6395 fn with_all_sockets_mut<
6396 O,
6397 F: FnOnce(&mut TcpSocketSet<Ipv6, Self::WeakDeviceId, BC>) -> O,
6398 >(
6399 &mut self,
6400 cb: F,
6401 ) -> O {
6402 cb(&mut self.tcp.v6.all_sockets)
6403 }
6404
6405 fn for_each_socket<
6406 F: FnMut(
6407 &TcpSocketId<Ipv6, Self::WeakDeviceId, BC>,
6408 &TcpSocketState<Ipv6, Self::WeakDeviceId, BC>,
6409 ),
6410 >(
6411 &mut self,
6412 mut cb: F,
6413 ) {
6414 for id in self.tcp.v6.all_sockets.keys() {
6415 cb(id, &id.get());
6416 }
6417 }
6418
6419 fn with_socket_mut_generators_transport_demux<
6420 O,
6421 F: for<'a> FnOnce(
6422 MaybeDualStack<
6423 (&'a mut Self::DualStackIpTransportAndDemuxCtx<'a>, Self::DualStackConverter),
6424 (
6425 &'a mut Self::SingleStackIpTransportAndDemuxCtx<'a>,
6426 Self::SingleStackConverter,
6427 ),
6428 >,
6429 &mut TcpSocketState<Ipv6, Self::WeakDeviceId, BC>,
6430 &IsnGenerator<BC::Instant>,
6431 &TimestampOffsetGenerator<BC::Instant>,
6432 ) -> O,
6433 >(
6434 &mut self,
6435 id: &TcpSocketId<Ipv6, Self::WeakDeviceId, BC>,
6436 cb: F,
6437 ) -> O {
6438 let isn = Rc::clone(&self.tcp.v6.isn_generator);
6439 let timestamp_offset = Rc::clone(&self.tcp.v6.timestamp_offset_generator);
6440 cb(
6441 MaybeDualStack::DualStack((self, ())),
6442 id.get_mut().deref_mut(),
6443 isn.deref(),
6444 timestamp_offset.deref(),
6445 )
6446 }
6447
6448 fn with_socket_and_converter<
6449 O,
6450 F: FnOnce(
6451 &TcpSocketState<Ipv6, Self::WeakDeviceId, BC>,
6452 MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>,
6453 ) -> O,
6454 >(
6455 &mut self,
6456 id: &TcpSocketId<Ipv6, Self::WeakDeviceId, BC>,
6457 cb: F,
6458 ) -> O {
6459 cb(id.get_mut().deref_mut(), MaybeDualStack::DualStack(()))
6460 }
6461 }
6462
6463 impl<D: FakeStrongDeviceId, BC: TcpTestBindingsTypes<D>> TcpContext<Ipv4, BC>
6464 for TcpCoreCtx<D, BC>
6465 {
6466 type ThisStackIpTransportAndDemuxCtx<'a> = Self;
6467 type SingleStackIpTransportAndDemuxCtx<'a> = Self;
6468 type SingleStackConverter = ();
6469 type DualStackIpTransportAndDemuxCtx<'a> = UninstantiableWrapper<Self>;
6470 type DualStackConverter = Uninstantiable;
6471 fn with_all_sockets_mut<
6472 O,
6473 F: FnOnce(&mut TcpSocketSet<Ipv4, Self::WeakDeviceId, BC>) -> O,
6474 >(
6475 &mut self,
6476 cb: F,
6477 ) -> O {
6478 cb(&mut self.tcp.v4.all_sockets)
6479 }
6480
6481 fn for_each_socket<
6482 F: FnMut(
6483 &TcpSocketId<Ipv4, Self::WeakDeviceId, BC>,
6484 &TcpSocketState<Ipv4, Self::WeakDeviceId, BC>,
6485 ),
6486 >(
6487 &mut self,
6488 mut cb: F,
6489 ) {
6490 for id in self.tcp.v4.all_sockets.keys() {
6491 cb(id, &id.get());
6492 }
6493 }
6494
6495 fn with_socket_mut_generators_transport_demux<
6496 O,
6497 F: for<'a> FnOnce(
6498 MaybeDualStack<
6499 (&'a mut Self::DualStackIpTransportAndDemuxCtx<'a>, Self::DualStackConverter),
6500 (
6501 &'a mut Self::SingleStackIpTransportAndDemuxCtx<'a>,
6502 Self::SingleStackConverter,
6503 ),
6504 >,
6505 &mut TcpSocketState<Ipv4, Self::WeakDeviceId, BC>,
6506 &IsnGenerator<BC::Instant>,
6507 &TimestampOffsetGenerator<BC::Instant>,
6508 ) -> O,
6509 >(
6510 &mut self,
6511 id: &TcpSocketId<Ipv4, Self::WeakDeviceId, BC>,
6512 cb: F,
6513 ) -> O {
6514 let isn: Rc<IsnGenerator<<BC as InstantBindingsTypes>::Instant>> =
6515 Rc::clone(&self.tcp.v4.isn_generator);
6516 let timestamp_offset: Rc<
6517 TimestampOffsetGenerator<<BC as InstantBindingsTypes>::Instant>,
6518 > = Rc::clone(&self.tcp.v4.timestamp_offset_generator);
6519 cb(
6520 MaybeDualStack::NotDualStack((self, ())),
6521 id.get_mut().deref_mut(),
6522 isn.deref(),
6523 timestamp_offset.deref(),
6524 )
6525 }
6526
6527 fn with_socket_and_converter<
6528 O,
6529 F: FnOnce(
6530 &TcpSocketState<Ipv4, Self::WeakDeviceId, BC>,
6531 MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>,
6532 ) -> O,
6533 >(
6534 &mut self,
6535 id: &TcpSocketId<Ipv4, Self::WeakDeviceId, BC>,
6536 cb: F,
6537 ) -> O {
6538 cb(id.get_mut().deref_mut(), MaybeDualStack::NotDualStack(()))
6539 }
6540 }
6541
6542 impl<D: FakeStrongDeviceId, BT: TcpTestBindingsTypes<D>>
6543 TcpDualStackContext<Ipv6, FakeWeakDeviceId<D>, BT> for TcpCoreCtx<D, BT>
6544 {
6545 type DualStackIpTransportCtx<'a> = Self;
6546 fn other_demux_id_converter(&self) -> impl DualStackDemuxIdConverter<Ipv6> {
6547 Ipv6SocketIdToIpv4DemuxIdConverter
6548 }
6549 fn dual_stack_enabled(&self, ip_options: &Ipv6Options) -> bool {
6550 ip_options.dual_stack_enabled
6551 }
6552 fn set_dual_stack_enabled(&self, ip_options: &mut Ipv6Options, value: bool) {
6553 ip_options.dual_stack_enabled = value;
6554 }
6555 fn with_both_demux_mut<
6556 O,
6557 F: FnOnce(
6558 &mut DemuxState<Ipv6, FakeWeakDeviceId<D>, BT>,
6559 &mut DemuxState<Ipv4, FakeWeakDeviceId<D>, BT>,
6560 ) -> O,
6561 >(
6562 &mut self,
6563 cb: F,
6564 ) -> O {
6565 cb(&mut self.tcp.v6.demux.borrow_mut(), &mut self.tcp.v4.demux.borrow_mut())
6566 }
6567 }
6568
6569 impl<I: Ip, D: FakeStrongDeviceId, BT: TcpTestBindingsTypes<D>>
6570 CounterContext<TcpCountersWithSocket<I>> for TcpCoreCtx<D, BT>
6571 {
6572 fn counters(&self) -> &TcpCountersWithSocket<I> {
6573 I::map_ip(
6574 (),
6575 |()| &self.tcp.v4.counters_with_socket,
6576 |()| &self.tcp.v6.counters_with_socket,
6577 )
6578 }
6579 }
6580
6581 impl<I: Ip, D: FakeStrongDeviceId, BT: TcpTestBindingsTypes<D>>
6582 CounterContext<TcpCountersWithoutSocket<I>> for TcpCoreCtx<D, BT>
6583 {
6584 fn counters(&self) -> &TcpCountersWithoutSocket<I> {
6585 I::map_ip(
6586 (),
6587 |()| &self.tcp.v4.counters_without_socket,
6588 |()| &self.tcp.v6.counters_without_socket,
6589 )
6590 }
6591 }
6592
6593 impl<I: DualStackIpExt, D: FakeStrongDeviceId, BT: TcpTestBindingsTypes<D>>
6594 ResourceCounterContext<TcpSocketId<I, FakeWeakDeviceId<D>, BT>, TcpCountersWithSocket<I>>
6595 for TcpCoreCtx<D, BT>
6596 {
6597 fn per_resource_counters<'a>(
6598 &'a self,
6599 resource: &'a TcpSocketId<I, FakeWeakDeviceId<D>, BT>,
6600 ) -> &'a TcpCountersWithSocket<I> {
6601 resource.counters()
6602 }
6603 }
6604
6605 impl<D, BT> TcpCoreCtx<D, BT>
6606 where
6607 D: FakeStrongDeviceId,
6608 BT: TcpBindingsTypes,
6609 BT::Instant: Default,
6610 {
6611 fn with_ip_socket_ctx_state(state: FakeDualStackIpSocketCtx<D>) -> Self {
6612 Self {
6613 tcp: Default::default(),
6614 ip_socket_ctx: FakeCoreCtx::with_state(state),
6615 recv_packet_marks: Default::default(),
6616 }
6617 }
6618 }
6619
6620 impl TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>> {
6621 pub(crate) fn new<I: TcpTestIpExt>(
6622 addr: SpecifiedAddr<I::Addr>,
6623 peer: SpecifiedAddr<I::Addr>,
6624 ) -> Self {
6625 Self::with_ip_socket_ctx_state(FakeDualStackIpSocketCtx::new(core::iter::once(
6626 FakeDeviceConfig {
6627 device: FakeDeviceId,
6628 local_ips: vec![addr],
6629 remote_ips: vec![peer],
6630 },
6631 )))
6632 }
6633 }
6634
6635 impl TcpCoreCtx<MultipleDevicesId, TcpBindingsCtx<MultipleDevicesId>> {
6636 fn new_multiple_devices() -> Self {
6637 let ip_v4_local =
6638 SpecifiedAddr::new(IpAddr::V4(*<Ipv4 as TestIpExt>::TEST_ADDRS.local_ip)).unwrap();
6639 let ip_v4_remote =
6640 SpecifiedAddr::new(IpAddr::V4(*<Ipv4 as TestIpExt>::TEST_ADDRS.remote_ip)).unwrap();
6641 let ip_v6_local =
6642 SpecifiedAddr::new(IpAddr::V6(*<Ipv6 as TestIpExt>::TEST_ADDRS.local_ip)).unwrap();
6643 let ip_v6_remote =
6644 SpecifiedAddr::new(IpAddr::V6(*<Ipv6 as TestIpExt>::TEST_ADDRS.remote_ip)).unwrap();
6645
6646 let ips = vec![ip_v4_local, ip_v4_remote, ip_v6_local, ip_v6_remote];
6647
6648 Self::with_ip_socket_ctx_state(FakeDualStackIpSocketCtx::new(
6649 MultipleDevicesId::all().into_iter().map(|device| {
6650 let local_ips = match device {
6651 MultipleDevicesId::A | MultipleDevicesId::B => ips.clone(),
6652 MultipleDevicesId::C => Vec::new(),
6653 };
6654 FakeDeviceConfig { device, remote_ips: local_ips.clone(), local_ips }
6655 }),
6656 ))
6657 }
6658 }
6659
6660 impl<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpTimerId<D, BT> {
6661 fn assert_ip_version<I: DualStackIpExt>(self) -> WeakTcpSocketId<I, D, BT> {
6662 I::map_ip_out(
6663 self,
6664 |v4| assert_matches!(v4, TcpTimerId::V4(v4) => v4),
6665 |v6| assert_matches!(v6, TcpTimerId::V6(v6) => v6),
6666 )
6667 }
6668 }
6669
6670 const LOCAL: &'static str = "local";
6671 const REMOTE: &'static str = "remote";
6672 pub(crate) const PORT_1: NonZeroU16 = NonZeroU16::new(42).unwrap();
6673 const PORT_2: NonZeroU16 = NonZeroU16::new(43).unwrap();
6674
6675 impl TcpTestIpExt for Ipv4 {
6676 type SingleStackConverter = ();
6677 type DualStackConverter = Uninstantiable;
6678 fn converter() -> MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter> {
6679 MaybeDualStack::NotDualStack(())
6680 }
6681 fn recv_src_addr(addr: Self::Addr) -> Self::RecvSrcAddr {
6682 Ipv4SourceAddr::new(addr).unwrap()
6683 }
6684 }
6685
6686 impl TcpTestIpExt for Ipv6 {
6687 type SingleStackConverter = Uninstantiable;
6688 type DualStackConverter = ();
6689 fn converter() -> MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter> {
6690 MaybeDualStack::DualStack(())
6691 }
6692 fn recv_src_addr(addr: Self::Addr) -> Self::RecvSrcAddr {
6693 Ipv6SourceAddr::new(addr).unwrap()
6694 }
6695 }
6696
6697 type TcpTestNetwork = FakeNetwork<
6698 FakeTcpNetworkSpec<FakeDeviceId>,
6699 &'static str,
6700 fn(
6701 &'static str,
6702 DualStackSendIpPacketMeta<FakeDeviceId>,
6703 ) -> Vec<(
6704 &'static str,
6705 DualStackSendIpPacketMeta<FakeDeviceId>,
6706 Option<core::time::Duration>,
6707 )>,
6708 >;
6709
6710 fn new_test_net<I: TcpTestIpExt>() -> TcpTestNetwork {
6711 FakeTcpNetworkSpec::new_network(
6712 [
6713 (
6714 LOCAL,
6715 TcpCtx {
6716 core_ctx: TcpCoreCtx::new::<I>(
6717 I::TEST_ADDRS.local_ip,
6718 I::TEST_ADDRS.remote_ip,
6719 ),
6720 bindings_ctx: TcpBindingsCtx::default(),
6721 },
6722 ),
6723 (
6724 REMOTE,
6725 TcpCtx {
6726 core_ctx: TcpCoreCtx::new::<I>(
6727 I::TEST_ADDRS.remote_ip,
6728 I::TEST_ADDRS.local_ip,
6729 ),
6730 bindings_ctx: TcpBindingsCtx::default(),
6731 },
6732 ),
6733 ],
6734 move |net, meta: DualStackSendIpPacketMeta<_>| {
6735 if net == LOCAL {
6736 alloc::vec![(REMOTE, meta, None)]
6737 } else {
6738 alloc::vec![(LOCAL, meta, None)]
6739 }
6740 },
6741 )
6742 }
6743
6744 impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpSocketId<I, D, BT> {
6746 fn get(&self) -> impl Deref<Target = TcpSocketState<I, D, BT>> + '_ {
6747 let Self(rc) = self;
6748 rc.locked_state.read()
6749 }
6750
6751 fn get_mut(&self) -> impl DerefMut<Target = TcpSocketState<I, D, BT>> + '_ {
6752 let Self(rc) = self;
6753 rc.locked_state.write()
6754 }
6755 }
6756
6757 fn assert_this_stack_conn<
6758 'a,
6759 I: DualStackIpExt,
6760 BC: TcpBindingsContext<CC::DeviceId>,
6761 CC: TcpContext<I, BC>,
6762 >(
6763 conn: &'a I::ConnectionAndAddr<CC::WeakDeviceId, BC>,
6764 converter: &MaybeDualStack<CC::DualStackConverter, CC::SingleStackConverter>,
6765 ) -> &'a (
6766 Connection<I, I, CC::WeakDeviceId, BC>,
6767 ConnAddr<ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
6768 ) {
6769 match converter {
6770 MaybeDualStack::NotDualStack(nds) => nds.convert(conn),
6771 MaybeDualStack::DualStack(ds) => {
6772 assert_matches!(ds.convert(conn), EitherStack::ThisStack(conn) => conn)
6773 }
6774 }
6775 }
6776
6777 pub(crate) trait TcpApiExt: ContextPair + Sized {
6779 fn tcp_api<I: Ip>(&mut self) -> TcpApi<I, &mut Self> {
6780 TcpApi::new(self)
6781 }
6782 }
6783
6784 impl<O> TcpApiExt for O where O: ContextPair + Sized {}
6785
6786 struct BindConfig {
6788 client_port: Option<NonZeroU16>,
6790 server_port: NonZeroU16,
6792 client_reuse_addr: bool,
6794 send_test_data: bool,
6797 }
6798
6799 fn bind_listen_connect_accept_inner<I: TcpTestIpExt>(
6816 listen_addr: I::Addr,
6817 BindConfig { client_port, server_port, client_reuse_addr, send_test_data }: BindConfig,
6818 seed: u128,
6819 drop_rate: f64,
6820 ) -> (
6821 TcpTestNetwork,
6822 TcpSocketId<I, FakeWeakDeviceId<FakeDeviceId>, TcpBindingsCtx<FakeDeviceId>>,
6823 Arc<Mutex<Vec<u8>>>,
6824 TcpSocketId<I, FakeWeakDeviceId<FakeDeviceId>, TcpBindingsCtx<FakeDeviceId>>,
6825 )
6826 where
6827 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
6828 I,
6829 TcpBindingsCtx<FakeDeviceId>,
6830 SingleStackConverter = I::SingleStackConverter,
6831 DualStackConverter = I::DualStackConverter,
6832 >,
6833 {
6834 let mut net = new_test_net::<I>();
6835 let mut rng = new_rng(seed);
6836
6837 let mut maybe_drop_frame =
6838 |_: &mut TcpCtx<_>, meta: DualStackSendIpPacketMeta<_>, buffer: Buf<Vec<u8>>| {
6839 let x: f64 = rng.random();
6840 (x > drop_rate).then_some((meta, buffer))
6841 };
6842
6843 let backlog = NonZeroUsize::new(1).unwrap();
6844 let server = net.with_context(REMOTE, |ctx| {
6845 let mut api = ctx.tcp_api::<I>();
6846 let server = api.create(Default::default());
6847 api.bind(
6848 &server,
6849 SpecifiedAddr::new(listen_addr).map(|a| ZonedAddr::Unzoned(a)),
6850 Some(server_port),
6851 )
6852 .expect("failed to bind the server socket");
6853 api.listen(&server, backlog).expect("can listen");
6854 server
6855 });
6856
6857 let client_ends = WriteBackClientBuffers::default();
6858 let client = net.with_context(LOCAL, |ctx| {
6859 let mut api = ctx.tcp_api::<I>();
6860 let socket = api.create(ProvidedBuffers::Buffers(client_ends.clone()));
6861 if client_reuse_addr {
6862 api.set_reuseaddr(&socket, true).expect("can set");
6863 }
6864 if let Some(port) = client_port {
6865 api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(port))
6866 .expect("failed to bind the client socket")
6867 }
6868 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), server_port)
6869 .expect("failed to connect");
6870 socket
6871 });
6872 if drop_rate == 0.0 {
6875 let _: StepResult = net.step();
6877 assert_matches!(
6879 &server.get().deref().socket_state,
6880 TcpSocketStateInner::Listener(Listener { accept_queue, .. }) => {
6881 assert_eq!(accept_queue.ready_len(), 0);
6882 assert_eq!(accept_queue.pending_len(), 1);
6883 }
6884 );
6885 net.with_context(REMOTE, |ctx| {
6887 let mut api = ctx.tcp_api::<I>();
6888 assert_matches!(api.accept(&server), Err(AcceptError::WouldBlock));
6889 });
6890 }
6891
6892 net.run_until_idle_with(&mut maybe_drop_frame);
6894 let (accepted, addr, accepted_ends) = net.with_context(REMOTE, |ctx| {
6895 ctx.tcp_api::<I>().accept(&server).expect("failed to accept")
6896 });
6897 if let Some(port) = client_port {
6898 assert_eq!(
6899 addr,
6900 SocketAddr { ip: ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip), port: port }
6901 );
6902 } else {
6903 assert_eq!(addr.ip, ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip));
6904 }
6905
6906 net.with_context(LOCAL, |ctx| {
6907 let mut api = ctx.tcp_api::<I>();
6908 assert_eq!(
6909 api.connect(
6910 &client,
6911 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)),
6912 server_port,
6913 ),
6914 Ok(())
6915 );
6916 });
6917
6918 let assert_connected = |conn_id: &TcpSocketId<I, _, _>| {
6919 assert_matches!(
6920 &conn_id.get().deref().socket_state,
6921 TcpSocketStateInner::Connected { conn, .. } => {
6922 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
6923 assert_matches!(
6924 conn,
6925 Connection {
6926 accept_queue: None,
6927 state: State::Established(_),
6928 ip_sock: _,
6929 defunct: false,
6930 soft_error: None,
6931 handshake_status: HandshakeStatus::Completed { reported: true },
6932 }
6933 );
6934 }
6935 )
6936 };
6937
6938 assert_connected(&client);
6939 assert_connected(&accepted);
6940
6941 let ClientBuffers { send: client_snd_end, receive: client_rcv_end } =
6942 client_ends.0.as_ref().lock().take().unwrap();
6943 let ClientBuffers { send: accepted_snd_end, receive: accepted_rcv_end } = accepted_ends;
6944
6945 if send_test_data {
6946 for snd_end in [client_snd_end.clone(), accepted_snd_end] {
6947 snd_end.lock().extend_from_slice(b"Hello");
6948 }
6949
6950 for (c, id) in [(LOCAL, &client), (REMOTE, &accepted)] {
6951 net.with_context(c, |ctx| ctx.tcp_api::<I>().do_send(id))
6952 }
6953 net.run_until_idle_with(&mut maybe_drop_frame);
6954
6955 for rcv_end in [client_rcv_end, accepted_rcv_end] {
6956 assert_eq!(
6957 rcv_end.lock().read_with(|avail| {
6958 let avail = avail.concat();
6959 assert_eq!(avail, b"Hello");
6960 avail.len()
6961 }),
6962 5
6963 );
6964 }
6965 }
6966
6967 assert_matches!(
6969 &server.get().deref().socket_state,
6970 TcpSocketStateInner::Listener(Listener {
6971 addr: _,
6972 backlog: actual_backlog,
6973 accept_queue: _,
6974 buffer_sizes
6975 }) => {
6976 assert_eq!(*actual_backlog, backlog);
6977 assert_eq!(*buffer_sizes, BufferSizes::default());
6978 }
6979 );
6980
6981 net.with_context(REMOTE, |ctx| {
6982 let mut api = ctx.tcp_api::<I>();
6983 assert_eq!(api.shutdown(&server, ShutdownType::Receive), Ok(false));
6984 api.close(server);
6985 });
6986
6987 (net, client, client_snd_end, accepted)
6988 }
6989
6990 #[test]
6991 fn test_socket_addr_display() {
6992 assert_eq!(
6993 format!(
6994 "{}",
6995 SocketAddr {
6996 ip: maybe_zoned(
6997 SpecifiedAddr::new(Ipv4Addr::new([192, 168, 0, 1]))
6998 .expect("failed to create specified addr"),
6999 &None::<usize>,
7000 ),
7001 port: NonZeroU16::new(1024).expect("failed to create NonZeroU16"),
7002 }
7003 ),
7004 String::from("192.168.0.1:1024"),
7005 );
7006 assert_eq!(
7007 format!(
7008 "{}",
7009 SocketAddr {
7010 ip: maybe_zoned(
7011 SpecifiedAddr::new(Ipv6Addr::new([0x2001, 0xDB8, 0, 0, 0, 0, 0, 1]))
7012 .expect("failed to create specified addr"),
7013 &None::<usize>,
7014 ),
7015 port: NonZeroU16::new(1024).expect("failed to create NonZeroU16"),
7016 }
7017 ),
7018 String::from("[2001:db8::1]:1024")
7019 );
7020 assert_eq!(
7021 format!(
7022 "{}",
7023 SocketAddr {
7024 ip: maybe_zoned(
7025 SpecifiedAddr::new(Ipv6Addr::new([0xFE80, 0, 0, 0, 0, 0, 0, 1]))
7026 .expect("failed to create specified addr"),
7027 &Some(42),
7028 ),
7029 port: NonZeroU16::new(1024).expect("failed to create NonZeroU16"),
7030 }
7031 ),
7032 String::from("[fe80::1%42]:1024")
7033 );
7034 }
7035
7036 #[ip_test(I)]
7037 #[test_case(BindConfig { client_port: None, server_port: PORT_1, client_reuse_addr: false, send_test_data: true }, I::UNSPECIFIED_ADDRESS)]
7038 #[test_case(BindConfig { client_port: Some(PORT_1), server_port: PORT_1, client_reuse_addr: false, send_test_data: true }, I::UNSPECIFIED_ADDRESS)]
7039 #[test_case(BindConfig { client_port: None, server_port: PORT_1, client_reuse_addr: true, send_test_data: true }, I::UNSPECIFIED_ADDRESS)]
7040 #[test_case(BindConfig { client_port: Some(PORT_1), server_port: PORT_1, client_reuse_addr: true, send_test_data: true }, I::UNSPECIFIED_ADDRESS)]
7041 #[test_case(BindConfig { client_port: None, server_port: PORT_1, client_reuse_addr: false, send_test_data: true }, *<I as TestIpExt>::TEST_ADDRS.remote_ip)]
7042 #[test_case(BindConfig { client_port: Some(PORT_1), server_port: PORT_1, client_reuse_addr: false, send_test_data: true }, *<I as TestIpExt>::TEST_ADDRS.remote_ip)]
7043 #[test_case(BindConfig { client_port: None, server_port: PORT_1, client_reuse_addr: true, send_test_data: true }, *<I as TestIpExt>::TEST_ADDRS.remote_ip)]
7044 #[test_case(BindConfig { client_port: Some(PORT_1), server_port: PORT_1, client_reuse_addr: true, send_test_data: true }, *<I as TestIpExt>::TEST_ADDRS.remote_ip)]
7045 fn bind_listen_connect_accept<I: TcpTestIpExt>(bind_config: BindConfig, listen_addr: I::Addr)
7046 where
7047 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7048 I,
7049 TcpBindingsCtx<FakeDeviceId>,
7050 SingleStackConverter = I::SingleStackConverter,
7051 DualStackConverter = I::DualStackConverter,
7052 >,
7053 {
7054 set_logger_for_test();
7055 let (mut net, client, _client_snd_end, accepted) =
7056 bind_listen_connect_accept_inner::<I>(listen_addr, bind_config, 0, 0.0);
7057
7058 let mut assert_counters =
7059 |context_name: &'static str,
7060 socket: &TcpSocketId<I, _, _>,
7061 expected: CounterExpectations,
7062 expected_without_socket: CounterExpectationsWithoutSocket,
7063 expected_per_socket: CounterExpectations| {
7064 net.with_context(context_name, |ctx| {
7065 let counters =
7066 CounterContext::<TcpCountersWithSocket<I>>::counters(&ctx.core_ctx);
7067 let counters_without_socket =
7068 CounterContext::<TcpCountersWithoutSocket<I>>::counters(&ctx.core_ctx);
7069 let counters_per_socket = ctx.core_ctx.per_resource_counters(socket);
7070 assert_eq!(expected, counters.as_ref().cast(), "{context_name}");
7071 assert_eq!(
7072 expected_without_socket,
7073 counters_without_socket.as_ref().cast(),
7074 "{context_name}"
7075 );
7076 assert_eq!(
7077 expected_per_socket,
7078 counters_per_socket.as_ref().cast(),
7079 "{context_name}"
7080 )
7081 })
7082 };
7083
7084 let local_with_socket_expects = || CounterExpectations {
7093 segments_sent: 4,
7094 received_segments_dispatched: 3,
7095 active_connection_openings: 1,
7096 syns_sent: 1,
7097 syns_received: 1,
7098 ..Default::default()
7099 };
7100 assert_counters(
7101 LOCAL,
7102 &client,
7103 local_with_socket_expects(),
7104 CounterExpectationsWithoutSocket { valid_segments_received: 3, ..Default::default() },
7105 local_with_socket_expects(),
7108 );
7109
7110 assert_counters(
7111 REMOTE,
7112 &accepted,
7113 CounterExpectations {
7114 segments_sent: 3,
7115 received_segments_dispatched: 4,
7116 passive_connection_openings: 1,
7117 syns_sent: 1,
7118 syns_received: 1,
7119 ..Default::default()
7120 },
7121 CounterExpectationsWithoutSocket { valid_segments_received: 4, ..Default::default() },
7122 CounterExpectations {
7127 segments_sent: 2,
7128 received_segments_dispatched: 3,
7129 ..Default::default()
7130 },
7131 );
7132 }
7133
7134 #[ip_test(I)]
7135 #[test_case(*<I as TestIpExt>::TEST_ADDRS.local_ip; "same addr")]
7136 #[test_case(I::UNSPECIFIED_ADDRESS; "any addr")]
7137 fn bind_conflict<I: TcpTestIpExt>(conflict_addr: I::Addr)
7138 where
7139 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7140 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7141 {
7142 set_logger_for_test();
7143 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
7144 I::TEST_ADDRS.local_ip,
7145 I::TEST_ADDRS.local_ip,
7146 ));
7147 let mut api = ctx.tcp_api::<I>();
7148 let s1 = api.create(Default::default());
7149 let s2 = api.create(Default::default());
7150
7151 api.bind(&s1, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
7152 .expect("first bind should succeed");
7153 assert_matches!(
7154 api.bind(&s2, SpecifiedAddr::new(conflict_addr).map(ZonedAddr::Unzoned), Some(PORT_1)),
7155 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
7156 );
7157 api.bind(&s2, SpecifiedAddr::new(conflict_addr).map(ZonedAddr::Unzoned), Some(PORT_2))
7158 .expect("able to rebind to a free address");
7159 }
7160
7161 #[ip_test(I)]
7162 #[test_case(NonZeroU16::new(u16::MAX).unwrap(), Ok(NonZeroU16::new(u16::MAX).unwrap()); "ephemeral available")]
7163 #[test_case(NonZeroU16::new(100).unwrap(), Err(LocalAddressError::FailedToAllocateLocalPort);
7164 "no ephemeral available")]
7165 fn bind_picked_port_all_others_taken<I: TcpTestIpExt>(
7166 available_port: NonZeroU16,
7167 expected_result: Result<NonZeroU16, LocalAddressError>,
7168 ) where
7169 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7170 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7171 {
7172 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
7173 I::TEST_ADDRS.local_ip,
7174 I::TEST_ADDRS.local_ip,
7175 ));
7176 let mut api = ctx.tcp_api::<I>();
7177 for port in 1..=u16::MAX {
7178 let port = NonZeroU16::new(port).unwrap();
7179 if port == available_port {
7180 continue;
7181 }
7182 let socket = api.create(Default::default());
7183
7184 api.bind(&socket, None, Some(port)).expect("uncontested bind");
7185 api.listen(&socket, NonZeroUsize::new(1).unwrap()).expect("can listen");
7186 }
7187
7188 let socket = api.create(Default::default());
7191 let result = api.bind(&socket, None, None).map(|()| {
7192 assert_matches!(
7193 api.get_info(&socket),
7194 SocketInfo::Bound(bound) => bound.port
7195 )
7196 });
7197 assert_eq!(result, expected_result.map_err(From::from));
7198
7199 api.close(socket);
7203 let socket = api.create(Default::default());
7204 let result =
7205 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), available_port);
7206 assert_eq!(result, Err(ConnectError::NoPort));
7207 }
7208
7209 #[ip_test(I)]
7210 fn bind_to_non_existent_address<I: TcpTestIpExt>()
7211 where
7212 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7213 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7214 {
7215 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
7216 I::TEST_ADDRS.local_ip,
7217 I::TEST_ADDRS.remote_ip,
7218 ));
7219 let mut api = ctx.tcp_api::<I>();
7220 let unbound = api.create(Default::default());
7221 assert_matches!(
7222 api.bind(&unbound, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), None),
7223 Err(BindError::LocalAddressError(LocalAddressError::AddressMismatch))
7224 );
7225
7226 assert_matches!(unbound.get().deref().socket_state, TcpSocketStateInner::Unbound(_));
7227 }
7228
7229 #[test]
7230 fn bind_addr_requires_zone() {
7231 let local_ip = LinkLocalAddr::new(net_ip_v6!("fe80::1")).unwrap().into_specified();
7232
7233 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(
7234 Ipv6::TEST_ADDRS.local_ip,
7235 Ipv6::TEST_ADDRS.remote_ip,
7236 ));
7237 let mut api = ctx.tcp_api::<Ipv6>();
7238 let unbound = api.create(Default::default());
7239 assert_matches!(
7240 api.bind(&unbound, Some(ZonedAddr::Unzoned(local_ip)), None),
7241 Err(BindError::LocalAddressError(LocalAddressError::Zone(
7242 ZonedAddressError::RequiredZoneNotProvided
7243 )))
7244 );
7245
7246 assert_matches!(unbound.get().deref().socket_state, TcpSocketStateInner::Unbound(_));
7247 }
7248
7249 #[test]
7250 fn connect_bound_requires_zone() {
7251 let ll_ip = LinkLocalAddr::new(net_ip_v6!("fe80::1")).unwrap().into_specified();
7252
7253 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(
7254 Ipv6::TEST_ADDRS.local_ip,
7255 Ipv6::TEST_ADDRS.remote_ip,
7256 ));
7257 let mut api = ctx.tcp_api::<Ipv6>();
7258 let socket = api.create(Default::default());
7259 api.bind(&socket, None, None).expect("bind succeeds");
7260 assert_matches!(
7261 api.connect(&socket, Some(ZonedAddr::Unzoned(ll_ip)), PORT_1,),
7262 Err(ConnectError::Zone(ZonedAddressError::RequiredZoneNotProvided))
7263 );
7264
7265 assert_matches!(
7266 socket.get().deref().socket_state,
7267 TcpSocketStateInner::Bound { .. } | TcpSocketStateInner::Connected { .. }
7268 );
7269 }
7270
7271 #[ip_test(I)]
7273 fn bind_listen_on_same_port_different_addrs<I: TcpTestIpExt>()
7274 where
7275 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7276 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7277 {
7278 set_logger_for_test();
7279
7280 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
7281 FakeDualStackIpSocketCtx::new(core::iter::once(FakeDeviceConfig {
7282 device: FakeDeviceId,
7283 local_ips: vec![I::TEST_ADDRS.local_ip, I::TEST_ADDRS.remote_ip],
7284 remote_ips: vec![],
7285 })),
7286 ));
7287 let mut api = ctx.tcp_api::<I>();
7288
7289 let s1 = api.create(Default::default());
7290 api.bind(&s1, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1)).unwrap();
7291 api.listen(&s1, NonZeroUsize::MIN).unwrap();
7292
7293 let s2 = api.create(Default::default());
7294 api.bind(&s2, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), Some(PORT_1)).unwrap();
7295 api.listen(&s2, NonZeroUsize::MIN).unwrap();
7296 }
7297
7298 #[ip_test(I)]
7299 #[test_case(None, None; "both any addr")]
7300 #[test_case(None, Some(<I as TestIpExt>::TEST_ADDRS.local_ip); "any then specified")]
7301 #[test_case(Some(<I as TestIpExt>::TEST_ADDRS.local_ip), None; "specified then any")]
7302 #[test_case(
7303 Some(<I as TestIpExt>::TEST_ADDRS.local_ip),
7304 Some(<I as TestIpExt>::TEST_ADDRS.local_ip);
7305 "both specified"
7306 )]
7307 fn cannot_listen_on_same_port_with_shadowed_address<I: TcpTestIpExt>(
7308 first: Option<SpecifiedAddr<I::Addr>>,
7309 second: Option<SpecifiedAddr<I::Addr>>,
7310 ) where
7311 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7312 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7313 {
7314 set_logger_for_test();
7315
7316 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
7317 FakeDualStackIpSocketCtx::new(core::iter::once(FakeDeviceConfig {
7318 device: FakeDeviceId,
7319 local_ips: vec![I::TEST_ADDRS.local_ip],
7320 remote_ips: vec![],
7321 })),
7322 ));
7323 let mut api = ctx.tcp_api::<I>();
7324
7325 let s1 = api.create(Default::default());
7326 api.set_reuseaddr(&s1, true).unwrap();
7327 api.bind(&s1, first.map(ZonedAddr::Unzoned), Some(PORT_1)).unwrap();
7328
7329 let s2 = api.create(Default::default());
7330 api.set_reuseaddr(&s2, true).unwrap();
7331 api.bind(&s2, second.map(ZonedAddr::Unzoned), Some(PORT_1)).unwrap();
7332
7333 api.listen(&s1, NonZeroUsize::MIN).unwrap();
7334 assert_eq!(api.listen(&s2, NonZeroUsize::MIN), Err(ListenError::ListenerExists));
7335 }
7336
7337 #[test]
7338 fn connect_unbound_picks_link_local_source_addr() {
7339 set_logger_for_test();
7340 let client_ip = SpecifiedAddr::new(net_ip_v6!("fe80::1")).unwrap();
7341 let server_ip = SpecifiedAddr::new(net_ip_v6!("1:2:3:4::")).unwrap();
7342 let mut net = FakeTcpNetworkSpec::new_network(
7343 [
7344 (LOCAL, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(client_ip, server_ip))),
7345 (REMOTE, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(server_ip, client_ip))),
7346 ],
7347 |net, meta| {
7348 if net == LOCAL {
7349 alloc::vec![(REMOTE, meta, None)]
7350 } else {
7351 alloc::vec![(LOCAL, meta, None)]
7352 }
7353 },
7354 );
7355 const PORT: NonZeroU16 = NonZeroU16::new(100).unwrap();
7356 let client_connection = net.with_context(LOCAL, |ctx| {
7357 let mut api = ctx.tcp_api();
7358 let socket: TcpSocketId<Ipv6, _, _> = api.create(Default::default());
7359 api.connect(&socket, Some(ZonedAddr::Unzoned(server_ip)), PORT).expect("can connect");
7360 socket
7361 });
7362 net.with_context(REMOTE, |ctx| {
7363 let mut api = ctx.tcp_api::<Ipv6>();
7364 let socket = api.create(Default::default());
7365 api.bind(&socket, None, Some(PORT)).expect("failed to bind the client socket");
7366 let _listener = api.listen(&socket, NonZeroUsize::MIN).expect("can listen");
7367 });
7368
7369 net.run_until_idle();
7371
7372 net.with_context(LOCAL, |ctx| {
7373 let mut api = ctx.tcp_api();
7374 assert_eq!(
7375 api.connect(&client_connection, Some(ZonedAddr::Unzoned(server_ip)), PORT),
7376 Ok(())
7377 );
7378
7379 let info = assert_matches!(
7380 api.get_info(&client_connection),
7381 SocketInfo::Connection(info) => info
7382 );
7383 let (local_ip, remote_ip) = assert_matches!(
7387 info,
7388 ConnectionInfo {
7389 local_addr: SocketAddr { ip: local_ip, port: _ },
7390 remote_addr: SocketAddr { ip: remote_ip, port: PORT },
7391 device: Some(FakeWeakDeviceId(FakeDeviceId))
7392 } => (local_ip, remote_ip)
7393 );
7394 assert_eq!(
7395 local_ip,
7396 ZonedAddr::Zoned(
7397 AddrAndZone::new(client_ip, FakeWeakDeviceId(FakeDeviceId)).unwrap()
7398 )
7399 );
7400 assert_eq!(remote_ip, ZonedAddr::Unzoned(server_ip));
7401
7402 assert_matches!(
7405 api.set_device(&client_connection, None),
7406 Err(SetDeviceError::ZoneChange)
7407 );
7408 });
7409 }
7410
7411 #[test]
7412 fn accept_connect_picks_link_local_addr() {
7413 set_logger_for_test();
7414 let server_ip = SpecifiedAddr::new(net_ip_v6!("fe80::1")).unwrap();
7415 let client_ip = SpecifiedAddr::new(net_ip_v6!("1:2:3:4::")).unwrap();
7416 let mut net = FakeTcpNetworkSpec::new_network(
7417 [
7418 (LOCAL, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(server_ip, client_ip))),
7419 (REMOTE, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(client_ip, server_ip))),
7420 ],
7421 |net, meta| {
7422 if net == LOCAL {
7423 alloc::vec![(REMOTE, meta, None)]
7424 } else {
7425 alloc::vec![(LOCAL, meta, None)]
7426 }
7427 },
7428 );
7429 const PORT: NonZeroU16 = NonZeroU16::new(100).unwrap();
7430 let server_listener = net.with_context(LOCAL, |ctx| {
7431 let mut api = ctx.tcp_api::<Ipv6>();
7432 let socket: TcpSocketId<Ipv6, _, _> = api.create(Default::default());
7433 api.bind(&socket, None, Some(PORT)).expect("failed to bind the client socket");
7434 api.listen(&socket, NonZeroUsize::MIN).expect("can listen");
7435 socket
7436 });
7437 let client_connection = net.with_context(REMOTE, |ctx| {
7438 let mut api = ctx.tcp_api::<Ipv6>();
7439 let socket = api.create(Default::default());
7440 api.connect(
7441 &socket,
7442 Some(ZonedAddr::Zoned(AddrAndZone::new(server_ip, FakeDeviceId).unwrap())),
7443 PORT,
7444 )
7445 .expect("failed to open a connection");
7446 socket
7447 });
7448
7449 net.run_until_idle();
7451
7452 net.with_context(LOCAL, |ctx| {
7453 let mut api = ctx.tcp_api();
7454 let (server_connection, _addr, _buffers) =
7455 api.accept(&server_listener).expect("connection is waiting");
7456
7457 let info = assert_matches!(
7458 api.get_info(&server_connection),
7459 SocketInfo::Connection(info) => info
7460 );
7461 let (local_ip, remote_ip) = assert_matches!(
7465 info,
7466 ConnectionInfo {
7467 local_addr: SocketAddr { ip: local_ip, port: PORT },
7468 remote_addr: SocketAddr { ip: remote_ip, port: _ },
7469 device: Some(FakeWeakDeviceId(FakeDeviceId))
7470 } => (local_ip, remote_ip)
7471 );
7472 assert_eq!(
7473 local_ip,
7474 ZonedAddr::Zoned(
7475 AddrAndZone::new(server_ip, FakeWeakDeviceId(FakeDeviceId)).unwrap()
7476 )
7477 );
7478 assert_eq!(remote_ip, ZonedAddr::Unzoned(client_ip));
7479
7480 assert_matches!(
7483 api.set_device(&server_connection, None),
7484 Err(SetDeviceError::ZoneChange)
7485 );
7486 });
7487 net.with_context(REMOTE, |ctx| {
7488 assert_eq!(
7489 ctx.tcp_api().connect(
7490 &client_connection,
7491 Some(ZonedAddr::Zoned(AddrAndZone::new(server_ip, FakeDeviceId).unwrap())),
7492 PORT,
7493 ),
7494 Ok(())
7495 );
7496 });
7497 }
7498
7499 #[ip_test(I)]
7502 fn connect_reset<I: TcpTestIpExt>()
7503 where
7504 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7505 I,
7506 TcpBindingsCtx<FakeDeviceId>,
7507 SingleStackConverter = I::SingleStackConverter,
7508 DualStackConverter = I::DualStackConverter,
7509 >,
7510 {
7511 set_logger_for_test();
7512 let mut net = new_test_net::<I>();
7513
7514 let client = net.with_context(LOCAL, |ctx| {
7515 let mut api = ctx.tcp_api::<I>();
7516 let conn = api.create(Default::default());
7517 api.bind(&conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
7518 .expect("failed to bind the client socket");
7519 api.connect(&conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
7520 .expect("failed to connect");
7521 conn
7522 });
7523
7524 let _: StepResult = net.step();
7526 net.collect_frames();
7528 assert_matches!(
7529 &net.iter_pending_frames().collect::<Vec<_>>()[..],
7530 [InstantAndData(_instant, PendingFrameData {
7531 dst_context: _,
7532 meta,
7533 frame,
7534 })] => {
7535 let mut buffer = Buf::new(frame, ..);
7536 match I::VERSION {
7537 IpVersion::V4 => {
7538 let meta = assert_matches!(meta, DualStackSendIpPacketMeta::V4(v4) => v4);
7539 let parsed = buffer.parse_with::<_, TcpSegment<_>>(
7540 TcpParseArgs::new(*meta.src_ip, *meta.dst_ip)
7541 ).expect("failed to parse");
7542 assert!(parsed.rst())
7543 }
7544 IpVersion::V6 => {
7545 let meta = assert_matches!(meta, DualStackSendIpPacketMeta::V6(v6) => v6);
7546 let parsed = buffer.parse_with::<_, TcpSegment<_>>(
7547 TcpParseArgs::new(*meta.src_ip, *meta.dst_ip)
7548 ).expect("failed to parse");
7549 assert!(parsed.rst())
7550 }
7551 }
7552 });
7553
7554 net.run_until_idle();
7555 assert_matches!(
7558 &client.get().deref().socket_state,
7559 TcpSocketStateInner::Connected { conn, .. } => {
7560 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
7561 assert_matches!(
7562 conn,
7563 Connection {
7564 accept_queue: None,
7565 state: State::Closed(Closed {
7566 reason: Some(ConnectionError::ConnectionRefused)
7567 }),
7568 ip_sock: _,
7569 defunct: false,
7570 soft_error: None,
7571 handshake_status: HandshakeStatus::Aborted,
7572 }
7573 );
7574 }
7575 );
7576 net.with_context(LOCAL, |ctx| {
7577 assert_matches!(
7578 ctx.tcp_api().connect(
7579 &client,
7580 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)),
7581 PORT_1
7582 ),
7583 Err(ConnectError::ConnectionError(ConnectionError::ConnectionRefused))
7584 );
7585 assert_eq!(ctx.tcp_api().get_socket_error(&client), None);
7587 });
7588 }
7589
7590 #[ip_test(I)]
7591 fn retransmission<I: TcpTestIpExt>()
7592 where
7593 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7594 I,
7595 TcpBindingsCtx<FakeDeviceId>,
7596 SingleStackConverter = I::SingleStackConverter,
7597 DualStackConverter = I::DualStackConverter,
7598 >,
7599 {
7600 set_logger_for_test();
7601 run_with_many_seeds(|seed| {
7602 let (_net, _client, _client_snd_end, _accepted) = bind_listen_connect_accept_inner::<I>(
7603 I::UNSPECIFIED_ADDRESS,
7604 BindConfig {
7605 client_port: None,
7606 server_port: PORT_1,
7607 client_reuse_addr: false,
7608 send_test_data: true,
7609 },
7610 seed,
7611 0.2,
7612 );
7613 });
7614 }
7615
7616 const LOCAL_PORT: NonZeroU16 = NonZeroU16::new(1845).unwrap();
7617
7618 #[ip_test(I)]
7619 fn listener_with_bound_device_conflict<I: TcpTestIpExt>()
7620 where
7621 TcpCoreCtx<MultipleDevicesId, TcpBindingsCtx<MultipleDevicesId>>:
7622 TcpContext<I, TcpBindingsCtx<MultipleDevicesId>>,
7623 {
7624 set_logger_for_test();
7625 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new_multiple_devices());
7626 let mut api = ctx.tcp_api::<I>();
7627 let sock_a = api.create(Default::default());
7628 assert_matches!(api.set_device(&sock_a, Some(MultipleDevicesId::A),), Ok(()));
7629 api.bind(&sock_a, None, Some(LOCAL_PORT)).expect("bind should succeed");
7630 api.listen(&sock_a, NonZeroUsize::new(10).unwrap()).expect("can listen");
7631
7632 let socket = api.create(Default::default());
7633 assert_matches!(
7636 api.bind(&socket, None, Some(LOCAL_PORT)),
7637 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
7638 );
7639
7640 assert_matches!(api.set_device(&socket, Some(MultipleDevicesId::B),), Ok(()));
7641 api.bind(&socket, None, Some(LOCAL_PORT)).expect("no conflict");
7642 }
7643
7644 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
7645 enum TestIp {
7646 A,
7647 B,
7648 }
7649
7650 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
7651 enum TestSocketConfig {
7652 AnyIp,
7653 AnyIpWithDev(MultipleDevicesId),
7654 IpOnly(TestIp),
7655 IpWithDev(MultipleDevicesId, TestIp),
7656 }
7657
7658 impl TestSocketConfig {
7659 fn create<'a, I: TcpTestIpExt>(
7660 self,
7661 api: &mut TcpApi<I, &'a mut TcpCtx<MultipleDevicesId>>,
7662 reuseaddr: bool,
7663 ) -> TcpApiSocketId<I, &'a mut TcpCtx<MultipleDevicesId>>
7664 where
7665 TcpCoreCtx<MultipleDevicesId, TcpBindingsCtx<MultipleDevicesId>>:
7666 TcpContext<I, TcpBindingsCtx<MultipleDevicesId>>,
7667 {
7668 let socket = api.create(Default::default());
7669 if reuseaddr {
7670 api.set_reuseaddr(&socket, true).unwrap();
7671 }
7672 match self {
7673 TestSocketConfig::AnyIp | TestSocketConfig::IpOnly(_) => {}
7674 TestSocketConfig::AnyIpWithDev(device) | TestSocketConfig::IpWithDev(device, _) => {
7675 assert_matches!(api.set_device(&socket, Some(device)), Ok(()));
7676 }
7677 }
7678 socket
7679 }
7680
7681 fn get_bind_addr<I: TcpTestIpExt>(
7682 self,
7683 ) -> Option<ZonedAddr<SpecifiedAddr<I::Addr>, MultipleDevicesId>> {
7684 match self {
7685 TestSocketConfig::AnyIp | TestSocketConfig::AnyIpWithDev(_) => None,
7686 TestSocketConfig::IpOnly(ip) | TestSocketConfig::IpWithDev(_, ip) => {
7687 let addr = match ip {
7688 TestIp::A => I::TEST_ADDRS.local_ip,
7689 TestIp::B => I::TEST_ADDRS.remote_ip,
7690 };
7691 Some(ZonedAddr::Unzoned(addr))
7692 }
7693 }
7694 }
7695
7696 fn create_and_bind<'a, I: TcpTestIpExt>(
7697 self,
7698 api: &mut TcpApi<I, &'a mut TcpCtx<MultipleDevicesId>>,
7699 port: NonZeroU16,
7700 reuseaddr: bool,
7701 ) -> TcpApiSocketId<I, &'a mut TcpCtx<MultipleDevicesId>>
7702 where
7703 TcpCoreCtx<MultipleDevicesId, TcpBindingsCtx<MultipleDevicesId>>:
7704 TcpContext<I, TcpBindingsCtx<MultipleDevicesId>>,
7705 {
7706 let socket = self.create(api, reuseaddr);
7707 api.bind(&socket, self.get_bind_addr::<I>(), Some(port)).expect("bind should succeed");
7708 socket
7709 }
7710 }
7711
7712 #[ip_test(I)]
7713 #[test_case(TestSocketConfig::AnyIp,
7714 TestSocketConfig::AnyIp,
7715 true; "both_wildcard")]
7716 #[test_case(TestSocketConfig::AnyIp,
7717 TestSocketConfig::AnyIpWithDev(MultipleDevicesId::A),
7718 true; "wildcard_then_wildcard_dev_a")]
7719 #[test_case(TestSocketConfig::AnyIp,
7720 TestSocketConfig::IpOnly(TestIp::A),
7721 true; "wildcard_vs_specific")]
7722 #[test_case(TestSocketConfig::AnyIp,
7723 TestSocketConfig::IpWithDev(MultipleDevicesId::A, TestIp::A),
7724 true; "wildcard_then_specific_dev_a")]
7725 #[test_case(TestSocketConfig::AnyIpWithDev(MultipleDevicesId::A),
7726 TestSocketConfig::AnyIp,
7727 true; "wildcard_dev_a_then_wildcard")]
7728 #[test_case(TestSocketConfig::AnyIpWithDev(MultipleDevicesId::A),
7729 TestSocketConfig::IpOnly(TestIp::A),
7730 true; "any_dev_a_then_ip_only")]
7731 #[test_case(TestSocketConfig::IpOnly(TestIp::A),
7732 TestSocketConfig::AnyIpWithDev(MultipleDevicesId::A),
7733 true; "ip_only_then_any_dev_a")]
7734 #[test_case(TestSocketConfig::IpOnly(TestIp::A),
7735 TestSocketConfig::IpOnly(TestIp::A),
7736 true; "same_ip")]
7737 #[test_case(TestSocketConfig::IpWithDev(MultipleDevicesId::A, TestIp::A),
7738 TestSocketConfig::AnyIp,
7739 true; "specific_dev_a_then_wildcard")]
7740 #[test_case(TestSocketConfig::IpOnly(TestIp::A),
7741 TestSocketConfig::AnyIp,
7742 true; "specific_vs_wildcard_diff_ip")]
7743 #[test_case(TestSocketConfig::AnyIpWithDev(MultipleDevicesId::A),
7745 TestSocketConfig::AnyIpWithDev(MultipleDevicesId::B),
7746 false; "different_devices_wildcard")]
7747 #[test_case(TestSocketConfig::IpWithDev(MultipleDevicesId::A, TestIp::A),
7748 TestSocketConfig::IpWithDev(MultipleDevicesId::B, TestIp::A),
7749 false; "different_devices_specific")]
7750 #[test_case(TestSocketConfig::IpOnly(TestIp::A),
7752 TestSocketConfig::IpOnly(TestIp::B),
7753 false; "different_ips")]
7754 #[test_case(TestSocketConfig::IpWithDev(MultipleDevicesId::A, TestIp::A),
7755 TestSocketConfig::IpWithDev(MultipleDevicesId::A, TestIp::B),
7756 false; "different_ips_same_device")]
7757 #[test_case(TestSocketConfig::IpWithDev(MultipleDevicesId::A, TestIp::A),
7758 TestSocketConfig::IpOnly(TestIp::B),
7759 false; "different_ips_overlapping_device")]
7760 fn test_address_conflict_detection<I: TcpTestIpExt>(
7761 sock_a_config: TestSocketConfig,
7762 sock_b_config: TestSocketConfig,
7763 have_conflict: bool,
7764 ) where
7765 TcpCoreCtx<MultipleDevicesId, TcpBindingsCtx<MultipleDevicesId>>:
7766 TcpContext<I, TcpBindingsCtx<MultipleDevicesId>>,
7767 {
7768 set_logger_for_test();
7769
7770 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new_multiple_devices());
7771 let mut api = ctx.tcp_api::<I>();
7772
7773 {
7775 let sock_a = sock_a_config.create_and_bind(&mut api, LOCAL_PORT, false);
7776
7777 let sock_b = sock_b_config.create(&mut api, false);
7778 let res = api.bind(&sock_b, sock_b_config.get_bind_addr::<I>(), Some(LOCAL_PORT));
7779 if have_conflict {
7780 assert_matches!(
7781 res,
7782 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
7783 );
7784 } else {
7785 res.expect("bind should succeed");
7786 }
7787
7788 api.close(sock_a);
7789 api.close(sock_b);
7790 }
7791
7792 {
7795 let sock_a = sock_a_config.create_and_bind(&mut api, LOCAL_PORT, false);
7796 api.listen(&sock_a, NonZeroUsize::new(10).unwrap()).expect("listen should succeed");
7797
7798 let sock_b = sock_b_config.create(&mut api, false);
7799 let res = api.bind(&sock_b, sock_b_config.get_bind_addr::<I>(), Some(LOCAL_PORT));
7800 if have_conflict {
7801 assert_matches!(
7802 res,
7803 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
7804 );
7805 } else {
7806 res.expect("bind should succeed");
7807 }
7808
7809 api.close(sock_a);
7810 api.close(sock_b);
7811 }
7812
7813 {
7816 let sock_a = sock_a_config.create_and_bind(&mut api, LOCAL_PORT, true);
7817 api.listen(&sock_a, NonZeroUsize::new(10).unwrap()).expect("listen should succeed");
7818
7819 let sock_b = sock_b_config.create(&mut api, true);
7820 let res = api.bind(&sock_b, sock_b_config.get_bind_addr::<I>(), Some(LOCAL_PORT));
7821 if have_conflict {
7822 assert_matches!(
7823 res,
7824 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
7825 );
7826 } else {
7827 res.expect("bind should succeed");
7828 }
7829
7830 api.close(sock_a);
7831 api.close(sock_b);
7832 }
7833
7834 {
7838 let sock_a = sock_a_config.create_and_bind(&mut api, LOCAL_PORT, true);
7839 let sock_b = sock_b_config.create_and_bind(&mut api, LOCAL_PORT, true);
7840
7841 api.listen(&sock_a, NonZeroUsize::new(10).unwrap())
7843 .expect("first listen should succeed");
7844
7845 let res = api.listen(&sock_b, NonZeroUsize::new(10).unwrap());
7847 if have_conflict {
7848 assert_matches!(res, Err(ListenError::ListenerExists));
7849 } else {
7850 res.expect("second listen should succeed");
7851 }
7852
7853 api.close(sock_a);
7854 api.close(sock_b);
7855 }
7856
7857 {
7861 let sock_a = sock_a_config.create_and_bind(&mut api, LOCAL_PORT, true);
7862 let sock_b = sock_b_config.create_and_bind(&mut api, LOCAL_PORT, true);
7863
7864 let res_a = api.set_reuseaddr(&sock_a, false);
7866 if have_conflict {
7867 assert_matches!(res_a, Err(SetReuseAddrError::AddrInUse));
7868 } else {
7869 res_a.expect("reset sock_a should succeed");
7870 }
7871
7872 let res_b = api.set_reuseaddr(&sock_b, false);
7874 if have_conflict {
7875 assert_matches!(res_b, Err(SetReuseAddrError::AddrInUse));
7876 } else {
7877 res_b.expect("reset sock_b should succeed");
7878 }
7879
7880 api.close(sock_a);
7881 api.close(sock_b);
7882 }
7883 }
7884
7885 #[test_case(None)]
7886 #[test_case(Some(MultipleDevicesId::B); "other")]
7887 fn set_bound_device_listener_on_zoned_addr(set_device: Option<MultipleDevicesId>) {
7888 set_logger_for_test();
7889 let ll_addr = LinkLocalAddr::new(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network()).unwrap();
7890
7891 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
7892 FakeDualStackIpSocketCtx::new(MultipleDevicesId::all().into_iter().map(|device| {
7893 FakeDeviceConfig {
7894 device,
7895 local_ips: vec![ll_addr.into_specified()],
7896 remote_ips: vec![ll_addr.into_specified()],
7897 }
7898 })),
7899 ));
7900 let mut api = ctx.tcp_api::<Ipv6>();
7901 let socket = api.create(Default::default());
7902 api.bind(
7903 &socket,
7904 Some(ZonedAddr::Zoned(
7905 AddrAndZone::new(ll_addr.into_specified(), MultipleDevicesId::A).unwrap(),
7906 )),
7907 Some(LOCAL_PORT),
7908 )
7909 .expect("bind should succeed");
7910
7911 assert_matches!(api.set_device(&socket, set_device), Err(SetDeviceError::ZoneChange));
7912 }
7913
7914 #[test_case(None)]
7915 #[test_case(Some(MultipleDevicesId::B); "other")]
7916 fn set_bound_device_connected_to_zoned_addr(set_device: Option<MultipleDevicesId>) {
7917 set_logger_for_test();
7918 let ll_addr = LinkLocalAddr::new(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network()).unwrap();
7919
7920 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
7921 FakeDualStackIpSocketCtx::new(MultipleDevicesId::all().into_iter().map(|device| {
7922 FakeDeviceConfig {
7923 device,
7924 local_ips: vec![ll_addr.into_specified()],
7925 remote_ips: vec![ll_addr.into_specified()],
7926 }
7927 })),
7928 ));
7929 let mut api = ctx.tcp_api::<Ipv6>();
7930 let socket = api.create(Default::default());
7931 api.connect(
7932 &socket,
7933 Some(ZonedAddr::Zoned(
7934 AddrAndZone::new(ll_addr.into_specified(), MultipleDevicesId::A).unwrap(),
7935 )),
7936 LOCAL_PORT,
7937 )
7938 .expect("connect should succeed");
7939
7940 assert_matches!(api.set_device(&socket, set_device), Err(SetDeviceError::ZoneChange));
7941 }
7942
7943 #[ip_test(I)]
7945 fn set_bound_to_device_after_connect_fails<I: TcpTestIpExt>()
7946 where
7947 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7948 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7949 {
7950 set_logger_for_test();
7951 let mut net = new_test_net::<I>();
7952 let socket = net.with_context(LOCAL, |ctx| {
7953 let mut api = ctx.tcp_api::<I>();
7954 let socket = api.create(Default::default());
7955 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
7956 .expect("bind should succeed");
7957 socket
7958 });
7959
7960 net.run_until_idle();
7961
7962 net.with_context(LOCAL, |ctx| {
7963 let mut api = ctx.tcp_api::<I>();
7964 assert_matches!(api.set_device(&socket, Some(FakeDeviceId)), Ok(()));
7965 let ConnectionInfo { local_addr: _, remote_addr, device } =
7966 assert_matches!(api.get_info(&socket), SocketInfo::Connection(c) => c);
7967 assert_eq!(
7968 remote_addr,
7969 SocketAddr { ip: ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip), port: PORT_1 }
7970 );
7971 assert_eq!(device, Some(FakeWeakDeviceId(FakeDeviceId)));
7972 api.close(socket);
7973 });
7974 }
7975
7976 #[test]
7977 fn set_device_dual_stack_listener() {
7978 set_logger_for_test();
7979 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new_multiple_devices());
7980 let mut api = ctx.tcp_api::<Ipv6>();
7981 let socket = api.create(Default::default());
7982 api.bind(&socket, None, Some(LOCAL_PORT)).expect("bind should succeed");
7983 assert_matches!(api.set_device(&socket, Some(MultipleDevicesId::A)), Ok(()));
7984 let info = api.get_info(&socket);
7985 let device = assert_matches!(info, SocketInfo::Bound(BoundInfo { device, .. }) => device);
7986 assert_eq!(device, Some(MultipleDevicesId::A.downgrade()));
7987 }
7988
7989 #[ip_test(I)]
7990 fn set_device_unbound_connect<I: TcpTestIpExt>()
7991 where
7992 TcpCoreCtx<MultipleDevicesId, TcpBindingsCtx<MultipleDevicesId>>:
7993 TcpContext<I, TcpBindingsCtx<MultipleDevicesId>>,
7994 {
7995 set_logger_for_test();
7996 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new_multiple_devices());
7997 let mut api = ctx.tcp_api::<I>();
7998 let socket = api.create(Default::default());
7999 assert_matches!(api.set_device(&socket, Some(MultipleDevicesId::A)), Ok(()));
8000 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
8001 .expect("connect should succeed");
8002 let info = api.get_info(&socket);
8003 let device =
8004 assert_matches!(info, SocketInfo::Connection(ConnectionInfo { device, .. }) => device);
8005 assert_eq!(device, Some(MultipleDevicesId::A.downgrade()));
8006
8007 let socket_c = api.create(Default::default());
8009 assert_matches!(api.set_device(&socket_c, Some(MultipleDevicesId::C)), Ok(()));
8010 assert_matches!(
8011 api.connect(&socket_c, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1),
8012 Err(ConnectError::NoRoute)
8013 );
8014 }
8015
8016 #[test]
8017 fn set_device_unbound_dual_stack_connect() {
8018 set_logger_for_test();
8019 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new_multiple_devices());
8020 let mut api = ctx.tcp_api::<Ipv6>();
8021 let socket = api.create(Default::default());
8022 assert_matches!(api.set_device(&socket, Some(MultipleDevicesId::A)), Ok(()));
8023 api.connect(
8024 &socket,
8025 Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.remote_ip).to_ipv6_mapped())),
8026 PORT_1,
8027 )
8028 .expect("connect should succeed");
8029 let info = api.get_info(&socket);
8030 let device =
8031 assert_matches!(info, SocketInfo::Connection(ConnectionInfo { device, .. }) => device);
8032 assert_eq!(device, Some(MultipleDevicesId::A.downgrade()));
8033
8034 let socket_c = api.create(Default::default());
8036 assert_matches!(api.set_device(&socket_c, Some(MultipleDevicesId::C)), Ok(()));
8037 assert_matches!(
8038 api.connect(
8039 &socket_c,
8040 Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.remote_ip).to_ipv6_mapped())),
8041 PORT_1,
8042 ),
8043 Err(ConnectError::NoRoute)
8044 );
8045 }
8046
8047 #[ip_test(I)]
8048 #[test_case(*<I as TestIpExt>::TEST_ADDRS.local_ip, true; "specified bound")]
8049 #[test_case(I::UNSPECIFIED_ADDRESS, true; "unspecified bound")]
8050 #[test_case(*<I as TestIpExt>::TEST_ADDRS.local_ip, false; "specified listener")]
8051 #[test_case(I::UNSPECIFIED_ADDRESS, false; "unspecified listener")]
8052 fn bound_socket_info<I: TcpTestIpExt>(ip_addr: I::Addr, listen: bool)
8053 where
8054 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8055 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8056 {
8057 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8058 I::TEST_ADDRS.local_ip,
8059 I::TEST_ADDRS.remote_ip,
8060 ));
8061 let mut api = ctx.tcp_api::<I>();
8062 let socket = api.create(Default::default());
8063
8064 let (addr, port) = (SpecifiedAddr::new(ip_addr).map(ZonedAddr::Unzoned), PORT_1);
8065
8066 api.bind(&socket, addr, Some(port)).expect("bind should succeed");
8067 if listen {
8068 api.listen(&socket, NonZeroUsize::new(25).unwrap()).expect("can listen");
8069 }
8070 let info = api.get_info(&socket);
8071 assert_eq!(
8072 info,
8073 SocketInfo::Bound(BoundInfo {
8074 addr: addr.map(|a| a.map_zone(FakeWeakDeviceId)),
8075 port,
8076 device: None
8077 })
8078 );
8079 }
8080
8081 #[ip_test(I)]
8082 fn connection_info<I: TcpTestIpExt>()
8083 where
8084 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8085 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8086 {
8087 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8088 I::TEST_ADDRS.local_ip,
8089 I::TEST_ADDRS.remote_ip,
8090 ));
8091 let mut api = ctx.tcp_api::<I>();
8092 let local = SocketAddr { ip: ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip), port: PORT_1 };
8093 let remote = SocketAddr { ip: ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip), port: PORT_2 };
8094
8095 let socket = api.create(Default::default());
8096 api.bind(&socket, Some(local.ip), Some(local.port)).expect("bind should succeed");
8097
8098 api.connect(&socket, Some(remote.ip), remote.port).expect("connect should succeed");
8099
8100 assert_eq!(
8101 api.get_info(&socket),
8102 SocketInfo::Connection(ConnectionInfo {
8103 local_addr: local.map_zone(FakeWeakDeviceId),
8104 remote_addr: remote.map_zone(FakeWeakDeviceId),
8105 device: None,
8106 }),
8107 );
8108 }
8109
8110 #[test_case(Ipv6::get_multicast_addr(1).into(), PhantomData::<Ipv6>)]
8111 #[test_case(Ipv4::get_multicast_addr(1).into(), PhantomData::<Ipv4>)]
8112 #[test_case(Ipv4::LIMITED_BROADCAST_ADDRESS, PhantomData::<Ipv4>)]
8113 fn non_unicast_ip_bind<I>(local_ip: SpecifiedAddr<I::Addr>, _ip: PhantomData<I>)
8114 where
8115 I: TcpTestIpExt + Ip,
8116 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8117 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8118 {
8119 let mut ctx =
8120 TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(local_ip, I::TEST_ADDRS.remote_ip));
8121 let mut api = ctx.tcp_api::<I>();
8122 let local = SocketAddr { ip: ZonedAddr::Unzoned(local_ip), port: PORT_1 };
8123 let socket = api.create(Default::default());
8124
8125 assert_eq!(
8126 api.bind(&socket, Some(local.ip), Some(local.port))
8127 .expect_err("bind should fail for non-unicast address"),
8128 BindError::LocalAddressError(LocalAddressError::CannotBindToAddress)
8129 );
8130 }
8131
8132 #[test_case(Ipv6::get_multicast_addr(1).into(), PhantomData::<Ipv6>)]
8133 #[test_case(Ipv4::get_multicast_addr(1).into(), PhantomData::<Ipv4>)]
8134 #[test_case(Ipv4::LIMITED_BROADCAST_ADDRESS, PhantomData::<Ipv4>)]
8135 fn non_unicast_ip_peer<I>(remote_ip: SpecifiedAddr<I::Addr>, _ip: PhantomData<I>)
8136 where
8137 I: TcpTestIpExt + Ip,
8138 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8139 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8140 {
8141 let mut ctx =
8142 TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(I::TEST_ADDRS.local_ip, remote_ip));
8143 let mut api = ctx.tcp_api::<I>();
8144 let remote = SocketAddr { ip: ZonedAddr::Unzoned(remote_ip), port: PORT_2 };
8145 let socket = api.create(Default::default());
8146
8147 assert_eq!(
8148 api.connect(&socket, Some(remote.ip), remote.port)
8149 .expect_err("connect should fail for non-unicast peer"),
8150 ConnectError::NoRoute
8151 );
8152 }
8153
8154 #[test_case(true; "any")]
8155 #[test_case(false; "link local")]
8156 fn accepted_connection_info_zone(listen_any: bool) {
8157 set_logger_for_test();
8158 let client_ip = SpecifiedAddr::new(net_ip_v6!("fe80::1")).unwrap();
8159 let server_ip = SpecifiedAddr::new(net_ip_v6!("fe80::2")).unwrap();
8160 let mut net = FakeTcpNetworkSpec::new_network(
8161 [
8162 (LOCAL, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(server_ip, client_ip))),
8163 (REMOTE, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(client_ip, server_ip))),
8164 ],
8165 move |net, meta: DualStackSendIpPacketMeta<_>| {
8166 if net == LOCAL {
8167 alloc::vec![(REMOTE, meta, None)]
8168 } else {
8169 alloc::vec![(LOCAL, meta, None)]
8170 }
8171 },
8172 );
8173
8174 let local_server = net.with_context(LOCAL, |ctx| {
8175 let mut api = ctx.tcp_api::<Ipv6>();
8176 let socket = api.create(Default::default());
8177 let device = FakeDeviceId;
8178 let bind_addr = match listen_any {
8179 true => None,
8180 false => Some(ZonedAddr::Zoned(AddrAndZone::new(server_ip, device).unwrap())),
8181 };
8182
8183 api.bind(&socket, bind_addr, Some(PORT_1)).expect("failed to bind the client socket");
8184 api.listen(&socket, NonZeroUsize::new(1).unwrap()).expect("can listen");
8185 socket
8186 });
8187
8188 let _remote_client = net.with_context(REMOTE, |ctx| {
8189 let mut api = ctx.tcp_api::<Ipv6>();
8190 let socket = api.create(Default::default());
8191 let device = FakeDeviceId;
8192 api.connect(
8193 &socket,
8194 Some(ZonedAddr::Zoned(AddrAndZone::new(server_ip, device).unwrap())),
8195 PORT_1,
8196 )
8197 .expect("failed to connect");
8198 socket
8199 });
8200
8201 net.run_until_idle();
8202
8203 let ConnectionInfo { remote_addr, local_addr, device } = net.with_context(LOCAL, |ctx| {
8204 let mut api = ctx.tcp_api();
8205 let (server_conn, _addr, _buffers) =
8206 api.accept(&local_server).expect("connection is available");
8207 assert_matches!(
8208 api.get_info(&server_conn),
8209 SocketInfo::Connection(info) => info
8210 )
8211 });
8212
8213 let device = assert_matches!(device, Some(device) => device);
8214 assert_eq!(
8215 local_addr,
8216 SocketAddr {
8217 ip: ZonedAddr::Zoned(AddrAndZone::new(server_ip, device).unwrap()),
8218 port: PORT_1
8219 }
8220 );
8221 let SocketAddr { ip: remote_ip, port: _ } = remote_addr;
8222 assert_eq!(remote_ip, ZonedAddr::Zoned(AddrAndZone::new(client_ip, device).unwrap()));
8223 }
8224
8225 #[test]
8226 fn bound_connection_info_zoned_addrs() {
8227 let local_ip = LinkLocalAddr::new(net_ip_v6!("fe80::1")).unwrap().into_specified();
8228 let remote_ip = LinkLocalAddr::new(net_ip_v6!("fe80::2")).unwrap().into_specified();
8229 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(local_ip, remote_ip));
8230
8231 let local_addr = SocketAddr {
8232 ip: ZonedAddr::Zoned(AddrAndZone::new(local_ip, FakeDeviceId).unwrap()),
8233 port: PORT_1,
8234 };
8235 let remote_addr = SocketAddr {
8236 ip: ZonedAddr::Zoned(AddrAndZone::new(remote_ip, FakeDeviceId).unwrap()),
8237 port: PORT_2,
8238 };
8239 let mut api = ctx.tcp_api::<Ipv6>();
8240
8241 let socket = api.create(Default::default());
8242 api.bind(&socket, Some(local_addr.ip), Some(local_addr.port)).expect("bind should succeed");
8243
8244 assert_eq!(
8245 api.get_info(&socket),
8246 SocketInfo::Bound(BoundInfo {
8247 addr: Some(local_addr.ip.map_zone(FakeWeakDeviceId)),
8248 port: local_addr.port,
8249 device: Some(FakeWeakDeviceId(FakeDeviceId))
8250 })
8251 );
8252
8253 api.connect(&socket, Some(remote_addr.ip), remote_addr.port)
8254 .expect("connect should succeed");
8255
8256 assert_eq!(
8257 api.get_info(&socket),
8258 SocketInfo::Connection(ConnectionInfo {
8259 local_addr: local_addr.map_zone(FakeWeakDeviceId),
8260 remote_addr: remote_addr.map_zone(FakeWeakDeviceId),
8261 device: Some(FakeWeakDeviceId(FakeDeviceId))
8262 })
8263 );
8264 }
8265
8266 #[ip_test(I)]
8267 #[test_case(true, 2 * MSL; "peer calls close")]
8271 #[test_case(false, DEFAULT_FIN_WAIT2_TIMEOUT; "peer doesn't call close")]
8274 fn connection_close_peer_calls_close<I: TcpTestIpExt>(
8275 peer_calls_close: bool,
8276 expected_time_to_close: Duration,
8277 ) where
8278 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
8279 I,
8280 TcpBindingsCtx<FakeDeviceId>,
8281 SingleStackConverter = I::SingleStackConverter,
8282 DualStackConverter = I::DualStackConverter,
8283 >,
8284 {
8285 set_logger_for_test();
8286 let (mut net, local, _local_snd_end, remote) = bind_listen_connect_accept_inner::<I>(
8287 I::UNSPECIFIED_ADDRESS,
8288 BindConfig {
8289 client_port: None,
8290 server_port: PORT_1,
8291 client_reuse_addr: false,
8292 send_test_data: false,
8293 },
8294 0,
8295 0.0,
8296 );
8297
8298 let weak_local = local.downgrade();
8299 let close_called = net.with_context(LOCAL, |ctx| {
8300 ctx.tcp_api().close(local);
8301 ctx.bindings_ctx.now()
8302 });
8303
8304 while {
8305 assert!(!net.step().is_idle());
8306 let is_fin_wait_2 = {
8307 let local = weak_local.upgrade().unwrap();
8308 let state = local.get();
8309 let state = assert_matches!(
8310 &state.deref().socket_state,
8311 TcpSocketStateInner::Connected { conn, .. } => {
8312 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8313 assert_matches!(
8314 conn,
8315 Connection {
8316 state,
8317 ..
8318 } => state
8319 )
8320 }
8321 );
8322 matches!(state, State::FinWait2(_))
8323 };
8324 !is_fin_wait_2
8325 } {}
8326
8327 let weak_remote = remote.downgrade();
8328 if peer_calls_close {
8329 net.with_context(REMOTE, |ctx| {
8330 ctx.tcp_api().close(remote);
8331 });
8332 }
8333
8334 net.run_until_idle();
8335
8336 net.with_context(LOCAL, |TcpCtx { core_ctx: _, bindings_ctx }| {
8337 assert_eq!(
8338 bindings_ctx.now().checked_duration_since(close_called).unwrap(),
8339 expected_time_to_close
8340 );
8341 assert_eq!(weak_local.upgrade(), None);
8342 });
8343 if peer_calls_close {
8344 assert_eq!(weak_remote.upgrade(), None);
8345 }
8346 }
8347
8348 #[ip_test(I)]
8349 fn connection_shutdown_then_close_peer_doesnt_call_close<I: TcpTestIpExt>()
8350 where
8351 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
8352 I,
8353 TcpBindingsCtx<FakeDeviceId>,
8354 SingleStackConverter = I::SingleStackConverter,
8355 DualStackConverter = I::DualStackConverter,
8356 >,
8357 {
8358 set_logger_for_test();
8359 let (mut net, local, _local_snd_end, _remote) = bind_listen_connect_accept_inner::<I>(
8360 I::UNSPECIFIED_ADDRESS,
8361 BindConfig {
8362 client_port: None,
8363 server_port: PORT_1,
8364 client_reuse_addr: false,
8365 send_test_data: false,
8366 },
8367 0,
8368 0.0,
8369 );
8370 net.with_context(LOCAL, |ctx| {
8371 assert_eq!(ctx.tcp_api().shutdown(&local, ShutdownType::Send), Ok(true));
8372 });
8373 loop {
8374 assert!(!net.step().is_idle());
8375 let is_fin_wait_2 = {
8376 let state = local.get();
8377 let state = assert_matches!(
8378 &state.deref().socket_state,
8379 TcpSocketStateInner::Connected { conn, .. } => {
8380 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8381 assert_matches!(
8382 conn,
8383 Connection {
8384 state, ..
8385 } => state
8386 )});
8387 matches!(state, State::FinWait2(_))
8388 };
8389 if is_fin_wait_2 {
8390 break;
8391 }
8392 }
8393
8394 let weak_local = local.downgrade();
8395 net.with_context(LOCAL, |ctx| {
8396 ctx.tcp_api().close(local);
8397 });
8398 net.run_until_idle();
8399 assert_eq!(weak_local.upgrade(), None);
8400 }
8401
8402 #[ip_test(I)]
8403 fn connection_shutdown_then_close<I: TcpTestIpExt>()
8404 where
8405 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
8406 I,
8407 TcpBindingsCtx<FakeDeviceId>,
8408 SingleStackConverter = I::SingleStackConverter,
8409 DualStackConverter = I::DualStackConverter,
8410 >,
8411 {
8412 set_logger_for_test();
8413 let (mut net, local, _local_snd_end, remote) = bind_listen_connect_accept_inner::<I>(
8414 I::UNSPECIFIED_ADDRESS,
8415 BindConfig {
8416 client_port: None,
8417 server_port: PORT_1,
8418 client_reuse_addr: false,
8419 send_test_data: false,
8420 },
8421 0,
8422 0.0,
8423 );
8424
8425 for (name, id) in [(LOCAL, &local), (REMOTE, &remote)] {
8426 net.with_context(name, |ctx| {
8427 let mut api = ctx.tcp_api();
8428 assert_eq!(
8429 api.shutdown(id,ShutdownType::Send),
8430 Ok(true)
8431 );
8432 assert_matches!(
8433 &id.get().deref().socket_state,
8434 TcpSocketStateInner::Connected { conn, .. } => {
8435 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8436 assert_matches!(
8437 conn,
8438 Connection {
8439 state: State::FinWait1(_),
8440 ..
8441 }
8442 );
8443 });
8444 assert_eq!(
8445 api.shutdown(id,ShutdownType::Send),
8446 Ok(true)
8447 );
8448 });
8449 }
8450 net.run_until_idle();
8451 for (name, id) in [(LOCAL, local), (REMOTE, remote)] {
8452 net.with_context(name, |ctx| {
8453 assert_matches!(
8454 &id.get().deref().socket_state,
8455 TcpSocketStateInner::Connected { conn, .. } => {
8456 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8457 assert_matches!(
8458 conn,
8459 Connection {
8460 state: State::Closed(_),
8461 ..
8462 }
8463 );
8464 });
8465 let weak_id = id.downgrade();
8466 ctx.tcp_api().close(id);
8467 assert_eq!(weak_id.upgrade(), None)
8468 });
8469 }
8470 }
8471
8472 #[ip_test(I)]
8473 fn remove_unbound<I: TcpTestIpExt>()
8474 where
8475 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8476 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8477 {
8478 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8479 I::TEST_ADDRS.local_ip,
8480 I::TEST_ADDRS.remote_ip,
8481 ));
8482 let mut api = ctx.tcp_api::<I>();
8483 let unbound = api.create(Default::default());
8484 let weak_unbound = unbound.downgrade();
8485 api.close(unbound);
8486 assert_eq!(weak_unbound.upgrade(), None);
8487 }
8488
8489 #[ip_test(I)]
8490 fn remove_bound<I: TcpTestIpExt>()
8491 where
8492 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8493 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8494 {
8495 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8496 I::TEST_ADDRS.local_ip,
8497 I::TEST_ADDRS.remote_ip,
8498 ));
8499 let mut api = ctx.tcp_api::<I>();
8500 let socket = api.create(Default::default());
8501 api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), None)
8502 .expect("bind should succeed");
8503 let weak_socket = socket.downgrade();
8504 api.close(socket);
8505 assert_eq!(weak_socket.upgrade(), None);
8506 }
8507
8508 #[ip_test(I)]
8509 fn shutdown_listener<I: TcpTestIpExt>()
8510 where
8511 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
8512 I,
8513 TcpBindingsCtx<FakeDeviceId>,
8514 SingleStackConverter = I::SingleStackConverter,
8515 DualStackConverter = I::DualStackConverter,
8516 >,
8517 {
8518 set_logger_for_test();
8519 let mut net = new_test_net::<I>();
8520 let local_listener = net.with_context(LOCAL, |ctx| {
8521 let mut api = ctx.tcp_api::<I>();
8522 let socket = api.create(Default::default());
8523 api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
8524 .expect("bind should succeed");
8525 api.listen(&socket, NonZeroUsize::new(5).unwrap()).expect("can listen");
8526 socket
8527 });
8528
8529 let remote_connection = net.with_context(REMOTE, |ctx| {
8530 let mut api = ctx.tcp_api::<I>();
8531 let socket = api.create(Default::default());
8532 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), PORT_1)
8533 .expect("connect should succeed");
8534 socket
8535 });
8536
8537 net.run_until_idle();
8541
8542 net.with_context(REMOTE, |ctx| {
8545 assert_eq!(
8546 ctx.tcp_api().connect(
8547 &remote_connection,
8548 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8549 PORT_1
8550 ),
8551 Ok(())
8552 );
8553 });
8554
8555 let second_connection = net.with_context(REMOTE, |ctx| {
8558 let mut api = ctx.tcp_api::<I>();
8559 let socket = api.create(Default::default());
8560 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), PORT_1)
8561 .expect("connect should succeed");
8562 socket
8563 });
8564
8565 let _: StepResult = net.step();
8566
8567 net.with_context(LOCAL, |TcpCtx { core_ctx: _, bindings_ctx }| {
8569 assert_matches!(bindings_ctx.timers.timers().len(), 1);
8570 });
8571
8572 net.with_context(LOCAL, |ctx| {
8573 assert_eq!(ctx.tcp_api().shutdown(&local_listener, ShutdownType::Receive,), Ok(false));
8574 });
8575
8576 net.with_context(LOCAL, |TcpCtx { core_ctx: _, bindings_ctx }| {
8578 assert_eq!(bindings_ctx.timers.timers().len(), 0);
8579 });
8580
8581 net.run_until_idle();
8582
8583 net.with_context(REMOTE, |ctx| {
8585 for conn in [&remote_connection, &second_connection] {
8586 assert_eq!(
8587 ctx.tcp_api().get_socket_error(conn),
8588 Some(ConnectionError::ConnectionReset),
8589 )
8590 }
8591
8592 assert_matches!(
8593 &remote_connection.get().deref().socket_state,
8594 TcpSocketStateInner::Connected { conn, .. } => {
8595 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8596 assert_matches!(
8597 conn,
8598 Connection {
8599 state: State::Closed(Closed {
8600 reason: None
8602 }),
8603 ..
8604 }
8605 );
8606 }
8607 );
8608 });
8609
8610 net.with_context(LOCAL, |ctx| {
8611 let mut api = ctx.tcp_api::<I>();
8612 let new_unbound = api.create(Default::default());
8613 assert_matches!(
8614 api.bind(
8615 &new_unbound,
8616 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip,)),
8617 Some(PORT_1),
8618 ),
8619 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
8620 );
8621 api.listen(&local_listener, NonZeroUsize::new(5).unwrap()).expect("can listen again");
8623 });
8624
8625 let new_remote_connection = net.with_context(REMOTE, |ctx| {
8626 let mut api = ctx.tcp_api::<I>();
8627 let socket = api.create(Default::default());
8628 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), PORT_1)
8629 .expect("connect should succeed");
8630 socket
8631 });
8632
8633 net.run_until_idle();
8634
8635 net.with_context(REMOTE, |ctx| {
8636 assert_matches!(
8637 &new_remote_connection.get().deref().socket_state,
8638 TcpSocketStateInner::Connected { conn, .. } => {
8639 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8640 assert_matches!(
8641 conn,
8642 Connection {
8643 state: State::Established(_),
8644 ..
8645 }
8646 );
8647 });
8648 assert_eq!(
8649 ctx.tcp_api().connect(
8650 &new_remote_connection,
8651 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8652 PORT_1,
8653 ),
8654 Ok(())
8655 );
8656 });
8657 }
8658
8659 #[ip_test(I)]
8660 fn clamp_buffer_size<I: TcpTestIpExt>()
8661 where
8662 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8663 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8664 {
8665 set_logger_for_test();
8666 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8667 I::TEST_ADDRS.local_ip,
8668 I::TEST_ADDRS.remote_ip,
8669 ));
8670 let mut api = ctx.tcp_api::<I>();
8671 let socket = api.create(Default::default());
8672
8673 let (min, max) =
8674 SettingsContext::<TcpSettings>::settings(&ctx.bindings_ctx).send_buffer.min_max();
8675 let mut api = ctx.tcp_api::<I>();
8676 api.set_send_buffer_size(&socket, min.get() - 1);
8677 assert_eq!(api.send_buffer_size(&socket), Some(min.get()));
8678 api.set_send_buffer_size(&socket, max.get() + 1);
8679 assert_eq!(api.send_buffer_size(&socket), Some(max.get()));
8680
8681 let (min, max) =
8682 SettingsContext::<TcpSettings>::settings(&ctx.bindings_ctx).receive_buffer.min_max();
8683 let mut api = ctx.tcp_api::<I>();
8684 api.set_receive_buffer_size(&socket, min.get() - 1);
8685 assert_eq!(api.receive_buffer_size(&socket), Some(min.get()));
8686 api.set_receive_buffer_size(&socket, max.get() + 1);
8687 assert_eq!(api.receive_buffer_size(&socket), Some(max.get()));
8688 }
8689
8690 #[ip_test(I)]
8691 fn set_reuseaddr_unbound<I: TcpTestIpExt>()
8692 where
8693 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8694 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8695 {
8696 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8697 I::TEST_ADDRS.local_ip,
8698 I::TEST_ADDRS.remote_ip,
8699 ));
8700 let mut api = ctx.tcp_api::<I>();
8701
8702 let first_bound = {
8703 let socket = api.create(Default::default());
8704 api.set_reuseaddr(&socket, true).expect("can set");
8705 api.bind(&socket, None, None).expect("bind succeeds");
8706 socket
8707 };
8708 let _second_bound = {
8709 let socket = api.create(Default::default());
8710 api.set_reuseaddr(&socket, true).expect("can set");
8711 api.bind(&socket, None, None).expect("bind succeeds");
8712 socket
8713 };
8714
8715 api.listen(&first_bound, NonZeroUsize::new(10).unwrap()).expect("can listen");
8716 }
8717
8718 #[ip_test(I)]
8719 #[test_case([true, true], Ok(()); "allowed with set")]
8720 #[test_case([false, true], Err(LocalAddressError::AddressInUse); "first unset")]
8721 #[test_case([true, false], Err(LocalAddressError::AddressInUse); "second unset")]
8722 #[test_case([false, false], Err(LocalAddressError::AddressInUse); "both unset")]
8723 fn reuseaddr_multiple_bound<I: TcpTestIpExt>(
8724 set_reuseaddr: [bool; 2],
8725 expected: Result<(), LocalAddressError>,
8726 ) where
8727 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8728 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8729 {
8730 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8731 I::TEST_ADDRS.local_ip,
8732 I::TEST_ADDRS.remote_ip,
8733 ));
8734 let mut api = ctx.tcp_api::<I>();
8735
8736 let first = api.create(Default::default());
8737 api.set_reuseaddr(&first, set_reuseaddr[0]).expect("can set");
8738 api.bind(&first, None, Some(PORT_1)).expect("bind succeeds");
8739
8740 let second = api.create(Default::default());
8741 api.set_reuseaddr(&second, set_reuseaddr[1]).expect("can set");
8742 let second_bind_result = api.bind(&second, None, Some(PORT_1));
8743
8744 assert_eq!(second_bind_result, expected.map_err(From::from));
8745 }
8746
8747 #[ip_test(I)]
8748 fn toggle_reuseaddr_bound_different_addrs<I: TcpTestIpExt>()
8749 where
8750 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8751 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8752 {
8753 let addrs = [1, 2].map(|i| I::get_other_ip_address(i));
8754 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
8755 FakeDualStackIpSocketCtx::new(core::iter::once(FakeDeviceConfig {
8756 device: FakeDeviceId,
8757 local_ips: addrs.iter().cloned().map(SpecifiedAddr::<IpAddr>::from).collect(),
8758 remote_ips: Default::default(),
8759 })),
8760 ));
8761 let mut api = ctx.tcp_api::<I>();
8762
8763 let first = api.create(Default::default());
8764 api.bind(&first, Some(ZonedAddr::Unzoned(addrs[0])), Some(PORT_1)).unwrap();
8765
8766 let second = api.create(Default::default());
8767 api.bind(&second, Some(ZonedAddr::Unzoned(addrs[1])), Some(PORT_1)).unwrap();
8768 api.set_reuseaddr(&first, true).expect("can set");
8771 api.set_reuseaddr(&first, false).expect("can un-set");
8772 }
8773
8774 #[ip_test(I)]
8775 fn unset_reuseaddr_bound_unspecified_specified<I: TcpTestIpExt>()
8776 where
8777 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8778 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8779 {
8780 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8781 I::TEST_ADDRS.local_ip,
8782 I::TEST_ADDRS.remote_ip,
8783 ));
8784 let mut api = ctx.tcp_api::<I>();
8785 let first = api.create(Default::default());
8786 api.set_reuseaddr(&first, true).expect("can set");
8787 api.bind(&first, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1)).unwrap();
8788
8789 let second = api.create(Default::default());
8790 api.set_reuseaddr(&second, true).expect("can set");
8791 api.bind(&second, None, Some(PORT_1)).unwrap();
8792
8793 assert_matches!(api.set_reuseaddr(&first, false), Err(SetReuseAddrError::AddrInUse));
8796 assert_matches!(api.set_reuseaddr(&second, false), Err(SetReuseAddrError::AddrInUse));
8797 }
8798
8799 #[ip_test(I)]
8800 fn reuseaddr_allows_binding_under_connection<I: TcpTestIpExt>()
8801 where
8802 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8803 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8804 {
8805 set_logger_for_test();
8806 let mut net = new_test_net::<I>();
8807
8808 let server = net.with_context(LOCAL, |ctx| {
8809 let mut api = ctx.tcp_api::<I>();
8810 let server = api.create(Default::default());
8811 api.set_reuseaddr(&server, true).expect("can set");
8812 api.bind(&server, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
8813 .expect("failed to bind the client socket");
8814 api.listen(&server, NonZeroUsize::new(10).unwrap()).expect("can listen");
8815 server
8816 });
8817
8818 let client = net.with_context(REMOTE, |ctx| {
8819 let mut api = ctx.tcp_api::<I>();
8820 let client = api.create(Default::default());
8821 api.connect(&client, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), PORT_1)
8822 .expect("connect should succeed");
8823 client
8824 });
8825 net.run_until_idle();
8827 net.with_context(REMOTE, |ctx| {
8828 assert_eq!(
8829 ctx.tcp_api().connect(
8830 &client,
8831 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8832 PORT_1
8833 ),
8834 Ok(())
8835 );
8836 });
8837
8838 net.with_context(LOCAL, |ctx| {
8842 let mut api = ctx.tcp_api();
8843 let (_server_conn, _, _): (_, SocketAddr<_, _>, ClientBuffers) =
8844 api.accept(&server).expect("pending connection");
8845
8846 assert_eq!(api.shutdown(&server, ShutdownType::Receive), Ok(false));
8847 api.close(server);
8848
8849 let unbound = api.create(Default::default());
8850 assert_eq!(
8851 api.bind(&unbound, None, Some(PORT_1)),
8852 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
8853 );
8854
8855 api.set_reuseaddr(&unbound, true).expect("can set");
8857 api.bind(&unbound, None, Some(PORT_1)).expect("bind succeeds");
8858 });
8859 }
8860
8861 #[ip_test(I)]
8862 #[test_case([true, true]; "specified specified")]
8863 #[test_case([false, true]; "any specified")]
8864 #[test_case([true, false]; "specified any")]
8865 #[test_case([false, false]; "any any")]
8866 fn set_reuseaddr_bound_allows_other_bound<I: TcpTestIpExt>(bind_specified: [bool; 2])
8867 where
8868 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8869 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8870 {
8871 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8872 I::TEST_ADDRS.local_ip,
8873 I::TEST_ADDRS.remote_ip,
8874 ));
8875 let mut api = ctx.tcp_api::<I>();
8876
8877 let [first_addr, second_addr] =
8878 bind_specified.map(|b| b.then_some(I::TEST_ADDRS.local_ip).map(ZonedAddr::Unzoned));
8879 let first_bound = {
8880 let socket = api.create(Default::default());
8881 api.bind(&socket, first_addr, Some(PORT_1)).expect("bind succeeds");
8882 socket
8883 };
8884
8885 let second = api.create(Default::default());
8886
8887 assert_matches!(
8890 api.bind(&second, second_addr, Some(PORT_1)),
8891 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
8892 );
8893
8894 api.set_reuseaddr(&second, true).expect("can set");
8896 assert_matches!(
8897 api.bind(&second, second_addr, Some(PORT_1)),
8898 Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
8899 );
8900
8901 api.set_reuseaddr(&first_bound, true).expect("only socket");
8903 api.bind(&second, second_addr, Some(PORT_1)).expect("can bind");
8904 }
8905
8906 #[ip_test(I)]
8907 fn clear_reuseaddr_listener<I: TcpTestIpExt>()
8908 where
8909 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8910 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8911 {
8912 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8913 I::TEST_ADDRS.local_ip,
8914 I::TEST_ADDRS.remote_ip,
8915 ));
8916 let mut api = ctx.tcp_api::<I>();
8917
8918 let bound = {
8919 let socket = api.create(Default::default());
8920 api.set_reuseaddr(&socket, true).expect("can set");
8921 api.bind(&socket, None, Some(PORT_1)).expect("bind succeeds");
8922 socket
8923 };
8924
8925 let listener = {
8926 let socket = api.create(Default::default());
8927 api.set_reuseaddr(&socket, true).expect("can set");
8928
8929 api.bind(&socket, None, Some(PORT_1)).expect("bind succeeds");
8930 api.listen(&socket, NonZeroUsize::new(5).unwrap()).expect("can listen");
8931 socket
8932 };
8933
8934 assert_matches!(api.set_reuseaddr(&listener, false), Err(SetReuseAddrError::AddrInUse));
8937
8938 api.connect(&bound, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
8941 .expect("can connect");
8942 api.set_reuseaddr(&listener, false).expect("can unset")
8943 }
8944
8945 fn deliver_icmp_error<
8946 I: TcpTestIpExt + IcmpIpExt,
8947 CC: TcpContext<I, BC, DeviceId = FakeDeviceId>
8948 + TcpContext<I::OtherVersion, BC, DeviceId = FakeDeviceId>,
8949 BC: TcpBindingsContext<CC::DeviceId>,
8950 >(
8951 core_ctx: &mut CC,
8952 bindings_ctx: &mut BC,
8953 original_src_ip: SpecifiedAddr<I::Addr>,
8954 original_dst_ip: SpecifiedAddr<I::Addr>,
8955 original_body: &[u8],
8956 err: I::ErrorCode,
8957 ) {
8958 <TcpIpTransportContext as IpTransportContext<I, _, _>>::receive_icmp_error(
8959 core_ctx,
8960 bindings_ctx,
8961 &FakeDeviceId,
8962 Some(original_src_ip),
8963 original_dst_ip,
8964 original_body,
8965 err,
8966 );
8967 }
8968
8969 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestNetworkUnreachable, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8970 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestHostUnreachable, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8971 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestProtocolUnreachable, IcmpDestUnreachable::default()) => ConnectionError::ProtocolUnreachable)]
8972 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestPortUnreachable, IcmpDestUnreachable::default()) => ConnectionError::PortUnreachable)]
8973 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::SourceRouteFailed, IcmpDestUnreachable::default()) => ConnectionError::SourceRouteFailed)]
8974 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestNetworkUnknown, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8975 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestHostUnknown, IcmpDestUnreachable::default()) => ConnectionError::DestinationHostDown)]
8976 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::SourceHostIsolated, IcmpDestUnreachable::default()) => ConnectionError::SourceHostIsolated)]
8977 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::NetworkAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8978 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8979 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::NetworkUnreachableForToS, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8980 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostUnreachableForToS, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8981 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::CommAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8982 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostPrecedenceViolation, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8983 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::PrecedenceCutoffInEffect, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8984 #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::PointerIndicatesError) => ConnectionError::ProtocolError)]
8985 #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::MissingRequiredOption) => ConnectionError::ProtocolError)]
8986 #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::BadLength) => ConnectionError::ProtocolError)]
8987 #[test_case(Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired) => ConnectionError::HostUnreachable)]
8988 #[test_case(Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::FragmentReassemblyTimeExceeded) => ConnectionError::TimedOut)]
8989 fn icmp_destination_unreachable_connect_v4(error: Icmpv4ErrorCode) -> ConnectionError {
8990 icmp_destination_unreachable_connect_inner::<Ipv4>(error)
8991 }
8992
8993 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute) => ConnectionError::NetworkUnreachable)]
8994 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::CommAdministrativelyProhibited) => ConnectionError::PermissionDenied)]
8995 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::BeyondScope) => ConnectionError::HostUnreachable)]
8996 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::AddrUnreachable) => ConnectionError::HostUnreachable)]
8997 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::PortUnreachable) => ConnectionError::PortUnreachable)]
8998 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::SrcAddrFailedPolicy) => ConnectionError::PermissionDenied)]
8999 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::RejectRoute) => ConnectionError::PermissionDenied)]
9000 #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::ErroneousHeaderField) => ConnectionError::ProtocolError)]
9001 #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType) => ConnectionError::ProtocolError)]
9002 #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::UnrecognizedIpv6Option) => ConnectionError::ProtocolError)]
9003 #[test_case(Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded) => ConnectionError::HostUnreachable)]
9004 #[test_case(Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::FragmentReassemblyTimeExceeded) => ConnectionError::HostUnreachable)]
9005 fn icmp_destination_unreachable_connect_v6(error: Icmpv6ErrorCode) -> ConnectionError {
9006 icmp_destination_unreachable_connect_inner::<Ipv6>(error)
9007 }
9008
9009 fn icmp_destination_unreachable_connect_inner<I: TcpTestIpExt + IcmpIpExt>(
9010 icmp_error: I::ErrorCode,
9011 ) -> ConnectionError
9012 where
9013 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<I, TcpBindingsCtx<FakeDeviceId>>
9014 + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>,
9015 {
9016 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
9017 I::TEST_ADDRS.local_ip,
9018 I::TEST_ADDRS.remote_ip,
9019 ));
9020 let mut api = ctx.tcp_api::<I>();
9021
9022 let connection = api.create(Default::default());
9023 api.connect(&connection, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
9024 .expect("failed to create a connection socket");
9025
9026 let (core_ctx, bindings_ctx) = api.contexts();
9027 let frames = core_ctx.ip_socket_ctx.take_frames();
9028 let frame = assert_matches!(&frames[..], [(_meta, frame)] => frame);
9029
9030 deliver_icmp_error::<I, _, _>(
9031 core_ctx,
9032 bindings_ctx,
9033 I::TEST_ADDRS.local_ip,
9034 I::TEST_ADDRS.remote_ip,
9035 &frame[0..8],
9036 icmp_error,
9037 );
9038 let err = api
9040 .connect(&connection, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
9041 .expect_err("should fail");
9042 assert_eq!(api.get_socket_error(&connection), None);
9044 assert_matches!(err, ConnectError::ConnectionError(e) => e)
9046 }
9047
9048 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestNetworkUnreachable, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
9049 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestHostUnreachable, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
9050 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestProtocolUnreachable, IcmpDestUnreachable::default()) => ConnectionError::ProtocolUnreachable)]
9051 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestPortUnreachable, IcmpDestUnreachable::default()) => ConnectionError::PortUnreachable)]
9052 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::SourceRouteFailed, IcmpDestUnreachable::default()) => ConnectionError::SourceRouteFailed)]
9053 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestNetworkUnknown, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
9054 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestHostUnknown, IcmpDestUnreachable::default()) => ConnectionError::DestinationHostDown)]
9055 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::SourceHostIsolated, IcmpDestUnreachable::default()) => ConnectionError::SourceHostIsolated)]
9056 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::NetworkAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
9057 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
9058 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::NetworkUnreachableForToS, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
9059 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostUnreachableForToS, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
9060 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::CommAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
9061 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostPrecedenceViolation, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
9062 #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::PrecedenceCutoffInEffect, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
9063 #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::PointerIndicatesError) => ConnectionError::ProtocolError)]
9064 #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::MissingRequiredOption) => ConnectionError::ProtocolError)]
9065 #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::BadLength) => ConnectionError::ProtocolError)]
9066 #[test_case(Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired) => ConnectionError::HostUnreachable)]
9067 #[test_case(Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::FragmentReassemblyTimeExceeded) => ConnectionError::TimedOut)]
9068 fn icmp_destination_unreachable_established_v4(error: Icmpv4ErrorCode) -> ConnectionError {
9069 icmp_destination_unreachable_established_inner::<Ipv4>(error)
9070 }
9071
9072 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute) => ConnectionError::NetworkUnreachable)]
9073 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::CommAdministrativelyProhibited) => ConnectionError::PermissionDenied)]
9074 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::BeyondScope) => ConnectionError::HostUnreachable)]
9075 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::AddrUnreachable) => ConnectionError::HostUnreachable)]
9076 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::PortUnreachable) => ConnectionError::PortUnreachable)]
9077 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::SrcAddrFailedPolicy) => ConnectionError::PermissionDenied)]
9078 #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::RejectRoute) => ConnectionError::PermissionDenied)]
9079 #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::ErroneousHeaderField) => ConnectionError::ProtocolError)]
9080 #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType) => ConnectionError::ProtocolError)]
9081 #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::UnrecognizedIpv6Option) => ConnectionError::ProtocolError)]
9082 #[test_case(Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded) => ConnectionError::HostUnreachable)]
9083 #[test_case(Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::FragmentReassemblyTimeExceeded) => ConnectionError::HostUnreachable)]
9084 fn icmp_destination_unreachable_established_v6(error: Icmpv6ErrorCode) -> ConnectionError {
9085 icmp_destination_unreachable_established_inner::<Ipv6>(error)
9086 }
9087
9088 fn icmp_destination_unreachable_established_inner<I: TcpTestIpExt + IcmpIpExt>(
9089 icmp_error: I::ErrorCode,
9090 ) -> ConnectionError
9091 where
9092 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9093 I,
9094 TcpBindingsCtx<FakeDeviceId>,
9095 SingleStackConverter = I::SingleStackConverter,
9096 DualStackConverter = I::DualStackConverter,
9097 > + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>,
9098 {
9099 let (mut net, local, local_snd_end, _remote) = bind_listen_connect_accept_inner::<I>(
9100 I::UNSPECIFIED_ADDRESS,
9101 BindConfig {
9102 client_port: None,
9103 server_port: PORT_1,
9104 client_reuse_addr: false,
9105 send_test_data: false,
9106 },
9107 0,
9108 0.0,
9109 );
9110 local_snd_end.lock().extend_from_slice(b"Hello");
9111 net.with_context(LOCAL, |ctx| {
9112 ctx.tcp_api().do_send(&local);
9113 });
9114 net.collect_frames();
9115 let original_body = assert_matches!(
9116 &net.iter_pending_frames().collect::<Vec<_>>()[..],
9117 [InstantAndData(_instant, PendingFrameData {
9118 dst_context: _,
9119 meta: _,
9120 frame,
9121 })] => {
9122 frame.clone()
9123 });
9124 net.with_context(LOCAL, |ctx| {
9125 let TcpCtx { core_ctx, bindings_ctx } = ctx;
9126 deliver_icmp_error::<I, _, _>(
9127 core_ctx,
9128 bindings_ctx,
9129 I::TEST_ADDRS.local_ip,
9130 I::TEST_ADDRS.remote_ip,
9131 &original_body[..],
9132 icmp_error,
9133 );
9134 let error = assert_matches!(
9136 ctx.tcp_api().get_socket_error(&local),
9137 Some(error) => error
9138 );
9139 assert_matches!(
9141 &local.get().deref().socket_state,
9142 TcpSocketStateInner::Connected { conn, .. } => {
9143 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
9144 assert_matches!(
9145 conn,
9146 Connection {
9147 state: State::Established(_),
9148 ..
9149 }
9150 );
9151 }
9152 );
9153 error
9154 })
9155 }
9156
9157 #[ip_test(I)]
9158 fn icmp_destination_unreachable_listener<I: TcpTestIpExt + IcmpIpExt>()
9159 where
9160 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<I, TcpBindingsCtx<FakeDeviceId>>
9161 + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>
9162 + CounterContext<TcpCountersWithSocket<I>>,
9163 {
9164 let mut net = new_test_net::<I>();
9165
9166 let backlog = NonZeroUsize::new(1).unwrap();
9167 let server = net.with_context(REMOTE, |ctx| {
9168 let mut api = ctx.tcp_api::<I>();
9169 let server = api.create(Default::default());
9170 api.bind(&server, None, Some(PORT_1)).expect("failed to bind the server socket");
9171 api.listen(&server, backlog).expect("can listen");
9172 server
9173 });
9174
9175 net.with_context(LOCAL, |ctx| {
9176 let mut api = ctx.tcp_api::<I>();
9177 let conn = api.create(Default::default());
9178 api.connect(&conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
9179 .expect("failed to connect");
9180 });
9181
9182 assert!(!net.step().is_idle());
9183
9184 net.collect_frames();
9185 let original_body = assert_matches!(
9186 &net.iter_pending_frames().collect::<Vec<_>>()[..],
9187 [InstantAndData(_instant, PendingFrameData {
9188 dst_context: _,
9189 meta: _,
9190 frame,
9191 })] => {
9192 frame.clone()
9193 });
9194 let icmp_error = I::map_ip(
9195 (),
9196 |()| {
9197 Icmpv4ErrorCode::DestUnreachable(
9198 Icmpv4DestUnreachableCode::DestPortUnreachable,
9199 IcmpDestUnreachable::default(),
9200 )
9201 },
9202 |()| Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::PortUnreachable),
9203 );
9204 net.with_context(REMOTE, |TcpCtx { core_ctx, bindings_ctx }| {
9205 let in_queue = {
9206 let state = server.get();
9207 let accept_queue = assert_matches!(
9208 &state.deref().socket_state,
9209 TcpSocketStateInner::Listener(Listener { accept_queue, .. }) => accept_queue
9210 );
9211 assert_eq!(accept_queue.len(), 1);
9212 accept_queue.collect_pending().first().unwrap().downgrade()
9213 };
9214 deliver_icmp_error::<I, _, _>(
9215 core_ctx,
9216 bindings_ctx,
9217 I::TEST_ADDRS.remote_ip,
9218 I::TEST_ADDRS.local_ip,
9219 &original_body[..],
9220 icmp_error,
9221 );
9222 {
9223 let state = server.get();
9224 let queue_len = assert_matches!(
9225 &state.deref().socket_state,
9226 TcpSocketStateInner::Listener(Listener { accept_queue, .. }) => accept_queue.len()
9227 );
9228 assert_eq!(queue_len, 0);
9229 }
9230 assert_eq!(in_queue.upgrade(), None);
9232 });
9233 }
9234
9235 #[ip_test(I)]
9236 fn time_wait_reuse<I: TcpTestIpExt>()
9237 where
9238 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9239 I,
9240 TcpBindingsCtx<FakeDeviceId>,
9241 SingleStackConverter = I::SingleStackConverter,
9242 DualStackConverter = I::DualStackConverter,
9243 >,
9244 {
9245 set_logger_for_test();
9246 const CLIENT_PORT: NonZeroU16 = NonZeroU16::new(2).unwrap();
9247 const SERVER_PORT: NonZeroU16 = NonZeroU16::new(1).unwrap();
9248 let (mut net, local, _local_snd_end, remote) = bind_listen_connect_accept_inner::<I>(
9249 I::UNSPECIFIED_ADDRESS,
9250 BindConfig {
9251 client_port: Some(CLIENT_PORT),
9252 server_port: SERVER_PORT,
9253 client_reuse_addr: true,
9254 send_test_data: false,
9255 },
9256 0,
9257 0.0,
9258 );
9259 let listener = net.with_context(LOCAL, |ctx| {
9261 let mut api = ctx.tcp_api::<I>();
9262 let listener = api.create(Default::default());
9263 api.set_reuseaddr(&listener, true).expect("can set");
9264 api.bind(
9265 &listener,
9266 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
9267 Some(CLIENT_PORT),
9268 )
9269 .expect("failed to bind");
9270 api.listen(&listener, NonZeroUsize::new(1).unwrap()).expect("failed to listen");
9271 listener
9272 });
9273 let extra_conn = net.with_context(REMOTE, |ctx| {
9275 let mut api = ctx.tcp_api::<I>();
9276 let extra_conn = api.create(Default::default());
9277 api.connect(&extra_conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), CLIENT_PORT)
9278 .expect("failed to connect");
9279 extra_conn
9280 });
9281 net.run_until_idle();
9282
9283 net.with_context(REMOTE, |ctx| {
9284 assert_eq!(
9285 ctx.tcp_api().connect(
9286 &extra_conn,
9287 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
9288 CLIENT_PORT,
9289 ),
9290 Ok(())
9291 );
9292 });
9293
9294 let weak_local = local.downgrade();
9297 net.with_context(LOCAL, |ctx| {
9298 ctx.tcp_api().close(local);
9299 });
9300 assert!(!net.step().is_idle());
9301 assert!(!net.step().is_idle());
9302 net.with_context(REMOTE, |ctx| {
9303 ctx.tcp_api().close(remote);
9304 });
9305 assert!(!net.step().is_idle());
9306 assert!(!net.step().is_idle());
9307 let (tw_last_seq, tw_last_ack, tw_expiry) = {
9309 assert_matches!(
9310 &weak_local.upgrade().unwrap().get().deref().socket_state,
9311 TcpSocketStateInner::Connected { conn, .. } => {
9312 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
9313 assert_matches!(
9314 conn,
9315 Connection {
9316 state: State::TimeWait(TimeWait {
9317 last_seq,
9318 closed_rcv,
9319 expiry,
9320 ..
9321 }), ..
9322 } => (*last_seq, closed_rcv.ack, *expiry)
9323 )
9324 }
9325 )
9326 };
9327
9328 let conn = net.with_context(REMOTE, |ctx| {
9331 let mut api = ctx.tcp_api::<I>();
9332 let conn = api.create(Default::default());
9333 api.connect(&conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), CLIENT_PORT)
9334 .expect("failed to connect");
9335 conn
9336 });
9337 while net.next_step() != Some(tw_expiry) {
9338 assert!(!net.step().is_idle());
9339 }
9340 assert_matches!(
9342 &conn.get().deref().socket_state,
9343 TcpSocketStateInner::Connected { conn, .. } => {
9344 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
9345 assert_matches!(
9346 conn,
9347 Connection {
9348 state: State::Closed(Closed { reason: Some(ConnectionError::TimedOut) }),
9349 ..
9350 }
9351 );
9352 });
9353
9354 net.with_context(LOCAL, |ctx| {
9356 let _accepted =
9357 ctx.tcp_api().accept(&listener).expect("failed to accept a new connection");
9358 });
9359 let conn = net.with_context(REMOTE, |ctx| {
9360 let mut api = ctx.tcp_api::<I>();
9361 let socket = api.create(Default::default());
9362 api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), Some(SERVER_PORT))
9363 .expect("failed to bind");
9364 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), CLIENT_PORT)
9365 .expect("failed to connect");
9366 socket
9367 });
9368 net.collect_frames();
9369 assert_matches!(
9370 &net.iter_pending_frames().collect::<Vec<_>>()[..],
9371 [InstantAndData(_instant, PendingFrameData {
9372 dst_context: _,
9373 meta,
9374 frame,
9375 })] => {
9376 let mut buffer = Buf::new(frame, ..);
9377 let iss = match I::VERSION {
9378 IpVersion::V4 => {
9379 let meta = assert_matches!(meta, DualStackSendIpPacketMeta::V4(meta) => meta);
9380 let parsed = buffer.parse_with::<_, TcpSegment<_>>(
9381 TcpParseArgs::new(*meta.src_ip, *meta.dst_ip)
9382 ).expect("failed to parse");
9383 assert!(parsed.syn());
9384 SeqNum::new(parsed.seq_num())
9385 }
9386 IpVersion::V6 => {
9387 let meta = assert_matches!(meta, DualStackSendIpPacketMeta::V6(meta) => meta);
9388 let parsed = buffer.parse_with::<_, TcpSegment<_>>(
9389 TcpParseArgs::new(*meta.src_ip, *meta.dst_ip)
9390 ).expect("failed to parse");
9391 assert!(parsed.syn());
9392 SeqNum::new(parsed.seq_num())
9393 }
9394 };
9395 assert!(iss.after(tw_last_ack) && iss.before(tw_last_seq));
9396 });
9397 net.run_until_idle();
9399 net.with_context(REMOTE, |ctx| {
9400 assert_eq!(
9401 ctx.tcp_api().connect(
9402 &conn,
9403 Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
9404 CLIENT_PORT
9405 ),
9406 Ok(())
9407 );
9408 });
9409 }
9410
9411 #[ip_test(I)]
9412 fn conn_addr_not_available<I: TcpTestIpExt + IcmpIpExt>()
9413 where
9414 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9415 I,
9416 TcpBindingsCtx<FakeDeviceId>,
9417 SingleStackConverter = I::SingleStackConverter,
9418 DualStackConverter = I::DualStackConverter,
9419 >,
9420 {
9421 set_logger_for_test();
9422 let (mut net, _local, _local_snd_end, _remote) = bind_listen_connect_accept_inner::<I>(
9423 I::UNSPECIFIED_ADDRESS,
9424 BindConfig {
9425 client_port: Some(PORT_1),
9426 server_port: PORT_1,
9427 client_reuse_addr: true,
9428 send_test_data: false,
9429 },
9430 0,
9431 0.0,
9432 );
9433 net.with_context(LOCAL, |ctx| {
9436 let mut api = ctx.tcp_api::<I>();
9437 let socket = api.create(Default::default());
9438 api.set_reuseaddr(&socket, true).expect("can set");
9439 api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
9440 .expect("failed to bind");
9441 assert_eq!(
9442 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1),
9443 Err(ConnectError::ConnectionExists),
9444 )
9445 });
9446 }
9447
9448 #[test_case::test_matrix(
9449 [None, Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.remote_ip).to_ipv6_mapped()))],
9450 [None, Some(PORT_1)],
9451 [true, false]
9452 )]
9453 fn dual_stack_connect(
9454 server_bind_ip: Option<ZonedAddr<SpecifiedAddr<Ipv6Addr>, FakeDeviceId>>,
9455 server_bind_port: Option<NonZeroU16>,
9456 bind_client: bool,
9457 ) {
9458 set_logger_for_test();
9459 let mut net = new_test_net::<Ipv4>();
9460 let backlog = NonZeroUsize::new(1).unwrap();
9461 let (server, listen_port) = net.with_context(REMOTE, |ctx| {
9462 let mut api = ctx.tcp_api::<Ipv6>();
9463 let server = api.create(Default::default());
9464 api.bind(&server, server_bind_ip, server_bind_port)
9465 .expect("failed to bind the server socket");
9466 api.listen(&server, backlog).expect("can listen");
9467 let port = assert_matches!(
9468 api.get_info(&server),
9469 SocketInfo::Bound(info) => info.port
9470 );
9471 (server, port)
9472 });
9473
9474 let client_ends = WriteBackClientBuffers::default();
9475 let client = net.with_context(LOCAL, |ctx| {
9476 let mut api = ctx.tcp_api::<Ipv6>();
9477 let socket = api.create(ProvidedBuffers::Buffers(client_ends.clone()));
9478 if bind_client {
9479 api.bind(&socket, None, None).expect("failed to bind");
9480 }
9481 api.connect(
9482 &socket,
9483 Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.remote_ip).to_ipv6_mapped())),
9484 listen_port,
9485 )
9486 .expect("failed to connect");
9487 socket
9488 });
9489
9490 net.run_until_idle();
9492 let (accepted, addr, accepted_ends) = net
9493 .with_context(REMOTE, |ctx| ctx.tcp_api().accept(&server).expect("failed to accept"));
9494 assert_eq!(addr.ip, ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.local_ip).to_ipv6_mapped()));
9495
9496 let ClientBuffers { send: client_snd_end, receive: client_rcv_end } =
9497 client_ends.0.as_ref().lock().take().unwrap();
9498 let ClientBuffers { send: accepted_snd_end, receive: accepted_rcv_end } = accepted_ends;
9499 for snd_end in [client_snd_end, accepted_snd_end] {
9500 snd_end.lock().extend_from_slice(b"Hello");
9501 }
9502 net.with_context(LOCAL, |ctx| ctx.tcp_api().do_send(&client));
9503 net.with_context(REMOTE, |ctx| ctx.tcp_api().do_send(&accepted));
9504 net.run_until_idle();
9505
9506 for rcv_end in [client_rcv_end, accepted_rcv_end] {
9507 assert_eq!(
9508 rcv_end.lock().read_with(|avail| {
9509 let avail = avail.concat();
9510 assert_eq!(avail, b"Hello");
9511 avail.len()
9512 }),
9513 5
9514 );
9515 }
9516
9517 let info = assert_matches!(
9520 net.with_context(LOCAL, |ctx| ctx.tcp_api().get_info(&client)),
9521 SocketInfo::Connection(info) => info
9522 );
9523 let (local_ip, remote_ip, port) = assert_matches!(
9524 info,
9525 ConnectionInfo {
9526 local_addr: SocketAddr { ip: local_ip, port: _ },
9527 remote_addr: SocketAddr { ip: remote_ip, port },
9528 device: _
9529 } => (local_ip.addr(), remote_ip.addr(), port)
9530 );
9531 assert_eq!(remote_ip, Ipv4::TEST_ADDRS.remote_ip.to_ipv6_mapped());
9532 assert_matches!(local_ip.to_ipv4_mapped(), Some(_));
9533 assert_eq!(port, listen_port);
9534 }
9535
9536 #[test]
9537 fn ipv6_dual_stack_enabled() {
9538 set_logger_for_test();
9539 let mut net = new_test_net::<Ipv4>();
9540 net.with_context(LOCAL, |ctx| {
9541 let mut api = ctx.tcp_api::<Ipv6>();
9542 let socket = api.create(Default::default());
9543 assert_eq!(api.dual_stack_enabled(&socket), Ok(true));
9544 api.set_dual_stack_enabled(&socket, false).expect("failed to disable dual stack");
9545 assert_eq!(api.dual_stack_enabled(&socket), Ok(false));
9546 assert_eq!(
9547 api.bind(
9548 &socket,
9549 Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.local_ip).to_ipv6_mapped())),
9550 Some(PORT_1),
9551 ),
9552 Err(BindError::LocalAddressError(LocalAddressError::CannotBindToAddress))
9553 );
9554 assert_eq!(
9555 api.connect(
9556 &socket,
9557 Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.remote_ip).to_ipv6_mapped())),
9558 PORT_1,
9559 ),
9560 Err(ConnectError::NoRoute)
9561 );
9562 });
9563 }
9564
9565 #[test]
9566 fn ipv4_dual_stack_enabled() {
9567 set_logger_for_test();
9568 let mut net = new_test_net::<Ipv4>();
9569 net.with_context(LOCAL, |ctx| {
9570 let mut api = ctx.tcp_api::<Ipv4>();
9571 let socket = api.create(Default::default());
9572 assert_eq!(api.dual_stack_enabled(&socket), Err(NotDualStackCapableError));
9573 assert_eq!(
9574 api.set_dual_stack_enabled(&socket, true),
9575 Err(NotDualStackCapableError.into())
9576 );
9577 });
9578 }
9579
9580 #[ip_test(I)]
9581 fn closed_not_in_demux<I: TcpTestIpExt>()
9582 where
9583 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9584 I,
9585 TcpBindingsCtx<FakeDeviceId>,
9586 SingleStackConverter = I::SingleStackConverter,
9587 DualStackConverter = I::DualStackConverter,
9588 >,
9589 {
9590 let (mut net, local, _local_snd_end, remote) = bind_listen_connect_accept_inner::<I>(
9591 I::UNSPECIFIED_ADDRESS,
9592 BindConfig {
9593 client_port: None,
9594 server_port: PORT_1,
9595 client_reuse_addr: false,
9596 send_test_data: false,
9597 },
9598 0,
9599 0.0,
9600 );
9601 for ctx_name in [LOCAL, REMOTE] {
9603 net.with_context(ctx_name, |CtxPair { core_ctx, bindings_ctx: _ }| {
9604 TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
9605 assert_eq!(socketmap.len(), 1);
9606 })
9607 });
9608 }
9609 for (ctx_name, socket) in [(LOCAL, &local), (REMOTE, &remote)] {
9610 net.with_context(ctx_name, |ctx| {
9611 assert_eq!(ctx.tcp_api().shutdown(socket, ShutdownType::SendAndReceive), Ok(true));
9612 });
9613 }
9614 net.run_until_idle();
9615 for ctx_name in [LOCAL, REMOTE] {
9619 net.with_context(ctx_name, |CtxPair { core_ctx, bindings_ctx: _ }| {
9620 TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
9621 assert_eq!(socketmap.len(), 0);
9622 })
9623 });
9624 }
9625 }
9626
9627 #[ip_test(I)]
9628 fn tcp_accept_queue_clean_up_closed<I: TcpTestIpExt>()
9629 where
9630 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
9631 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
9632 {
9633 let mut net = new_test_net::<I>();
9634 let backlog = NonZeroUsize::new(1).unwrap();
9635 let server_port = NonZeroU16::new(1024).unwrap();
9636 let server = net.with_context(REMOTE, |ctx| {
9637 let mut api = ctx.tcp_api::<I>();
9638 let server = api.create(Default::default());
9639 api.bind(&server, None, Some(server_port)).expect("failed to bind the server socket");
9640 api.listen(&server, backlog).expect("can listen");
9641 server
9642 });
9643
9644 let client = net.with_context(LOCAL, |ctx| {
9645 let mut api = ctx.tcp_api::<I>();
9646 let socket = api.create(ProvidedBuffers::Buffers(WriteBackClientBuffers::default()));
9647 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), server_port)
9648 .expect("failed to connect");
9649 socket
9650 });
9651 assert!(!net.step().is_idle());
9653 assert_matches!(
9655 &server.get().deref().socket_state,
9656 TcpSocketStateInner::Listener(Listener { accept_queue, .. }) => {
9657 assert_eq!(accept_queue.ready_len(), 0);
9658 assert_eq!(accept_queue.pending_len(), 1);
9659 }
9660 );
9661 net.with_context(LOCAL, |ctx| {
9663 let mut api = ctx.tcp_api::<I>();
9664 api.close(client);
9665 });
9666 net.run_until_idle();
9669 assert_matches!(
9671 &server.get().deref().socket_state,
9672 TcpSocketStateInner::Listener(Listener { accept_queue, .. }) => {
9673 assert_eq!(accept_queue.ready_len(), 0);
9674 assert_eq!(accept_queue.pending_len(), 0);
9675 }
9676 );
9677 net.with_context(REMOTE, |ctx| {
9679 ctx.core_ctx.with_all_sockets_mut(|all_sockets| {
9680 assert_eq!(all_sockets.keys().collect::<Vec<_>>(), [&server]);
9681 })
9682 })
9683 }
9684
9685 #[ip_test(I, test = false)]
9686 #[test_case::test_matrix(
9687 [MarkDomain::Mark1, MarkDomain::Mark2],
9688 [None, Some(0), Some(1)]
9689 )]
9690 fn tcp_socket_marks<I: TcpTestIpExt>(domain: MarkDomain, mark: Option<u32>)
9691 where
9692 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
9693 TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
9694 {
9695 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
9696 I::TEST_ADDRS.local_ip,
9697 I::TEST_ADDRS.remote_ip,
9698 ));
9699 let mut api = ctx.tcp_api::<I>();
9700 let socket = api.create(Default::default());
9701
9702 assert_eq!(api.get_mark(&socket, domain), Mark(None));
9704
9705 let mark = Mark(mark);
9706 api.set_mark(&socket, domain, mark);
9708 assert_eq!(api.get_mark(&socket, domain), mark);
9709 }
9710
9711 #[ip_test(I)]
9712 fn tcp_marks_for_accepted_sockets<I: TcpTestIpExt>()
9713 where
9714 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9715 I,
9716 TcpBindingsCtx<FakeDeviceId>,
9717 SingleStackConverter = I::SingleStackConverter,
9718 DualStackConverter = I::DualStackConverter,
9719 >,
9720 {
9721 let expected_marks = [(MarkDomain::Mark1, 101), (MarkDomain::Mark2, 102)];
9724 let packet_marks =
9725 netstack3_base::Marks::new([(MarkDomain::Mark1, 101), (MarkDomain::Mark2, 2)]);
9726 let mut net = new_test_net::<I>();
9727
9728 for c in [LOCAL, REMOTE] {
9729 net.with_context(c, |ctx| {
9730 ctx.core_ctx.recv_packet_marks = packet_marks;
9731 })
9732 }
9733
9734 let backlog = NonZeroUsize::new(1).unwrap();
9735 let server_port = NonZeroU16::new(1234).unwrap();
9736
9737 let server = net.with_context(REMOTE, |ctx| {
9738 let mut api = ctx.tcp_api::<I>();
9739 let server = api.create(Default::default());
9740 api.set_mark(&server, MarkDomain::Mark1, Mark(Some(1)));
9741 api.set_mark(&server, MarkDomain::Mark2, Mark(Some(102)));
9742 api.bind(&server, None, Some(server_port)).expect("failed to bind the server socket");
9743 api.listen(&server, backlog).expect("can listen");
9744 server
9745 });
9746
9747 let client_ends = WriteBackClientBuffers::default();
9748 let _client = net.with_context(LOCAL, |ctx| {
9749 let mut api = ctx.tcp_api::<I>();
9750 let socket = api.create(ProvidedBuffers::Buffers(client_ends.clone()));
9751 api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), server_port)
9752 .expect("failed to connect");
9753 socket
9754 });
9755 net.run_until_idle();
9756 net.with_context(REMOTE, |ctx| {
9757 let (accepted, _addr, _accepted_ends) =
9758 ctx.tcp_api::<I>().accept(&server).expect("failed to accept");
9759 for (domain, expected) in expected_marks {
9760 assert_eq!(ctx.tcp_api::<I>().get_mark(&accepted, domain), Mark(Some(expected)));
9761 }
9762 });
9763 }
9764
9765 #[ip_test(I)]
9766 fn do_send_can_remove_sockets_from_demux_state<I: TcpTestIpExt>()
9767 where
9768 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9769 I,
9770 TcpBindingsCtx<FakeDeviceId>,
9771 SingleStackConverter = I::SingleStackConverter,
9772 DualStackConverter = I::DualStackConverter,
9773 >,
9774 {
9775 let (mut net, client, _client_snd_end, accepted) = bind_listen_connect_accept_inner(
9776 I::UNSPECIFIED_ADDRESS,
9777 BindConfig {
9778 client_port: None,
9779 server_port: PORT_1,
9780 client_reuse_addr: false,
9781 send_test_data: false,
9782 },
9783 0,
9784 0.0,
9785 );
9786 net.with_context(LOCAL, |ctx| {
9787 let mut api = ctx.tcp_api::<I>();
9788 assert_eq!(api.shutdown(&client, ShutdownType::Send), Ok(true));
9789 });
9790 assert!(!net.step().is_idle());
9792 assert!(!net.step().is_idle());
9794 net.with_context(REMOTE, |ctx| {
9795 let mut api = ctx.tcp_api::<I>();
9796 assert_eq!(api.shutdown(&accepted, ShutdownType::Send), Ok(true));
9797 });
9798 assert!(!net.step().is_idle());
9800 assert!(!net.step().is_idle());
9802
9803 net.with_context(LOCAL, |CtxPair { core_ctx, bindings_ctx: _ }| {
9805 TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
9806 assert_eq!(socketmap.len(), 1);
9807 })
9808 });
9809 assert_matches!(
9810 &client.get().deref().socket_state,
9811 TcpSocketStateInner::Connected { conn, .. } => {
9812 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(
9813 conn,
9814 &I::converter()
9815 );
9816 assert_matches!(
9817 conn,
9818 Connection {
9819 state: State::TimeWait(_),
9820 ..
9821 }
9822 );
9823 }
9824 );
9825 net.with_context(LOCAL, |ctx| {
9826 ctx.with_fake_timer_ctx_mut(|ctx| {
9828 ctx.instant.time =
9829 ctx.instant.time.checked_add(Duration::from_secs(120 * 60)).unwrap()
9830 });
9831 let mut api = ctx.tcp_api::<I>();
9833 api.do_send(&client);
9834 });
9835 assert_matches!(
9836 &client.get().deref().socket_state,
9837 TcpSocketStateInner::Connected { conn, .. } => {
9838 let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(
9839 conn,
9840 &I::converter()
9841 );
9842 assert_matches!(
9843 conn,
9844 Connection {
9845 state: State::Closed(_),
9846 ..
9847 }
9848 );
9849 }
9850 );
9851 net.with_context(LOCAL, |CtxPair { core_ctx, bindings_ctx: _ }| {
9852 TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
9853 assert_eq!(socketmap.len(), 0);
9854 })
9855 });
9856 }
9857
9858 #[ip_test(I)]
9859 #[test_case(true; "server read over mss")]
9860 #[test_case(false; "server read under mss")]
9861 fn tcp_data_dequeue_sends_window_update<I: TcpTestIpExt>(server_read_over_mss: bool)
9862 where
9863 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9864 I,
9865 TcpBindingsCtx<FakeDeviceId>,
9866 SingleStackConverter = I::SingleStackConverter,
9867 DualStackConverter = I::DualStackConverter,
9868 >,
9869 {
9870 const EXTRA_DATA_AMOUNT: usize = 128;
9871 set_logger_for_test();
9872
9873 let (mut net, client, client_snd_end, accepted) = bind_listen_connect_accept_inner(
9874 I::UNSPECIFIED_ADDRESS,
9875 BindConfig {
9876 client_port: None,
9877 server_port: PORT_1,
9878 client_reuse_addr: false,
9879 send_test_data: false,
9880 },
9881 0,
9882 0.0,
9883 );
9884
9885 let accepted_rcv_bufsize = net
9886 .with_context(REMOTE, |ctx| ctx.tcp_api::<I>().receive_buffer_size(&accepted).unwrap());
9887
9888 client_snd_end.lock().extend(core::iter::repeat(0xAB).take(accepted_rcv_bufsize));
9890 net.with_context(LOCAL, |ctx| {
9891 ctx.tcp_api().do_send(&client);
9892 });
9893 net.run_until_idle();
9894
9895 client_snd_end.lock().extend(core::iter::repeat(0xAB).take(EXTRA_DATA_AMOUNT));
9904 net.with_context(LOCAL, |ctx| {
9905 ctx.tcp_api().do_send(&client);
9906 });
9907 let _ = net.step_deliver_frames();
9908
9909 let send_buf_len = net
9910 .with_context(LOCAL, |ctx| {
9911 ctx.tcp_api::<I>().with_send_buffer(&client, |buf| {
9912 let BufferLimits { len, capacity: _ } = buf.limits();
9913 len
9914 })
9915 })
9916 .unwrap();
9917 assert_eq!(send_buf_len, EXTRA_DATA_AMOUNT);
9918
9919 if server_read_over_mss {
9920 let nread = net
9922 .with_context(REMOTE, |ctx| {
9923 ctx.tcp_api::<I>().with_receive_buffer(&accepted, |buf| {
9924 buf.lock().read_with(|readable| readable.iter().map(|buf| buf.len()).sum())
9925 })
9926 })
9927 .unwrap();
9928 assert_eq!(nread, accepted_rcv_bufsize);
9929
9930 net.with_context(REMOTE, |ctx| ctx.tcp_api::<I>().on_receive_buffer_read(&accepted));
9933
9934 let (server_snd_max, server_acknum) = {
9935 let socket = accepted.get();
9936 let state = assert_matches!(
9937 &socket.deref().socket_state,
9938 TcpSocketStateInner::Connected { conn, .. } => {
9939 assert_matches!(I::get_state(conn), State::Established(e) => e)
9940 }
9941 );
9942
9943 (state.snd.max, state.rcv.nxt())
9944 };
9945
9946 assert_eq!(
9948 net.step_deliver_frames_with(|_, meta, frame| {
9949 let mut buffer = Buf::new(frame.clone(), ..);
9950
9951 let (packet_seq, packet_ack, window_size, body_len) = match I::VERSION {
9952 IpVersion::V4 => {
9953 let meta =
9954 assert_matches!(&meta, DualStackSendIpPacketMeta::V4(v4) => v4);
9955
9956 assert_eq!(*meta.src_ip, Ipv4::TEST_ADDRS.remote_ip.into_addr());
9958 assert_eq!(*meta.dst_ip, Ipv4::TEST_ADDRS.local_ip.into_addr());
9959
9960 let parsed = buffer
9961 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
9962 *meta.src_ip,
9963 *meta.dst_ip,
9964 ))
9965 .expect("failed to parse");
9966
9967 (
9968 parsed.seq_num(),
9969 parsed.ack_num().unwrap(),
9970 parsed.window_size(),
9971 parsed.body().len(),
9972 )
9973 }
9974 IpVersion::V6 => {
9975 let meta =
9976 assert_matches!(&meta, DualStackSendIpPacketMeta::V6(v6) => v6);
9977
9978 assert_eq!(*meta.src_ip, Ipv6::TEST_ADDRS.remote_ip.into_addr());
9980 assert_eq!(*meta.dst_ip, Ipv6::TEST_ADDRS.local_ip.into_addr());
9981
9982 let parsed = buffer
9983 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
9984 *meta.src_ip,
9985 *meta.dst_ip,
9986 ))
9987 .expect("failed to parse");
9988
9989 (
9990 parsed.seq_num(),
9991 parsed.ack_num().unwrap(),
9992 parsed.window_size(),
9993 parsed.body().len(),
9994 )
9995 }
9996 };
9997
9998 assert_eq!(packet_seq, u32::from(server_snd_max));
10001 assert_eq!(packet_ack, u32::from(server_acknum));
10002 assert_eq!(window_size, 65535);
10003 assert_eq!(body_len, 0);
10004
10005 Some((meta, frame))
10006 })
10007 .frames_sent,
10008 1
10009 );
10010
10011 assert_eq!(
10013 net.step_deliver_frames_with(|_, meta, frame| {
10014 let mut buffer = Buf::new(frame.clone(), ..);
10015
10016 let body_len = match I::VERSION {
10017 IpVersion::V4 => {
10018 let meta =
10019 assert_matches!(&meta, DualStackSendIpPacketMeta::V4(v4) => v4);
10020
10021 assert_eq!(*meta.src_ip, Ipv4::TEST_ADDRS.local_ip.into_addr());
10023 assert_eq!(*meta.dst_ip, Ipv4::TEST_ADDRS.remote_ip.into_addr());
10024
10025 let parsed = buffer
10026 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
10027 *meta.src_ip,
10028 *meta.dst_ip,
10029 ))
10030 .expect("failed to parse");
10031
10032 parsed.body().len()
10033 }
10034 IpVersion::V6 => {
10035 let meta =
10036 assert_matches!(&meta, DualStackSendIpPacketMeta::V6(v6) => v6);
10037
10038 assert_eq!(*meta.src_ip, Ipv6::TEST_ADDRS.local_ip.into_addr());
10040 assert_eq!(*meta.dst_ip, Ipv6::TEST_ADDRS.remote_ip.into_addr());
10041
10042 let parsed = buffer
10043 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
10044 *meta.src_ip,
10045 *meta.dst_ip,
10046 ))
10047 .expect("failed to parse");
10048
10049 parsed.body().len()
10050 }
10051 };
10052
10053 assert_eq!(body_len, EXTRA_DATA_AMOUNT);
10054
10055 Some((meta, frame))
10056 })
10057 .frames_sent,
10058 1
10059 );
10060
10061 assert_eq!(
10064 net.step_deliver_frames_with(|_, meta, frame| {
10065 let mut buffer = Buf::new(frame.clone(), ..);
10066
10067 let (packet_seq, packet_ack, body_len) = match I::VERSION {
10068 IpVersion::V4 => {
10069 let meta =
10070 assert_matches!(&meta, DualStackSendIpPacketMeta::V4(v4) => v4);
10071
10072 assert_eq!(*meta.src_ip, Ipv4::TEST_ADDRS.remote_ip.into_addr());
10074 assert_eq!(*meta.dst_ip, Ipv4::TEST_ADDRS.local_ip.into_addr());
10075
10076 let parsed = buffer
10077 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
10078 *meta.src_ip,
10079 *meta.dst_ip,
10080 ))
10081 .expect("failed to parse");
10082
10083 (parsed.seq_num(), parsed.ack_num().unwrap(), parsed.body().len())
10084 }
10085 IpVersion::V6 => {
10086 let meta =
10087 assert_matches!(&meta, DualStackSendIpPacketMeta::V6(v6) => v6);
10088
10089 assert_eq!(*meta.src_ip, Ipv6::TEST_ADDRS.remote_ip.into_addr());
10091 assert_eq!(*meta.dst_ip, Ipv6::TEST_ADDRS.local_ip.into_addr());
10092
10093 let parsed = buffer
10094 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
10095 *meta.src_ip,
10096 *meta.dst_ip,
10097 ))
10098 .expect("failed to parse");
10099
10100 (parsed.seq_num(), parsed.ack_num().unwrap(), parsed.body().len())
10101 }
10102 };
10103
10104 assert_eq!(packet_seq, u32::from(server_snd_max));
10105 assert_eq!(
10106 packet_ack,
10107 u32::from(server_acknum) + u32::try_from(EXTRA_DATA_AMOUNT).unwrap()
10108 );
10109 assert_eq!(body_len, 0);
10110
10111 Some((meta, frame))
10112 })
10113 .frames_sent,
10114 1
10115 );
10116
10117 let send_buf_len = net
10118 .with_context(LOCAL, |ctx| {
10119 ctx.tcp_api::<I>().with_send_buffer(&client, |buf| {
10120 let BufferLimits { len, capacity: _ } = buf.limits();
10121 len
10122 })
10123 })
10124 .unwrap();
10125 assert_eq!(send_buf_len, 0);
10126 } else {
10127 let nread = net
10130 .with_context(REMOTE, |ctx| {
10131 ctx.tcp_api::<I>()
10132 .with_receive_buffer(&accepted, |buf| buf.lock().read_with(|_readable| 1))
10133 })
10134 .unwrap();
10135 assert_eq!(nread, 1);
10136
10137 net.with_context(REMOTE, |ctx| ctx.tcp_api::<I>().on_receive_buffer_read(&accepted));
10140 assert_eq!(net.step_deliver_frames().frames_sent, 0);
10141
10142 let send_buf_len = net
10143 .with_context(LOCAL, |ctx| {
10144 ctx.tcp_api::<I>().with_send_buffer(&client, |buf| {
10145 let BufferLimits { len, capacity: _ } = buf.limits();
10146 len
10147 })
10148 })
10149 .unwrap();
10150 assert_eq!(send_buf_len, EXTRA_DATA_AMOUNT);
10153 }
10154 }
10155
10156 impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpSocketId<I, D, BT> {
10157 fn established_state(
10158 state: &impl Deref<Target = TcpSocketState<I, D, BT>>,
10159 ) -> &Established<BT::Instant, BT::ReceiveBuffer, BT::SendBuffer> {
10160 assert_matches!(
10161 &state.deref().socket_state,
10162 TcpSocketStateInner::Connected { conn, .. } => {
10163 assert_matches!(I::get_state(conn), State::Established(e) => e)
10164 }
10165 )
10166 }
10167
10168 fn mss(&self) -> Mss {
10169 *Self::established_state(&self.get()).snd.congestion_control().mss().mss()
10170 }
10171
10172 fn cwnd(&self) -> CongestionWindow {
10173 Self::established_state(&self.get()).snd.congestion_control().inspect_cwnd()
10174 }
10175 }
10176
10177 #[derive(PartialEq)]
10178 enum MssUpdate {
10179 Decrease,
10180 DecreaseBelowMin,
10181 Same,
10182 Increase,
10183 }
10184
10185 #[ip_test(I)]
10186 #[test_case(MssUpdate::Decrease; "update if decrease")]
10187 #[test_case(MssUpdate::DecreaseBelowMin; "update to min if decreased below min")]
10188 #[test_case(MssUpdate::Same; "ignore if same")]
10189 #[test_case(MssUpdate::Increase; "ignore if increase")]
10190 fn pmtu_update_mss<I: TcpTestIpExt + IcmpIpExt>(mss_update: MssUpdate)
10191 where
10192 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<I, TcpBindingsCtx<FakeDeviceId>>
10193 + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>,
10194 {
10195 let mut net = new_test_net::<I>();
10196
10197 let server = net.with_context(REMOTE, |ctx| {
10198 let mut api = ctx.tcp_api::<I>();
10199 let server = api.create(Default::default());
10200 api.bind(&server, None, Some(PORT_1)).expect("bind to port");
10201 api.listen(&server, NonZeroUsize::MIN).expect("can listen");
10202 server
10203 });
10204
10205 let client_buffers = WriteBackClientBuffers::default();
10206 let client = net.with_context(LOCAL, |ctx| {
10207 let mut api = ctx.tcp_api::<I>();
10208 let client = api.create(ProvidedBuffers::Buffers(client_buffers.clone()));
10209 api.connect(&client, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
10210 .expect("connect to server");
10211 client
10212 });
10213
10214 net.run_until_idle();
10216 let (_accepted, accepted_buffers) = net.with_context(REMOTE, |ctx| {
10217 let (accepted, _addr, accepted_ends) =
10218 ctx.tcp_api::<I>().accept(&server).expect("accept incoming connection");
10219 (accepted, accepted_ends)
10220 });
10221
10222 let initial_mss = client.mss();
10223
10224 let min_mtu = u32::from(Mss::MIN)
10226 + I::IP_HEADER_LENGTH.get()
10227 + packet_formats::tcp::HDR_PREFIX_LEN as u32;
10228
10229 let pmtu_update = match mss_update {
10230 MssUpdate::DecreaseBelowMin => Mtu::new(min_mtu - 1),
10231 MssUpdate::Decrease => Mtu::new(min_mtu),
10232 MssUpdate::Same => LINK_MTU,
10233 MssUpdate::Increase => Mtu::max(),
10234 };
10235 let icmp_error = I::map_ip(
10236 (),
10237 |()| {
10238 let mtu = u16::try_from(pmtu_update.get()).unwrap_or(u16::MAX);
10239 let mtu = NonZeroU16::new(mtu).unwrap();
10240 Icmpv4ErrorCode::DestUnreachable(
10241 Icmpv4DestUnreachableCode::FragmentationRequired,
10242 IcmpDestUnreachable::new_for_frag_req(mtu),
10243 )
10244 },
10245 |()| Icmpv6ErrorCode::PacketTooBig(pmtu_update),
10246 );
10247
10248 let ClientBuffers { send: client_snd_end, receive: _ } =
10251 client_buffers.0.as_ref().lock().take().unwrap();
10252 let payload = vec![0xFF; min_mtu.try_into().unwrap()];
10253 client_snd_end.lock().extend_from_slice(&payload);
10254 net.with_context(LOCAL, |ctx| {
10255 ctx.tcp_api().do_send(&client);
10256 let (core_ctx, bindings_ctx) = ctx.contexts();
10257 let frames = core_ctx.ip_socket_ctx.take_frames();
10258 let frame = assert_matches!(&frames[..], [(_meta, frame)] => frame);
10259
10260 deliver_icmp_error::<I, _, _>(
10261 core_ctx,
10262 bindings_ctx,
10263 I::TEST_ADDRS.local_ip,
10264 I::TEST_ADDRS.remote_ip,
10265 &frame[0..8],
10266 icmp_error,
10267 );
10268 });
10269
10270 let requested_mms = Mms::from_mtu::<I>(pmtu_update, 0 ).unwrap();
10271 let requested_mss = Mss::from_mms(requested_mms);
10272 match mss_update {
10273 MssUpdate::DecreaseBelowMin => {
10274 assert_eq!(requested_mss, None);
10276 }
10277 MssUpdate::Decrease => {
10278 assert_matches!(requested_mss, Some(mss) if mss < initial_mss);
10279 }
10280 MssUpdate::Same => {
10281 assert_eq!(requested_mss, Some(initial_mss));
10282 }
10283 MssUpdate::Increase => {
10284 assert_matches!(requested_mss, Some(mss) if mss > initial_mss);
10285 }
10286 };
10287
10288 match mss_update {
10290 MssUpdate::Decrease | MssUpdate::DecreaseBelowMin => {}
10291 MssUpdate::Same | MssUpdate::Increase => {
10292 assert_eq!(client.mss(), initial_mss);
10293 return;
10294 }
10295 }
10296
10297 let expected_mss = requested_mss.unwrap_or(Mss::MIN);
10300 let expected_mms = usize::from(expected_mss) + packet_formats::tcp::HDR_PREFIX_LEN;
10301
10302 assert_eq!(client.mss(), expected_mss);
10303 let cwnd = client.cwnd().cwnd();
10305 let expected_mss = u32::from(expected_mss);
10306 assert!(cwnd > expected_mss, "{cwnd} > {expected_mss}");
10307
10308 net.with_context(LOCAL, |ctx| {
10310 let frames = ctx.core_ctx().ip_socket_ctx.frames();
10311 let frame = assert_matches!(&frames[..], [(_meta, frame)] => frame);
10312 assert_eq!(frame.len(), expected_mms);
10313 });
10314
10315 net.run_until_idle();
10318 let ClientBuffers { send: _, receive: accepted_rcv_end } = accepted_buffers;
10319 let read = accepted_rcv_end.lock().read_with(|avail| {
10320 let avail = avail.concat();
10321 assert_eq!(avail, payload);
10322 avail.len()
10323 });
10324 assert_eq!(read, payload.len());
10325 }
10326
10327 #[ip_test(I)]
10328 fn connect_timeout<I: TcpTestIpExt>()
10329 where
10330 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
10331 I,
10332 TcpBindingsCtx<FakeDeviceId>,
10333 SingleStackConverter = I::SingleStackConverter,
10334 DualStackConverter = I::DualStackConverter,
10335 >,
10336 {
10337 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
10338 I::TEST_ADDRS.local_ip,
10339 I::TEST_ADDRS.remote_ip,
10340 ));
10341 let mut api = ctx.tcp_api::<I>();
10342 let socket = api.create(Default::default());
10343 let connect_addr = Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip));
10344 api.connect(&socket, connect_addr, PORT_1).expect("first connect should succeed");
10345 assert_eq!(api.connect(&socket, connect_addr, PORT_1), Err(ConnectError::Pending));
10346 while let Some(id) = ctx.bindings_ctx.timers.pop_next_timer_and_advance_time() {
10347 let mut api = ctx.tcp_api::<I>();
10348 assert_eq!(api.connect(&socket, connect_addr, PORT_1), Err(ConnectError::Pending));
10349 api.handle_timer(id.assert_ip_version());
10350 }
10351 let mut api = ctx.tcp_api::<I>();
10353 assert_eq!(
10354 api.connect(&socket, connect_addr, PORT_1),
10355 Err(ConnectError::ConnectionError(ConnectionError::TimedOut))
10356 );
10357
10358 assert_eq!(api.get_socket_error(&socket), None);
10361 }
10362
10363 #[test]
10365 fn conflict_with_same_link_local_addr_on_different_interfaces() {
10366 set_logger_for_test();
10367 const LOCAL_IP: Ipv6Addr = net_ip_v6!("fe80::1");
10368 const REMOTE_IP: Ipv6Addr = net_ip_v6!("fe80::2");
10369 const LOCAL_PORT: NonZeroU16 = NonZeroU16::new(12345).unwrap();
10370 const REMOTE_PORT: NonZeroU16 = NonZeroU16::new(54321).unwrap();
10371
10372 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
10373 FakeDualStackIpSocketCtx::new(MultipleDevicesId::all().into_iter().map(|device| {
10374 FakeDeviceConfig {
10375 device,
10376 local_ips: vec![SpecifiedAddr::new(LOCAL_IP).unwrap()],
10377 remote_ips: vec![SpecifiedAddr::new(REMOTE_IP).unwrap()],
10378 }
10379 })),
10380 ));
10381 let mut api = ctx.tcp_api::<Ipv6>();
10382 let socket = api.create(Default::default());
10383 api.bind(&socket, None, Some(LOCAL_PORT)).expect("bind should succeed");
10384
10385 api.listen(&socket, NonZeroUsize::new(5).unwrap()).unwrap();
10386
10387 let mut builder =
10388 TcpSegmentBuilder::new(REMOTE_IP, LOCAL_IP, REMOTE_PORT, LOCAL_PORT, 1, None, u16::MAX);
10389 builder.syn(true);
10390 let syn = builder
10391 .wrap_body(Buf::new(vec![], ..))
10392 .serialize_vec_outer(&mut NetworkSerializationContext::default())
10393 .unwrap()
10394 .into_inner();
10395
10396 <TcpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
10397 &mut ctx.core_ctx,
10398 &mut ctx.bindings_ctx,
10399 &MultipleDevicesId::A,
10400 Ipv6::recv_src_addr(REMOTE_IP),
10401 SpecifiedAddr::new(LOCAL_IP).unwrap(),
10402 syn.clone(),
10403 &mut Default::default(),
10404 None,
10405 )
10406 .expect("failed to deliver bytes");
10407
10408 <TcpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
10409 &mut ctx.core_ctx,
10410 &mut ctx.bindings_ctx,
10411 &MultipleDevicesId::B,
10412 Ipv6::recv_src_addr(REMOTE_IP),
10413 SpecifiedAddr::new(LOCAL_IP).unwrap(),
10414 syn,
10415 &mut Default::default(),
10416 None,
10417 )
10418 .expect("failed to deliver bytes");
10419 }
10420
10421 #[ip_test(I)]
10422 fn multicast_syn_ignored<I: TcpTestIpExt>()
10423 where
10424 TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<I, TcpBindingsCtx<FakeDeviceId>>
10425 + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>,
10426 {
10427 set_logger_for_test();
10428 let local_ip = I::TEST_ADDRS.local_ip;
10429 let remote_ip = I::TEST_ADDRS.remote_ip;
10430
10431 let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(local_ip, remote_ip));
10432 let mut api = ctx.tcp_api::<I>();
10433 let listener = api.create(Default::default());
10434 api.bind(&listener, None, Some(PORT_1)).expect("bind should succeed");
10435 api.listen(&listener, NonZeroUsize::new(5).unwrap()).unwrap();
10436
10437 let multicast_ip = I::map_ip((), |()| net_ip_v4!("224.0.0.1"), |()| net_ip_v6!("ff02::1"));
10438 let multicast_addr = SpecifiedAddr::new(multicast_ip).unwrap();
10439
10440 let mut builder =
10441 TcpSegmentBuilder::new(*remote_ip, *multicast_addr, PORT_2, PORT_1, 1, None, u16::MAX);
10442 builder.syn(true);
10443 let syn = builder
10444 .wrap_body(Buf::new(vec![], ..))
10445 .serialize_vec_outer(&mut NetworkSerializationContext::default())
10446 .unwrap()
10447 .into_inner();
10448
10449 let (core_ctx, bindings_ctx) = api.contexts();
10450
10451 <TcpIpTransportContext as IpTransportContext<I, _, _>>::receive_ip_packet(
10452 core_ctx,
10453 bindings_ctx,
10454 &FakeDeviceId,
10455 I::recv_src_addr(*remote_ip),
10456 multicast_addr,
10457 syn,
10458 &mut Default::default(),
10459 None,
10460 )
10461 .expect("failed to deliver bytes");
10462
10463 assert_eq!(
10464 CounterContext::<TcpCountersWithoutSocket<I>>::counters(core_ctx)
10465 .as_ref()
10466 .invalid_ip_addrs_received
10467 .get(),
10468 1
10469 );
10470
10471 assert_matches!(
10472 &listener.get().deref().socket_state,
10473 TcpSocketStateInner::Listener(Listener { accept_queue, .. }) => {
10474 assert_eq!(accept_queue.ready_len(), 0);
10475 assert_eq!(accept_queue.pending_len(), 0);
10476 }
10477 );
10478 }
10479}