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