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